Skip to content

Commit f4953da

Browse files
committed
Add restriction for allowed separators in configuration object construction
1 parent fca2c16 commit f4953da

File tree

3 files changed

+51
-3
lines changed

3 files changed

+51
-3
lines changed

src/AzureAppConfiguration.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ interface IConfigurationObject {
2929
export interface ConfigurationObjectConstructionOptions {
3030
/**
3131
* The separator to use when converting hierarchical keys to object properties.
32+
* Supported values: '.', ',', ';', '-', '_', '__', '/', ':'.
3233
* If separator is undefined, '.' will be used by default.
33-
3434
*/
35-
separator?: string;
35+
separator?: "." | "," | ";" | "-" | "_" | "__" | "/" | ":";
3636
}
3737

3838
interface IGettable {

src/AzureAppConfigurationImpl.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ export class AzureAppConfigurationImpl implements AzureAppConfiguration {
184184
*/
185185
constructConfigurationObject(options?: ConfigurationObjectConstructionOptions): Record<string, any> {
186186
const separator = options?.separator ?? ".";
187+
const validSeparators = [".", ",", ";", "-", "_", "__", "/", ":"];
188+
if (!validSeparators.includes(separator)) {
189+
throw new Error(`Invalid separator '${separator}'. Supported values: ${validSeparators.map(s => `'${s}'`).join(", ")}.`);
190+
}
187191

188192
// construct hierarchical data object from map
189193
const data: Record<string, any> = {};

test/load.test.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@ const mockedKVs = [{
1414
}, {
1515
key: "app.settings.fontSize",
1616
value: "40",
17+
}, {
18+
key: "app/settings/fontColor",
19+
value: "red",
20+
}, {
21+
key: "app/settings/fontSize",
22+
value: "40",
23+
}, {
24+
key: "app%settings%fontColor",
25+
value: "red",
26+
}, {
27+
key: "app%settings%fontSize",
28+
value: "40",
1729
}, {
1830
key: "TestKey",
1931
label: "Test",
@@ -50,7 +62,7 @@ const mockedKVs = [{
5062
}, {
5163
key: "app5.settings",
5264
value: "placeholder"
53-
},
65+
}
5466
].map(createMockedKeyValue);
5567

5668
describe("load", function () {
@@ -287,4 +299,36 @@ describe("load", function () {
287299
expect(data.app4.excludedFolders[0]).eq("node_modules");
288300
expect(data.app4.excludedFolders[1]).eq("dist");
289301
});
302+
303+
it("should construct configuration object with customized separator", async () => {
304+
const connectionString = createMockedConnectionString();
305+
const settings = await load(connectionString, {
306+
selectors: [{
307+
keyFilter: "app/settings/*"
308+
}]
309+
});
310+
expect(settings).not.undefined;
311+
const data = settings.constructConfigurationObject({ separator: "/" });
312+
expect(data).not.undefined;
313+
expect(data.app.settings.fontColor).eq("red");
314+
expect(data.app.settings.fontSize).eq("40");
315+
});
316+
317+
it("should throw error when construct configuration object with invalid separator", async () => {
318+
const connectionString = createMockedConnectionString();
319+
const settings = await load(connectionString, {
320+
selectors: [{
321+
keyFilter: "app%settings%*"
322+
}]
323+
});
324+
expect(settings).not.undefined;
325+
326+
expect(() => {
327+
// Below line will throw error because of type checking, i.e. Type '"%"' is not assignable to type '"/" | "." | "," | ";" | "-" | "_" | "__" | ":" | undefined'.ts(2322)
328+
// Here force to turn if off for testing purpose, as JavaScript does not have type checking.
329+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
330+
// @ts-ignore
331+
settings.constructConfigurationObject({ separator: "%" });
332+
}).to.throw("Invalid separator '%'. Supported values: '.', ',', ';', '-', '_', '__', '/', ':'.");
333+
});
290334
});

0 commit comments

Comments
 (0)