zcb 0.1.0 → 0.1.2

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/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.1.0",
4
+ "version": "0.1.2",
5
5
  "author": "Dylan Aubrey",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/badbatch/zod-config-builder",
@@ -205,38 +205,37 @@ describe('createConfigBuilder', () => {
205
205
  expect(config.$values()).toEqual({ colors: ['red', 'yellow', 'pink', 'green'] });
206
206
  });
207
207
  });
208
- });
209
208
 
210
- describe('and a config has an invalid default value', () => {
211
- describe('and that value is a record of booleans', () => {
209
+ describe('and that value is an object of key/value pairs', () => {
212
210
  it('should throw an error', async () => {
213
211
  const { createConfigBuilder } = await import('./createConfigBuilder.ts');
214
212
 
215
213
  const extendedSchema = configSchema.extend({
216
- flags: z.record(z.boolean().default(true)).optional(),
214
+ flags: z
215
+ .object({
216
+ alpha: z.boolean().default(true),
217
+ bravo: z.boolean().default(true),
218
+ })
219
+ .optional(),
217
220
  });
218
221
 
219
- expect(() => createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema)).toThrow(
220
- 'When setting schema property defaults for the object assigned to "flags", set them on the object and not the property.'
221
- );
222
+ const config = createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema);
223
+ expect(config.$values()).toEqual({ flags: { alpha: true, bravo: true } });
222
224
  });
223
225
  });
226
+ });
224
227
 
