bupkis 0.1.2 → 0.3.0

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.
Files changed (198) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +16 -16
  3. package/dist/commonjs/assertion/assertion-async.d.ts +2 -1
  4. package/dist/commonjs/assertion/assertion-async.d.ts.map +1 -1
  5. package/dist/commonjs/assertion/assertion-async.js +84 -2
  6. package/dist/commonjs/assertion/assertion-async.js.map +1 -1
  7. package/dist/commonjs/assertion/assertion-sync.d.ts +1 -1
  8. package/dist/commonjs/assertion/assertion-sync.d.ts.map +1 -1
  9. package/dist/commonjs/assertion/assertion-sync.js +5 -1
  10. package/dist/commonjs/assertion/assertion-sync.js.map +1 -1
  11. package/dist/commonjs/assertion/assertion-types.d.ts +39 -84
  12. package/dist/commonjs/assertion/assertion-types.d.ts.map +1 -1
  13. package/dist/commonjs/assertion/assertion.d.ts +1 -1
  14. package/dist/commonjs/assertion/assertion.d.ts.map +1 -1
  15. package/dist/commonjs/assertion/assertion.js +1 -14
  16. package/dist/commonjs/assertion/assertion.js.map +1 -1
  17. package/dist/commonjs/assertion/create.d.ts +5 -33
  18. package/dist/commonjs/assertion/create.d.ts.map +1 -1
  19. package/dist/commonjs/assertion/create.js +17 -6
  20. package/dist/commonjs/assertion/create.js.map +1 -1
  21. package/dist/commonjs/assertion/impl/async.d.ts +122 -21
  22. package/dist/commonjs/assertion/impl/async.d.ts.map +1 -1
  23. package/dist/commonjs/assertion/impl/async.js +114 -90
  24. package/dist/commonjs/assertion/impl/async.js.map +1 -1
  25. package/dist/commonjs/assertion/impl/callback.d.ts +104 -0
  26. package/dist/commonjs/assertion/impl/callback.d.ts.map +1 -0
  27. package/dist/commonjs/assertion/impl/callback.js +694 -0
  28. package/dist/commonjs/assertion/impl/callback.js.map +1 -0
  29. package/dist/commonjs/assertion/impl/index.d.ts +1 -1
  30. package/dist/commonjs/assertion/impl/index.d.ts.map +1 -1
  31. package/dist/commonjs/assertion/impl/index.js.map +1 -1
  32. package/dist/commonjs/assertion/impl/sync-esoteric.js +1 -1
  33. package/dist/commonjs/assertion/impl/sync-esoteric.js.map +1 -1
  34. package/dist/commonjs/assertion/impl/sync-parametric.d.ts +37 -34
  35. package/dist/commonjs/assertion/impl/sync-parametric.d.ts.map +1 -1
  36. package/dist/commonjs/assertion/impl/sync-parametric.js +32 -47
  37. package/dist/commonjs/assertion/impl/sync-parametric.js.map +1 -1
  38. package/dist/commonjs/assertion/impl/sync.d.ts +105 -58
  39. package/dist/commonjs/assertion/impl/sync.d.ts.map +1 -1
  40. package/dist/commonjs/assertion/impl/sync.js +4 -1
  41. package/dist/commonjs/assertion/impl/sync.js.map +1 -1
  42. package/dist/commonjs/bootstrap.d.ts +199 -85
  43. package/dist/commonjs/bootstrap.d.ts.map +1 -1
  44. package/dist/commonjs/bootstrap.js +19 -10
  45. package/dist/commonjs/bootstrap.js.map +1 -1
  46. package/dist/commonjs/constant.js +7 -1
  47. package/dist/commonjs/constant.js.map +1 -1
  48. package/dist/commonjs/error.d.ts +32 -5
  49. package/dist/commonjs/error.d.ts.map +1 -1
  50. package/dist/commonjs/error.js +60 -5
  51. package/dist/commonjs/error.js.map +1 -1
  52. package/dist/commonjs/expect.d.ts +130 -3
  53. package/dist/commonjs/expect.d.ts.map +1 -1
  54. package/dist/commonjs/expect.js +116 -1
  55. package/dist/commonjs/expect.js.map +1 -1
  56. package/dist/commonjs/guards.d.ts +45 -20
  57. package/dist/commonjs/guards.d.ts.map +1 -1
  58. package/dist/commonjs/guards.js +56 -40
  59. package/dist/commonjs/guards.js.map +1 -1
  60. package/dist/commonjs/index.d.ts +241 -86
  61. package/dist/commonjs/index.d.ts.map +1 -1
  62. package/dist/commonjs/index.js +44 -42
  63. package/dist/commonjs/index.js.map +1 -1
  64. package/dist/commonjs/metadata.d.ts +1 -27
  65. package/dist/commonjs/metadata.d.ts.map +1 -1
  66. package/dist/commonjs/metadata.js +16 -15
  67. package/dist/commonjs/metadata.js.map +1 -1
  68. package/dist/commonjs/schema.d.ts +76 -33
  69. package/dist/commonjs/schema.d.ts.map +1 -1
  70. package/dist/commonjs/schema.js +77 -34
  71. package/dist/commonjs/schema.js.map +1 -1
  72. package/dist/commonjs/types.d.ts +480 -39
  73. package/dist/commonjs/types.d.ts.map +1 -1
  74. package/dist/commonjs/types.js +12 -2
  75. package/dist/commonjs/types.js.map +1 -1
  76. package/dist/commonjs/util.d.ts +72 -49
  77. package/dist/commonjs/util.d.ts.map +1 -1
  78. package/dist/commonjs/util.js +175 -155
  79. package/dist/commonjs/util.js.map +1 -1
  80. package/dist/commonjs/value-to-schema.d.ts +122 -0
  81. package/dist/commonjs/value-to-schema.d.ts.map +1 -0
  82. package/dist/commonjs/value-to-schema.js +309 -0
  83. package/dist/commonjs/value-to-schema.js.map +1 -0
  84. package/dist/esm/assertion/assertion-async.d.ts +2 -1
  85. package/dist/esm/assertion/assertion-async.d.ts.map +1 -1
  86. package/dist/esm/assertion/assertion-async.js +85 -3
  87. package/dist/esm/assertion/assertion-async.js.map +1 -1
  88. package/dist/esm/assertion/assertion-sync.d.ts +1 -1
  89. package/dist/esm/assertion/assertion-sync.d.ts.map +1 -1
  90. package/dist/esm/assertion/assertion-sync.js +6 -2
  91. package/dist/esm/assertion/assertion-sync.js.map +1 -1
  92. package/dist/esm/assertion/assertion-types.d.ts +39 -84
  93. package/dist/esm/assertion/assertion-types.d.ts.map +1 -1
  94. package/dist/esm/assertion/assertion.d.ts +1 -1
  95. package/dist/esm/assertion/assertion.d.ts.map +1 -1
  96. package/dist/esm/assertion/assertion.js +1 -14
  97. package/dist/esm/assertion/assertion.js.map +1 -1
  98. package/dist/esm/assertion/create.d.ts +5 -33
  99. package/dist/esm/assertion/create.d.ts.map +1 -1
  100. package/dist/esm/assertion/create.js +14 -4
  101. package/dist/esm/assertion/create.js.map +1 -1
  102. package/dist/esm/assertion/impl/async.d.ts +122 -21
  103. package/dist/esm/assertion/impl/async.d.ts.map +1 -1
  104. package/dist/esm/assertion/impl/async.js +113 -89
  105. package/dist/esm/assertion/impl/async.js.map +1 -1
  106. package/dist/esm/assertion/impl/callback.d.ts +104 -0
  107. package/dist/esm/assertion/impl/callback.d.ts.map +1 -0
  108. package/dist/esm/assertion/impl/callback.js +691 -0
  109. package/dist/esm/assertion/impl/callback.js.map +1 -0
  110. package/dist/esm/assertion/impl/index.d.ts +1 -1
  111. package/dist/esm/assertion/impl/index.d.ts.map +1 -1
  112. package/dist/esm/assertion/impl/index.js +1 -1
  113. package/dist/esm/assertion/impl/index.js.map +1 -1
  114. package/dist/esm/assertion/impl/sync-esoteric.js +2 -2
  115. package/dist/esm/assertion/impl/sync-esoteric.js.map +1 -1
  116. package/dist/esm/assertion/impl/sync-parametric.d.ts +37 -34
  117. package/dist/esm/assertion/impl/sync-parametric.d.ts.map +1 -1
  118. package/dist/esm/assertion/impl/sync-parametric.js +32 -47
  119. package/dist/esm/assertion/impl/sync-parametric.js.map +1 -1
  120. package/dist/esm/assertion/impl/sync.d.ts +105 -58
  121. package/dist/esm/assertion/impl/sync.d.ts.map +1 -1
  122. package/dist/esm/assertion/impl/sync.js +3 -1
  123. package/dist/esm/assertion/impl/sync.js.map +1 -1
  124. package/dist/esm/bootstrap.d.ts +199 -85
  125. package/dist/esm/bootstrap.d.ts.map +1 -1
  126. package/dist/esm/bootstrap.js +19 -10
  127. package/dist/esm/bootstrap.js.map +1 -1
  128. package/dist/esm/constant.js +6 -0
  129. package/dist/esm/constant.js.map +1 -1
  130. package/dist/esm/error.d.ts +32 -5
  131. package/dist/esm/error.d.ts.map +1 -1
  132. package/dist/esm/error.js +59 -5
  133. package/dist/esm/error.js.map +1 -1
  134. package/dist/esm/expect.d.ts +130 -3
  135. package/dist/esm/expect.d.ts.map +1 -1
  136. package/dist/esm/expect.js +117 -2
  137. package/dist/esm/expect.js.map +1 -1
  138. package/dist/esm/guards.d.ts +45 -20
  139. package/dist/esm/guards.d.ts.map +1 -1
  140. package/dist/esm/guards.js +48 -31
  141. package/dist/esm/guards.js.map +1 -1
  142. package/dist/esm/index.d.ts +241 -86
  143. package/dist/esm/index.d.ts.map +1 -1
  144. package/dist/esm/index.js +46 -7
  145. package/dist/esm/index.js.map +1 -1
  146. package/dist/esm/metadata.d.ts +1 -27
  147. package/dist/esm/metadata.d.ts.map +1 -1
  148. package/dist/esm/metadata.js +2 -1
  149. package/dist/esm/metadata.js.map +1 -1
  150. package/dist/esm/schema.d.ts +76 -33
  151. package/dist/esm/schema.d.ts.map +1 -1
  152. package/dist/esm/schema.js +77 -34
  153. package/dist/esm/schema.js.map +1 -1
  154. package/dist/esm/types.d.ts +480 -39
  155. package/dist/esm/types.d.ts.map +1 -1
  156. package/dist/esm/types.js +12 -2
  157. package/dist/esm/types.js.map +1 -1
  158. package/dist/esm/util.d.ts +72 -49
  159. package/dist/esm/util.d.ts.map +1 -1
  160. package/dist/esm/util.js +159 -153
  161. package/dist/esm/util.js.map +1 -1
  162. package/dist/esm/value-to-schema.d.ts +122 -0
  163. package/dist/esm/value-to-schema.d.ts.map +1 -0
  164. package/dist/esm/value-to-schema.js +305 -0
  165. package/dist/esm/value-to-schema.js.map +1 -0
  166. package/package.json +94 -17
  167. package/src/assertion/assertion-async.ts +113 -3
  168. package/src/assertion/assertion-sync.ts +5 -2
  169. package/src/assertion/assertion-types.ts +52 -45
  170. package/src/assertion/assertion.ts +2 -17
  171. package/src/assertion/create.ts +16 -65
  172. package/src/assertion/impl/async.ts +132 -92
  173. package/src/assertion/impl/callback.ts +882 -0
  174. package/src/assertion/impl/index.ts +1 -1
  175. package/src/assertion/impl/sync-esoteric.ts +2 -2
  176. package/src/assertion/impl/sync-parametric.ts +41 -49
  177. package/src/assertion/impl/sync.ts +3 -0
  178. package/src/bootstrap.ts +21 -11
  179. package/src/constant.ts +8 -0
  180. package/src/error.ts +75 -4
  181. package/src/expect.ts +275 -20
  182. package/src/guards.ts +74 -69
  183. package/src/index.ts +72 -11
  184. package/src/metadata.ts +3 -4
  185. package/src/schema.ts +80 -36
  186. package/src/types.ts +625 -72
  187. package/src/util.ts +174 -222
  188. package/src/value-to-schema.ts +464 -0
  189. package/dist/commonjs/api.d.ts +0 -93
  190. package/dist/commonjs/api.d.ts.map +0 -1
  191. package/dist/commonjs/api.js +0 -8
  192. package/dist/commonjs/api.js.map +0 -1
  193. package/dist/esm/api.d.ts +0 -93
  194. package/dist/esm/api.d.ts.map +0 -1
  195. package/dist/esm/api.js +0 -7
  196. package/dist/esm/api.js.map +0 -1
  197. package/src/api.ts +0 -149
  198. package/src/schema.md +0 -15
