This package is used to describe the contract your application has to its running environment, and make this contract available to other downstream consumers of your package.
You can define a (machine readable) JSON/YAML file, that will be used to generate a TypeScript Environment class for consumption in your application
{
"$schema": "./node_modules/@rocketmakers/environment/schema/environment-schema.json",
"version": 1,
"name": "Authentication",
"prefix": "AUTH",
"variables": [
{ "kind": "string", "name": "TOKEN", "secret": true },
{ "kind": "string", "name": "NAME", "optional": true },
{ "kind": "string", "name": "CONTACTS", "optional": true, "array": true },
{ "kind": "number", "name": "RATE" },
{ "kind": "integer", "name": "PORT" },
{ "kind": "file-path", "name": "RSA_FILE", "secret": true }
]
}
Note:
secret
is purely advisory for any consumers, and not directly used within this package!
Will generate environment.generated.ts
...
/*
This file is generated via the "@rocketmakers/environment" package
!!!DO NOT MODIFY THE CODE DIRECTLY INSIDE THIS FILE!!!
To make changes, modify the environment json file and run the "environment-generate" command
*/
import { environmentVariable } from '@rocketmakers/environment';
/* Generated Environment Configuration */
export class AuthenticationEnvironment {
/* contacts :: AUTH_CONTACTS_0, AUTH_CONTACTS_1, ..., AUTH_CONTACTS_<n> */
@environmentVariable.string('AUTH_CONTACTS', { optional: true, array: true })
contacts?: string[];
/* name :: AUTH_NAME */
@environmentVariable.string('AUTH_NAME', { optional: true })
name?: string;
/* port :: AUTH_PORT */
@environmentVariable.integer('AUTH_PORT')
port!: number;
/* rate :: AUTH_RATE */
@environmentVariable.number('AUTH_RATE')
rate!: number;
/* rsaFile :: AUTH_RSA_FILE */
@environmentVariable.filePath('AUTH_RSA_FILE')
rsaFile!: string;
/* token :: AUTH_TOKEN */
@environmentVariable.string('AUTH_TOKEN')
token!: string;
}
Note: Array properties will append the index onto the Key at runtime, e.g. To build the array from "XYZ", we will search for "XYZ_0" then "XYZ_1"... until an undefined value is found to terminate the read
If you place the json file in the root of your project (environment.json
) - you can add a script to your package.json
to turn the json into the typescript Environment class!
If your project is TypeScript 4
{
"scripts": {
"env-generate": "environment-generate ./environment.json ./source/environment.generated.ts"
}
If your project is TypeScript 3
{
"scripts": {
"env-generate": "environment-generate-v3 ./environment.json ./source/environment.generated.ts"
}
environment-generate
takes 2 parameters
- input file (.json/.yaml)
- output file (.ts)
Alternatively, you can just author your own Environment class (as per the example above)!
To resolve your configuration from the environment...
import { readFromEnvironment } from '@rocketmakers/environment';
import { AuthenticationEnvironment } from './environment.generated';
export function getConfig(): Promise<AuthenticationEnvironment> {
return readFromEnvironment(AuthenticationEnvironment);
}
There is a further helper method to allow you to supply the overriding optional values (making the properties mandatory - Required<T>
)
import { ensureEnvironmentRequired, readFromEnvironment } from '@rocketmakers/environment';
import { AuthenticationEnvironment } from './environment.generated';
export async function getConfig(): Promise<Required<AuthenticationEnvironment>> {
const withOptional = await readFromEnvironment(AuthenticationEnvironment);
return ensureEnvironmentRequired(withOptional, {
name: 'Only used if not supplied by the environment',
contacts: [],
});
}