225
- describe('and that value is an object of key/value pairs', () => {
228
+ describe('and a config has an invalid default value', () => {
229
+ describe('and that value is a record of booleans', () => {
226
230
  it('should throw an error', async () => {
227
231
  const { createConfigBuilder } = await import('./createConfigBuilder.ts');
228
232
 
229
233
  const extendedSchema = configSchema.extend({
230
- flags: z
231
- .object({
232
- alpha: z.boolean().default(true),
233
- bravo: z.boolean().default(true),
234
- })
235
- .optional(),
234
+ flags: z.record(z.boolean().default(true)).optional(),
236
235
  });
237
236
 
238
237
  expect(() => createConfigBuilder<z.infer<typeof extendedSchema>>(extendedSchema)).toThrow(
239
- 'When setting schema property defaults for the object assigned to "flags", set them on the object and not the property.'
238
+ 'When setting schema property defaults for the value of the record assigned to "flags", set them on the record and not the value.'
240
239
  );
241
240
  });
242
241
  });
@@ -1,9 +1,11 @@
1
1
  import { type JSONSchema7 } from 'json-schema';
2
+ import { cloneDeep, merge } from 'lodash-es';
2
3
  import { type ZodError, type z } from 'zod';
3
4
  import { zodToJsonSchema } from 'zod-to-json-schema';
4
5
  import { cloneNonEnumerableValues } from './transformers/cloneNonEnumerableValues.ts';
5
6
  import { NonEmumeralProperties } from './types.ts';
6
7
  import { arrayHasInvalidDefaults } from './utils/arrayHasInvalidDefaults.ts';
8
+ import { collateObjectPropertyDefaults } from './utils/collateObjectPropertyDefaults.ts';
7
9
  import { isDerivedValueCallback } from './utils/isDerivedValueCallback.ts';
8
10
  import { isInvalidPropertyOverride } from './utils/isInvalidPropertyOverride.ts';
9
11
  import { RESERVED_KEYWORDS, isPropertyReservedWord } from './utils/isPropertyReservedWord.ts';
@@ -11,7 +13,6 @@ import { isSchemaValid } from './utils/isSchemaValid.ts';
11
13
  import { isValidPropertyDefinition } from './utils/isValidPropertyDefinition.ts';
12
14
  import { isValidValue } from './utils/isValidValue.ts';
13
15
  import { jsonStringifyReplacer } from './utils/jsonStringifyReplacer.ts';
14
- import { objectHasInvalidDefaults } from './utils/objectHasInvalidDefaults.ts';
15
16
  import { recordHasInvalidDefaults } from './utils/recordHasInvalidDefaults.ts';
16
17
  import { transformConfigSync } from './utils/transformConfig.ts';
17
18
 
@@ -51,7 +52,8 @@ export const createConfigBuilder = <ZodTypes>(
51
52
  };
52
53
 
53
54
  type DerivedValueCallback<K extends keyof Config = keyof Config> = (c: Config) => Config[K];
54
- let config = initialValues as Config;
55
+ let config = cloneDeep(initialValues) as Config;
56
+ const defaultValues = {} as Partial<Config>;
55
57
 
56
58
  Object.defineProperty(config, NonEmumeralProperties.ZCB, {
57
59
  configurable: false,
@@ -95,7 +97,7 @@ export const createConfigBuilder = <ZodTypes>(
95
97
  },
96
98
  $flush: () => {
97
99
  const values = configBuilder.$values();
98
- config = {} as Config;
100
+ config = cloneDeep(defaultValues) as Config;
99
101
 
100
102
  Object.defineProperty(config, NonEmumeralProperties.ZCB, {
101
103
  configurable: false,
@@ -155,7 +157,7 @@ export const createConfigBuilder = <ZodTypes>(
155
157
 
156
158
  if (isValidPropertyDefinition(propertyDefinition)) {
157
159
  if (propertyDefinition.default) {
158
- config[castProperty] = propertyDefinition.default as Config[keyof Config];
160
+ defaultValues[castProperty] = propertyDefinition.default as Config[keyof Config];
159
161
  }
160
162
 
161
163
  if (propertyDefinition.type === 'array' && arrayHasInvalidDefaults(propertyDefinition)) {
@@ -167,22 +169,22 @@ export const createConfigBuilder = <ZodTypes>(
167
169
  }
168
170
 
169
171
  if (propertyDefinition.type === 'object') {
170
- if (objectHasInvalidDefaults(propertyDefinition)) {
172
+ if (recordHasInvalidDefaults(propertyDefinition)) {
171
173
  throw new Error(
172
- `When setting schema property defaults for the object assigned to "${String(
174
+ `When setting schema property defaults for the value of the record assigned to "${String(
173
175
  castProperty
174
- )}", set them on the object and not the property.`
176
+ )}", set them on the record and not the value.`
175
177
  );
176
178
  }
177
179
 
178
- if (recordHasInvalidDefaults(propertyDefinition)) {
179
- throw new Error(
180
- `When setting schema property defaults for the object assigned to "${String(
181
- castProperty
182
- )}", set them on the object and not the property.`
183
- );
180
+ const propertyDefaults = collateObjectPropertyDefaults(propertyDefinition);
181
+
182
+ if (propertyDefaults) {
183
+ defaultValues[castProperty] = propertyDefaults as Config[keyof Config];
184
184
  }
185
185
  }
186
+
187
+ merge(config, cloneDeep(defaultValues));
186
188
  }
187
189
 
188
190
  configBuilder[castProperty] = ((value: Config[keyof Config] | DerivedValueCallback, override?: boolean) => {
@@ -0,0 +1,26 @@
1
+ import type { JSONSchema7 } from 'json-schema';
2
+ import { isBoolean, isUndefined } from 'lodash-es';
3
+ import type { Jsonifiable } from 'type-fest';
4
+ import { objectPropertyHasDefaults } from './objectPropertyHasDefaults.ts';
5
+
6
+ export const collateObjectPropertyDefaults = (propertyDefinition: JSONSchema7) => {
7
+ const { properties } = propertyDefinition;
8
+
9
+ if (!properties || !objectPropertyHasDefaults(propertyDefinition)) {
10
+ return;
11
+ }
12
+
13
+ return Object.keys(properties).reduce<Record<string, Jsonifiable>>((acc, key) => {
14
+ const propertyDef = properties[key];
15
+
16
+ if (!propertyDef || isBoolean(propertyDef)) {
17
+ return acc;
18
+ }
19
+
20
+ if ('default' in propertyDef && !isUndefined(propertyDef.default)) {
21
+ acc[key] = propertyDef.default;
22
+ }
23
+
24
+ return acc;
25
+ }, {});
26
+ };
@@ -1,5 +1,5 @@
1
1
  import type { JSONSchema7 } from 'json-schema';
2
2
 
3
- export const objectHasInvalidDefaults = (propertyDefinition: JSONSchema7) =>
3
+ export const objectPropertyHasDefaults = (propertyDefinition: JSONSchema7) =>
4
4
  propertyDefinition.properties &&
5
5
  Object.values(propertyDefinition.properties).some(value => typeof value === 'object' && 'default' in value);
@@ -1,3 +0,0 @@
1
- import type { JSONSchema7 } from 'json-schema';
2
- export declare const objectHasInvalidDefaults: (propertyDefinition: JSONSchema7) => boolean | undefined;
3
- //# sourceMappingURL=objectHasInvalidDefaults.d.cts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"objectHasInvalidDefaults.d.cts","sourceRoot":"","sources":["../../../../src/utils/objectHasInvalidDefaults.cts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,wBAAwB,uBAAwB,WAAW,wBAEqC,CAAC"}
@@ -1,3 +0,0 @@
1
- import type { JSONSchema7 } from 'json-schema';
2
- export declare const objectHasInvalidDefaults: (propertyDefinition: JSONSchema7) => boolean | undefined;
3
- //# sourceMappingURL=objectHasInvalidDefaults.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"objectHasInvalidDefaults.d.ts","sourceRoot":"","sources":["../../../../src/utils/objectHasInvalidDefaults.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,eAAO,MAAM,wBAAwB,uBAAwB,WAAW,wBAEqC,CAAC"}