@@ -0,0 +1,305 @@
1
+ import { z } from 'zod/v4';
2
+ import { isNonNullObject, isObject, isPromiseLike, isString, isZodType, } from './guards.js';
3
+ import { RegExpSchema, StrongMapSchema, StrongSetSchema, WrappedPromiseLikeSchema, } from './schema.js';
4
+ /**
5
+ * Recursively converts an arbitrary value to a Zod v4 schema that would
6
+ * validate values with the same structure.
7
+ *
8
+ * This function analyzes the runtime value and generates a corresponding Zod
9
+ * schema that captures the value's structure and type information. It handles
10
+ * primitives, objects, arrays, functions, and various built-in types, with
11
+ * support for circular reference detection.
12
+ *
13
+ * @example
14
+ *
15
+ * ```typescript
16
+ * // Primitive types
17
+ * valueToSchema('hello'); // z.string()
18
+ * valueToSchema(42); // z.number()
19
+ * valueToSchema(true); // z.boolean()
20
+ *
21
+ * // Objects
22
+ * valueToSchema({ name: 'John', age: 30 });
23
+ * // z.object({ name: z.string(), age: z.number() })
24
+ *
25
+ * // Arrays
26
+ * valueToSchema(['a', 'b', 'c']); // z.array(z.string())
27
+ * valueToSchema([1, 'mixed']); // z.array(z.union([z.number(), z.string()]))
28
+ *
29
+ * // Nested structures
30
+ * valueToSchema({ users: [{ name: 'John' }] });
31
+ * // z.object({ users: z.array(z.object({ name: z.string() })) })
32
+ * ```
33
+ *
34
+ * @param value - The value to convert to a schema
35
+ * @param options - Configuration options for schema generation
36
+ * @param visited - Internal WeakSet for circular reference detection
37
+ * @returns A Zod schema that validates values matching the input's structure.
38
+ * This value is unfortunately untyped due to the complexity involved. But the
39
+ * schema works!
40
+ */
41
+ export const valueToSchema = (value, options = {}, visited = new WeakSet()) => {
42
+ const { _currentDepth = 0, literalEmptyObjects = false, literalPrimitives = false, literalRegExp = false, literalTuples = false, maxDepth = 10, noMixedArrays = false, strict = false, } = options;
43
+ // Prevent infinite recursion
44
+ if (_currentDepth >= maxDepth) {
45
+ return z.unknown();
46
+ }
47
+ // Handle primitives
48
+ if (value === null) {
49
+ return z.null();
50
+ }
51
+ if (value === undefined) {
52
+ return literalPrimitives
53
+ ? z.custom((val) => val === undefined, {
54
+ message: 'Expected undefined',
55
+ })
56
+ : z.undefined();
57
+ }
58
+ if (Number.isNaN(value)) {
59
+ return z.nan();
60
+ }
61
+ if (value === Infinity || value === -Infinity) {
62
+ return z.literal(value);
63
+ }
64
+ const valueType = typeof value;
65
+ switch (valueType) {
66
+ case 'bigint':
67
+ return literalPrimitives ? z.literal(value) : z.bigint();
68
+ case 'boolean':
69
+ return literalPrimitives ? z.literal(value) : z.boolean();
70
+ case 'function':
71
+ return z.function();
72
+ case 'number':
73
+ return literalPrimitives ? z.literal(value) : z.number();
74
+ case 'string':
75
+ return literalPrimitives ? z.literal(value) : z.string();
76
+ case 'symbol':
77
+ return z.symbol();
78
+ }
79
+ // Handle objects
80
+ if (typeof value === 'object' && value !== null) {
81
+ // Check for circular references
82
+ if (visited.has(value)) {
83
+ // Return a recursive schema reference or unknown for circular refs
84
+ return z.unknown();
85
+ }
86
+ visited.add(value);
87
+ try {
88
+ // Check for objects with own __proto__ property - these can cause unexpected behavior
89
+ if (Object.hasOwn(value, '__proto__')) {
90
+ throw new TypeError('Objects with an own "__proto__" property are not supported by valueToSchema');
91
+ }
92
+ // Handle built-in object types
93
+ if (value instanceof Date) {
94
+ // Check if it's a valid date
95
+ if (isNaN(value.getTime())) {
96
+ // For invalid dates, use a literal or custom validator
97
+ return z.custom((val) => val instanceof Date && isNaN(val.getTime()), {
98
+ message: 'Expected an invalid Date',
99
+ });
100
+ }
101
+ return z.date();
102
+ }
103
+ if (value instanceof RegExp) {
104
+ if (literalRegExp) {
105
+ return RegExpSchema;
106
+ }
107
+ return z.coerce.string().regex(value);
108
+ }
109
+ if (value instanceof Map) {
110
+ return StrongMapSchema;
111
+ }
112
+ if (value instanceof Set) {
113
+ return StrongSetSchema;
114
+ }
115
+ if (value instanceof WeakMap) {
116
+ return z.instanceof(WeakMap);
117
+ }
118
+ if (value instanceof WeakSet) {
119
+ return z.instanceof(WeakSet);
120
+ }
121
+ if (value instanceof Error) {
122
+ return z.instanceof(Error);
123
+ }
124
+ if (isPromiseLike(value)) {
125
+ return WrappedPromiseLikeSchema;
126
+ }
127
+ // Handle arrays
128
+ if (Array.isArray(value)) {
129
+ // For arrays, we need to preserve undefined values while allowing
130
+ // other elements to use the original literalPrimitives setting
131
+ const filteredValue = value; // Always process all elements
132
+ if (filteredValue.length === 0) {
133
+ // For empty arrays, use z.tuple() if literalTuples is enabled
134
+ if (literalTuples) {
135
+ return z.tuple([]);
136
+ }
137
+ return z.array(z.never());
138
+ }
139
+ const elementSchemas = filteredValue.map((item) => {
140
+ // Use literal mode for undefined values to preserve them exactly,
141
+ // but use the original setting for other values
142
+ const itemLiteralPrimitives = item === undefined ? true : literalPrimitives;
143
+ return valueToSchema(item, {
144
+ ...options,
145
+ _currentDepth: _currentDepth + 1,
146
+ literalPrimitives: itemLiteralPrimitives,
147
+ }, visited);
148
+ });
149
+ // Use z.tuple() if literalTuples is enabled
150
+ if (literalTuples) {
151
+ return z.tuple(elementSchemas);
152
+ }
153
+ if (!noMixedArrays) {
154
+ // Helper function to generate structural keys for schemas
155
+ const getSchemaKey = (zodType) => {
156
+ const schema = zodType;
157
+ if (isZodType(schema, 'literal')) {
158
+ return `${schema.constructor.name}:${String(schema.def.values)}`;
159
+ }
160
+ if (isZodType(schema, 'array')) {
161
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
162
+ const elementKey = getSchemaKey(schema.def.element);
163
+ return `ZodArray<${elementKey}>`;
164
+ }
165
+ if (isZodType(schema, 'object')) {
166
+ // For objects, create a key based on the property keys and their types
167
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
168
+ const shape = schema.def.shape;
169
+ const shapeKeys = Object.keys(shape)
170
+ .sort()
171
+ .map((key) => {
172
+ const propSchema = shape[key];
173
+ return `${key}:${getSchemaKey(propSchema)}`;
174
+ });
175
+ return `ZodObject<{${shapeKeys.join(',')}}>`;
176
+ }
177
+ if (isZodType(schema, 'union')) {
178
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
179
+ const optionKeys = schema.def.options
180
+ .map((option) => getSchemaKey(option))
181
+ .sort();
182
+ return `ZodUnion<[${optionKeys.join(',')}]>`;
183
+ }
184
+ // For other types, use the constructor name
185
+ return schema.constructor.name;
186
+ };
187
+ const seenSchemaKeys = new Set();
188
+ const uniqueSchemas = [];
189
+ for (const schema of elementSchemas) {
190
+ const schemaKey = getSchemaKey(schema);
191
+ if (!seenSchemaKeys.has(schemaKey)) {
192
+ seenSchemaKeys.add(schemaKey);
193
+ uniqueSchemas.push(schema);
194
+ }
195
+ }
196
+ if (uniqueSchemas.length === 1) {
197
+ return z.array(uniqueSchemas[0]);
198
+ }
199
+ else {
200
+ return z.array(z.union(uniqueSchemas));
201
+ }
202
+ }
203
+ else {
204
+ // Use the first element's schema for all elements
205
+ return z.array(elementSchemas[0]);
206
+ }
207
+ }
208
+ // Handle plain objects
209
+ if (isNonNullObject(value)) {
210
+ const schemaShape = {};
211
+ const undefinedKeys = [];
212
+ for (const [key, val] of Object.entries(value)) {
213
+ if (isString(key)) {
214
+ // Skip undefined values unless we're in literalPrimitives mode
215
+ // This prevents objects with only undefined values from matching any object
216
+ if (val === undefined && !literalPrimitives) {
217
+ continue;
218
+ }
219
+ if (val === undefined && literalPrimitives) {
220
+ // Track keys that should have undefined values
221
+ undefinedKeys.push(key);
222
+ schemaShape[key] = z.undefined();
223
+ }
224
+ else {
225
+ schemaShape[key] = valueToSchema(val, {
226
+ ...options,
227
+ _currentDepth: _currentDepth + 1,
228
+ }, visited);
229
+ }
230
+ }
231
+ }
232
+ // Create the base object schema
233
+ const baseSchema = strict
234
+ ? z.strictObject(schemaShape)
235
+ : z.looseObject(schemaShape);
236
+ // If we have undefined keys in literalPrimitives mode, add validation to ensure they exist
237
+ if (undefinedKeys.length > 0 && literalPrimitives) {
238
+ return baseSchema.superRefine((data, ctx) => {
239
+ if (typeof data !== 'object' || data === null) {
240
+ ctx.addIssue({
241
+ code: z.ZodIssueCode.custom,
242
+ message: 'Expected an object',
243
+ });
244
+ return;
245
+ }
246
+ const obj = data;
247
+ for (const key of undefinedKeys) {
248
+ if (!Object.hasOwn(obj, key)) {
249
+ ctx.addIssue({
250
+ code: z.ZodIssueCode.custom,
251
+ message: `Expected property "${key}" to exist with value undefined`,
252
+ path: [key],
253
+ });
254
+ }
255
+ }
256
+ });
257
+ }
258
+ // Check if this is an empty object and literalEmptyObjects is enabled
259
+ if (Object.keys(schemaShape).length === 0 && literalEmptyObjects) {
260
+ // Create a schema that only matches empty objects
261
+ return z.custom((val) => isObject(val) && Object.keys(val).length === 0, {
262
+ message: 'Expected an empty object with no own properties',
263
+ });
264
+ }
265
+ return baseSchema;
266
+ }
267
+ // Handle other object types (ArrayBuffer, etc.)
268
+ return z.custom((val) => typeof val === 'object' && val !== null, { message: 'Expected an object' });
269
+ }
270
+ finally {
271
+ visited.delete(value);
272
+ }
273
+ }
274
+ // Fallback for unknown types
275
+ return z.unknown();
276
+ };
277
+ /**
278
+ * Predefined options for {@link valueToSchema} optimized for object satisfaction
279
+ * checks.
280
+ *
281
+ * Uses literal primitives and tuples for exact matching while allowing extra
282
+ * properties.
283
+ */
284
+ export const valueToSchemaOptionsForSatisfies = Object.freeze({
285
+ literalEmptyObjects: true,
286
+ literalPrimitives: true,
287
+ literalRegExp: false,
288
+ literalTuples: true,
289
+ strict: false,
290
+ });
291
+ /**
292
+ * Predefined options for {@link valueToSchema} optimized for deep equality
293
+ * checks.
294
+ *
295
+ * Uses literal primitives, regexp, and tuples with strict validation for exact
296
+ * matching.
297
+ */
298
+ export const valueToSchemaOptionsForDeepEqual = Object.freeze({
299
+ literalEmptyObjects: true,
300
+ literalPrimitives: true,
301
+ literalRegExp: true,
302
+ literalTuples: true,
303
+ strict: true,
304
+ });
305
+ //# sourceMappingURL=value-to-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value-to-schema.js","sourceRoot":"","sources":["../../src/value-to-schema.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bupkis",
3
- "version": "0.1.2",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Uncommonly extensible assertions for the beautiful people",
6
6
  "repository": {
@@ -20,6 +20,56 @@
20
20
  "module": "./dist/esm/index.js",
21
21
  "exports": {
22
22
  "./package.json": "./package.json",
23
+ "./types": {
24
+ "import": {
25
+ "types": "./dist/esm/types.d.ts",
26
+ "default": "./dist/esm/types.js"
27
+ },
28
+ "require": {
29
+ "types": "./dist/commonjs/types.d.ts",
30
+ "default": "./dist/commonjs/types.js"
31
+ }
32
+ },
33
+ "./util": {
34
+ "import": {
35
+ "types": "./dist/esm/util.d.ts",
36
+ "default": "./dist/esm/util.js"
37
+ },
38
+ "require": {
39
+ "types": "./dist/commonjs/util.d.ts",
40
+ "default": "./dist/commonjs/util.js"
41
+ }
42
+ },
43
+ "./schema": {
44
+ "import": {
45
+ "types": "./dist/esm/schema.d.ts",
46
+ "default": "./dist/esm/schema.js"
47
+ },
48
+ "require": {
49
+ "types": "./dist/commonjs/schema.d.ts",
50
+ "default": "./dist/commonjs/schema.js"
51
+ }
52
+ },
53
+ "./guards": {
54
+ "import": {
55
+ "types": "./dist/esm/guards.d.ts",
56
+ "default": "./dist/esm/guards.js"
57
+ },
58
+ "require": {
59
+ "types": "./dist/commonjs/guards.d.ts",
60
+ "default": "./dist/commonjs/guards.js"
61
+ }
62
+ },
63
+ "./assertions": {
64
+ "import": {
65
+ "types": "./dist/esm/assertion/index.d.ts",
66
+ "default": "./dist/esm/assertion/index.js"
67
+ },
68
+ "require": {
69
+ "types": "./dist/commonjs/assertion/index.d.ts",
70
+ "default": "./dist/commonjs/assertion/index.js"
71
+ }
72
+ },
23
73
  ".": {
24
74
  "import": {
25
75
  "types": "./dist/esm/index.d.ts",
@@ -57,27 +107,30 @@
57
107
  ],
58
108
  "scripts": {
59
109
  "build": "tshy",
60
- "build:docs": "typedoc",
61
- "build:docs:watch": "npm run --silent build:docs -- --watch",
62
- "dev": "tshy --watch",
63
- "dev:docs": "run-p build:docs:watch serve",
64
- "lint": "run-p lint:eslint lint:types lint:knip",
110
+ "build:dev": "tshy --watch",
111
+ "build:docs": "typedoc --cleanOutputDir --treatWarningsAsErrors",
112
+ "build:docs:dev": "run-s \"build:docs -- --watch\"",
113
+ "docs:dev": "run-p build:docs:dev serve",
114
+ "lint": "run-p lint:eslint lint:types lint:knip lint:markdown lint:spelling",
65
115
  "lint:commit": "commitlint",
66
116
  "lint:eslint": "eslint .",
67
117
  "lint:fix": "run-s \"lint:eslint -- --fix\"",
68
118
  "lint:knip": "knip",
69
119
  "lint:markdown": "markdownlint-cli2 \"**/*.md\"",
120
+ "lint:spelling": "cspell \"**\"",
70
121
  "lint:staged": "lint-staged",
71
122
  "lint:types": "tsc -b .config/tsconfig.eslint.json",
72
- "lint:types:dev": "npm run --silent lint:types -- --watch",
123
+ "lint:types:dev": "run-s \"lint:types -- --watch\"",
73
124
  "prepare": "husky; run-s build",
74
125
  "prepublishOnly": "run-s build",
75
126
  "serve": "serve docs",
76
- "test": "node --import tsx --test \"test/**/*.ts\"",
77
- "test:profile": "node --cpu-prof --cpu-prof-dir=.profiles --test --import tsx \"test/**/*.ts\"",
78
- "test:property": "node --import tsx --test \"test/property/**/*.test.ts\"",
79
- "test:property:dev": "node --import tsx --test --watch \"test/property/**/*.test.ts\"",
80
- "test:watch": "node --import tsx --test \"test/**/*.ts\" --watch"
127
+ "test": "run-s \"test:base -- test/**/*.test.ts\"",
128
+ "test:base": "node --test --test-reporter=spec --import tsx",
129
+ "test:coverage": "c8 --reporter=lcov --reporter=text npm test",
130
+ "test:dev": "node --test --import tsx --watch --test-reporter=spec \"test/**/*.test.ts\"",
131
+ "test:profile": "node --cpu-prof --cpu-prof-dir=.profiles --test --import tsx --test-reporter=spec \"test/**/*.test.ts\"",
132
+ "test:property": "node --test --import tsx --test-reporter=spec \"test/property/*.test.ts\"",
133
+ "test:property:dev": "node --test --import tsx --test-reporter=spec --watch \"test/property/*.test.ts\""
81
134
  },
82
135
  "peerDependencies": {
83
136
  "zod": "^4.1.5"
@@ -97,6 +150,8 @@
97
150
  "@types/node": "22.18.1",
98
151
  "@types/slug": "5.0.9",
99
152
  "@types/wallabyjs": "0.0.15",
153
+ "c8": "10.1.3",
154
+ "cspell": "9.2.1",
100
155
  "eslint": "9.35.0",
101
156
  "eslint-plugin-jsonc": "2.20.1",
102
157
  "eslint-plugin-perfectionist": "4.15.0",
@@ -118,10 +173,13 @@
118
173
  "tsx": "4.20.5",
119
174
  "type-fest": "4.41.0",
120
175
  "typedoc": "0.28.12",
176
+ "typedoc-plugin-dt-links": "2.0.18",
177
+ "typedoc-plugin-extras": "4.0.1",
121
178
  "typedoc-plugin-mdn-links": "5.0.9",
179
+ "typedoc-plugin-redirect": "1.2.0",
122
180
  "typedoc-plugin-zod": "1.4.2",
123
181
  "typescript": "5.9.2",
124
- "typescript-eslint": "8.42.0"
182
+ "typescript-eslint": "8.43.0"
125
183
  },
126
184
  "publishConfig": {
127
185
  "access": "public",
@@ -136,7 +194,7 @@
136
194
  ".wallaby.js",
137
195
  "**/*.cts",
138
196
  "**/*.d.ts",
139
- "assets/**/*"
197
+ "site/media/**/*"
140
198
  ],
141
199
  "tags": [
142
200
  "-knipignore"
@@ -144,17 +202,26 @@
144
202
  "node": {
145
203
  "entry": [
146
204
  "scripts/*.js",
147
- "test/**/*.test.ts"
205
+ "test/**/*.test.ts",
206
+ "test/types.types-test.ts",
207
+ "src/assertion/index.ts",
208
+ "src/index.ts",
209
+ "src/types.ts",
210
+ "src/util.ts",
211
+ "src/schema.ts",
212
+ "src/guards.ts"
148
213
  ]
149
214
  }
150
215
  },
151
216
  "lint-staged": {
152
217
  "*.{ts,cts,js,json,yml,json5}": [
153
218
  "eslint --fix",
154
- "prettier --write"
219
+ "prettier --write",
220
+ "cspell"
155
221
  ],
156
222
  "**/!(.github/prompts)/*.md": [
157
- "prettier --write"
223
+ "prettier --write",
224
+ "cspell"
158
225
  ]
159
226
  },
160
227
  "prettier": {
@@ -168,9 +235,19 @@
168
235
  "singleQuote": true,
169
236
  "tsdoc": true
170
237
  },
238
+ "testConfig": {
239
+ "test_flags": "--import tsx --test --test-reporter=spec",
240
+ "test_pattern_all": "test/**/*.ts",
241
+ "test_pattern_property": "test/property/**/*.test.ts"
242
+ },
171
243
  "tshy": {
172
244
  "exports": {
173
245
  "./package.json": "./package.json",
246
+ "./types": "./src/types.ts",
247
+ "./util": "./src/util.ts",
248
+ "./schema": "./src/schema.ts",
249
+ "./guards": "./src/guards.ts",
250
+ "./assertions": "./src/assertion/index.ts",
174
251
  ".": "./src/index.ts"
175
252
  }
176
253
  }
@@ -4,7 +4,13 @@ import z from 'zod/v4';
4
4
 
5
5
  import { kStringLiteral } from '../constant.js';
6
6
  import { AssertionError } from '../error.js';
7
- import { isA, isAssertionFailure, isBoolean, isZodType } from '../guards.js';
7
+ import {
8
+ isA,
9
+ isAssertionFailure,
10
+ isBoolean,
11
+ isError,
12
+ isZodType,
13
+ } from '../guards.js';
8
14
  import { BupkisRegistry } from '../metadata.js';
9
15
  import {
10
16
  type AssertionAsync,
@@ -16,6 +22,7 @@ import {
16
22
  type AssertionSchemaAsync,
17
23
  type AssertionSlots,
18
24
  type ParsedResult,
25
+ type ParsedResultSuccess,
19
26
  type ParsedValues,
20
27
  } from './assertion-types.js';
21
28
  import { BupkisAssertion } from './assertion.js';
@@ -133,6 +140,8 @@ export class BupkisAssertionFunctionAsync<
133
140
  expected: result.expected,
134
141
  message: result.message ?? `Assertion ${this} failed`,
135
142
  });
143
+ } else if (isError(result) && result instanceof z.ZodError) {
144
+ throw this.translateZodError(stackStartFn, result, ...parsedValues);
136
145
  } else if (result as unknown) {
137
146
  throw new TypeError(
138
147
  `Invalid return type from assertion ${this}; expected boolean, ZodType, or AssertionFailure`,
@@ -166,9 +175,31 @@ export class BupkisAssertionSchemaAsync<
166
175
  parsedValues: ParsedValues<Parts>,
167
176
  _args: unknown[],
168
177
  stackStartFn: (...args: any[]) => any,
169
- _parseResult?: ParsedResult<Parts>,
178
+ parseResult?: ParsedResult<Parts>,
170
179
  ): Promise<void> {
171
- // For async, fall back to standard implementation for now
180
+ // Check if we have cached validation result from parseValuesAsync
181
+ const cachedValidation = parseResult?.success
182
+ ? parseResult.subjectValidationResult
183
+ : undefined;
184
+
185
+ if (cachedValidation) {
186
+ debug(
187
+ 'Using cached subject validation result from parseValuesAsync for %s',
188
+ this,
189
+ );
190
+ if (!cachedValidation.success) {
191
+ // Subject validation failed during parseValuesAsync, throw the cached error
192
+ throw this.translateZodError(
193
+ stackStartFn,
194
+ cachedValidation.error,
195
+ ...parsedValues,
196
+ );
197
+ }
198
+ // Subject validation passed, nothing more to do
199
+ return;
200
+ }
201
+
202
+ // Fall back to standard validation if no cached result
172
203
  const [subject] = parsedValues;
173
204
  try {
174
205
  await this.impl.parseAsync(subject);
@@ -180,6 +211,85 @@ export class BupkisAssertionSchemaAsync<
180
211
  }
181
212
  }
182
213
 
214
+ override async parseValuesAsync<Args extends readonly unknown[]>(
215
+ args: Args,
216
+ ): Promise<ParsedResult<Parts>> {
217
+ const { slots } = this;
218
+ const parsedValues: any[] = [];
219
+ const mismatch = this.maybeParseValuesArgMismatch(args);
220
+ if (mismatch) {
221
+ return mismatch;
222
+ }
223
+
224
+ let exactMatch = true;
225
+ let subjectValidationResult:
226
+ | undefined
227
+ | { data: any; success: true }
228
+ | { error: z.ZodError; success: false };
229
+
230
+ for (let i = 0; i < slots.length; i++) {
231
+ const slot = slots[i]!;
232
+ const arg = args[i];
233
+ const parsedLiteralResult = this.parseSlotForLiteral(slot, i, arg);
234
+ if (parsedLiteralResult === true) {
235
+ continue;
236
+ } else if (parsedLiteralResult !== false) {
237
+ return parsedLiteralResult;
238
+ }
239
+
240
+ // For the subject slot (first slot if it's unknown/any), try optimized validation
241
+ if (
242
+ i === 0 &&
243
+ (slot.def.type === 'unknown' || slot.def.type === 'any') &&
244
+ this.isSimpleSchemaAssertion()
245
+ ) {
246
+ try {
247
+ const result = await this.impl.parseAsync(arg);
248
+ subjectValidationResult = { data: result, success: true };
249
+ parsedValues.push(result); // Use validated data
250
+ } catch (error) {
251
+ if (isA(error, z.ZodError)) {
252
+ subjectValidationResult = { error, success: false };
253
+ parsedValues.push(arg); // Keep original for error reporting
254
+ } else {
255
+ throw error; // Re-throw non-Zod errors
256
+ }
257
+ }
258
+ exactMatch = false; // Subject was validated, so we know the exact type
259
+ continue;
260
+ }
261
+
262
+ // Standard slot processing for non-optimized cases
263
+ if (slot.def.type === 'unknown' || slot.def.type === 'any') {
264
+ debug('Skipping unknown/any slot validation for arg', arg);
265
+ parsedValues.push(arg);
266
+ exactMatch = false;
267
+ continue;
268
+ }
269
+
270
+ const result = await slot.safeParseAsync(arg);
271
+ if (!result.success) {
272
+ return {
273
+ success: false,
274
+ };
275
+ }
276
+ parsedValues.push(result.data);
277
+ }
278
+
279
+ const result: ParsedResultSuccess<Parts> = {
280
+ exactMatch,
281
+ parsedValues: parsedValues as unknown as ParsedValues<Parts>,
282
+ success: true,
283
+ };
284
+
285
+ // Add cached validation result if we performed optimization
286
+ if (subjectValidationResult) {
287
+ result.subjectValidationResult = subjectValidationResult;
288
+ }
289
+
290
+ return result;
291
+ }
292
+
183
293
  /**
184
294
  * Determines if this assertion can be optimized (simple single-subject
185
295
  * schema). Only simple assertions like ['to be a string'] with z.string()