zcb 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/cli.cjs +1 -1
- package/dist/cjs/cli.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/templates/config.ts.hbs +1 -1
- package/dist/esm/cli.mjs +1 -1
- package/dist/esm/cli.mjs.map +1 -1
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/templates/config.ts.hbs +1 -1
- package/dist/production.analysis.txt +24 -24
- package/dist/types/cjs/cli.d.cts +7 -1
- package/dist/types/cjs/cli.d.cts.map +1 -1
- package/dist/types/cjs/createConfigBuilder.d.cts +3 -3
- package/dist/types/cjs/createConfigBuilder.d.cts.map +1 -1
- package/dist/types/cjs/createConfigParser.d.cts.map +1 -1
- package/dist/types/cjs/transformers/runExperiments.d.cts.map +1 -1
- package/dist/types/cjs/utils/arrayHasInvalidDefaults.d.cts +2 -2
- package/dist/types/cjs/utils/arrayHasInvalidDefaults.d.cts.map +1 -1
- package/dist/types/cjs/utils/collateDefaultValues.d.cts +2 -2
- package/dist/types/cjs/utils/collateDefaultValues.d.cts.map +1 -1
- package/dist/types/cjs/utils/collateObjectPropertyDefaults.d.cts +2 -2
- package/dist/types/cjs/utils/collateObjectPropertyDefaults.d.cts.map +1 -1
- package/dist/types/cjs/utils/importValidateTransformWriteConfig.d.cts +2 -2
- package/dist/types/cjs/utils/importValidateTransformWriteConfig.d.cts.map +1 -1
- package/dist/types/cjs/utils/isInvalidPropertyOverride.d.cts.map +1 -1
- package/dist/types/cjs/utils/isPropertyReservedWord.d.cts.map +1 -1
- package/dist/types/cjs/utils/isSchemaValid.d.cts +2 -2
- package/dist/types/cjs/utils/isSchemaValid.d.cts.map +1 -1
- package/dist/types/cjs/utils/isValidPropertyDefinition.d.cts +2 -2
- package/dist/types/cjs/utils/isValidPropertyDefinition.d.cts.map +1 -1
- package/dist/types/cjs/utils/objectPropertyHasDefaults.d.cts +2 -2
- package/dist/types/cjs/utils/objectPropertyHasDefaults.d.cts.map +1 -1
- package/dist/types/cjs/utils/recordHasInvalidDefaults.d.cts +2 -2
- package/dist/types/cjs/utils/recordHasInvalidDefaults.d.cts.map +1 -1
- package/dist/types/cjs/utils/transformConfig.d.cts.map +1 -1
- package/dist/types/cjs/utils/transformWriteConfig.d.cts.map +1 -1
- package/dist/types/esm/cli.d.ts +7 -1
- package/dist/types/esm/cli.d.ts.map +1 -1
- package/dist/types/esm/createConfigBuilder.d.ts +3 -3
- package/dist/types/esm/createConfigBuilder.d.ts.map +1 -1
- package/dist/types/esm/createConfigParser.d.ts.map +1 -1
- package/dist/types/esm/transformers/runExperiments.d.ts.map +1 -1
- package/dist/types/esm/utils/arrayHasInvalidDefaults.d.ts +2 -2
- package/dist/types/esm/utils/arrayHasInvalidDefaults.d.ts.map +1 -1
- package/dist/types/esm/utils/collateDefaultValues.d.ts +2 -2
- package/dist/types/esm/utils/collateDefaultValues.d.ts.map +1 -1
- package/dist/types/esm/utils/collateObjectPropertyDefaults.d.ts +2 -2
- package/dist/types/esm/utils/collateObjectPropertyDefaults.d.ts.map +1 -1
- package/dist/types/esm/utils/importValidateTransformWriteConfig.d.ts +2 -2
- package/dist/types/esm/utils/importValidateTransformWriteConfig.d.ts.map +1 -1
- package/dist/types/esm/utils/isInvalidPropertyOverride.d.ts.map +1 -1
- package/dist/types/esm/utils/isPropertyReservedWord.d.ts.map +1 -1
- package/dist/types/esm/utils/isSchemaValid.d.ts +2 -2
- package/dist/types/esm/utils/isSchemaValid.d.ts.map +1 -1
- package/dist/types/esm/utils/isValidPropertyDefinition.d.ts +2 -2
- package/dist/types/esm/utils/isValidPropertyDefinition.d.ts.map +1 -1
- package/dist/types/esm/utils/objectPropertyHasDefaults.d.ts +2 -2
- package/dist/types/esm/utils/objectPropertyHasDefaults.d.ts.map +1 -1
- package/dist/types/esm/utils/recordHasInvalidDefaults.d.ts +2 -2
- package/dist/types/esm/utils/recordHasInvalidDefaults.d.ts.map +1 -1
- package/dist/types/esm/utils/transformConfig.d.ts.map +1 -1
- package/dist/types/esm/utils/transformWriteConfig.d.ts.map +1 -1
- package/dist/types/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +48 -43
- package/pnpm-workspace.yaml +4 -0
- package/src/__testUtils__/builtConfig.ts +1 -1
- package/src/__testUtils__/configBuilder.ts +28 -22
- package/src/__testUtils__/schema.ts +2 -2
- package/src/cli.ts +9 -3
- package/src/createConfigBuilder.test.ts +157 -38
- package/src/createConfigBuilder.ts +44 -41
- package/src/createConfigParser.ts +1 -1
- package/src/createConfigReader.ts +2 -2
- package/src/templates/config.ts.hbs +1 -1
- package/src/transformers/cloneNonEnumerableValues.ts +1 -1
- package/src/transformers/runExperiments.ts +16 -5
- package/src/utils/arrayHasInvalidDefaults.ts +3 -3
- package/src/utils/collateDefaultValues.ts +5 -5
- package/src/utils/collateObjectPropertyDefaults.ts +4 -2
- package/src/utils/importValidateTransformWriteConfig.ts +25 -13
- package/src/utils/isInvalidPropertyOverride.ts +1 -1
- package/src/utils/isPropertyReservedWord.ts +1 -1
- package/src/utils/isSchemaValid.ts +2 -2
- package/src/utils/isValidPropertyDefinition.ts +3 -3
- package/src/utils/objectPropertyHasDefaults.ts +3 -3
- package/src/utils/recordHasInvalidDefaults.ts +3 -3
- package/src/utils/transformConfig.test.ts +14 -0
- package/src/utils/transformConfig.ts +16 -4
- package/src/utils/transformWriteConfig.test.ts +111 -0
- package/src/utils/transformWriteConfig.ts +15 -8
- package/dist/types/cjs/utils/jsonStringifyReplacer.d.cts +0 -109
- package/dist/types/cjs/utils/jsonStringifyReplacer.d.cts.map +0 -1
- package/dist/types/esm/utils/jsonStringifyReplacer.d.ts +0 -109
- package/dist/types/esm/utils/jsonStringifyReplacer.d.ts.map +0 -1
- package/src/__snapshots__/createConfigBuilder.test.ts.snap +0 -30
- package/src/utils/jsonStringifyReplacer.ts +0 -6
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
import { type JSONSchema7 } from 'json-schema';
|
|
2
1
|
import { cloneDeep, merge } from 'lodash-es';
|
|
3
2
|
import { v4 as uuidV4 } from 'uuid';
|
|
4
|
-
import {
|
|
5
|
-
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
3
|
+
import { ZodError, z } from 'zod';
|
|
6
4
|
import { cloneNonEnumerableValues } from './transformers/cloneNonEnumerableValues.ts';
|
|
7
5
|
import { collateDefaultValues } from './utils/collateDefaultValues.ts';
|
|
8
6
|
import { isDerivedValueCallback } from './utils/isDerivedValueCallback.ts';
|
|
@@ -10,7 +8,6 @@ import { isInvalidPropertyOverride } from './utils/isInvalidPropertyOverride.ts'
|
|
|
10
8
|
import { RESERVED_KEYWORDS, isPropertyReservedWord } from './utils/isPropertyReservedWord.ts';
|
|
11
9
|
import { isSchemaValid } from './utils/isSchemaValid.ts';
|
|
12
10
|
import { isValidValue } from './utils/isValidValue.ts';
|
|
13
|
-
import { jsonStringifyReplacer } from './utils/jsonStringifyReplacer.ts';
|
|
14
11
|
import { transformConfigSync } from './utils/transformConfig.ts';
|
|
15
12
|
|
|
16
13
|
export type ConfigBuilder<ZodTypes> = {
|
|
@@ -20,7 +17,7 @@ export type ConfigBuilder<ZodTypes> = {
|
|
|
20
17
|
) => ConfigBuilder<ZodTypes>;
|
|
21
18
|
} & {
|
|
22
19
|
$disable: () => ConfigBuilder<ZodTypes>;
|
|
23
|
-
$errors: () => ZodError['
|
|
20
|
+
$errors: () => ZodError['issues'];
|
|
24
21
|
$experiment: (key: string) => ConfigBuilder<ZodTypes>;
|
|
25
22
|
$extend: (configBuilder: ConfigBuilder<ZodTypes>) => ConfigBuilder<ZodTypes>;
|
|
26
23
|
$flush: () => ZodTypes;
|
|
@@ -38,7 +35,7 @@ export type CreateConfigBuilderOptions = {
|
|
|
38
35
|
};
|
|
39
36
|
|
|
40
37
|
export const createConfigBuilder = <ZodTypes>(
|
|
41
|
-
zodSchema: z.
|
|
38
|
+
zodSchema: z.ZodType,
|
|
42
39
|
options: CreateConfigBuilderOptions = {},
|
|
43
40
|
derivedValueCallbacks: Partial<
|
|
44
41
|
Record<
|
|
@@ -58,9 +55,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
58
55
|
|
|
59
56
|
type DerivedValueCallback<K extends keyof Config = keyof Config> = (c: Config) => Config[K];
|
|
60
57
|
|
|
61
|
-
|
|
62
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
63
|
-
const jsonSchema = zodToJsonSchema(zodSchema) as JSONSchema7;
|
|
58
|
+
const jsonSchema = z.toJSONSchema(zodSchema);
|
|
64
59
|
|
|
65
60
|
if (isSchemaValid(jsonSchema)) {
|
|
66
61
|
throw new Error(`The root type of a config schema must be "object", but received "${String(jsonSchema.type)}"`);
|
|
@@ -68,29 +63,31 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
68
63
|
|
|
69
64
|
const uuid = options.overrides?.uuid ?? uuidV4;
|
|
70
65
|
|
|
71
|
-
const addNonEnumeralBaseProperties = (conf: Config) => {
|
|
72
|
-
Object.
|
|
73
|
-
|
|
74
|
-
enumerable: false,
|
|
75
|
-
value: true,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
Object.defineProperty(conf, '__id', {
|
|
79
|
-
configurable: false,
|
|
80
|
-
enumerable: false,
|
|
81
|
-
value: uuid(),
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if (options.type) {
|
|
85
|
-
Object.defineProperty(conf, '__type', {
|
|
66
|
+
const addNonEnumeralBaseProperties = (conf: Config): void => {
|
|
67
|
+
Object.defineProperties(conf, {
|
|
68
|
+
__id: {
|
|
86
69
|
configurable: false,
|
|
87
70
|
enumerable: false,
|
|
88
|
-
value:
|
|
89
|
-
}
|
|
90
|
-
|
|
71
|
+
value: uuid(),
|
|
72
|
+
},
|
|
73
|
+
__zcb: {
|
|
74
|
+
configurable: false,
|
|
75
|
+
enumerable: false,
|
|
76
|
+
value: true,
|
|
77
|
+
},
|
|
78
|
+
...(options.type
|
|
79
|
+
? {
|
|
80
|
+
__type: {
|
|
81
|
+
configurable: false,
|
|
82
|
+
enumerable: false,
|
|
83
|
+
value: options.type,
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
: undefined),
|
|
87
|
+
});
|
|
91
88
|
};
|
|
92
89
|
|
|
93
|
-
const createInitialConfig = () => {
|
|
90
|
+
const createInitialConfig = (): Config => {
|
|
94
91
|
// Not casting here as loads of downstream impacts that make
|
|
95
92
|
// subsequent typing really difficult.
|
|
96
93
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -102,7 +99,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
102
99
|
let config = createInitialConfig();
|
|
103
100
|
let callbacks: Partial<Record<keyof Config, DerivedValueCallback>> = { ...derivedValueCallbacks };
|
|
104
101
|
|
|
105
|
-
// Aimed at making it easier for
|
|
102
|
+
// Aimed at making it easier for TypeScript to derive type.
|
|
106
103
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
107
104
|
const configBuilder = {
|
|
108
105
|
$disable: () => {
|
|
@@ -119,9 +116,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
119
116
|
zodSchema.parse(configBuilder.$values());
|
|
120
117
|
return [];
|
|
121
118
|
} catch (error: unknown) {
|
|
122
|
-
|
|
123
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
124
|
-
return (error as ZodError).errors;
|
|
119
|
+
return error instanceof ZodError ? error.issues : [];
|
|
125
120
|
}
|
|
126
121
|
},
|
|
127
122
|
$experiment: (key: string) => {
|
|
@@ -136,7 +131,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
136
131
|
$extend: (builder: ConfigBuilder<Config>) => {
|
|
137
132
|
config = transformConfigSync<Config>(builder.$values(), [cloneNonEnumerableValues]);
|
|
138
133
|
// @ts-expect-error private property
|
|
139
|
-
// As __callbacks is private property,
|
|
134
|
+
// As __callbacks is private property, TypeScript doesn't know what type is.
|
|
140
135
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
141
136
|
callbacks = { ...builder.__callbacks } as Partial<Record<keyof Config, DerivedValueCallback>>;
|
|
142
137
|
},
|
|
@@ -146,7 +141,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
146
141
|
return values;
|
|
147
142
|
},
|
|
148
143
|
$fork: () => createConfigBuilder<Config>(zodSchema, options, derivedValueCallbacks, initialValues),
|
|
149
|
-
$toJson: () => JSON.stringify(configBuilder.$values(),
|
|
144
|
+
$toJson: () => JSON.stringify(configBuilder.$values(), undefined, 2),
|
|
150
145
|
$validate: () => {
|
|
151
146
|
try {
|
|
152
147
|
zodSchema.parse(configBuilder.$values());
|
|
@@ -157,13 +152,15 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
157
152
|
}
|
|
158
153
|
},
|
|
159
154
|
$values: () => {
|
|
160
|
-
for (const
|
|
161
|
-
|
|
155
|
+
for (const propertyName in callbacks) {
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
157
|
+
const castPropertyName = propertyName as keyof Config;
|
|
158
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
159
|
+
const callback = callbacks[castPropertyName];
|
|
162
160
|
|
|
163
161
|
if (callback) {
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
config[property as keyof Config] = callback(config);
|
|
162
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
163
|
+
config[castPropertyName] = callback(config);
|
|
167
164
|
}
|
|
168
165
|
}
|
|
169
166
|
|
|
@@ -190,7 +187,12 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
190
187
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
191
188
|
const castPropertyName = propertyName as keyof Config;
|
|
192
189
|
|
|
193
|
-
|
|
190
|
+
if (!jsonSchema.required?.includes(propertyName) && !Object.hasOwn(config, propertyName)) {
|
|
191
|
+
// @ts-expect-error Optional properties we want to exist in the config with undefined initial values.
|
|
192
|
+
config[propertyName] = undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Aimed at making it easier for TypeScript to derive type.
|
|
194
196
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
195
197
|
configBuilder[castPropertyName] = ((value: Config[keyof Config] | DerivedValueCallback, override?: boolean) => {
|
|
196
198
|
if (isInvalidPropertyOverride(config[castPropertyName], override)) {
|
|
@@ -201,7 +203,6 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
201
203
|
);
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
let propertyValue: Config[keyof Config];
|
|
205
206
|
const MAX_DEPTH = 1;
|
|
206
207
|
|
|
207
208
|
if (!isValidValue(value)) {
|
|
@@ -212,6 +213,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
212
213
|
);
|
|
213
214
|
}
|
|
214
215
|
|
|
216
|
+
let propertyValue: Config[keyof Config];
|
|
217
|
+
|
|
215
218
|
if (isDerivedValueCallback<DerivedValueCallback>(value)) {
|
|
216
219
|
callbacks[castPropertyName] = value;
|
|
217
220
|
propertyValue = value(config);
|
|
@@ -5,7 +5,7 @@ import { transformConfig } from './utils/transformConfig.ts';
|
|
|
5
5
|
export const createConfigParser = async <Config extends object>(
|
|
6
6
|
config: Config,
|
|
7
7
|
{ experimentsCallback }: ConfigParserOptions = {},
|
|
8
|
-
) => {
|
|
8
|
+
): Promise<Config> => {
|
|
9
9
|
const handlers: TransformConfigHandler[] = [];
|
|
10
10
|
|
|
11
11
|
if (experimentsCallback) {
|
|
@@ -9,7 +9,7 @@ export interface ConfigReader<Config extends object> {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const createConfigReader = <Config extends object>(config: Config): ConfigReader<Config> => {
|
|
12
|
-
// Aimed at reducing the amount of work for
|
|
12
|
+
// Aimed at reducing the amount of work for TypeScript to resolve type.
|
|
13
13
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
14
14
|
return {
|
|
15
15
|
read: <P extends Path<Config>>(path: P, variables?: Record<string, string | number>) => {
|
|
@@ -32,7 +32,7 @@ export const createConfigReader = <Config extends object>(config: Config): Confi
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
return Object.keys(variables).reduce<string>((acc, key) => {
|
|
35
|
-
return acc.replace(new RegExp(`{{${key}}}`), String(variables[key]));
|
|
35
|
+
return acc.replace(new RegExp(`{{${key}}}`), () => String(variables[key]));
|
|
36
36
|
}, output);
|
|
37
37
|
},
|
|
38
38
|
scope: <S extends Scope<Config>>(scope: S) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable
|
|
1
|
+
/* eslint-disable import-x/no-default-export, unicorn/numeric-separators-style, unicorn/no-null */
|
|
2
2
|
/* This file is autogenerated, do not edit directly, your changes will not perist. */
|
|
3
3
|
|
|
4
4
|
export default {{{ config }}} as const;
|
|
@@ -10,7 +10,7 @@ export const cloneNonEnumerableValues: TransformConfigHandlerSync = <
|
|
|
10
10
|
config: Config2,
|
|
11
11
|
) => {
|
|
12
12
|
for (const nonEnumerableKey of NON_ENUMERABLE_KEYS) {
|
|
13
|
-
if (nonEnumerableKey
|
|
13
|
+
if (Object.hasOwn(config, nonEnumerableKey)) {
|
|
14
14
|
Object.defineProperty(clone, nonEnumerableKey, {
|
|
15
15
|
configurable: false,
|
|
16
16
|
enumerable: false,
|
|
@@ -1,16 +1,27 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type AnyRecord,
|
|
3
|
+
type Buckets,
|
|
4
|
+
type RunExperimentsCallback,
|
|
5
|
+
type TransformConfigHandler,
|
|
6
|
+
type TransformConfigHandlerReturnType,
|
|
7
|
+
} from '../types.ts';
|
|
2
8
|
|
|
3
9
|
export const runExperiments =
|
|
4
10
|
(callback: RunExperimentsCallback): TransformConfigHandler =>
|
|
5
|
-
async <Config extends AnyRecord>(
|
|
11
|
+
async <Config extends AnyRecord>(
|
|
12
|
+
clone: Config,
|
|
13
|
+
config: Config,
|
|
14
|
+
): Promise<TransformConfigHandlerReturnType<Config>> => {
|
|
6
15
|
if ('__experiment' in config && typeof config.__experiment === 'object') {
|
|
7
|
-
// As __experiment is private property,
|
|
16
|
+
// As __experiment is private property, TypeScript doesn't know what type is.
|
|
8
17
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
9
18
|
const { buckets, id } = config.__experiment as { buckets: Buckets<Config>; id: string };
|
|
10
19
|
const bucket = await callback(id);
|
|
11
20
|
|
|
12
|
-
if (
|
|
13
|
-
|
|
21
|
+
if (Object.hasOwn(buckets, bucket)) {
|
|
22
|
+
// The check above essentially makes sure the value cannot be null
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
24
|
+
return buckets[bucket]!;
|
|
14
25
|
}
|
|
15
26
|
}
|
|
16
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
|
|
3
|
-
export const arrayHasInvalidDefaults = (propertyDefinition:
|
|
3
|
+
export const arrayHasInvalidDefaults = (propertyDefinition: JSONSchema.JSONSchema): boolean => {
|
|
4
4
|
const { items } = propertyDefinition;
|
|
5
|
-
return items && typeof items === 'object' && 'default' in items;
|
|
5
|
+
return !!items && typeof items === 'object' && 'default' in items;
|
|
6
6
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
import { arrayHasInvalidDefaults } from './arrayHasInvalidDefaults.ts';
|
|
3
3
|
import { collateObjectPropertyDefaults } from './collateObjectPropertyDefaults.ts';
|
|
4
4
|
import { RESERVED_KEYWORDS, isPropertyReservedWord } from './isPropertyReservedWord.ts';
|
|
5
5
|
import { isValidPropertyDefinition } from './isValidPropertyDefinition.ts';
|
|
6
6
|
import { recordHasInvalidDefaults } from './recordHasInvalidDefaults.ts';
|
|
7
7
|
|
|
8
|
-
export const collateDefaultValues = <Config>(jsonSchema:
|
|
8
|
+
export const collateDefaultValues = <Config>(jsonSchema: JSONSchema.JSONSchema): Partial<Config> => {
|
|
9
9
|
const defaultValues: Partial<Config> = {};
|
|
10
10
|
|
|
11
11
|
for (const propertyName in jsonSchema.properties) {
|
|
@@ -17,14 +17,14 @@ export const collateDefaultValues = <Config>(jsonSchema: JSONSchema7) => {
|
|
|
17
17
|
);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
//
|
|
20
|
+
// TypeScript not inferring property is key of Config.
|
|
21
21
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
22
22
|
const castPropertyName = propertyName as keyof Config;
|
|
23
23
|
const propertyDefinition = jsonSchema.properties[propertyName];
|
|
24
24
|
|
|
25
25
|
if (isValidPropertyDefinition(propertyDefinition)) {
|
|
26
26
|
if (propertyDefinition.default) {
|
|
27
|
-
//
|
|
27
|
+
// TypeScript not inferring propertyDefinition.default is Config value.
|
|
28
28
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
29
29
|
defaultValues[castPropertyName] = propertyDefinition.default as Config[keyof Config];
|
|
30
30
|
}
|
|
@@ -49,7 +49,7 @@ export const collateDefaultValues = <Config>(jsonSchema: JSONSchema7) => {
|
|
|
49
49
|
const propertyDefaults = collateObjectPropertyDefaults(propertyDefinition);
|
|
50
50
|
|
|
51
51
|
if (propertyDefaults) {
|
|
52
|
-
//
|
|
52
|
+
// TypeScript not inferring propertyDefaults is Config value.
|
|
53
53
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
54
54
|
defaultValues[castPropertyName] = propertyDefaults as Config[keyof Config];
|
|
55
55
|
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { type JSONSchema7 } from 'json-schema';
|
|
2
1
|
import { isBoolean, isUndefined } from 'lodash-es';
|
|
3
2
|
import { type Jsonifiable } from 'type-fest';
|
|
3
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
4
4
|
import { objectPropertyHasDefaults } from './objectPropertyHasDefaults.ts';
|
|
5
5
|
|
|
6
|
-
export const collateObjectPropertyDefaults = (
|
|
6
|
+
export const collateObjectPropertyDefaults = (
|
|
7
|
+
propertyDefinition: JSONSchema.JSONSchema,
|
|
8
|
+
): Record<string, Jsonifiable> | undefined => {
|
|
7
9
|
const { properties } = propertyDefinition;
|
|
8
10
|
|
|
9
11
|
if (!properties || !objectPropertyHasDefaults(propertyDefinition)) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { resolve } from 'node:path';
|
|
2
2
|
import shelljs from 'shelljs';
|
|
3
|
-
import { type
|
|
3
|
+
import { type CliCommands } from '../cli.ts';
|
|
4
4
|
import { type ConfigBuilder } from '../createConfigBuilder.ts';
|
|
5
5
|
import { type SetupExperimentsCallback } from '../types.ts';
|
|
6
6
|
import { transformWriteConfig } from './transformWriteConfig.ts';
|
|
@@ -8,10 +8,12 @@ import { transformWriteConfig } from './transformWriteConfig.ts';
|
|
|
8
8
|
export const importValidateTransformWriteConfig = (
|
|
9
9
|
inputFile: string,
|
|
10
10
|
outputFile: string,
|
|
11
|
-
command:
|
|
11
|
+
command: CliCommands,
|
|
12
12
|
experimentCallbackFile?: string,
|
|
13
|
-
) => {
|
|
13
|
+
): void => {
|
|
14
14
|
import(resolve(process.cwd(), inputFile))
|
|
15
|
+
// TODO: Will revisit
|
|
16
|
+
// eslint-disable-next-line unicorn/prefer-await
|
|
15
17
|
.then(({ default: configBuilder }: { default: ConfigBuilder<object> }) => {
|
|
16
18
|
if (!configBuilder.$validate()) {
|
|
17
19
|
shelljs.echo(`zcd ${command} => invalid config`);
|
|
@@ -25,16 +27,22 @@ export const importValidateTransformWriteConfig = (
|
|
|
25
27
|
|
|
26
28
|
if (experimentCallbackFile) {
|
|
27
29
|
import(resolve(process.cwd(), experimentCallbackFile))
|
|
30
|
+
// TODO: Will revisit
|
|
31
|
+
// eslint-disable-next-line unicorn/prefer-await
|
|
28
32
|
.then(({ default: experimentsCallback }: { default: SetupExperimentsCallback }) => {
|
|
29
33
|
void transformWriteConfig(configBuilder.$values(), { experimentsCallback, outputFile });
|
|
30
34
|
})
|
|
35
|
+
// TODO: Will revisit
|
|
36
|
+
// eslint-disable-next-line unicorn/prefer-await
|
|
31
37
|
.catch((error: unknown) => {
|
|
32
|
-
if (error instanceof Error) {
|
|
33
|
-
|
|
38
|
+
if (!(error instanceof Error)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
shelljs.echo(`zcd ${command} => error message: ${error.message}`);
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
44
|
+
if (error.stack) {
|
|
45
|
+
shelljs.echo(`zcd ${command} => error stack:\n${error.stack}\n`);
|
|
38
46
|
}
|
|
39
47
|
});
|
|
40
48
|
|
|
@@ -43,13 +51,17 @@ export const importValidateTransformWriteConfig = (
|
|
|
43
51
|
|
|
44
52
|
void transformWriteConfig(configBuilder.$values(), { outputFile });
|
|
45
53
|
})
|
|
54
|
+
// TODO: Will revisit
|
|
55
|
+
// eslint-disable-next-line unicorn/prefer-await
|
|
46
56
|
.catch((error: unknown) => {
|
|
47
|
-
if (error instanceof Error) {
|
|
48
|
-
|
|
57
|
+
if (!(error instanceof Error)) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
shelljs.echo(`zcd ${command} => error message: ${error.message}`);
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
63
|
+
if (error.stack) {
|
|
64
|
+
shelljs.echo(`zcd ${command} => error stack:\n${error.stack}\n`);
|
|
53
65
|
}
|
|
54
66
|
});
|
|
55
67
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
2
|
-
export const isInvalidPropertyOverride = (propertyValue: any, override = false) =>
|
|
2
|
+
export const isInvalidPropertyOverride = (propertyValue: any, override = false): boolean =>
|
|
3
3
|
!override && propertyValue !== undefined;
|
|
@@ -10,4 +10,4 @@ export const RESERVED_KEYWORDS = new Set([
|
|
|
10
10
|
'$values',
|
|
11
11
|
]);
|
|
12
12
|
|
|
13
|
-
export const isPropertyReservedWord = (propertyName: string) => RESERVED_KEYWORDS.has(propertyName);
|
|
13
|
+
export const isPropertyReservedWord = (propertyName: string): boolean => RESERVED_KEYWORDS.has(propertyName);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
|
|
3
|
-
export const isSchemaValid = (schema:
|
|
3
|
+
export const isSchemaValid = (schema: JSONSchema.JSONSchema): boolean => schema.type !== 'object';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
|
|
3
3
|
export const isValidPropertyDefinition = (
|
|
4
|
-
propertyDefinition
|
|
5
|
-
): propertyDefinition is
|
|
4
|
+
propertyDefinition?: JSONSchema._JSONSchema,
|
|
5
|
+
): propertyDefinition is JSONSchema.JSONSchema => !!propertyDefinition && typeof propertyDefinition === 'object';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
|
|
3
|
-
export const objectPropertyHasDefaults = (propertyDefinition:
|
|
4
|
-
propertyDefinition.properties &&
|
|
3
|
+
export const objectPropertyHasDefaults = (propertyDefinition: JSONSchema.JSONSchema): boolean =>
|
|
4
|
+
!!propertyDefinition.properties &&
|
|
5
5
|
Object.values(propertyDefinition.properties).some(value => typeof value === 'object' && 'default' in value);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type JSONSchema } from 'zod/v4/core';
|
|
2
2
|
|
|
3
|
-
export const recordHasInvalidDefaults = (propertyDefinition:
|
|
4
|
-
propertyDefinition.additionalProperties &&
|
|
3
|
+
export const recordHasInvalidDefaults = (propertyDefinition: JSONSchema.JSONSchema): boolean =>
|
|
4
|
+
!!propertyDefinition.additionalProperties &&
|
|
5
5
|
typeof propertyDefinition.additionalProperties === 'object' &&
|
|
6
6
|
'default' in propertyDefinition.additionalProperties;
|
|
@@ -17,18 +17,23 @@ describe('transformConfig', () => {
|
|
|
17
17
|
"locales": [
|
|
18
18
|
"en_GB",
|
|
19
19
|
],
|
|
20
|
+
"name": undefined,
|
|
20
21
|
"pages": {
|
|
21
22
|
"contactDetails": {
|
|
22
23
|
"name": "contactDetails",
|
|
24
|
+
"path": undefined,
|
|
25
|
+
"queryParams": undefined,
|
|
23
26
|
"sections": [
|
|
24
27
|
{
|
|
25
28
|
"name": "header",
|
|
29
|
+
"sections": undefined,
|
|
26
30
|
},
|
|
27
31
|
{
|
|
28
32
|
"name": "body",
|
|
29
33
|
"sections": [
|
|
30
34
|
{
|
|
31
35
|
"name": "main",
|
|
36
|
+
"sections": undefined,
|
|
32
37
|
},
|
|
33
38
|
{
|
|
34
39
|
"name": "sidebar",
|
|
@@ -65,8 +70,10 @@ describe('transformConfig', () => {
|
|
|
65
70
|
},
|
|
66
71
|
"routes": [
|
|
67
72
|
{
|
|
73
|
+
"aliases": undefined,
|
|
68
74
|
"page": "personalDetails",
|
|
69
75
|
"path": "personal-details",
|
|
76
|
+
"routes": undefined,
|
|
70
77
|
},
|
|
71
78
|
{
|
|
72
79
|
"page": "contactDetails",
|
|
@@ -100,18 +107,23 @@ describe('transformConfigSync', () => {
|
|
|
100
107
|
"locales": [
|
|
101
108
|
"en_GB",
|
|
102
109
|
],
|
|
110
|
+
"name": undefined,
|
|
103
111
|
"pages": {
|
|
104
112
|
"contactDetails": {
|
|
105
113
|
"name": "contactDetails",
|
|
114
|
+
"path": undefined,
|
|
115
|
+
"queryParams": undefined,
|
|
106
116
|
"sections": [
|
|
107
117
|
{
|
|
108
118
|
"name": "header",
|
|
119
|
+
"sections": undefined,
|
|
109
120
|
},
|
|
110
121
|
{
|
|
111
122
|
"name": "body",
|
|
112
123
|
"sections": [
|
|
113
124
|
{
|
|
114
125
|
"name": "main",
|
|
126
|
+
"sections": undefined,
|
|
115
127
|
},
|
|
116
128
|
{
|
|
117
129
|
"name": "sidebar",
|
|
@@ -148,8 +160,10 @@ describe('transformConfigSync', () => {
|
|
|
148
160
|
},
|
|
149
161
|
"routes": [
|
|
150
162
|
{
|
|
163
|
+
"aliases": undefined,
|
|
151
164
|
"page": "personalDetails",
|
|
152
165
|
"path": "personal-details",
|
|
166
|
+
"routes": undefined,
|
|
153
167
|
},
|
|
154
168
|
{
|
|
155
169
|
"page": "contactDetails",
|
|
@@ -46,15 +46,21 @@ export const transformConfig = async <Config extends AnyRecord>(
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
for (const key in config) {
|
|
49
|
+
// TODO: Need to look at this
|
|
50
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
49
51
|
const value = config[key];
|
|
50
52
|
|
|
51
53
|
if (isPlainObject(value)) {
|
|
54
|
+
// TODO: Need to look at this
|
|
55
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
52
56
|
transform[key] = await transformConfig(value, handler);
|
|
53
57
|
} else if (Array.isArray(value)) {
|
|
54
|
-
//
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
58
|
+
// TODO: Need to look at this
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, unicorn/no-unsafe-property-key
|
|
56
60
|
transform[key] = (await transformArray(value, handler)) as Config[Extract<keyof Config, string>];
|
|
57
61
|
} else {
|
|
62
|
+
// TODO: Need to look at this
|
|
63
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
58
64
|
transform[key] = value;
|
|
59
65
|
}
|
|
60
66
|
}
|
|
@@ -107,15 +113,21 @@ export const transformConfigSync = <Config extends AnyRecord>(
|
|
|
107
113
|
}
|
|
108
114
|
|
|
109
115
|
for (const key in config) {
|
|
116
|
+
// TODO: Need to look at this
|
|
117
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
110
118
|
const value = config[key];
|
|
111
119
|
|
|
112
120
|
if (isPlainObject(value)) {
|
|
121
|
+
// TODO: Need to look at this
|
|
122
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
113
123
|
transform[key] = transformConfigSync(value, handler);
|
|
114
124
|
} else if (Array.isArray(value)) {
|
|
115
|
-
//
|
|
116
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
125
|
+
// TODO: Need to look at this
|
|
126
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, unicorn/no-unsafe-property-key
|
|
117
127
|
transform[key] = transformArraySync(value, handler) as Config[Extract<keyof Config, string>];
|
|
118
128
|
} else {
|
|
129
|
+
// TODO: Need to look at this
|
|
130
|
+
// eslint-disable-next-line unicorn/no-unsafe-property-key
|
|
119
131
|
transform[key] = value;
|
|
120
132
|
}
|
|
121
133
|
}
|