zcb 0.3.2 → 0.3.4
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/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/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/production.analysis.txt +13 -13
- package/dist/types/cjs/createConfigBuilder.d.cts.map +1 -1
- package/dist/types/cjs/types.d.cts +4 -3
- package/dist/types/cjs/types.d.cts.map +1 -1
- package/dist/types/cjs/utils/transformWriteConfig.d.cts.map +1 -1
- package/dist/types/esm/createConfigBuilder.d.ts.map +1 -1
- package/dist/types/esm/types.d.ts +4 -3
- package/dist/types/esm/types.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 +4 -1
- package/src/createConfigBuilder.test.ts +130 -15
- package/src/createConfigBuilder.ts +5 -0
- package/src/createConfigReader.test.ts +1 -0
- package/src/types.ts +15 -10
- package/src/utils/transformConfig.test.ts +14 -0
- package/src/utils/transformWriteConfig.test.ts +111 -0
- package/src/utils/transformWriteConfig.ts +10 -5
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zcb",
|
|
3
3
|
"description": "Build configs with type safety from zod schema.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.4",
|
|
5
5
|
"author": "miami-man",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/badbatch/zod-config-builder",
|
|
@@ -14,6 +14,9 @@
|
|
|
14
14
|
"main": "./dist/cjs/index.cjs",
|
|
15
15
|
"module": "./dist/esm/index.mjs",
|
|
16
16
|
"types": "./dist/types/cjs/index.d.cts",
|
|
17
|
+
"imports": {
|
|
18
|
+
"#*": "./src/*"
|
|
19
|
+
},
|
|
17
20
|
"exports": {
|
|
18
21
|
".": {
|
|
19
22
|
"types": {
|
|
@@ -62,7 +62,11 @@ describe('createConfigBuilder', () => {
|
|
|
62
62
|
it('should copy over all values to the new config', async () => {
|
|
63
63
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
64
64
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
65
|
-
|
|
65
|
+
|
|
66
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
67
|
+
path: ({ page }) => kebabCase(page),
|
|
68
|
+
});
|
|
69
|
+
|
|
66
70
|
const page = createConfigBuilder<PageType>(pageSchema);
|
|
67
71
|
|
|
68
72
|
config
|
|
@@ -85,13 +89,19 @@ describe('createConfigBuilder', () => {
|
|
|
85
89
|
it('should copy over all experiments to the new config', async () => {
|
|
86
90
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
87
91
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
88
|
-
|
|
92
|
+
|
|
93
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
94
|
+
path: ({ page }) => kebabCase(page),
|
|
95
|
+
});
|
|
96
|
+
|
|
89
97
|
const page = createConfigBuilder<PageType>(pageSchema);
|
|
90
98
|
|
|
91
99
|
config
|
|
92
100
|
.$experiment('FEAT_ALPHA@0.0.1')
|
|
93
101
|
.name('alpha')
|
|
94
|
-
.pages({
|
|
102
|
+
.pages({
|
|
103
|
+
contactDetails: page.$experiment('FEAT_BRAVO@0.0.1').name('contactDetails').$flush(),
|
|
104
|
+
})
|
|
95
105
|
.routes([route.$experiment('FEAT_CHARLIE@0.0.1').page('contactDetails').$flush()]);
|
|
96
106
|
|
|
97
107
|
const childConfig = createConfigBuilder<ConfigType>(configSchema);
|
|
@@ -120,13 +130,19 @@ describe('createConfigBuilder', () => {
|
|
|
120
130
|
it('should copy over all disabled flags to the new config', async () => {
|
|
121
131
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
122
132
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
123
|
-
|
|
133
|
+
|
|
134
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
135
|
+
path: ({ page }) => kebabCase(page),
|
|
136
|
+
});
|
|
137
|
+
|
|
124
138
|
const page = createConfigBuilder<PageType>(pageSchema);
|
|
125
139
|
|
|
126
140
|
config
|
|
127
141
|
.$disable()
|
|
128
142
|
.name('alpha')
|
|
129
|
-
.pages({
|
|
143
|
+
.pages({
|
|
144
|
+
contactDetails: page.$disable().name('contactDetails').$flush(),
|
|
145
|
+
})
|
|
130
146
|
.routes([route.$disable().page('contactDetails').$flush()]);
|
|
131
147
|
|
|
132
148
|
const childConfig = createConfigBuilder<ConfigType>(configSchema);
|
|
@@ -154,12 +170,20 @@ describe('createConfigBuilder', () => {
|
|
|
154
170
|
|
|
155
171
|
it('should copy over all derived value callbacks to the new config builder', async () => {
|
|
156
172
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
157
|
-
|
|
173
|
+
|
|
174
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
175
|
+
path: ({ page }) => kebabCase(page),
|
|
176
|
+
});
|
|
177
|
+
|
|
158
178
|
route.page('personalDetails');
|
|
159
179
|
const childRoute = createConfigBuilder<RouteType>(routeSchema);
|
|
160
180
|
childRoute.$extend(route);
|
|
161
181
|
childRoute.page('contactDetails', true);
|
|
162
|
-
|
|
182
|
+
|
|
183
|
+
expect(childRoute.$values()).toEqual({
|
|
184
|
+
page: 'contactDetails',
|
|
185
|
+
path: 'contact-details',
|
|
186
|
+
});
|
|
163
187
|
});
|
|
164
188
|
});
|
|
165
189
|
|
|
@@ -174,7 +198,23 @@ describe('createConfigBuilder', () => {
|
|
|
174
198
|
});
|
|
175
199
|
|
|
176
200
|
const config = createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema);
|
|
177
|
-
|
|
201
|
+
|
|
202
|
+
expect(config.$values()).toMatchInlineSnapshot(`
|
|
203
|
+
{
|
|
204
|
+
"countryCode": undefined,
|
|
205
|
+
"countryName": undefined,
|
|
206
|
+
"description": "This is the description.",
|
|
207
|
+
"distanceUnit": undefined,
|
|
208
|
+
"enabled": undefined,
|
|
209
|
+
"languageCodes": undefined,
|
|
210
|
+
"locales": undefined,
|
|
211
|
+
"name": undefined,
|
|
212
|
+
"pages": undefined,
|
|
213
|
+
"routes": undefined,
|
|
214
|
+
"timeouts": undefined,
|
|
215
|
+
"timezone": undefined,
|
|
216
|
+
}
|
|
217
|
+
`);
|
|
178
218
|
});
|
|
179
219
|
});
|
|
180
220
|
|
|
@@ -187,7 +227,27 @@ describe('createConfigBuilder', () => {
|
|
|
187
227
|
});
|
|
188
228
|
|
|
189
229
|
const config = createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema);
|
|
190
|
-
|
|
230
|
+
|
|
231
|
+
expect(config.$values()).toMatchInlineSnapshot(`
|
|
232
|
+
{
|
|
233
|
+
"countryCode": undefined,
|
|
234
|
+
"countryName": undefined,
|
|
235
|
+
"distanceUnit": undefined,
|
|
236
|
+
"enabled": undefined,
|
|
237
|
+
"flags": {
|
|
238
|
+
"alpha": true,
|
|
239
|
+
"bravo": false,
|
|
240
|
+
"charlie": false,
|
|
241
|
+
},
|
|
242
|
+
"languageCodes": undefined,
|
|
243
|
+
"locales": undefined,
|
|
244
|
+
"name": undefined,
|
|
245
|
+
"pages": undefined,
|
|
246
|
+
"routes": undefined,
|
|
247
|
+
"timeouts": undefined,
|
|
248
|
+
"timezone": undefined,
|
|
249
|
+
}
|
|
250
|
+
`);
|
|
191
251
|
});
|
|
192
252
|
});
|
|
193
253
|
|
|
@@ -200,7 +260,28 @@ describe('createConfigBuilder', () => {
|
|
|
200
260
|
});
|
|
201
261
|
|
|
202
262
|
const config = createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema);
|
|
203
|
-
|
|
263
|
+
|
|
264
|
+
expect(config.$values()).toMatchInlineSnapshot(`
|
|
265
|
+
{
|
|
266
|
+
"colors": [
|
|
267
|
+
"red",
|
|
268
|
+
"yellow",
|
|
269
|
+
"pink",
|
|
270
|
+
"green",
|
|
271
|
+
],
|
|
272
|
+
"countryCode": undefined,
|
|
273
|
+
"countryName": undefined,
|
|
274
|
+
"distanceUnit": undefined,
|
|
275
|
+
"enabled": undefined,
|
|
276
|
+
"languageCodes": undefined,
|
|
277
|
+
"locales": undefined,
|
|
278
|
+
"name": undefined,
|
|
279
|
+
"pages": undefined,
|
|
280
|
+
"routes": undefined,
|
|
281
|
+
"timeouts": undefined,
|
|
282
|
+
"timezone": undefined,
|
|
283
|
+
}
|
|
284
|
+
`);
|
|
204
285
|
});
|
|
205
286
|
});
|
|
206
287
|
|
|
@@ -218,7 +299,26 @@ describe('createConfigBuilder', () => {
|
|
|
218
299
|
});
|
|
219
300
|
|
|
220
301
|
const config = createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema);
|
|
221
|
-
|
|
302
|
+
|
|
303
|
+
expect(config.$values()).toMatchInlineSnapshot(`
|
|
304
|
+
{
|
|
305
|
+
"countryCode": undefined,
|
|
306
|
+
"countryName": undefined,
|
|
307
|
+
"distanceUnit": undefined,
|
|
308
|
+
"enabled": undefined,
|
|
309
|
+
"flags": {
|
|
310
|
+
"alpha": true,
|
|
311
|
+
"bravo": true,
|
|
312
|
+
},
|
|
313
|
+
"languageCodes": undefined,
|
|
314
|
+
"locales": undefined,
|
|
315
|
+
"name": undefined,
|
|
316
|
+
"pages": undefined,
|
|
317
|
+
"routes": undefined,
|
|
318
|
+
"timeouts": undefined,
|
|
319
|
+
"timezone": undefined,
|
|
320
|
+
}
|
|
321
|
+
`);
|
|
222
322
|
});
|
|
223
323
|
});
|
|
224
324
|
});
|
|
@@ -399,7 +499,11 @@ describe('createConfigBuilder', () => {
|
|
|
399
499
|
it('should add the value to the config', async () => {
|
|
400
500
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
401
501
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
402
|
-
|
|
502
|
+
|
|
503
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
504
|
+
path: ({ page }) => kebabCase(page),
|
|
505
|
+
});
|
|
506
|
+
|
|
403
507
|
const subRoute = route.$fork();
|
|
404
508
|
|
|
405
509
|
config.routes([
|
|
@@ -428,7 +532,10 @@ describe('createConfigBuilder', () => {
|
|
|
428
532
|
it('should be a valid config', async () => {
|
|
429
533
|
const { createConfigBuilder } = await import('./createConfigBuilder.ts');
|
|
430
534
|
const config = createConfigBuilder<ConfigType>(configSchema);
|
|
431
|
-
|
|
535
|
+
|
|
536
|
+
const route = createConfigBuilder<RouteType>(routeSchema, undefined, {
|
|
537
|
+
path: ({ page }) => kebabCase(page),
|
|
538
|
+
});
|
|
432
539
|
|
|
433
540
|
config.routes([
|
|
434
541
|
route.page('personalDetails').$flush(),
|
|
@@ -483,7 +590,11 @@ describe('createConfigBuilder', () => {
|
|
|
483
590
|
languageCodes?.length && countryCode ? languageCodes.map(code => `${code}_${countryCode}` as const) : [],
|
|
484
591
|
);
|
|
485
592
|
|
|
486
|
-
expect(config.$values()).toEqual({
|
|
593
|
+
expect(config.$values()).toEqual({
|
|
594
|
+
countryCode: 'GB',
|
|
595
|
+
languageCodes: ['en'],
|
|
596
|
+
locales: ['en_GB'],
|
|
597
|
+
});
|
|
487
598
|
});
|
|
488
599
|
|
|
489
600
|
it('should update the value to the config automatically', async () => {
|
|
@@ -499,7 +610,11 @@ describe('createConfigBuilder', () => {
|
|
|
499
610
|
)
|
|
500
611
|
.languageCodes(['fr'], true);
|
|
501
612
|
|
|
502
|
-
expect(config.$values()).toEqual({
|
|
613
|
+
expect(config.$values()).toEqual({
|
|
614
|
+
countryCode: 'GB',
|
|
615
|
+
languageCodes: ['fr'],
|
|
616
|
+
locales: ['fr_GB'],
|
|
617
|
+
});
|
|
503
618
|
});
|
|
504
619
|
|
|
505
620
|
it('should be a valid config', async () => {
|
|
@@ -190,6 +190,11 @@ export const createConfigBuilder = <ZodTypes>(
|
|
|
190
190
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
191
191
|
const castPropertyName = propertyName as keyof Config;
|
|
192
192
|
|
|
193
|
+
if (!jsonSchema.required?.includes(propertyName) && !(propertyName in config)) {
|
|
194
|
+
// @ts-expect-error Optional properties we want to exist in the config with undefined initial values.
|
|
195
|
+
config[propertyName] = undefined;
|
|
196
|
+
}
|
|
197
|
+
|
|
193
198
|
// Aimed at making it easier for Typescript to derive type.
|
|
194
199
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
195
200
|
configBuilder[castPropertyName] = ((value: Config[keyof Config] | DerivedValueCallback, override?: boolean) => {
|
|
@@ -56,6 +56,7 @@ describe('createConfigReader', () => {
|
|
|
56
56
|
it('should throw the expected error', () => {
|
|
57
57
|
const reader = createReader();
|
|
58
58
|
|
|
59
|
+
// @ts-expect-error Required to test error
|
|
59
60
|
expect(() => reader.read('pages.contactDetails.sections')).toThrow(
|
|
60
61
|
'Path resolved to an object or an array of objects, but `read` can only resolve to a primitive value or an array of primitives. Use the `scope` method instead',
|
|
61
62
|
);
|
package/src/types.ts
CHANGED
|
@@ -55,16 +55,11 @@ export type Primitive = string | number | boolean | bigint | symbol | null | und
|
|
|
55
55
|
|
|
56
56
|
export type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, ...0[]];
|
|
57
57
|
|
|
58
|
-
export type
|
|
59
|
-
? never
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
T extends readonly any[]
|
|
64
|
-
? LeafPath
|
|
65
|
-
: {
|
|
66
|
-
[K in keyof T & string]: Leaves<T[K], [...LeafPath, K], Prev[Depth]>;
|
|
67
|
-
}[keyof T & string];
|
|
58
|
+
export type IsArrayOfPrimitives<T> = T extends readonly (infer U)[]
|
|
59
|
+
? Exclude<U, Primitive> extends never
|
|
60
|
+
? true
|
|
61
|
+
: false
|
|
62
|
+
: false;
|
|
68
63
|
|
|
69
64
|
export type OwnKeys<T> = Exclude<
|
|
70
65
|
{
|
|
@@ -74,6 +69,16 @@ export type OwnKeys<T> = Exclude<
|
|
|
74
69
|
`${string}[Symbol.${string}`
|
|
75
70
|
>;
|
|
76
71
|
|
|
72
|
+
export type Leaves<T, LeafPath extends string[] = [], Depth extends number = 10> = Depth extends never
|
|
73
|
+
? never
|
|
74
|
+
: T extends Primitive
|
|
75
|
+
? LeafPath
|
|
76
|
+
: IsArrayOfPrimitives<T> extends true
|
|
77
|
+
? LeafPath
|
|
78
|
+
: {
|
|
79
|
+
[K in OwnKeys<T>]: Leaves<T[K], [...LeafPath, K], Prev[Depth]>;
|
|
80
|
+
}[OwnKeys<T>];
|
|
81
|
+
|
|
77
82
|
export type Paths<T, ScopePath extends string[] = [], Depth extends number = 10> = Depth extends never
|
|
78
83
|
? never
|
|
79
84
|
: T extends Primitive
|
|
@@ -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",
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { jest } from '@jest/globals';
|
|
2
|
+
import configBuilder from '../__testUtils__/configBuilder.ts';
|
|
3
|
+
|
|
4
|
+
jest.unstable_mockModule('fs-extra/esm', () => ({
|
|
5
|
+
outputFileSync: jest.fn(),
|
|
6
|
+
}));
|
|
7
|
+
|
|
8
|
+
jest.unstable_mockModule('shelljs', () => ({
|
|
9
|
+
default: {
|
|
10
|
+
echo: jest.fn(),
|
|
11
|
+
exec: jest.fn(),
|
|
12
|
+
exit: jest.fn(),
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
const { outputFileSync } = jest.mocked(await import('fs-extra/esm'));
|
|
17
|
+
const { transformWriteConfig } = await import('./transformWriteConfig.ts');
|
|
18
|
+
|
|
19
|
+
describe('transformWriteConfig', () => {
|
|
20
|
+
it('should call outputFileSync with the expected file content', async () => {
|
|
21
|
+
await transformWriteConfig(configBuilder.$values(), {
|
|
22
|
+
outputFile: 'config.ts',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
expect(outputFileSync.mock.calls[0]?.[1]).toMatchInlineSnapshot(`
|
|
26
|
+
"/* eslint-disable prettier/prettier, import-x/no-default-export, unicorn/numeric-separators-style, unicorn/no-null */
|
|
27
|
+
/* This file is autogenerated, do not edit directly, your changes will not perist. */
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
countryCode: "GB",
|
|
31
|
+
countryName: null,
|
|
32
|
+
distanceUnit: "km",
|
|
33
|
+
enabled: true,
|
|
34
|
+
languageCodes: [
|
|
35
|
+
"en"
|
|
36
|
+
],
|
|
37
|
+
locales: [
|
|
38
|
+
"en_GB"
|
|
39
|
+
],
|
|
40
|
+
name: undefined,
|
|
41
|
+
pages: {
|
|
42
|
+
contactDetails: {
|
|
43
|
+
path: undefined,
|
|
44
|
+
queryParams: undefined,
|
|
45
|
+
sections: [
|
|
46
|
+
{
|
|
47
|
+
sections: undefined,
|
|
48
|
+
name: "header"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: "body",
|
|
52
|
+
sections: [
|
|
53
|
+
{
|
|
54
|
+
sections: undefined,
|
|
55
|
+
name: "main"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: "sidebar"
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: "footer"
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
name: "contactDetails"
|
|
67
|
+
},
|
|
68
|
+
personalDetails: {
|
|
69
|
+
name: "personalDetails",
|
|
70
|
+
sections: [
|
|
71
|
+
{
|
|
72
|
+
name: "header"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: "body",
|
|
76
|
+
sections: [
|
|
77
|
+
{
|
|
78
|
+
name: "main"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "sidebar"
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: "footer"
|
|
87
|
+
}
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
routes: [
|
|
92
|
+
{
|
|
93
|
+
aliases: undefined,
|
|
94
|
+
routes: undefined,
|
|
95
|
+
page: "personalDetails",
|
|
96
|
+
path: "personal-details"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
page: "contactDetails",
|
|
100
|
+
path: "contact-details"
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
timeouts: {
|
|
104
|
+
apollo: 10000
|
|
105
|
+
},
|
|
106
|
+
timezone: "Europe/London"
|
|
107
|
+
} as const;
|
|
108
|
+
"
|
|
109
|
+
`);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -20,13 +20,18 @@ export const transformWriteConfig = async <Config extends object>(
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const template = Handlebars.compile(
|
|
23
|
-
readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '
|
|
23
|
+
readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '../templates/config.ts.hbs'), { encoding: 'utf8' }),
|
|
24
24
|
);
|
|
25
25
|
|
|
26
|
-
const output = template({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const output = template({
|
|
27
|
+
config: JSON.stringify(
|
|
28
|
+
await transformConfig(config, handlers),
|
|
29
|
+
(_k, v: unknown) => (v === undefined ? 'undefined' : v),
|
|
30
|
+
2,
|
|
31
|
+
),
|
|
32
|
+
})
|
|
33
|
+
.replaceAll(/"([A-Za-z][\dA-Za-z]+)":/g, '$1:')
|
|
34
|
+
.replaceAll('"undefined"', 'undefined');
|
|
30
35
|
|
|
31
36
|
shelljs.echo(`zcd watch => writing to file: ${outputFile}`);
|
|
32
37
|
shelljs.echo(`zcd watch => content to write:\n${output}\n`);
|