0.5.1 • Published 6 months ago

@rocketmakers/environment v0.5.1

Weekly downloads
-
License
ISC
Repository
-
Last release
6 months ago

Rocketmakers Environment

Introduction

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.

Code Generation

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)

Do It Yourself

Alternatively, you can just author your own Environment class (as per the example above)!

Consuming in your Application

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: [],
  });
}