Skip to content

Instantly share code, notes, and snippets.

@jtmthf
Created May 4, 2022 16:22
Show Gist options
  • Save jtmthf/77fc5c1494ee1dd9365a21c306822685 to your computer and use it in GitHub Desktop.
Save jtmthf/77fc5c1494ee1dd9365a21c306822685 to your computer and use it in GitHub Desktop.

PropertySource

A PropertySource is an interface that allows a configuration value to be loaded by its name. An implementation may either be sync or async depending on its backing implmentation.

interface PropertySource {
  get(key: string): unknown;
}

interface AsyncPropertySource {
  get(key: string): Promise<unknown>;
}

There can also be a CompositePropertySource that is created from multiple sources and aggregates all of its sources.

class CompositePropertySource implements AsyncPropertySource {
  static from(...sources: (PropertySource | AsyncPropertySource)[]): CompositePropertySource
}

A number of predefined property source implementations can be published and developers will have the ability to create their own as needed.

  • SSMPropertySource
  • SecretsManagerPropertySource
  • EnvironmentPropertySource
  • CommandLinePropertySource
  • JsonPropertySource
  • YamlPropertySource

Property names should be normalized when requested. This will allow values from environment variables FOO_BAR and ssm foo/bar to be used interchangeably without concern to their implementation.

// the below forms are all equivalent
source.get('app.aws.accessKey');
source.get('app_aws_accesskey');
source.get('APP_AWS_ACCESSKEY');

Binding

As configuration values should be accessed in a typesafe manner and validated upfront, a mechanism should be provided to bind property sources to a validated object that in turn can be injected.

This can be done as a class and/or functional approach.

@ConfigurationProperties({prefix: 'app.aws')
class GatewayProperties {

  @NotEmpty()
  accessKey: string;
}
const gatewayProperties = configurationSchema({
  prefix: 'app.aws',
  properties: {
    accessKey: string().notEmpty()
  },
});

## Usage

The typesafe configuration objects can then be injected into services.

```ts
class AwsGateway {
  constructor(private @Inject(GatewayProperties) properties) {
  }
  
  assumeRole() {
    const accessKey = this.properties.accessKey;
    // ...
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment