From Zero to Hero
Step by step guide on how to integrate the MapColonies™ Config Management system into your service.
Assumptions
This guide assumes that you have an already existing service based on the MapColonies boilerplate repo, and basic knowledge of JSON Schema. If needed you can read and learn about JSON Schema in the following link: https://json-schema.org/understanding-json-schema.
It is also recommended to read the schemas package readme.
Before we start
In general, the implementation of the MapColonies™ Config Management system consists of the following steps:
- Work environment setup.
- Define a JSON Schema for your service configuration.
- Validating that the schema and the generated types are correct.
- Integrating the schema with your service. Below each step is explained in detail.
Initialize the work environment
- Clone the schemas repo into your own machine:
git clone git@github.com:MapColonies/schemas.git
- Change the working directory.
cd schemas
- Install the dependencies.
npm install
- Create a new branch for your schema.
git branch <my-branch-name>
- Open the repository in your editor (vscode for this guide).
code .
-
Create a file for your schema under the schemas folder.
The directory hierarchy represents the ID of the schema. For example, a common schema that handles redis configuration might be under
schemas/common/redis/v1.schema.json
and its id will behttps://mapcolonies.com/common/redis/v1
.The file name is based on the order of the schema. If it's the first one, the name should be
v1.schema.json
, otherwise it should be the next number in order.
Creating the schema
- Start by filling all the metadata for your JSON Schema. The more metadata you fill, it will be easier to understand and use your schema.
{
"$id": "https://mapcolonies.com/my-domain/my-schema/v1",
"type": "object",
"title": "myDomainMySchemaV1",
"description": "My domain's schema"
}
- Create your schema content. Use the official JSON Schema docs, The tips page and check other schemas in the repo for reference.
{
"$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"
}
}
}
- If we want our service schema to extend the base boilerplate schema we could do this like that:
{
"$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"
},
"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"
}
}
}
}
}
The result is a combined object with both the boilerplate schema and our own properties.
When extending the boilerplate, you should check and make sure you extend the newest version. The version in this guide might be older.
Run validations
We want to make sure that the schema are valid, therefore we need to check the schema for errors. To do so we can run the following command and make changes based on the feedback.
npm run validate
To see all the validations check the following doc: https://github.com/MapColonies/schemas?tab=readme-ov-file#validations
Validating the types
The types that the schemas package exports are automatically generated from the json schema. We want to make sure that the types are correct before we move forward. This way we can check the types and if anything is wrong go back and fix the schema.
- Build the package:
npm run build
- Check that the types are as you expected. They can be found under the
build
directory under the same hierarchy as the schema. For example, those are the types generated for the schema we created above extending the boilerplate schema:
import { typeSymbol } from '../../symbol.js';
declare const exported: {
readonly [typeSymbol]: {
[x: string]: unknown;
myDomain?: {
[x: string]: unknown;
id?: string | undefined;
name?: string | undefined;
age?: number | undefined;
isAlive?: boolean | undefined;
} | undefined;
openapiConfig: {
[x: string]: unknown;
filePath: string;
basePath: string;
rawPath: string;
uiPath: string;
};
telemetry: {
[x: string]: unknown;
logger: {
[x: string]: unknown;
level: "info" | "trace" | "debug" | "warn" | "error" | "fatal";
prettyPrint: boolean;
};
shared: {
[x: string]: unknown;
serviceName?: string | undefined;
serviceVersion?: string | undefined;
hostname?: string | undefined;
};
tracing: {
[x: string]: unknown;
debug?: boolean | undefined;
url?: string | undefined;
traceRatio?: number | undefined;
isEnabled: boolean;
};
};
server: {
[x: string]: unknown;
port: number;
request: {
[x: string]: unknown;
payload: {
[x: string]: unknown;
limit: string;
};
};
};
};
...
The rest of the file is important for the inner working of the schemas package. You should check only the types.
Checking integration with your service
Before merging the changes you made, we want to make sure it works with your service.
- install the development version of the schemas package into your service. There are multiple ways to achieve that, with some of them described below.
- Github
- Local Path
- NPM Pack
- Other Options
When opening a PR in the schemas repo, the latest version of your branch will be built and be available for a week.
- Push your changes to the remote repository.
git push --set-upstream origin <my-branch-name>
- Open a PR in the schemas repo.
- If all the validations pass, a comment will appear with instructions and link to the package.
- Insert the link into your service's
package.json
file.
{
"dependencies": {
"@map-colonies/schemas": <insert-generated-link>
}
}
- Install the package.
npm install
- Build the schemas package.
npm run build
- Edit your service's
package.json
file with the local path to the schemas repo.
{
"dependencies": {
"@map-colonies/schemas": "file:../schemas"
}
}
- Install the package.
npm install
- Now any time you rebuild the schemas package, it will be available in your service.
if you get ESLint or TSC errors, you should just reload it in your editor.
- Build the schemas package.
npm run build
- Pack the package.
npm pack
- Edit your service's
package.json
file with the path to the packed package.
{
"dependencies": {
"@map-colonies/schemas": "<path-to-packed-package>"
}
}
- Install the package.
npm install
Other options are available, but they won't be covered in this guide. If you you want to check them out, you can read the following docs:
- Change the config in your service to use the new schema.
import { type ConfigInstance, config } from '@map-colonies/config';
import { <your-new-schema>, type [your-new-schema-type] } from '@map-colonies/schemas';
// Choose here the type of the config instance and import this type from the entire application
type ConfigType = ConfigInstance<[your-new-schema-type]>;
let configInstance: ConfigType | undefined;
/**
* Initializes the configuration by fetching it from the server.
* This should only be called from the instrumentation file.
* @returns A Promise that resolves when the configuration is successfully initialized.
*/
async function initConfig(offlineMode?:boolean): Promise<void> {
configInstance = await config({
configName: 'boiler-config',
configServerUrl: 'http://localhost:8080',
schema: <your-new-schema>,
version: 'latest',
offlineMode: offlineMode
});
}
- Check that the service works as expected.
Next steps
Now that you finished writing your schema, you can submit a PR to the schemas repo and ask for it to be reviewed.
You can also check the default configs guide to learn how to define default configs for your schema.
We hope this guide was helpful and you were able to integrate the MapColonies™ Config Management system into your service.
If you have any questions or need help, feel free to ask for help.
If you have any suggestions for this guide, please open a pull request.