zodselect 1.0.8 → 1.0.10

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.
@@ -61,18 +61,18 @@ function buildSelect(schema, cache = new Map()) {
61
61
  const hasLazy = types.some(item => isZodLazy(item));
62
62
  if (hasLazy) {
63
63
  return z.lazy(() => {
64
- return buildSelectMerge(types);
64
+ return buildSelectMerge(types, cache);
65
65
  });
66
66
  }
67
- return buildSelectMerge(types);
67
+ return buildSelectMerge(types, cache);
68
68
  }
69
69
  return z.boolean().optional();
70
70
  }
71
- function buildSelectMerge(types) {
71
+ function buildSelectMerge(types, cache) {
72
72
  const shape = {};
73
73
  let isStrict = false;
74
74
  for (const cur of types) {
75
- const select = buildSelect(cur);
75
+ const select = buildSelect(cur, cache);
76
76
  let clause;
77
77
  if (isZodLazy(select)) {
78
78
  clause = select.def.getter();
@@ -60,6 +60,18 @@ describe('.buildSelectSchema()', () => {
60
60
  });
61
61
  assert.throws(() => selectSchema.parse({ valueC: true }), /Unrecognized key/);
62
62
  });
63
+ it('z.infer of a union select schema should be a plain select type', () => {
64
+ const schema = z.union([
65
+ z.object({ shared: z.string(), type: z.literal('a'), valueA: z.string() }).strict(),
66
+ z.object({ shared: z.string(), type: z.literal('b'), valueB: z.number() }).strict()
67
+ ]);
68
+ const selectSchema = buildSelectSchema(schema);
69
+ // Runtime: the schema correctly parses a plain select object
70
+ assert.deepEqual(selectSchema.parse({ shared: true, type: true, valueA: true }), { shared: true, type: true, valueA: true });
71
+ const plain = {};
72
+ void plain;
73
+ assert.ok(true);
74
+ });
63
75
  it('should support intersections of objects', () => {
64
76
  const schema = z.intersection(z.object({ a: z.string() }), z.object({ b: z.number() }));
65
77
  const select = buildSelectSchema(schema);
@@ -75,7 +87,7 @@ describe('.buildSelectSchema()', () => {
75
87
  assert.strictEqual(getInnerType(select.shape.foo).def.type, 'boolean');
76
88
  assert.strictEqual(getInnerType(select.shape.bar).def.type, 'boolean');
77
89
  });
78
- it('should return a strict schema if all members are strict', () => {
90
+ it('should return a strict schema if any member is strict', () => {
79
91
  const schema = z.union([
80
92
  z.object({ strictA: z.string() }).strict(),
81
93
  z.object({ strictB: z.number() }).strict()
@@ -83,6 +95,16 @@ describe('.buildSelectSchema()', () => {
83
95
  const select = buildSelectSchema(schema);
84
96
  assert.strictEqual(isZodObjectLoose(select), false);
85
97
  });
98
+ it('should return a strict schema when only one union member is strict', () => {
99
+ const schema = z.union([
100
+ z.object({ strictA: z.string() }).strict(),
101
+ z.looseObject({ looseB: z.number() })
102
+ ]);
103
+ const select = buildSelectSchema(schema);
104
+ // Any strict member makes the merged select strict so callers cannot
105
+ // accidentally reference fields outside any member's defined shape.
106
+ assert.strictEqual(isZodObjectLoose(select), false);
107
+ });
86
108
  it('should allow optional keys in the select schema', () => {
87
109
  const schema = z.object({
88
110
  optionalField: z.string().optional()
@@ -91,13 +113,13 @@ describe('.buildSelectSchema()', () => {
91
113
  assert.strictEqual(getInnerType(select.shape.optionalField).def.type, 'boolean');
92
114
  });
93
115
  it('should handle direct recursion', () => {
94
- const RoleSchema = z.lazy(() => {
116
+ const roleSchema = z.lazy(() => {
95
117
  return (z.object({
96
118
  name: z.string(),
97
- roles: z.array(RoleSchema)
119
+ roles: z.array(roleSchema)
98
120
  }));
99
121
  });
100
- const select = buildSelectSchema(RoleSchema);
122
+ const select = buildSelectSchema(roleSchema);
101
123
  assert.deepStrictEqual(Object.keys(select.shape), ['name', 'roles']);
102
124
  const nameSelect = select.shape.name;
103
125
  assert.strictEqual(nameSelect.def.type, 'optional');
@@ -112,13 +134,13 @@ describe('.buildSelectSchema()', () => {
112
134
  assert.strictEqual(roleItem.def.type, 'object');
113
135
  });
114
136
  it('should support mutual recursion (cross-recursive)', () => {
115
- const A = z.lazy(() => z.object({
116
- b: B
137
+ const schemaA = z.lazy(() => z.object({
138
+ b: schemaB
117
139
  }));
118
- const B = z.lazy(() => z.object({
119
- a: A
140
+ const schemaB = z.lazy(() => z.object({
141
+ a: schemaA
120
142
  }));
121
- const select = buildSelectSchema(A);
143
+ const select = buildSelectSchema(schemaA);
122
144
  assert.strictEqual(select.shape.b.def.type, 'lazy');
123
145
  const bUnion = select.shape.b.def.getter();
124
146
  assert.strictEqual(bUnion.def.innerType.def.type, 'union');
@@ -126,11 +148,11 @@ describe('.buildSelectSchema()', () => {
126
148
  assert.strictEqual(bObj.shape.a.def.type, 'lazy');
127
149
  });
128
150
  it('should share the same instance in recursion (no infinite loop)', () => {
129
- const Role = z.lazy(() => z.object({
151
+ const role = z.lazy(() => z.object({
130
152
  name: z.string(),
131
- roles: z.array(Role)
153
+ roles: z.array(role)
132
154
  }));
133
- const select = buildSelectSchema(Role);
155
+ const select = buildSelectSchema(role);
134
156
  const rolesSelect = select.shape.roles;
135
157
  const unionSelect = rolesSelect.def.getter().def.innerType;
136
158
  const nestedRoleSelect = unionSelect.def.options[1].shape.roles;
@@ -152,6 +174,19 @@ describe('.buildSelectSchema()', () => {
152
174
  assert.strictEqual(union.def.options[1].def.valueType.type, 'optional');
153
175
  assert.strictEqual(union.def.options[1].def.valueType.def.innerType.type, 'boolean');
154
176
  });
177
+ it('should share the same lazy instance for a recursive schema referenced by multiple union members', () => {
178
+ const nested = z.lazy(() => z.object({ children: z.array(nested) }));
179
+ const schema = z.union([
180
+ z.object({ a: nested }),
181
+ z.object({ b: nested })
182
+ ]);
183
+ const select = buildSelectSchema(schema);
184
+ // Both 'a' and 'b' reference the same `nested` schema.
185
+ // Their select schemas must be the same lazy instance (shared cache).
186
+ const aSelect = select.shape.a;
187
+ const bSelect = select.shape.b;
188
+ assert.strictEqual(aSelect, bSelect);
189
+ });
155
190
  it('should support unknown types', () => {
156
191
  const schema = z.object({
157
192
  tags: z.unknown()
@@ -6,7 +6,7 @@ export function refineSchema(schema, shape) {
6
6
  const refinedShape = {};
7
7
  const schemaShape = schema.shape;
8
8
  for (const key in shape) {
9
- if (key in schemaShape) {
9
+ if (key in schemaShape && shape[key] !== false) {
10
10
  refinedShape[key] = refineSchemaField(schemaShape[key], shape[key]);
11
11
  }
12
12
  }
@@ -4,16 +4,16 @@ import { z, ZodError } from 'zod';
4
4
  import { refineSchema } from './refine-schema.js';
5
5
  describe('.refineSchema()', () => {
6
6
  it('should retain required fields', () => {
7
- const UserSchema = z.object({
7
+ const userSchema = z.object({
8
8
  age: z.number().optional(),
9
9
  firstName: z.string(),
10
10
  lastName: z.string()
11
11
  });
12
- const RefinedSchema = refineSchema(UserSchema, {
12
+ const refinedSchema = refineSchema(userSchema, {
13
13
  firstName: true,
14
14
  lastName: true
15
15
  });
16
- const parsedData = RefinedSchema.parse({
16
+ const parsedData = refinedSchema.parse({
17
17
  firstName: 'John',
18
18
  lastName: 'Doe'
19
19
  });
@@ -21,74 +21,74 @@ describe('.refineSchema()', () => {
21
21
  assert.equal(parsedData.lastName, 'Doe');
22
22
  });
23
23
  it('should handle optional fields', () => {
24
- const UserSchema = z.object({
24
+ const userSchema = z.object({
25
25
  age: z.number().optional(),
26
26
  firstName: z.string(),
27
27
  lastName: z.string()
28
28
  });
29
- const RefinedSchema = refineSchema(UserSchema, {
29
+ const refinedSchema = refineSchema(userSchema, {
30
30
  age: true
31
31
  });
32
- const parsedData = RefinedSchema.parse({ age: 25 });
32
+ const parsedData = refinedSchema.parse({ age: 25 });
33
33
  assert.equal(parsedData.age, 25);
34
- const parsedWithoutAge = RefinedSchema.parse({});
34
+ const parsedWithoutAge = refinedSchema.parse({});
35
35
  assert.equal(parsedWithoutAge.age, undefined);
36
36
  });
37
37
  it('should handle nullable fields', () => {
38
- const RoleSchema = z.object({
38
+ const roleSchema = z.object({
39
39
  name: z.string()
40
40
  });
41
- const UserSchema = z.object({
41
+ const userSchema = z.object({
42
42
  firstName: z.string(),
43
- role: RoleSchema.nullable()
43
+ role: roleSchema.nullable()
44
44
  });
45
- const RefinedSchema = refineSchema(UserSchema, {
45
+ const refinedSchema = refineSchema(userSchema, {
46
46
  role: true
47
47
  });
48
- const parsedWithNullRole = RefinedSchema.parse({
48
+ const parsedWithNullRole = refinedSchema.parse({
49
49
  firstName: 'Alice',
50
50
  role: null
51
51
  });
52
52
  assert.equal(parsedWithNullRole.role, null);
53
53
  });
54
54
  it('should handle both optional and nullable fields', () => {
55
- const RoleSchema = z.object({
55
+ const roleSchema = z.object({
56
56
  name: z.string()
57
57
  });
58
- const UserSchema = z.object({
58
+ const userSchema = z.object({
59
59
  firstName: z.string(),
60
- role: RoleSchema.nullable().optional()
60
+ role: roleSchema.nullable().optional()
61
61
  });
62
- const RefinedSchema = refineSchema(UserSchema, {
62
+ const refinedSchema = refineSchema(userSchema, {
63
63
  role: {
64
64
  name: true
65
65
  }
66
66
  });
67
- const parsedWithRole = RefinedSchema.parse({
67
+ const parsedWithRole = refinedSchema.parse({
68
68
  firstName: 'Alice',
69
69
  role: { name: 'Admin' }
70
70
  });
71
71
  assert.deepStrictEqual(parsedWithRole.role, { name: 'Admin' });
72
- const parsedWithNullRole = RefinedSchema.parse({
72
+ const parsedWithNullRole = refinedSchema.parse({
73
73
  firstName: 'Alice',
74
74
  role: null
75
75
  });
76
76
  assert.strictEqual(parsedWithNullRole.role, null);
77
- const parsedWithoutRole = RefinedSchema.parse({ firstName: 'Alice' });
77
+ const parsedWithoutRole = refinedSchema.parse({ firstName: 'Alice' });
78
78
  assert.strictEqual(parsedWithoutRole.role, undefined);
79
79
  });
80
80
  it('should apply custom schema transformations', () => {
81
- const RoleSchema = z.object({
81
+ const roleSchema = z.object({
82
82
  name: z.string()
83
83
  });
84
- const UserSchema = z.object({
84
+ const userSchema = z.object({
85
85
  firstName: z.string(),
86
- role: RoleSchema
86
+ role: roleSchema
87
87
  });
88
- const RefinedSchema = refineSchema(UserSchema, {
89
- role: (schema) => schema.extend({ permissions: z.array(z.string()) })
88
+ const refinedSchema = refineSchema(userSchema, {
89
+ role: schema => schema.extend({ permissions: z.array(z.string()) })
90
90
  });
91
- const parsedData = RefinedSchema.parse({
91
+ const parsedData = refinedSchema.parse({
92
92
  firstName: 'Bob',
93
93
  role: { name: 'User', permissions: ['read', 'write'] }
94
94
  });
@@ -98,46 +98,46 @@ describe('.refineSchema()', () => {
98
98
  });
99
99
  });
100
100
  it('should handle nested arrays', () => {
101
- const RoleSchema = z.object({
101
+ const roleSchema = z.object({
102
102
  level: z.number(),
103
103
  title: z.string()
104
104
  });
105
- const UserSchema = z.object({
105
+ const userSchema = z.object({
106
106
  age: z.number().optional(),
107
107
  firstName: z.string(),
108
108
  lastName: z.string(),
109
109
  nestedArray: z.array(z.object({ name: z.string(), value: z.number() })).optional().nullable(),
110
- role: RoleSchema.nullable().optional(),
110
+ role: roleSchema.nullable().optional(),
111
111
  tags: z.array(z.string()).optional()
112
112
  });
113
- const RefinedSchema = refineSchema(UserSchema, {
113
+ const refinedSchema = refineSchema(userSchema, {
114
114
  nestedArray: {
115
115
  name: true
116
116
  }
117
117
  });
118
- const parsedData = RefinedSchema.parse({
118
+ const parsedData = refinedSchema.parse({
119
119
  firstName: 'Alice',
120
120
  lastName: 'Smith',
121
121
  nestedArray: [{ name: 'Feature1', value: 10 }, { name: 'Feature2', value: 20 }]
122
122
  });
123
123
  assert.deepStrictEqual(parsedData.nestedArray, [{ name: 'Feature1' }, { name: 'Feature2' }]);
124
124
  // Test optional array
125
- const parsedWithoutNestedArray = RefinedSchema.parse({
125
+ const parsedWithoutNestedArray = refinedSchema.parse({
126
126
  firstName: 'Alice',
127
127
  lastName: 'Smith'
128
128
  });
129
129
  assert.equal(parsedWithoutNestedArray.nestedArray, undefined);
130
130
  });
131
131
  it('should handle custom fields', () => {
132
- const UserSchema = z.object({
132
+ const userSchema = z.object({
133
133
  address: z.custom().optional(),
134
134
  firstName: z.string(),
135
135
  lastName: z.string()
136
136
  });
137
- const RefinedSchema = refineSchema(UserSchema, {
137
+ const refinedSchema = refineSchema(userSchema, {
138
138
  address: true
139
139
  });
140
- const parsedData = RefinedSchema.parse({
140
+ const parsedData = refinedSchema.parse({
141
141
  address: {
142
142
  city: 'Austin',
143
143
  state: 'TX',
@@ -155,45 +155,45 @@ describe('.refineSchema()', () => {
155
155
  });
156
156
  });
157
157
  it('should support unions of objects', () => {
158
- const Person = z.object({
158
+ const person = z.object({
159
159
  firstName: z.string(),
160
160
  lastName: z.string()
161
161
  });
162
- const Address = z.object({
162
+ const address = z.object({
163
163
  address: z.string(),
164
164
  city: z.string()
165
165
  });
166
- const Schema = refineSchema(z.union([Person, Address]), {
166
+ const schema = refineSchema(z.union([person, address]), {
167
167
  address: true,
168
168
  firstName: true
169
169
  });
170
- let parseResult = Schema.parse({
170
+ let parseResult = schema.parse({
171
171
  address: '123 Main Street',
172
172
  firstName: 'Jerry',
173
173
  lastName: 'Springer'
174
174
  });
175
175
  deepStrictEqual(parseResult, { firstName: 'Jerry' });
176
- parseResult = Schema.parse({
176
+ parseResult = schema.parse({
177
177
  address: '123 Main Street',
178
178
  city: 'Austin'
179
179
  });
180
180
  deepStrictEqual(parseResult, { address: '123 Main Street' });
181
181
  });
182
182
  it('should error if none of the types are matched', () => {
183
- const Person = z.object({
183
+ const person = z.object({
184
184
  firstName: z.string(),
185
185
  lastName: z.string()
186
186
  });
187
- const Address = z.object({
187
+ const address = z.object({
188
188
  address: z.string(),
189
189
  city: z.string()
190
190
  });
191
- const Schema = refineSchema(z.union([Person, Address]), {
191
+ const schema = refineSchema(z.union([person, address]), {
192
192
  address: true,
193
193
  firstName: true
194
194
  });
195
195
  throws(() => {
196
- Schema.parse({
196
+ schema.parse({
197
197
  lastName: 'Springer'
198
198
  });
199
199
  }, (err) => {
@@ -203,21 +203,34 @@ describe('.refineSchema()', () => {
203
203
  return true;
204
204
  });
205
205
  });
206
+ it('should exclude fields specified as false in the shape', () => {
207
+ const schema = z.object({
208
+ firstName: z.string(),
209
+ lastName: z.string()
210
+ });
211
+ const refined = refineSchema(schema, {
212
+ firstName: true,
213
+ lastName: false
214
+ });
215
+ // lastName was specified as false — it should be excluded from the refined schema
216
+ const result = refined.parse({ firstName: 'Alice', lastName: 'Smith' });
217
+ assert.deepStrictEqual(result, { firstName: 'Alice' });
218
+ });
206
219
  it('should support unions of objects and simple types', () => {
207
- const Person = z.object({
220
+ const person = z.object({
208
221
  firstName: z.string(),
209
222
  lastName: z.string()
210
223
  });
211
- const Schema = refineSchema(z.union([Person, z.string()]), {
224
+ const schema = refineSchema(z.union([person, z.string()]), {
212
225
  address: true,
213
226
  firstName: true
214
227
  });
215
- let parseResult = Schema.parse({
228
+ let parseResult = schema.parse({
216
229
  firstName: 'Jerry',
217
230
  lastName: 'Springer'
218
231
  });
219
232
  deepStrictEqual(parseResult, { firstName: 'Jerry' });
220
- parseResult = Schema.parse('123 Main Street');
233
+ parseResult = schema.parse('123 Main Street');
221
234
  deepStrictEqual(parseResult, '123 Main Street');
222
235
  });
223
236
  });
package/dist/select.d.ts CHANGED
@@ -7,6 +7,9 @@ type InferTuple<T extends ZodType<object> | ZodUnion, U extends readonly ZodSele
7
7
  };
8
8
  export type InferType<T extends ZodType<object> | ZodUnion, U extends ZodSelect<T>> = U extends ZodType<object> ? z.infer<U> : U extends ZodUnion ? z.infer<U> : T extends ZodUnion ? (U extends RefineZodUnion<T> ? z.infer<RefinedUnionSchema<T, U>> : z.infer<T>) : T extends ZodType<object> ? (U extends RefineObject<z.infer<T>, false> ? z.infer<RefinedTypeSchema<z.infer<T>, U>> : z.infer<T>) : z.infer<T>;
9
9
  export type MergeSelect<T extends ZodType<object> | ZodUnion, TSelect1 extends ZodSelect<T>, TSelect2 extends MultiSelect<T>> = TSelect2 extends undefined ? [TSelect1, T] : IsEqual<TSelect2, T, TSelect1, TSelect2 extends [ZodSelect<T>, ...ZodSelect<T>[]] ? [TSelect1, ...TSelect2] : [TSelect1, TSelect2]>;
10
- export type MultiSelect<T extends ZodType<object> | ZodUnion> = [ZodSelect<T>, ...ZodSelect<T>[]] | undefined | ZodSelect<T>;
11
- export type ZodSelect<T extends ZodTuple | ZodType<object> | ZodUnion, TIsSimple extends boolean = false> = (T extends ZodUnion ? (RefineZodUnion<T> | ZodUnion) : T extends ZodTuple ? (RefineZodTuple<T> | ZodTuple) : T extends ZodType<object> ? (RefineObject<z.infer<T>, TIsSimple> | ZodType<object>) : never);
10
+ export type MultiSelect<T extends ZodType<object> | ZodUnion> = [
11
+ ZodSelect<T>,
12
+ ...ZodSelect<T>[]
13
+ ] | undefined | ZodSelect<T>;
14
+ export type ZodSelect<T extends ZodTuple | ZodType<object> | ZodUnion, TIsSimple extends boolean = false> = (T extends ZodUnion ? (RefineZodUnion<T> | (TIsSimple extends true ? never : ZodUnion)) : T extends ZodTuple ? (RefineZodTuple<T> | (TIsSimple extends true ? never : ZodTuple)) : T extends ZodType<object> ? (RefineObject<z.infer<T>, TIsSimple> | (TIsSimple extends true ? never : ZodType<object>)) : never);
12
15
  export {};
@@ -30,8 +30,8 @@ describe('.utilities()', () => {
30
30
  assert.strictEqual(inner.def.type, 'string');
31
31
  });
32
32
  it('should unwrap lazy inside nested wrappers', () => {
33
- const LazySchema = z.lazy(() => z.string());
34
- const wrapped = LazySchema.optional().nullable().default('abc');
33
+ const lazySchema = z.lazy(() => z.string());
34
+ const wrapped = lazySchema.optional().nullable().default('abc');
35
35
  const inner = getInnerType(wrapped);
36
36
  assert.strictEqual(inner.def.type, 'string');
37
37
  });
@@ -56,20 +56,20 @@ describe('.utilities()', () => {
56
56
  });
57
57
  it('isZodRecord detects complex record schemas with optional fields', () => {
58
58
  // Create a sample RecordAttachmentSchema
59
- const RecordAttachmentSchema = z.object({
59
+ const recordAttachmentSchema = z.object({
60
60
  name: z.string(),
61
61
  size: z.number(),
62
62
  type: z.string()
63
63
  });
64
64
  // Create a record schema with optional field
65
- const attachmentsSchema = z.record(z.string(), RecordAttachmentSchema).optional();
65
+ const attachmentsSchema = z.record(z.string(), recordAttachmentSchema).optional();
66
66
  const nonRecordSchema = z.object({ field: z.string() });
67
67
  // Test record detection
68
- assert.ok(isZodRecord(z.record(z.string(), RecordAttachmentSchema)), 'Should detect record schema');
68
+ assert.ok(isZodRecord(z.record(z.string(), recordAttachmentSchema)), 'Should detect record schema');
69
69
  assert.ok(isZodRecord(attachmentsSchema.unwrap()), 'Should detect optional record schema when unwrapped');
70
70
  assert.ok(!isZodRecord(nonRecordSchema), 'Should not detect object schema as record');
71
71
  // Test with actual record data
72
- const validRecord = z.record(z.string(), RecordAttachmentSchema).parse({
72
+ const validRecord = z.record(z.string(), recordAttachmentSchema).parse({
73
73
  'file1': { name: 'test.pdf', size: 1024, type: 'application/pdf' },
74
74
  'file2': { name: 'image.jpg', size: 2048, type: 'image/jpeg' }
75
75
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zodselect",
3
- "version": "1.0.8",
3
+ "version": "1.0.10",
4
4
  "description": "Type-safe selection utility built on top of Zod. Allows for strongly typed field selection, schema merging, and runtime refinement for frontend or backend use.",
5
5
  "author": "SecureDataSystems",
6
6
  "license": "MIT",
@@ -25,21 +25,22 @@
25
25
  }
26
26
  },
27
27
  "devDependencies": {
28
- "@secure-data-systems/eslint-config": "^1.0.26",
29
- "@secure-data-systems/tsconfig": "^1.0.2",
30
- "@types/node": "^24.10.1",
31
- "glob": "^11.0.3",
32
- "tsx": "^4.20.6",
28
+ "@secure-data-systems/eslint-config": "^1.0.33",
29
+ "@secure-data-systems/tsconfig": "^1.0.3",
30
+ "@types/node": "^25.3.0",
31
+ "tsx": "^4.21.0",
33
32
  "typescript": "^5.9.3"
34
33
  },
35
34
  "dependencies": {
36
- "zod": "^4.1.12"
35
+ "zod": "^4.3.6"
37
36
  },
38
37
  "scripts": {
39
38
  "build": "node scripts/build.mjs && tsc --project tsconfig.build.json",
39
+ "clean": "node scripts/clean.mjs",
40
40
  "deploy": "npm run build && node ./scripts/publish.mjs",
41
41
  "lint": "eslint . --c eslint.config.mjs",
42
42
  "lint:fix": "eslint . --c eslint.config.mjs --fix",
43
- "test": "glob -c \"tsx --tsconfig ./tsconfig.build.json --test\" \"./src/**/*.{spec,test}.ts\""
43
+ "prune": "node scripts/prune.mjs",
44
+ "test": "tsx --tsconfig ./tsconfig.build.json --test ./src/**/*.{spec,test}.ts ./test/**/*.{spec,test}.ts"
44
45
  }
45
46
  }