Skip to content

Commit

Permalink
Implement lazy Property for Cfgu Declaration (#347)
Browse files Browse the repository at this point in the history
  • Loading branch information
RonConfigu committed Jan 31, 2024
1 parent 1048b0a commit e2be9b2
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 7 deletions.
40 changes: 40 additions & 0 deletions ts/packages/ts/src/ConfigSchema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { ConfigSchema } from './ConfigSchema';
import { ConfigError } from './utils';

describe(`ConfigSchema`, () => {
describe('cfguStructureValidator', () => {
test('Empty SchemaContents', () => {
expect(() => new ConfigSchema('empty', {})).toThrow(ConfigError);
});
describe('Tests for lazy configs', () => {
test('parse ConfigSchema with `lazy=true` and `default=any`', () => {
expect(
() =>
new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
default: '1',
},
}),
).toThrow(ConfigError);
});
test('parse ConfigSchema with `lazy=true` and `template=any`', () => {
expect(
() =>
new ConfigSchema('lazy', {
T1: {
type: 'String',
default: 'Template',
},
K1: {
type: 'String',
lazy: true,
template: '{{ T1 }}',
},
}),
).toThrow(ConfigError);
});
});
});
});
9 changes: 8 additions & 1 deletion ts/packages/ts/src/ConfigSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ const cfguStructureValidator = (cfgu: Cfgu) => {
`value "${cfgu.default}" must be one of ${_.map(cfgu.options, (option) => `'${option}'`).join(',')}`,
);
}
if (cfgu.lazy) {
throw new ConfigError(reason, `default mustn't set together with lazy property`);
}
try {
cfguValueTypeValidator(cfgu, cfgu.default);
} catch (error) {
Expand All @@ -380,10 +383,14 @@ const cfguStructureValidator = (cfgu: Cfgu) => {
}

if (cfgu.template) {
const reason = 'invalid template property';
if (cfgu.lazy) {
throw new ConfigError(reason, `template mustn't set together with lazy property`);
}
try {
TMPL.parse(cfgu.template);
} catch (error) {
throw new ConfigError('invalid template property', error.message);
throw new ConfigError(reason, error.message);
}
// todo: this is a "weak" validation and NAME() util collides with CONFIGU_SET.[prop]
// const isInvalidTemplate =
Expand Down
9 changes: 3 additions & 6 deletions ts/packages/ts/src/commands/EvalCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,12 @@ export class EvalCommand extends Command<EvalCommandReturn> {
}

private evalFromConfigsOverride(result: EvalCommandReturn): EvalCommandReturn {
if (!this.parameters.configs) {
return result;
}

return _.mapValues(result, (current) => {
const { context } = current;
const hasConfigOverrideValue = Object.prototype.hasOwnProperty.call(this.parameters.configs, context.key);
const hasConfigOverrideValue =
this.parameters.configs && Object.prototype.hasOwnProperty.call(this.parameters.configs, context.key);

if (!hasConfigOverrideValue) {
if (!hasConfigOverrideValue && !context.cfgu.lazy) {
return current;
}

Expand Down
4 changes: 4 additions & 0 deletions ts/packages/ts/src/commands/UpsertCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ export class UpsertCommand extends Command<void> {
);
}

if (cfgu.lazy) {
throw new ConfigError('invalid config key', `keys declared as lazy mustn't have a value`, errorScope);
}

if (value) {
if (cfgu.template) {
throw new ConfigError(
Expand Down
152 changes: 152 additions & 0 deletions ts/packages/ts/src/commands/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,27 @@ describe(`commands`, () => {
},
});

describe(`UpsertCommand`, () => {
describe('Tests for lazy configs', () => {
test('run UpsertCommand with lazy config', async () => {
await expect(() =>
new UpsertCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
},
}),
configs: {
K1: '1',
},
}).run(),
).rejects.toBeInstanceOf(ConfigError);
});
});
});
describe(`EvalCommand`, () => {
test.each<{
name: string;
Expand Down Expand Up @@ -223,6 +244,137 @@ describe(`commands`, () => {
await Promise.all(deletePromises);
}
});
describe('Tests for lazy configs', () => {
beforeAll(async () => {
await store1.init();
await new UpsertCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
},
}),
configs: {
K1: '2',
},
}).run();
});
test('run EvalCommand WITHOUT configs overrides but one config is `cfgu.lazy && cfgu.required = true`', async () => {
expect.assertions(1);
await expect(() =>
new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
required: true,
},
}),
}).run(),
).rejects.toBeInstanceOf(ConfigError);
});
test('run EvalCommand WITHOUT configs overrides but one config is `cfgu.lazy && cfgu.required = false`', async () => {
const result = await new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
},
}),
}).run();
expect(result).toMatchObject({ K1: { result: { value: '' } } });
});
test('run EvalCommand WITH configs overrides but not for the one config is `cfgu.lazy && cfgu.required = true`', async () => {
expect.assertions(1);
await expect(() =>
new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
required: true,
},
K2: {
type: 'String',
},
}),
configs: {
K2: '2',
},
}).run(),
).rejects.toBeInstanceOf(ConfigError);
});
test('run EvalCommand WITH configs overrides for the one config is `cfgu.lazy && cfgu.required = false`', async () => {
const result = await new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
required: false,
},
}),
configs: {
K1: '1',
},
}).run();
expect(result).toMatchObject({ K1: { result: { value: '1' } } });
});
test('run EvalCommand WITH configs overrides for the one config is `cfgu.lazy && cfgu.required = true`', async () => {
const result = await new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
required: true,
},
}),
configs: {
K1: '1',
},
}).run();
expect(result).toMatchObject({ K1: { result: { value: '1' } } });
});
test('run EvalCommand with override for lazy config when there is a value in the store and get the override value in the result', async () => {
const result = await new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
},
}),
configs: {
K1: '1',
},
}).run();
expect(result).toMatchObject({ K1: { result: { value: '1' } } });
});
test("run EvalCommand without override for lazy config when there is a value in the store and don't get it back in the result", async () => {
const result = await new EvalCommand({
store: store1,
set: set1,
schema: new ConfigSchema('lazy', {
K1: {
type: 'String',
lazy: true,
},
}),
}).run();
expect(result).toMatchObject({ K1: { result: { value: '' } } });
});
});
});
describe(`ExportCommand`, () => {
const getEvalResult = async () => {
Expand Down
4 changes: 4 additions & 0 deletions ts/packages/ts/src/types/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export interface Cfgu {
default?: string;
depends?: string[];
description?: string;
lazy?: boolean;
options?: string[];
pattern?: string;
required?: boolean;
Expand Down Expand Up @@ -61,6 +62,7 @@ export interface ConfigSchemaContents {
default?: string;
depends?: string[];
description?: string;
lazy?: boolean;
options?: string[];
pattern?: string;
required?: boolean;
Expand Down Expand Up @@ -347,6 +349,7 @@ const typeMap: any = {
{ json: "default", js: "default", typ: u(undefined, "") },
{ json: "depends", js: "depends", typ: u(undefined, a("")) },
{ json: "description", js: "description", typ: u(undefined, "") },
{ json: "lazy", js: "lazy", typ: u(undefined, true) },
{ json: "options", js: "options", typ: u(undefined, a("")) },
{ json: "pattern", js: "pattern", typ: u(undefined, "") },
{ json: "required", js: "required", typ: u(undefined, true) },
Expand All @@ -367,6 +370,7 @@ const typeMap: any = {
{ json: "default", js: "default", typ: u(undefined, "") },
{ json: "depends", js: "depends", typ: u(undefined, a("")) },
{ json: "description", js: "description", typ: u(undefined, "") },
{ json: "lazy", js: "lazy", typ: u(undefined, true) },
{ json: "options", js: "options", typ: u(undefined, a("")) },
{ json: "pattern", js: "pattern", typ: u(undefined, "") },
{ json: "required", js: "required", typ: u(undefined, true) },
Expand Down
1 change: 1 addition & 0 deletions types/Cfgu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,5 @@ export interface Cfgu {
depends?: string[];
template?: string;
options?: string[];
lazy?: boolean;
}

0 comments on commit e2be9b2

Please sign in to comment.