Skip to content

Commit 650da91

Browse files
committed
feat: adds $allowNull option for $substitute
1 parent 8b2b991 commit 650da91

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

app-config-extensions/src/index.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,24 @@ describe('$substitute directive', () => {
723723
expect(parsed.toJSON()).toEqual({ foo: 'bar' });
724724
});
725725

726+
it('allows null value when $allowNull', async () => {
727+
const source = new LiteralSource({
728+
foo: { $substitute: { $name: 'FOO', $fallback: null, $allowNull: true } },
729+
});
730+
731+
const parsed = await source.read([environmentVariableSubstitution()]);
732+
733+
expect(parsed.toJSON()).toEqual({ foo: null });
734+
});
735+
736+
it('does not allow number even when $allowNull', async () => {
737+
const source = new LiteralSource({
738+
foo: { $substitute: { $name: 'FOO', $fallback: 42, $allowNull: true } },
739+
});
740+
741+
await expect(source.read([environmentVariableSubstitution()])).rejects.toThrow();
742+
});
743+
726744
it('doesnt visit fallback if name is defined', async () => {
727745
const failDirective = forKey('$fail', () => () => {
728746
throw new Error();

app-config-extensions/src/index.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,10 @@ export function environmentVariableSubstitution(
174174
stringSchema(),
175175
);
176176

177+
const validateStringOrNull: ValidationFunction<string> = validationFunction(
178+
({ fromJsonSchema }) => fromJsonSchema({ type: ['null', 'string'] } as const),
179+
);
180+
177181
return forKey(['$substitute', '$subs'], (value, key, ctx) => async (parse) => {
178182
if (typeof value === 'string') {
179183
return parse(performAllSubstitutions(value, envType), { shouldFlatten: true });
@@ -182,7 +186,7 @@ export function environmentVariableSubstitution(
182186
validateObject(value, [...ctx, key]);
183187
if (Array.isArray(value)) throw new AppConfigError('$substitute was given an array');
184188

185-
const { $name: variableName, $fallback: fallback } = value;
189+
const { $name: variableName, $fallback: fallback, $allowNull: allowNull } = value;
186190
validateString(variableName, [...ctx, key, [InObject, '$name']]);
187191

188192
const resolvedValue = process.env[variableName];
@@ -193,7 +197,12 @@ export function environmentVariableSubstitution(
193197

194198
if (fallback !== undefined) {
195199
const fallbackValue = (await parse(fallback)).toJSON();
196-
validateString(fallbackValue, [...ctx, key, [InObject, '$fallback']]);
200+
201+
if (allowNull) {
202+
validateStringOrNull(fallbackValue, [...ctx, key, [InObject, '$fallback']]);
203+
} else {
204+
validateString(fallbackValue, [...ctx, key, [InObject, '$fallback']]);
205+
}
197206

198207
return parse(fallbackValue, { shouldFlatten: true });
199208
}

0 commit comments

Comments
 (0)