Skip to content

Commit 6285b3d

Browse files
committed
refactor:environment via parsing extension context
1 parent 1e7836c commit 6285b3d

File tree

9 files changed

+34
-25
lines changed

9 files changed

+34
-25
lines changed

app-config-config/src/index.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,7 @@ export async function loadUnvalidatedConfig({
9090
const environmentAliases =
9191
environmentAliasesArg ?? meta.value.environmentAliases ?? defaultAliases;
9292

93-
const parsingExtensions =
94-
parsingExtensionsArg ??
95-
defaultExtensions(environmentAliases, environmentOverride, undefined, environmentSourceNames);
93+
const parsingExtensions = parsingExtensionsArg ?? defaultExtensions();
9694

9795
const secretsFileExtensions =
9896
secretsFileExtensionsArg ?? parsingExtensions.concat(markAllValuesAsSecret());
@@ -112,15 +110,13 @@ export async function loadUnvalidatedConfig({
112110
join(directory, fileNameBase),
113111
environmentOverride,
114112
environmentAliases,
115-
undefined,
116113
environmentSourceNames,
117114
).read(parsingExtensions),
118115

119116
new FlexibleFileSource(
120117
join(directory, secretsFileNameBase),
121118
environmentOverride,
122119
environmentAliases,
123-
undefined,
124120
environmentSourceNames,
125121
)
126122
.read(secretsFileExtensions)
@@ -210,6 +206,7 @@ export async function loadValidatedConfig(
210206
: undefined,
211207
environmentOverride: options?.environmentOverride,
212208
environmentAliases: options?.environmentAliases,
209+
environmentSourceNames: options?.environmentSourceNames,
213210
...schemaOptions,
214211
}),
215212
loadUnvalidatedConfig(options),

app-config-core/src/config-source.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { safeLoad as parseYAML, safeDump as stringifyYAML } from 'js-yaml';
44
import { parse as parseJSON5, stringify as stringifyJSON5 } from 'json5';
55
import { Json, JsonObject } from '@app-config/utils';
66
import { logger } from '@app-config/logging';
7-
import { ParsedValue, ParsingExtension } from './parsed-value';
7+
import { ParsedValue, ParsingContext, ParsingExtension } from './parsed-value';
88
import { AppConfigError, NotFoundError, ParsingError, BadFileType } from './errors';
99

1010
export enum FileType {
@@ -30,15 +30,15 @@ export abstract class ConfigSource {
3030
}
3131

3232
/** Reads the contents of the source into a full ParsedValue (not the raw JSON, like readValue) */
33-
async read(extensions?: ParsingExtension[]): Promise<ParsedValue> {
33+
async read(extensions?: ParsingExtension[], context?: ParsingContext): Promise<ParsedValue> {
3434
const rawValue = await this.readValue();
3535

36-
return ParsedValue.parse(rawValue, this, extensions);
36+
return ParsedValue.parse(rawValue, this, extensions, undefined, context);
3737
}
3838

3939
/** Ergonomic helper for chaining `source.read(extensions).then(v => v.toJSON())` */
40-
async readToJSON(extensions?: ParsingExtension[]): Promise<Json> {
41-
const parsed = await this.read(extensions);
40+
async readToJSON(extensions?: ParsingExtension[], context?: ParsingContext): Promise<Json> {
41+
const parsed = await this.read(extensions, context);
4242

4343
return parsed.toJSON();
4444
}
@@ -82,8 +82,10 @@ export class CombinedSource extends ConfigSource {
8282
}
8383

8484
// override so that ParsedValue is directly from the originating ConfigSource
85-
async read(extensions?: ParsingExtension[]): Promise<ParsedValue> {
86-
const values = await Promise.all(this.sources.map((source) => source.read(extensions)));
85+
async read(extensions?: ParsingExtension[], context?: ParsingContext): Promise<ParsedValue> {
86+
const values = await Promise.all(
87+
this.sources.map((source) => source.read(extensions, context)),
88+
);
8789

8890
const merged = values.reduce<ParsedValue | undefined>((acc, parsed) => {
8991
if (!acc) return parsed;
@@ -137,11 +139,11 @@ export class FallbackSource extends ConfigSource {
137139
}
138140

139141
// override so that ParsedValue is directly from the originating ConfigSource
140-
async read(extensions?: ParsingExtension[]): Promise<ParsedValue> {
142+
async read(extensions?: ParsingExtension[], context?: ParsingContext): Promise<ParsedValue> {
141143
// take the first value that comes back without an error
142144
for (const source of this.sources) {
143145
try {
144-
const value = await source.read(extensions);
146+
const value = await source.read(extensions, context);
145147
logger.verbose(`FallbackSource found successful source`);
146148

147149
return value;

app-config-core/src/parsed-value.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ export type ParsingExtensionKey =
1717
| [typeof InArray, number]
1818
| [typeof Root];
1919

20-
export type ParsingContext = Record<string, string | Record<string, string>>;
20+
export interface ParsingContext {
21+
[k: string]: string | Record<string, string> | string[] | undefined;
22+
}
2123

2224
export type ParsingExtension<T extends Json = Json> = (
2325
value: T,
@@ -69,8 +71,9 @@ export class ParsedValue {
6971
source: ConfigSource,
7072
extensions?: ParsingExtension[],
7173
metadata?: ParsedValueMetadata,
74+
context?: ParsingContext,
7275
): Promise<ParsedValue> {
73-
return parseValue(raw, source, extensions, metadata);
76+
return parseValue(raw, source, extensions, metadata, context);
7477
}
7578

7679
/** Parses (with extensions) from a plain JSON object */

app-config-default-extensions/index.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
// NOTE: Also, we don't require modules up-front - lazy load them instead.
66
// This avoids circular dependency chains.
7-
const { defaultAliases } = require('@app-config/node');
87

98
module.exports = {
109
defaultExtensions() {

app-config-extensions/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ function getEnv(context: ParsingContext) {
534534

535535
return (
536536
(environmentOverride as string) ??
537-
currentEnvironment(getAliases(context), environmentSourceNames as string)
537+
currentEnvironment(getAliases(context), environmentSourceNames as string | string[])
538538
);
539539
}
540540

app-config-node/src/file-source.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
ParsingExtension,
99
AppConfigError,
1010
NotFoundError,
11+
ParsingContext,
1112
} from '@app-config/core';
1213
import { logger } from '@app-config/logging';
1314
import { currentEnvironment, defaultAliases, EnvironmentAliases } from './environment';
@@ -46,8 +47,8 @@ export class FlexibleFileSource extends ConfigSource {
4647
private readonly filePath: string,
4748
private readonly environmentOverride?: string,
4849
private readonly environmentAliases: EnvironmentAliases = defaultAliases,
49-
private readonly fileExtensions: string[] = ['yml', 'yaml', 'toml', 'json', 'json5'],
5050
private readonly environmentSourceNames?: string[] | string,
51+
private readonly fileExtensions: string[] = ['yml', 'yaml', 'toml', 'json', 'json5'],
5152
) {
5253
super();
5354
}
@@ -90,10 +91,15 @@ export class FlexibleFileSource extends ConfigSource {
9091
return this.resolveSource().then((source) => source.readContents());
9192
}
9293

93-
async read(extensions?: ParsingExtension[]): Promise<ParsedValue> {
94+
async read(extensions?: ParsingExtension[], context?: ParsingContext): Promise<ParsedValue> {
9495
const source = await this.resolveSource();
9596

96-
return source.read(extensions);
97+
return source.read(extensions, {
98+
environmentOverride: this.environmentOverride,
99+
environmentAliases: this.environmentAliases,
100+
environmentSourceNames: this.environmentSourceNames,
101+
...context,
102+
});
97103
}
98104
}
99105

app-config-schema/src/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
} from '@app-config/core';
1616
import { logger } from '@app-config/logging';
1717
import {
18-
defaultAliases,
1918
EnvironmentAliases,
2019
EnvironmentSource,
2120
FileSource,
@@ -30,6 +29,7 @@ export interface SchemaLoadingOptions {
3029
environmentVariableName?: string;
3130
environmentOverride?: string;
3231
environmentAliases?: EnvironmentAliases;
32+
environmentSourceNames?: string[] | string;
3333
parsingExtensions?: ParsingExtension[];
3434
}
3535

@@ -48,7 +48,8 @@ export async function loadSchema({
4848
fileNameBase = '.app-config.schema',
4949
environmentVariableName = 'APP_CONFIG_SCHEMA',
5050
environmentOverride,
51-
environmentAliases = defaultAliases,
51+
environmentAliases,
52+
environmentSourceNames,
5253
parsingExtensions = [],
5354
}: SchemaLoadingOptions = {}): Promise<Schema> {
5455
const env = new EnvironmentSource(environmentVariableName);
@@ -72,6 +73,7 @@ export async function loadSchema({
7273
join(directory, fileNameBase),
7374
environmentOverride,
7475
environmentAliases,
76+
environmentSourceNames,
7577
);
7678

7779
parsed = await source.read(parsingExtensions);

tests/parsing-extensions/eval-package/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = (options) => (value, [, key]) => {
1+
module.exports = (options) => (value, [[, key]]) => {
22
if (key === '$eval') {
33
if (typeof value === 'string') {
44
return (parse) => parse(eval(value), { shouldFlatten: true });

tests/parsing-extensions/random-package/main.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module.exports = (options) => (value, [, key]) => {
1+
module.exports = (options) => (value, [[, key]]) => {
22
const rng = require('seedrandom')(options.seed);
33

44
if (key === '$random') {

0 commit comments

Comments
 (0)