๐ฆธโโ๏ธ From Zero to Hero
Welcome! This step-by-step guide will show you exactly how to integrate the MapColoniesโข Config Management system into your service. Let's get you set up! ๐
๐ง Assumptionsโ
We assume you have an existing service based on the MapColonies boilerplate repo and a solid grasp of JSON Schema. Need a refresher? Check out Understanding JSON Schema.
We highly recommend reading the schemas package readme before diving in.
๐บ๏ธ The Game Planโ
Integrating the config management system requires just four high-level steps:
- Initialize: Set up your work environment.
- Define: Create a JSON Schema for your service configuration.
- Validate: Ensure your schema and generated types are structurally perfect.
- Integrate: Wire the schema into your service.
Let's break these down.
๐๏ธ 1. Initialize the Work Environmentโ
- Clone the schemas repository:
git clone git@github.com:MapColonies/schemas.git
- Navigate into the directory:
cd schemas
- Install dependencies:
npm install
- Branch out: Create a new branch for your schema.
git branch <my-branch-name>
- Open your editor (VS Code recommended):
code .
- Create your schema file:
Place your new file under the
schemasfolder. The folder hierarchy defines the ID of your schema. (Example: A schema handling Redis configuration might live atschemas/common/redis/v1.schema.jsonwith the IDhttps://mapcolonies.com/common/redis/v1). Always start withv1.schema.jsonand increment sequentially for future versions.
โ๏ธ 2. Creating the Schemaโ
- Add Metadata: Start by filling out the JSON Schema metadata. Rich metadata makes your schema vastly easier for others to understand and use!
{
"$id": "https://mapcolonies.com/my-domain/my-schema/v1",
"type": "object",
"title": "myDomainMySchemaV1",
"description": "My domain's schema"
}
- Add Properties: Build out your schema content. Use the official JSON Schema docs, our Tips page, and other repo schemas for inspiration!
{
"$id": "https://mapcolonies.com/my-domain/my-schema/v1",
"type": "object",
"title": "myDomainMySchemaV1",
"description": "My domain's schema",
"properties": {
"id": {
"type": "string",
"description": "The unique identifier for the entity"
},
"name": {
"type": "string",
"description": "The name of the entity"
},
"age": {
"type": "integer",
"description": "The age of the entity",
"x-env-value": "ENTITY_AGE"
},
"isAlive": {
"type": "boolean",
"description": "Is the entity alive",
"x-env-value": "ENTITY_IS_ALIVE"
}
}
}
Use x-env-value to allow overriding a field's value via environment variables! Read more in the config docs and schema docs.
- Extend the Boilerplate (Optional): Want your schema to inherit the base boilerplate schema? Simply combine them using
allOf:
{
"$id": "https://mapcolonies.com/my-domain/my-schema/v1",
"type": "object",
"title": "myDomainMySchemaV1",
"description": "My domain's schema",
"allOf": [
{
"$ref": "https://mapcolonies.com/common/boilerplate/v2"
},
{
"type": "object",
"properties": {
"myDomain": {
"$ref": "#/definitions/myDomainMySchemaV1"
}
}
}
],
"definitions": {
"myDomainMySchemaV1": {
"type": "object",
"properties": {
"id": {
"type": "string",
"description": "The unique identifier for the entity"
},
"name": {
"type": "string",
"description": "The name of the entity"
}
}
}
}
}
When extending the boilerplate, always double-check that you are referencing the newest version!
โ 3. Run Validationsโ
Let's ensure your schema is flawless. Run the validation script to catch any errors early:
npm run validate
Curious what it checks? View all validation rules here.
๐ 4. Validating the Typesโ
The types exported by the schemas package are auto-generated. Let's make sure they generated correctly!
- Build the package:
npm run build
- Inspect the types: Check the
.d.tsfiles inside thebuilddirectory matching your schema hierarchy. Ensure your properties typed out correctly!
import { typeSymbol } from '../../symbol.js';
declare const exported: {
readonly [typeSymbol]: {
[x: string]: unknown;
myDomain?: {
[x: string]: unknown;
id?: string | undefined;
name?: string | undefined;
} | undefined;
// ... (boilerplate types continue)
};
๐ 5. Integration With Your Serviceโ
Before opening a PR, we need to test this locally inside your service.
1. Install your development schema package. You have a few options:
- Github PR
- Local Path
- NPM Pack
Opening a PR auto-builds a preview package valid for one week!
- Push your branch:
git push --set-upstream origin <my-branch-name> - Open a PR in the schemas repo.
- Copy the generated preview link from the PR comment.
- Add it to your service's
package.json:
{
"dependencies": {
"@map-colonies/schemas": "<insert-generated-link>"
}
}
- Run
npm install.
- Run
npm run buildin the schemas repo. - Link it locally in your service's
package.json:
{
"dependencies": {
"@map-colonies/schemas": "file:../schemas"
}
}
- Run
npm install. (Note: Reload your editor if TSC/ESLint complains!)
- Run
npm run buildthennpm packin the schemas repo. - Link the tarball in your service:
{
"dependencies": {
"@map-colonies/schemas": "<path-to-packed-package>"
}
}
- Run
npm install.
2. Update your service configuration.
import { type ConfigInstance, config } from '@map-colonies/config';
import { myDomainMySchemaV1, type myDomainMySchemaV1Type } from '@map-colonies/schemas';
// Define the global config type
type ConfigType = ConfigInstance<myDomainMySchemaV1Type>;
let configInstance: ConfigType | undefined;
/**
* Initializes the configuration. Call this early in instrumentation!
*/
async function initConfig(offlineMode?: boolean): Promise<void> {
configInstance = await config({
configName: 'boiler-config',
configServerUrl: 'http://localhost:8080',
schema: myDomainMySchemaV1,
version: 'latest',
offlineMode: offlineMode
});
}
Your exported schema names are automatically derived from the $id.
https://mapcolonies.com/my-domain/my-schema/v1 automatically becomes myDomainMySchemaV1 and myDomainMySchemaV1Type.
๐ฏ Next Stepsโ
You did it! ๐
- Submit your PR to the schemas repo for review.
- Check out the Default Configs guide to learn how to ship safe defaults.