zcb 0.2.6 → 0.2.7
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/bin/zcb.js +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 +35 -35
- package/dist/types/cjs/cli.d.cts.map +1 -1
- package/dist/types/cjs/createConfigBuilder.d.cts +1 -1
- package/dist/types/cjs/createConfigBuilder.d.cts.map +1 -1
- package/dist/types/cjs/createConfigParser.d.cts.map +1 -1
- package/dist/types/cjs/createConfigReader.d.cts.map +1 -1
- package/dist/types/cjs/transformers/cloneNonEnumerableValues.d.cts.map +1 -1
- package/dist/types/cjs/transformers/removeDisabledSlices.d.cts.map +1 -1
- package/dist/types/cjs/transformers/runExperiments.d.cts.map +1 -1
- package/dist/types/cjs/types.d.cts +4 -4
- package/dist/types/cjs/types.d.cts.map +1 -1
- package/dist/types/cjs/utils/collateDefaultValues.d.cts.map +1 -1
- package/dist/types/cjs/utils/isDerivedValueCallback.d.cts.map +1 -1
- package/dist/types/cjs/utils/isValidPropertyDefinition.d.cts.map +1 -1
- package/dist/types/cjs/utils/isValidValue.d.cts.map +1 -1
- package/dist/types/cjs/utils/jsonStringifyReplacer.d.cts +4 -2
- package/dist/types/cjs/utils/jsonStringifyReplacer.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.map +1 -1
- package/dist/types/esm/createConfigBuilder.d.ts +1 -1
- package/dist/types/esm/createConfigBuilder.d.ts.map +1 -1
- package/dist/types/esm/createConfigParser.d.ts.map +1 -1
- package/dist/types/esm/createConfigReader.d.ts.map +1 -1
- package/dist/types/esm/transformers/cloneNonEnumerableValues.d.ts.map +1 -1
- package/dist/types/esm/transformers/removeDisabledSlices.d.ts.map +1 -1
- package/dist/types/esm/transformers/runExperiments.d.ts.map +1 -1
- package/dist/types/esm/types.d.ts +4 -4
- package/dist/types/esm/types.d.ts.map +1 -1
- package/dist/types/esm/utils/collateDefaultValues.d.ts.map +1 -1
- package/dist/types/esm/utils/isDerivedValueCallback.d.ts.map +1 -1
- package/dist/types/esm/utils/isValidPropertyDefinition.d.ts.map +1 -1
- package/dist/types/esm/utils/isValidValue.d.ts.map +1 -1
- package/dist/types/esm/utils/jsonStringifyReplacer.d.ts +4 -2
- package/dist/types/esm/utils/jsonStringifyReplacer.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 +45 -77
- package/shellScripts/installActivateMise.sh +12 -0
- package/src/__testUtils__/builtConfig.ts +1 -1
- package/src/__testUtils__/configBuilder.ts +1 -2
- package/src/cli.ts +27 -17
- package/src/createConfigBuilder.test.ts +14 -16
- package/src/createConfigBuilder.ts +24 -7
- package/src/createConfigParser.ts +1 -1
- package/src/createConfigReader.test.ts +2 -2
- package/src/createConfigReader.ts +5 -1
- package/src/templates/config.ts.hbs +1 -1
- package/src/transformers/cloneNonEnumerableValues.ts +2 -3
- package/src/transformers/removeDisabledSlices.ts +1 -2
- package/src/transformers/runExperiments.ts +3 -1
- package/src/types.ts +15 -11
- package/src/utils/collateDefaultValues.ts +12 -6
- package/src/utils/importValidateTransformWriteConfig.ts +1 -1
- package/src/utils/isValidPropertyDefinition.ts +1 -1
- package/src/utils/isValidValue.ts +2 -0
- package/src/utils/transformConfig.ts +15 -4
- package/src/utils/transformWriteConfig.ts +3 -3
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcb",
|
|
3
3
|
"description": "Build configs with type safety from zod schema.",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.7",
|
|
5
5
|
"author": "Dylan Aubrey",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/badbatch/zod-config-builder",
|
|
8
|
-
"repository": "
|
|
8
|
+
"repository": "badbatch/zod-config-builder",
|
|
9
9
|
"bugs": "https://github.com/badbatch/zod-config-builder/issues",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"bin": {
|
|
@@ -28,93 +28,59 @@
|
|
|
28
28
|
"access": "public"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@types/fs-extra": "^11.0.
|
|
32
|
-
"@types/json-schema": "^7.0.
|
|
33
|
-
"@types/
|
|
34
|
-
"@types/
|
|
35
|
-
"@types/
|
|
36
|
-
"
|
|
37
|
-
"
|
|
31
|
+
"@types/fs-extra": "^11.0.4",
|
|
32
|
+
"@types/json-schema": "^7.0.15",
|
|
33
|
+
"@types/lodash-es": "^4.17.12",
|
|
34
|
+
"@types/shelljs": "^0.8.15",
|
|
35
|
+
"@types/uuid": "^10.0.0",
|
|
36
|
+
"@types/yargs": "^17.0.33",
|
|
37
|
+
"core-js": "^3.39.0",
|
|
38
|
+
"fs-extra": "^11.2.0",
|
|
39
|
+
"handlebars": "^4.7.8",
|
|
38
40
|
"json-schema": "^0.4.0",
|
|
41
|
+
"lodash-es": "^4.17.21",
|
|
39
42
|
"shelljs": "^0.8.5",
|
|
43
|
+
"ts-node": "^10.9.2",
|
|
40
44
|
"ts-toolbelt": "^9.6.0",
|
|
41
|
-
"type-fest": "^
|
|
42
|
-
"uuid": "^
|
|
43
|
-
"yargs": "^
|
|
44
|
-
"zod": "^3.
|
|
45
|
-
"zod-to-json-schema": "^3.
|
|
46
|
-
},
|
|
47
|
-
"peerDependencies": {
|
|
48
|
-
"core-js": "<4",
|
|
49
|
-
"lodash-es": "<5",
|
|
50
|
-
"ts-node": "<11"
|
|
45
|
+
"type-fest": "^4.26.1",
|
|
46
|
+
"uuid": "^11.0.2",
|
|
47
|
+
"yargs": "^17.7.2",
|
|
48
|
+
"zod": "^3.23.8",
|
|
49
|
+
"zod-to-json-schema": "^3.23.5"
|
|
51
50
|
},
|
|
52
51
|
"devDependencies": {
|
|
53
|
-
"@commitlint/cli": "^
|
|
54
|
-
"@commitlint/config-conventional": "^17.6.3",
|
|
55
|
-
"@commitlint/prompt-cli": "^17.6.3",
|
|
52
|
+
"@commitlint/cli": "^19.5.0",
|
|
56
53
|
"@jest/globals": "^29.7.0",
|
|
57
|
-
"@repodog/
|
|
58
|
-
"@repodog/
|
|
59
|
-
"@repodog/
|
|
60
|
-
"@repodog/eslint-config": "^
|
|
61
|
-
"@repodog/
|
|
62
|
-
"@repodog/
|
|
63
|
-
"@repodog/
|
|
64
|
-
"@repodog/
|
|
65
|
-
"@repodog/
|
|
66
|
-
"@repodog/
|
|
67
|
-
"@repodog/
|
|
68
|
-
"@repodog/ts-config": "^1.4.1",
|
|
69
|
-
"@rollup/plugin-babel": "^6.0.3",
|
|
70
|
-
"@rollup/plugin-commonjs": "^25.0.7",
|
|
71
|
-
"@rollup/plugin-image": "^3.0.2",
|
|
72
|
-
"@rollup/plugin-json": "^6.0.0",
|
|
73
|
-
"@rollup/plugin-node-resolve": "^15.0.2",
|
|
54
|
+
"@repodog/cli": "^1.6.36",
|
|
55
|
+
"@repodog/commitlint-config": "^19.0.3",
|
|
56
|
+
"@repodog/eslint-config": "^9.0.6",
|
|
57
|
+
"@repodog/eslint-config-jest": "^9.0.3",
|
|
58
|
+
"@repodog/jest-config": "^29.0.2",
|
|
59
|
+
"@repodog/markdownlint-config": "^1.2.4",
|
|
60
|
+
"@repodog/prettier-config": "^3.0.2",
|
|
61
|
+
"@repodog/rollup-config": "^4.0.3",
|
|
62
|
+
"@repodog/swc-config": "^1.0.3",
|
|
63
|
+
"@repodog/syncpack-config": "^13.0.2",
|
|
64
|
+
"@repodog/ts-config": "^5.0.4",
|
|
74
65
|
"@rollup/plugin-swc": "^0.3.0",
|
|
75
|
-
"@
|
|
76
|
-
"@swc/core": "^1.4.1",
|
|
66
|
+
"@swc/core": "^1.7.26",
|
|
77
67
|
"@swc/jest": "^0.2.36",
|
|
78
|
-
"@types/jest": "^29.5.
|
|
79
|
-
"@types/
|
|
80
|
-
"@types/node": "^20.11.0",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^5.59.5",
|
|
82
|
-
"@typescript-eslint/parser": "^5.59.5",
|
|
83
|
-
"babel-jest": "^29.5.0",
|
|
84
|
-
"babel-plugin-codegen": "^4.1.5",
|
|
85
|
-
"babel-plugin-macros": "^3.1.0",
|
|
86
|
-
"core-js": "^3.30.2",
|
|
68
|
+
"@types/jest": "^29.5.13",
|
|
69
|
+
"@types/node": "^22.5.5",
|
|
87
70
|
"cts-types": "^0.0.6",
|
|
88
|
-
"del-cli": "^
|
|
89
|
-
"eslint": "^
|
|
90
|
-
"eslint-config-prettier": "^8.8.0",
|
|
91
|
-
"eslint-import-resolver-typescript": "^3.5.5",
|
|
92
|
-
"eslint-plugin-import": "^2.27.5",
|
|
93
|
-
"eslint-plugin-jest": "^27.2.1",
|
|
94
|
-
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
95
|
-
"eslint-plugin-prettier": "^4.2.1",
|
|
96
|
-
"eslint-plugin-sort-class-members": "^1.18.0",
|
|
97
|
-
"eslint-plugin-sort-destructure-keys": "^1.5.0",
|
|
98
|
-
"eslint-plugin-sort-keys-fix": "^1.1.2",
|
|
99
|
-
"eslint-plugin-typescript-sort-keys": "^2.3.0",
|
|
100
|
-
"eslint-plugin-unicorn": "^46.0.1",
|
|
71
|
+
"del-cli": "^6.0.0",
|
|
72
|
+
"eslint": "^9.11.0",
|
|
101
73
|
"generate-changelog": "^1.8.0",
|
|
102
|
-
"husky": "^
|
|
103
|
-
"identity-obj-proxy": "^3.0.0",
|
|
74
|
+
"husky": "^9.1.6",
|
|
104
75
|
"jest": "^29.7.0",
|
|
105
76
|
"jest-environment-jsdom": "^29.7.0",
|
|
106
77
|
"jest-environment-node": "^29.7.0",
|
|
107
|
-
"
|
|
108
|
-
"
|
|
109
|
-
"
|
|
110
|
-
"rollup": "^3.21.6",
|
|
111
|
-
"rollup-plugin-analyzer": "^4.0.0",
|
|
112
|
-
"rollup-plugin-copy": "^3.4.0",
|
|
113
|
-
"rollup-plugin-sourcemaps": "^0.6.3",
|
|
78
|
+
"markdownlint-cli2": "^0.14.0",
|
|
79
|
+
"prettier": "^3.3.3",
|
|
80
|
+
"rollup": "^4.22.4",
|
|
114
81
|
"suppress-experimental-warnings": "^2.0.0",
|
|
115
|
-
"syncpack": "^
|
|
116
|
-
"
|
|
117
|
-
"typescript": "^5.0.4"
|
|
82
|
+
"syncpack": "^13.0.0",
|
|
83
|
+
"typescript": "^5.6.2"
|
|
118
84
|
},
|
|
119
85
|
"keywords": [
|
|
120
86
|
"config",
|
|
@@ -131,8 +97,10 @@
|
|
|
131
97
|
"compile:esm": "rollup -c ./rollup.config.cjs",
|
|
132
98
|
"compile:types": "tsc --project ./tsconfig.build.json && cts-types build dist/types/esm dist/types/cjs",
|
|
133
99
|
"cut:changelog": "changelog",
|
|
134
|
-
"
|
|
135
|
-
"lint": "eslint .
|
|
100
|
+
"lint": "pnpm run /^lint:.*/",
|
|
101
|
+
"lint:code": "eslint .",
|
|
102
|
+
"lint:docs": "markdownlint-cli2 --config \".markdownlint.json\" \"**/*.md\" \"!**/node_modules/**\"",
|
|
103
|
+
"postinstall": "sh shellScripts/installActivateMise.sh",
|
|
136
104
|
"repodog": "repodog",
|
|
137
105
|
"syncpack": "syncpack format && syncpack list-mismatches && syncpack lint-semver-ranges",
|
|
138
106
|
"test": "COMPILER=swc node --require=suppress-experimental-warnings --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier,
|
|
1
|
+
/* eslint-disable prettier/prettier, unicorn/numeric-separators-style */
|
|
2
2
|
/* This file is autogenerated, do not edit directly, your changes will not perist. */
|
|
3
3
|
|
|
4
4
|
export default {
|
|
@@ -23,7 +23,7 @@ configBuilder
|
|
|
23
23
|
.distanceUnit('km')
|
|
24
24
|
.languageCodes(['en'])
|
|
25
25
|
.locales(({ countryCode, languageCodes }) =>
|
|
26
|
-
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}`) : []
|
|
26
|
+
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}`) : [],
|
|
27
27
|
)
|
|
28
28
|
.name('alpha')
|
|
29
29
|
.pages({
|
|
@@ -54,5 +54,4 @@ configBuilder
|
|
|
54
54
|
.timeouts({ apollo: 10_000 })
|
|
55
55
|
.timezone('Europe/London');
|
|
56
56
|
|
|
57
|
-
// eslint-disable-next-line import/no-default-export
|
|
58
57
|
export default configBuilder;
|
package/src/cli.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { watchFile } from 'node:fs';
|
|
2
2
|
import { resolve } from 'node:path';
|
|
3
3
|
import shelljs from 'shelljs';
|
|
4
|
-
import yargs from 'yargs';
|
|
4
|
+
import yargs, { type Argv } from 'yargs';
|
|
5
|
+
import { hideBin } from 'yargs/helpers';
|
|
5
6
|
import { importValidateTransformWriteConfig } from './utils/importValidateTransformWriteConfig.ts';
|
|
6
7
|
|
|
7
8
|
export enum Commands {
|
|
@@ -9,7 +10,7 @@ export enum Commands {
|
|
|
9
10
|
WATCH = 'watch',
|
|
10
11
|
}
|
|
11
12
|
|
|
12
|
-
const generateArguments = (cmdYargs:
|
|
13
|
+
const generateArguments = (cmdYargs: Argv) =>
|
|
13
14
|
cmdYargs
|
|
14
15
|
.positional('input-file', {
|
|
15
16
|
demandOption: true,
|
|
@@ -27,40 +28,49 @@ const generateArguments = (cmdYargs: yargs.Argv) =>
|
|
|
27
28
|
});
|
|
28
29
|
|
|
29
30
|
export const cli = () => {
|
|
30
|
-
yargs
|
|
31
|
+
// yargs does not provide a way to pass generic to type args.
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
33
|
+
const argv = yargs(hideBin(process.argv)) as Argv<{
|
|
34
|
+
'experiments-callback-file'?: string;
|
|
35
|
+
'input-file': string;
|
|
36
|
+
'output-file': string;
|
|
37
|
+
}>;
|
|
38
|
+
|
|
39
|
+
void argv
|
|
31
40
|
.command(
|
|
32
41
|
'watch <input-file> <output-file>',
|
|
33
42
|
'Watch a config builder and write config',
|
|
34
43
|
cmdYargs => generateArguments(cmdYargs),
|
|
35
|
-
|
|
36
|
-
shelljs.echo(`zcd watch => watching file: ${
|
|
44
|
+
cmdYargs => {
|
|
45
|
+
shelljs.echo(`zcd watch => watching file: ${cmdYargs['input-file']}`);
|
|
37
46
|
|
|
38
|
-
watchFile(resolve(process.cwd(),
|
|
47
|
+
watchFile(resolve(process.cwd(), cmdYargs['input-file']), () => {
|
|
39
48
|
shelljs.echo('zcd watch => file change detected');
|
|
40
49
|
|
|
41
50
|
importValidateTransformWriteConfig(
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
cmdYargs['input-file'],
|
|
52
|
+
cmdYargs['output-file'],
|
|
44
53
|
Commands.WATCH,
|
|
45
|
-
|
|
54
|
+
cmdYargs['experiments-callback-file'],
|
|
46
55
|
);
|
|
47
56
|
});
|
|
48
|
-
}
|
|
57
|
+
},
|
|
49
58
|
)
|
|
50
59
|
.command(
|
|
51
60
|
'build <input-file> <output-file>',
|
|
52
61
|
'Write config from a config builder',
|
|
53
62
|
cmdYargs => generateArguments(cmdYargs),
|
|
54
|
-
|
|
55
|
-
shelljs.echo(`zcd build => building file: ${
|
|
63
|
+
cmdYargs => {
|
|
64
|
+
shelljs.echo(`zcd build => building file: ${cmdYargs['input-file']}`);
|
|
56
65
|
|
|
57
66
|
importValidateTransformWriteConfig(
|
|
58
|
-
|
|
59
|
-
|
|
67
|
+
cmdYargs['input-file'],
|
|
68
|
+
cmdYargs['output-file'],
|
|
60
69
|
Commands.BUILD,
|
|
61
|
-
|
|
70
|
+
cmdYargs['experiments-callback-file'],
|
|
62
71
|
);
|
|
63
|
-
}
|
|
72
|
+
},
|
|
64
73
|
)
|
|
65
|
-
.help()
|
|
74
|
+
.help()
|
|
75
|
+
.parseAsync();
|
|
66
76
|
};
|
|
@@ -17,7 +17,7 @@ describe('createConfigBuilder', () => {
|
|
|
17
17
|
const invalidSchema = z.array(z.string());
|
|
18
18
|
|
|
19
19
|
expect(() => createConfigBuilder<z.infer<typeof invalidSchema>>(invalidSchema)).toThrow(
|
|
20
|
-
'The root type of a config schema must be "object", but received "array"'
|
|
20
|
+
'The root type of a config schema must be "object", but received "array"',
|
|
21
21
|
);
|
|
22
22
|
});
|
|
23
23
|
});
|
|
@@ -33,7 +33,7 @@ describe('createConfigBuilder', () => {
|
|
|
33
33
|
expect(() => createConfigBuilder<z.infer<typeof invalidSchema>>(invalidSchema)).toThrow(
|
|
34
34
|
`"$values" is a reserved keyword within the config builder. Please use a different property name. The full list of reserved keywords is: ${[
|
|
35
35
|
...RESERVED_KEYWORDS,
|
|
36
|
-
].join(', ')}
|
|
36
|
+
].join(', ')}`,
|
|
37
37
|
);
|
|
38
38
|
});
|
|
39
39
|
});
|
|
@@ -109,12 +109,11 @@ describe('createConfigBuilder', () => {
|
|
|
109
109
|
}),
|
|
110
110
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
111
111
|
routes: expect.arrayContaining([
|
|
112
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
113
112
|
expect.objectContaining({
|
|
114
113
|
__experiment: 'FEAT_CHARLIE@0.0.1',
|
|
115
114
|
}),
|
|
116
115
|
]),
|
|
117
|
-
})
|
|
116
|
+
}),
|
|
118
117
|
);
|
|
119
118
|
});
|
|
120
119
|
|
|
@@ -145,12 +144,11 @@ describe('createConfigBuilder', () => {
|
|
|
145
144
|
}),
|
|
146
145
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
147
146
|
routes: expect.arrayContaining([
|
|
148
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
149
147
|
expect.objectContaining({
|
|
150
148
|
__disabled: true,
|
|
151
149
|
}),
|
|
152
150
|
]),
|
|
153
|
-
})
|
|
151
|
+
}),
|
|
154
152
|
);
|
|
155
153
|
});
|
|
156
154
|
|
|
@@ -235,7 +233,7 @@ describe('createConfigBuilder', () => {
|
|
|
235
233
|
});
|
|
236
234
|
|
|
237
235
|
expect(() => createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema)).toThrow(
|
|
238
|
-
'When setting schema property defaults for the value of the record assigned to "flags", set them on the record and not the value.'
|
|
236
|
+
'When setting schema property defaults for the value of the record assigned to "flags", set them on the record and not the value.',
|
|
239
237
|
);
|
|
240
238
|
});
|
|
241
239
|
});
|
|
@@ -249,7 +247,7 @@ describe('createConfigBuilder', () => {
|
|
|
249
247
|
});
|
|
250
248
|
|
|
251
249
|
expect(() => createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema)).toThrow(
|
|
252
|
-
'When setting schema array defaults for the array assigned to "colors", set them on the array and not the item.'
|
|
250
|
+
'When setting schema array defaults for the array assigned to "colors", set them on the array and not the item.',
|
|
253
251
|
);
|
|
254
252
|
});
|
|
255
253
|
});
|
|
@@ -264,7 +262,7 @@ describe('createConfigBuilder', () => {
|
|
|
264
262
|
config.name('alpha');
|
|
265
263
|
|
|
266
264
|
expect(() => config.name('bravo')).toThrow(
|
|
267
|
-
'A value already exists for "name". You may be trying to add a new values before flushing the old one. If you intended to override the existing value, pass in true as the second argument.'
|
|
265
|
+
'A value already exists for "name". You may be trying to add a new values before flushing the old one. If you intended to override the existing value, pass in true as the second argument.',
|
|
268
266
|
);
|
|
269
267
|
});
|
|
270
268
|
});
|
|
@@ -368,9 +366,9 @@ describe('createConfigBuilder', () => {
|
|
|
368
366
|
personalDetails: {
|
|
369
367
|
name: 'personalDetails',
|
|
370
368
|
},
|
|
371
|
-
})
|
|
369
|
+
}),
|
|
372
370
|
).toThrow(
|
|
373
|
-
'"pages" value has a depth greater than 1. To pass in objects with a depth greater than 1, create a builder for that config slice.'
|
|
371
|
+
'"pages" value has a depth greater than 1. To pass in objects with a depth greater than 1, create a builder for that config slice.',
|
|
374
372
|
);
|
|
375
373
|
});
|
|
376
374
|
|
|
@@ -453,7 +451,7 @@ describe('createConfigBuilder', () => {
|
|
|
453
451
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
454
452
|
|
|
455
453
|
expect(() => config.routes([{ page: 'personalDetails', path: 'personal-details' }])).toThrow(
|
|
456
|
-
'"routes" value has a depth greater than 1. To pass in objects with a depth greater than 1, create a builder for that config slice.'
|
|
454
|
+
'"routes" value has a depth greater than 1. To pass in objects with a depth greater than 1, create a builder for that config slice.',
|
|
457
455
|
);
|
|
458
456
|
});
|
|
459
457
|
|
|
@@ -482,7 +480,7 @@ describe('createConfigBuilder', () => {
|
|
|
482
480
|
.languageCodes(['en'])
|
|
483
481
|
.locales(({ countryCode, languageCodes }) =>
|
|
484
482
|
// eslint-disable-next-line jest/no-conditional-in-test
|
|
485
|
-
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}` as const) : []
|
|
483
|
+
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}` as const) : [],
|
|
486
484
|
);
|
|
487
485
|
|
|
488
486
|
expect(config.$values()).toEqual({ countryCode: 'GB', languageCodes: ['en'], locales: ['en_GB'] });
|
|
@@ -497,7 +495,7 @@ describe('createConfigBuilder', () => {
|
|
|
497
495
|
.languageCodes(['en'])
|
|
498
496
|
.locales(({ countryCode, languageCodes }) =>
|
|
499
497
|
// eslint-disable-next-line jest/no-conditional-in-test
|
|
500
|
-
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}` as const) : []
|
|
498
|
+
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}` as const) : [],
|
|
501
499
|
)
|
|
502
500
|
.languageCodes(['fr'], true);
|
|
503
501
|
|
|
@@ -513,7 +511,7 @@ describe('createConfigBuilder', () => {
|
|
|
513
511
|
.languageCodes(['en'])
|
|
514
512
|
.locales(({ countryCode, languageCodes }) =>
|
|
515
513
|
// eslint-disable-next-line jest/no-conditional-in-test
|
|
516
|
-
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}`) : []
|
|
514
|
+
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}`) : [],
|
|
517
515
|
);
|
|
518
516
|
|
|
519
517
|
expect(config.$validate()).toBe(true);
|
|
@@ -538,7 +536,7 @@ describe('createConfigBuilder', () => {
|
|
|
538
536
|
alpha: z.string(),
|
|
539
537
|
bravo: z.boolean(),
|
|
540
538
|
})
|
|
541
|
-
.optional()
|
|
539
|
+
.optional(),
|
|
542
540
|
);
|
|
543
541
|
|
|
544
542
|
expect(config.$toJson()).toMatchSnapshot();
|
|
@@ -17,7 +17,7 @@ import { transformConfigSync } from './utils/transformConfig.ts';
|
|
|
17
17
|
export type ConfigBuilder<ZodTypes> = {
|
|
18
18
|
[Key in keyof Required<ZodTypes>]: (
|
|
19
19
|
value: ZodTypes[Key] | ((c: ZodTypes) => ZodTypes[Key]),
|
|
20
|
-
override?: boolean
|
|
20
|
+
override?: boolean,
|
|
21
21
|
) => ConfigBuilder<ZodTypes>;
|
|
22
22
|
} & {
|
|
23
23
|
$disable: () => ConfigBuilder<ZodTypes>;
|
|
@@ -51,7 +51,7 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
51
51
|
> = {},
|
|
52
52
|
initialValues: Partial<{
|
|
53
53
|
[Key in keyof ZodTypes]: ZodTypes[Key];
|
|
54
|
-
}> = {}
|
|
54
|
+
}> = {},
|
|
55
55
|
): ConfigBuilder<ZodTypes> => {
|
|
56
56
|
type Config = {
|
|
57
57
|
[Key in keyof ZodTypes]: ZodTypes[Key];
|
|
@@ -59,6 +59,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
59
59
|
|
|
60
60
|
type DerivedValueCallback<K extends keyof Config = keyof Config> = (c: Config) => Config[K];
|
|
61
61
|
|
|
62
|
+
// Added to simplify type returned from zodToJsonSchema.
|
|
63
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
62
64
|
const jsonSchema = zodToJsonSchema(zodSchema) as JSONSchema7;
|
|
63
65
|
|
|
64
66
|
if (isSchemaValid(jsonSchema)) {
|
|
@@ -90,6 +92,9 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
90
92
|
};
|
|
91
93
|
|
|
92
94
|
const createInitialConfig = () => {
|
|
95
|
+
// Not casting here as loads of downstream impacts that make
|
|
96
|
+
// subsequent typing really difficult.
|
|
97
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
93
98
|
const config = merge(cloneDeep(initialValues), collateDefaultValues(jsonSchema)) as Config;
|
|
94
99
|
addNonEnumeralBaseProperties(config);
|
|
95
100
|
return config;
|
|
@@ -98,6 +103,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
98
103
|
let config = createInitialConfig();
|
|
99
104
|
let callbacks: Partial<Record<keyof Config, DerivedValueCallback>> = { ...derivedValueCallbacks };
|
|
100
105
|
|
|
106
|
+
// Aimed at making it easier for Typescript to derive type.
|
|
107
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
101
108
|
const configBuilder = {
|
|
102
109
|
$disable: () => {
|
|
103
110
|
Object.defineProperty(config, NonEmumeralProperties.DISABLED, {
|
|
@@ -113,6 +120,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
113
120
|
zodSchema.parse(configBuilder.$values());
|
|
114
121
|
return [];
|
|
115
122
|
} catch (error: unknown) {
|
|
123
|
+
// This will always be an instance of ZodError.
|
|
124
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
116
125
|
return (error as ZodError).errors;
|
|
117
126
|
}
|
|
118
127
|
},
|
|
@@ -128,6 +137,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
128
137
|
$extend: (builder: ConfigBuilder<Config>) => {
|
|
129
138
|
config = transformConfigSync<Config>(builder.$values(), [cloneNonEnumerableValues]);
|
|
130
139
|
// @ts-expect-error private property
|
|
140
|
+
// As __callbacks is private property, Typescript doesn't know what type is.
|
|
141
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
131
142
|
callbacks = { ...builder.__callbacks } as Partial<Record<keyof Config, DerivedValueCallback>>;
|
|
132
143
|
},
|
|
133
144
|
$flush: () => {
|
|
@@ -151,6 +162,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
151
162
|
const callback = callbacks[property];
|
|
152
163
|
|
|
153
164
|
if (callback) {
|
|
165
|
+
// Typescript not inferring property is key of Config.
|
|
166
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
154
167
|
config[property as keyof Config] = callback(config);
|
|
155
168
|
}
|
|
156
169
|
}
|
|
@@ -170,18 +183,22 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
170
183
|
throw new Error(
|
|
171
184
|
`"${propertyName}" is a reserved keyword within the config builder. Please use a different property name. The full list of reserved keywords is: ${[
|
|
172
185
|
...RESERVED_KEYWORDS,
|
|
173
|
-
].join(', ')}
|
|
186
|
+
].join(', ')}`,
|
|
174
187
|
);
|
|
175
188
|
}
|
|
176
189
|
|
|
190
|
+
// Hard to derive jsonSchema.properties are all keys of Config.
|
|
191
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
177
192
|
const castPropertyName = propertyName as keyof Config;
|
|
178
193
|
|
|
194
|
+
// Aimed at making it easier for Typescript to derive type.
|
|
195
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
179
196
|
configBuilder[castPropertyName] = ((value: Config[keyof Config] | DerivedValueCallback, override?: boolean) => {
|
|
180
197
|
if (isInvalidPropertyOverride(config[castPropertyName], override)) {
|
|
181
198
|
throw new Error(
|
|
182
199
|
`A value already exists for "${String(
|
|
183
|
-
castPropertyName
|
|
184
|
-
)}". You may be trying to add a new values before flushing the old one. If you intended to override the existing value, pass in true as the second argument
|
|
200
|
+
castPropertyName,
|
|
201
|
+
)}". You may be trying to add a new values before flushing the old one. If you intended to override the existing value, pass in true as the second argument.`,
|
|
185
202
|
);
|
|
186
203
|
}
|
|
187
204
|
|
|
@@ -191,8 +208,8 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
191
208
|
if (!isValidValue(value)) {
|
|
192
209
|
throw new Error(
|
|
193
210
|
`"${String(
|
|
194
|
-
castPropertyName
|
|
195
|
-
)}" value has a depth greater than ${MAX_DEPTH}. To pass in objects with a depth greater than ${MAX_DEPTH}, create a builder for that config slice
|
|
211
|
+
castPropertyName,
|
|
212
|
+
)}" value has a depth greater than ${String(MAX_DEPTH)}. To pass in objects with a depth greater than ${String(MAX_DEPTH)}, create a builder for that config slice.`,
|
|
196
213
|
);
|
|
197
214
|
}
|
|
198
215
|
|
|
@@ -4,7 +4,7 @@ import { transformConfig } from './utils/transformConfig.ts';
|
|
|
4
4
|
|
|
5
5
|
export const createConfigParser = async <Config extends object>(
|
|
6
6
|
config: Config,
|
|
7
|
-
{ experimentsCallback }: ConfigParserOptions = {}
|
|
7
|
+
{ experimentsCallback }: ConfigParserOptions = {},
|
|
8
8
|
) => {
|
|
9
9
|
const handlers: TransformConfigHandler[] = [];
|
|
10
10
|
|
|
@@ -30,8 +30,8 @@ describe('createConfigReader', () => {
|
|
|
30
30
|
// @ts-expect-error path does not resovle to a string
|
|
31
31
|
expect(() => reader.read('pages.contactDetails', { vars })).toThrow(
|
|
32
32
|
new Error(
|
|
33
|
-
'config reader received variables to use in string template, but the path did not resolve to a string.'
|
|
34
|
-
)
|
|
33
|
+
'config reader received variables to use in string template, but the path did not resolve to a string.',
|
|
34
|
+
),
|
|
35
35
|
);
|
|
36
36
|
});
|
|
37
37
|
});
|
|
@@ -12,6 +12,8 @@ export interface ConfigReader<Config extends object> {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export const createConfigReader = <Config extends object>(config: Config): ConfigReader<Config> => {
|
|
15
|
+
// Aimed at reducing the amount of work for typescript to resolve type.
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
15
17
|
const configReader = {
|
|
16
18
|
read: <P extends Path<Config>>(path: P, { vars }: ReadOptions = {}) => {
|
|
17
19
|
if (!vars) {
|
|
@@ -22,7 +24,7 @@ export const createConfigReader = <Config extends object>(config: Config): Confi
|
|
|
22
24
|
|
|
23
25
|
if (!isString(output)) {
|
|
24
26
|
throw new Error(
|
|
25
|
-
'config reader received variables to use in string template, but the path did not resolve to a string.'
|
|
27
|
+
'config reader received variables to use in string template, but the path did not resolve to a string.',
|
|
26
28
|
);
|
|
27
29
|
}
|
|
28
30
|
|
|
@@ -30,6 +32,8 @@ export const createConfigReader = <Config extends object>(config: Config): Confi
|
|
|
30
32
|
return acc.replace(new RegExp(`{{${key}}}`), String(vars[key]));
|
|
31
33
|
}, output);
|
|
32
34
|
},
|
|
35
|
+
// Aimed at reducing the amount of work for typescript to resolve type.
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
33
37
|
scope: <S extends Scope<Config>>(scope: S) => createConfigReader(get(config, scope) as Get<Config, S>),
|
|
34
38
|
} as ConfigReader<Config>;
|
|
35
39
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* eslint-disable prettier/prettier, import/no-default-export, unicorn/numeric-separators-style */
|
|
1
|
+
/* eslint-disable prettier/prettier, import-x/no-default-export, unicorn/numeric-separators-style */
|
|
2
2
|
/* This file is autogenerated, do not edit directly, your changes will not perist. */
|
|
3
3
|
|
|
4
4
|
export default {{{ config }}} as const;
|
|
@@ -2,13 +2,12 @@ import { type AnyRecord, NonEmumeralProperties, type TransformConfigHandlerSync
|
|
|
2
2
|
|
|
3
3
|
const NON_ENUMERABLE_KEYS = new Set(Object.values(NonEmumeralProperties));
|
|
4
4
|
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
5
|
export const cloneNonEnumerableValues: TransformConfigHandlerSync = <
|
|
7
6
|
Config1 extends AnyRecord,
|
|
8
|
-
Config2 extends AnyRecord
|
|
7
|
+
Config2 extends AnyRecord,
|
|
9
8
|
>(
|
|
10
9
|
clone: Config1,
|
|
11
|
-
config: Config2
|
|
10
|
+
config: Config2,
|
|
12
11
|
) => {
|
|
13
12
|
for (const nonEnumerableKey of NON_ENUMERABLE_KEYS) {
|
|
14
13
|
if (nonEnumerableKey in config) {
|
|
@@ -5,10 +5,9 @@ import {
|
|
|
5
5
|
type TransformConfigHandlerSync,
|
|
6
6
|
} from '../types.ts';
|
|
7
7
|
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
8
|
export const removeDisabledSlices: TransformConfigHandlerSync = <Config extends AnyRecord>(
|
|
10
9
|
clone: Config,
|
|
11
|
-
config: Config
|
|
10
|
+
config: Config,
|
|
12
11
|
) => {
|
|
13
12
|
if (NonEmumeralProperties.DISABLED in config) {
|
|
14
13
|
return {
|
|
@@ -10,11 +10,13 @@ export const runExperiments =
|
|
|
10
10
|
(callback: RunExperimentsCallback): TransformConfigHandler =>
|
|
11
11
|
async <Config extends AnyRecord>(clone: Config, config: Config) => {
|
|
12
12
|
if (NonEmumeralProperties.EXPERIMENT in config && typeof config.__experiment === 'object') {
|
|
13
|
+
// As __experiment is private property, Typescript doesn't know what type is.
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
13
15
|
const { buckets, id } = config.__experiment as { buckets: Buckets<Config>; id: string };
|
|
14
16
|
const bucket = await callback(id);
|
|
15
17
|
|
|
16
18
|
if (bucket && bucket in buckets && buckets[bucket]) {
|
|
17
|
-
return buckets[bucket]
|
|
19
|
+
return buckets[bucket];
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
|