@synnaxlabs/x 0.54.0 → 0.54.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.
Files changed (64) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/dist/src/binary/codec.d.ts.map +1 -1
  3. package/dist/src/color/color.d.ts +1 -1
  4. package/dist/src/color/palette.d.ts +2 -2
  5. package/dist/src/deep/atKeys.d.ts +27 -0
  6. package/dist/src/deep/atKeys.d.ts.map +1 -0
  7. package/dist/src/deep/atKeys.spec.d.ts +2 -0
  8. package/dist/src/deep/atKeys.spec.d.ts.map +1 -0
  9. package/dist/src/deep/external.d.ts +1 -0
  10. package/dist/src/deep/external.d.ts.map +1 -1
  11. package/dist/src/fmt/external.d.ts +3 -0
  12. package/dist/src/fmt/external.d.ts.map +1 -0
  13. package/dist/src/fmt/index.d.ts +2 -0
  14. package/dist/src/fmt/index.d.ts.map +1 -0
  15. package/dist/src/fmt/path.d.ts +13 -0
  16. package/dist/src/fmt/path.d.ts.map +1 -0
  17. package/dist/src/fmt/path.spec.d.ts +2 -0
  18. package/dist/src/fmt/path.spec.d.ts.map +1 -0
  19. package/dist/src/fmt/value.d.ts +23 -0
  20. package/dist/src/fmt/value.d.ts.map +1 -0
  21. package/dist/src/fmt/value.spec.d.ts +2 -0
  22. package/dist/src/fmt/value.spec.d.ts.map +1 -0
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/label/types.gen.d.ts +2 -2
  26. package/dist/src/narrow/narrow.d.ts +9 -0
  27. package/dist/src/narrow/narrow.d.ts.map +1 -1
  28. package/dist/src/primitive/primitive.d.ts +10 -0
  29. package/dist/src/primitive/primitive.d.ts.map +1 -1
  30. package/dist/src/status/status.d.ts +14 -2
  31. package/dist/src/status/status.d.ts.map +1 -1
  32. package/dist/src/status/types.gen.d.ts +1 -1
  33. package/dist/src/telem/series.d.ts +4 -4
  34. package/dist/src/telem/telem.d.ts +10 -10
  35. package/dist/src/zod/external.d.ts +1 -0
  36. package/dist/src/zod/external.d.ts.map +1 -1
  37. package/dist/src/zod/parse.d.ts +47 -0
  38. package/dist/src/zod/parse.d.ts.map +1 -0
  39. package/dist/src/zod/parse.spec.d.ts +2 -0
  40. package/dist/src/zod/parse.spec.d.ts.map +1 -0
  41. package/dist/x.cjs +16 -7
  42. package/dist/x.js +2190 -1869
  43. package/package.json +3 -3
  44. package/src/binary/codec.ts +3 -2
  45. package/src/deep/atKeys.spec.ts +107 -0
  46. package/src/deep/atKeys.ts +49 -0
  47. package/src/deep/external.ts +1 -0
  48. package/src/fmt/external.ts +11 -0
  49. package/src/fmt/index.ts +10 -0
  50. package/src/fmt/path.spec.ts +46 -0
  51. package/src/fmt/path.ts +30 -0
  52. package/src/fmt/value.spec.ts +206 -0
  53. package/src/fmt/value.ts +83 -0
  54. package/src/index.ts +1 -0
  55. package/src/narrow/narrow.spec.ts +43 -0
  56. package/src/narrow/narrow.ts +15 -0
  57. package/src/primitive/primitive.spec.ts +51 -0
  58. package/src/primitive/primitive.ts +12 -0
  59. package/src/status/status.spec.ts +152 -0
  60. package/src/status/status.ts +67 -19
  61. package/src/zod/external.ts +1 -0
  62. package/src/zod/parse.spec.ts +702 -0
  63. package/src/zod/parse.ts +519 -0
  64. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,519 @@
1
+ // Copyright 2026 Synnax Labs, Inc.
2
+ //
3
+ // Use of this software is governed by the Business Source License included in the file
4
+ // licenses/BSL.txt.
5
+ //
6
+ // As of the Change Date specified in that file, in accordance with the Business Source
7
+ // License, use of this software will be governed by the Apache License, Version 2.0,
8
+ // included in the file licenses/APL.txt.
9
+
10
+ import { type z } from "zod";
11
+
12
+ import { deep } from "@/deep";
13
+ import { errors } from "@/errors";
14
+ import { fmt } from "@/fmt";
15
+ import { primitive } from "@/primitive";
16
+ import { type status } from "@/status";
17
+
18
+ const DEFAULT_LABEL = "value";
19
+ const PARSE_ERROR_TYPE = "zod.parse";
20
+ const MARKER = "✗";
21
+ const MAX_ALIGN_WIDTH = 60;
22
+
23
+ export interface ParseOptions {
24
+ label?: string;
25
+ context?: Record<string, unknown>;
26
+ }
27
+
28
+ // Tight defaults for sibling context values rendered inline in a parent view.
29
+ // Callers can override any individual field via `ParseOptions.formatOptions`; the
30
+ // faithful version of the input lives on `err.input` and in
31
+ // `toStatus().details.input` for callers that need the full structure.
32
+ const DEFAULT_PARENT_VIEW_OPTIONS: fmt.Options = {
33
+ maxStringLength: 60,
34
+ maxArrayLength: 3,
35
+ maxDepth: 3,
36
+ };
37
+
38
+ const parentPath = (path: ReadonlyArray<PropertyKey>): ReadonlyArray<PropertyKey> =>
39
+ path.slice(0, -1);
40
+
41
+ /**
42
+ * Returns a concise "expected X" phrase for a single zod issue. This is the core
43
+ * description used everywhere: in the margin-annotated parent view as the reason
44
+ * text, and as a prefix for the flat root-level form that appends `, received Y`.
45
+ *
46
+ * The `received` value is intentionally NOT part of this phrase; callers that need
47
+ * to show it append it separately depending on whether they have a local value or
48
+ * the root itself is the failing one.
49
+ */
50
+ const describeCore = (issue: z.core.$ZodIssue): string => {
51
+ switch (issue.code) {
52
+ case "invalid_type":
53
+ return `expected ${issue.expected}`;
54
+ case "invalid_value":
55
+ return `expected one of ${JSON.stringify(issue.values)}`;
56
+ case "unrecognized_keys":
57
+ return "unexpected key";
58
+ case "too_small": {
59
+ const op = issue.inclusive === false ? ">" : ">=";
60
+ return `${issue.origin} too small: expected ${op}${issue.minimum}`;
61
+ }
62
+ case "too_big": {
63
+ const op = issue.inclusive === false ? "<" : "<=";
64
+ return `${issue.origin} too large: expected ${op}${issue.maximum}`;
65
+ }
66
+ case "invalid_format":
67
+ return `expected ${issue.format} format`;
68
+ case "not_multiple_of":
69
+ return `expected multiple of ${issue.divisor}`;
70
+ case "custom":
71
+ return issue.message || "custom validation failed";
72
+ default:
73
+ return issue.message;
74
+ }
75
+ };
76
+
77
+ /**
78
+ * A "expected X, received Y" phrase for root-level issues where the whole input is
79
+ * the failing value. Only reached for path-less issues since `expandUnrecognizedKeys`
80
+ * pushes any `unrecognized_keys` issues into the parent-view path before this runs.
81
+ */
82
+ const describeFlat = (
83
+ issue: z.core.$ZodIssue,
84
+ root: unknown,
85
+ options: fmt.Options,
86
+ ): string => {
87
+ const received = JSON.stringify(fmt.value(root, options));
88
+ return `${describeCore(issue)}, received ${received}`;
89
+ };
90
+
91
+ /**
92
+ * Returns the maximum path depth reached by any issue within a list, recursing into
93
+ * nested invalid_union / invalid_key / invalid_element branches. Used to pick the
94
+ * union branch that got furthest before failing, which is usually the variant the
95
+ * caller actually intended.
96
+ */
97
+ const branchDepth = (issues: ReadonlyArray<z.core.$ZodIssue>): number => {
98
+ let max = 0;
99
+ for (const issue of issues) {
100
+ if (issue.path.length > max) max = issue.path.length;
101
+ if (issue.code === "invalid_union" && "errors" in issue)
102
+ for (const branch of issue.errors) {
103
+ const d = branchDepth(branch);
104
+ if (d > max) max = d;
105
+ }
106
+ if (
107
+ (issue.code === "invalid_key" || issue.code === "invalid_element") &&
108
+ "issues" in issue
109
+ ) {
110
+ const d = branchDepth(issue.issues);
111
+ if (d > max) max = d;
112
+ }
113
+ }
114
+ return max;
115
+ };
116
+
117
+ /**
118
+ * Walks a list of zod issues and expands every nested-issue container into its
119
+ * leaves, with the outer path prepended:
120
+ *
121
+ * - `invalid_union` → picks the deepest-reaching branch and flattens it
122
+ * - `invalid_element` → flattens nested issues, prepending the failing element's
123
+ * key as a path segment (so errors point at `record[badKey]` directly)
124
+ * - `invalid_key` → flattens nested issues at the outer path, since the "bad key"
125
+ * has no distinct position in the input
126
+ *
127
+ * The result is a flat list of leaf issues pointing at specific locations in the
128
+ * input.
129
+ */
130
+ const flattenIssues = (
131
+ issues: ReadonlyArray<z.core.$ZodIssue>,
132
+ basePath: ReadonlyArray<PropertyKey> = [],
133
+ ): z.core.$ZodIssue[] => {
134
+ const out: z.core.$ZodIssue[] = [];
135
+ for (const issue of issues) {
136
+ const fullPath = [...basePath, ...issue.path];
137
+ if (
138
+ issue.code === "invalid_union" &&
139
+ "errors" in issue &&
140
+ issue.errors.length > 0
141
+ ) {
142
+ let best = issue.errors[0];
143
+ let bestDepth = branchDepth(best);
144
+ for (let i = 1; i < issue.errors.length; i++) {
145
+ const d = branchDepth(issue.errors[i]);
146
+ if (d > bestDepth) {
147
+ best = issue.errors[i];
148
+ bestDepth = d;
149
+ }
150
+ }
151
+ out.push(...flattenIssues(best, fullPath));
152
+ continue;
153
+ }
154
+ if (
155
+ issue.code === "invalid_element" &&
156
+ "issues" in issue &&
157
+ "key" in issue &&
158
+ (typeof issue.key === "string" || typeof issue.key === "number")
159
+ ) {
160
+ out.push(...flattenIssues(issue.issues, [...fullPath, issue.key]));
161
+ continue;
162
+ }
163
+ if (issue.code === "invalid_key" && "issues" in issue) {
164
+ out.push(...flattenIssues(issue.issues, fullPath));
165
+ continue;
166
+ }
167
+ out.push({ ...issue, path: fullPath } as z.core.$ZodIssue);
168
+ }
169
+ return out;
170
+ };
171
+
172
+ /**
173
+ * Expands unrecognized_keys issues into per-key issues so each bad key becomes its
174
+ * own mark in the parent view. After expansion each synthesized issue points at a
175
+ * single offending key via its path.
176
+ */
177
+ const expandUnrecognizedKeys = (
178
+ issues: ReadonlyArray<z.core.$ZodIssue>,
179
+ ): z.core.$ZodIssue[] => {
180
+ const out: z.core.$ZodIssue[] = [];
181
+ for (const issue of issues) {
182
+ if (
183
+ issue.code === "unrecognized_keys" &&
184
+ "keys" in issue &&
185
+ Array.isArray(issue.keys)
186
+ ) {
187
+ for (const key of issue.keys)
188
+ out.push({ ...issue, path: [...issue.path, key] } as z.core.$ZodIssue);
189
+ continue;
190
+ }
191
+ out.push(issue);
192
+ }
193
+ return out;
194
+ };
195
+
196
+ interface Mark {
197
+ reason: string;
198
+ missing: boolean;
199
+ }
200
+
201
+ /**
202
+ * Renders an object or array with margin markers (`✗`) on the keys that have issues,
203
+ * annotating each bad key with the expected type. Synthetic `<missing>` entries are
204
+ * appended for keys the schema expected but the input didn't contain.
205
+ *
206
+ * `baseIndent` is the column at which the opening brace sits. Marked lines place the
207
+ * marker two columns to the left of where the key's quote begins so that content
208
+ * still aligns with unmarked lines.
209
+ *
210
+ * For array parents, the truncation window is extended to include any marked
211
+ * index so that the reader can always see the annotated element.
212
+ */
213
+ const renderParentView = (
214
+ parent: unknown,
215
+ marks: Map<string, Mark>,
216
+ baseIndent: string,
217
+ callerOptions: fmt.Options,
218
+ ): string[] => {
219
+ const inner = `${baseIndent} `;
220
+ const marked = `${baseIndent + MARKER} `;
221
+
222
+ // Merge tight parent-view defaults with any caller overrides; caller fields win.
223
+ let options: fmt.Options = { ...DEFAULT_PARENT_VIEW_OPTIONS, ...callerOptions };
224
+
225
+ // For array parents, ensure the truncation window includes all marked indices
226
+ // so the ✗ lines aren't silently dropped when a bad entry lies past the
227
+ // effective maxArrayLength.
228
+ if (Array.isArray(parent)) {
229
+ let maxIdx = -1;
230
+ for (const key of marks.keys()) {
231
+ const idx = Number(key);
232
+ if (Number.isInteger(idx) && idx > maxIdx) maxIdx = idx;
233
+ }
234
+ const effectiveMax = options.maxArrayLength ?? 3;
235
+ if (maxIdx >= effectiveMax) options = { ...options, maxArrayLength: maxIdx + 2 };
236
+ }
237
+
238
+ // Pass the parent through fmt.value so depth / array / string truncation is
239
+ // applied consistently to the rendered siblings.
240
+ const sanitized = fmt.value(parent, options);
241
+
242
+ // Fallback for non-container parents. Only reachable when the union flattener
243
+ // picks a branch whose parent path doesn't exist in the input at all: we still
244
+ // want to show the reader *something*, so we render the failing value and the
245
+ // first mark's reason on a single marker line.
246
+ if (sanitized == null || typeof sanitized !== "object") {
247
+ const val = JSON.stringify(sanitized);
248
+ const first = marks.values().next().value;
249
+ const reason = first ? ` × ${first.reason}` : "";
250
+ return [`${marked}${val}${reason}`];
251
+ }
252
+
253
+ const lines: string[] = [];
254
+ const isArray = Array.isArray(sanitized);
255
+ lines.push(`${baseIndent}${isArray ? "[" : "{"}`);
256
+
257
+ interface Entry {
258
+ content: string;
259
+ mark?: Mark;
260
+ }
261
+
262
+ const entries: Entry[] = [];
263
+
264
+ if (isArray) {
265
+ const arr = sanitized as unknown[];
266
+ for (let i = 0; i < arr.length; i++) {
267
+ const mark = marks.get(String(i));
268
+ entries.push({
269
+ content: JSON.stringify(arr[i]),
270
+ mark: mark && !mark.missing ? mark : undefined,
271
+ });
272
+ }
273
+ } else {
274
+ const obj = sanitized as Record<string, unknown>;
275
+ for (const k of Object.keys(obj)) {
276
+ const mark = marks.get(k);
277
+ entries.push({
278
+ content: `"${k}": ${JSON.stringify(obj[k])}`,
279
+ mark: mark && !mark.missing ? mark : undefined,
280
+ });
281
+ }
282
+ // Synthetic missing entries for fields the schema expected but the input lacks.
283
+ for (const [k, mark] of marks.entries())
284
+ if (mark.missing)
285
+ entries.push({
286
+ content: `"${k}": <missing>`,
287
+ mark,
288
+ });
289
+ }
290
+
291
+ // Compute alignment width for the reasons, capped so that one abnormally long
292
+ // marked line doesn't push the column way to the right.
293
+ let alignWidth = 0;
294
+ entries.forEach((e, i) => {
295
+ if (e.mark == null) return;
296
+ const trailing = i < entries.length - 1 ? 1 : 0;
297
+ const w = e.content.length + trailing;
298
+ if (w > alignWidth && w <= MAX_ALIGN_WIDTH) alignWidth = w;
299
+ });
300
+
301
+ entries.forEach((e, i) => {
302
+ const comma = i < entries.length - 1 ? "," : "";
303
+ const line = e.content + comma;
304
+ if (e.mark != null) {
305
+ const pad = " ".repeat(Math.max(2, alignWidth - line.length + 2));
306
+ lines.push(`${marked}${line}${pad}× ${e.mark.reason}`);
307
+ } else lines.push(`${inner}${line}`);
308
+ });
309
+
310
+ lines.push(baseIndent + (isArray ? "]" : "}"));
311
+ return lines;
312
+ };
313
+
314
+ const ROOT_GROUP = "__root__";
315
+
316
+ const renderIssues = (
317
+ issues: ReadonlyArray<z.core.$ZodIssue>,
318
+ root: unknown,
319
+ options: fmt.Options,
320
+ ): string => {
321
+ // Group issues by parent path. Map iteration order is insertion order, which
322
+ // preserves zod's traversal order without a parallel index array.
323
+ const groups = new Map<string, z.core.$ZodIssue[]>();
324
+ for (const issue of issues) {
325
+ const key =
326
+ issue.path.length === 0 ? ROOT_GROUP : `::${fmt.path(parentPath(issue.path))}`;
327
+ const existing = groups.get(key);
328
+ if (existing != null) existing.push(issue);
329
+ else groups.set(key, [issue]);
330
+ }
331
+
332
+ const blocks: string[] = [];
333
+ for (const [key, group] of groups) {
334
+ // Root-level issues (path.length === 0): flat bullets, no parent view.
335
+ if (key === ROOT_GROUP) {
336
+ blocks.push(group.map((i) => ` × ${describeFlat(i, root, options)}`).join("\n"));
337
+ continue;
338
+ }
339
+
340
+ const parentArr = parentPath(group[0].path);
341
+ const { present, value: parent } = deep.atKeys(root, parentArr);
342
+
343
+ // If the union flattener picked a branch whose parent doesn't exist in the
344
+ // input, we can't render a parent view. Fall back to a flat at/× block.
345
+ if (!present) {
346
+ blocks.push(
347
+ group
348
+ .map(
349
+ (i) => ` at ${fmt.path(i.path)}\n × ${describeFlat(i, root, options)}`,
350
+ )
351
+ .join("\n"),
352
+ );
353
+ continue;
354
+ }
355
+
356
+ // Build a marks map keyed by the last path segment so renderParentView can
357
+ // annotate each bad key in place.
358
+ const marks = new Map<string, Mark>();
359
+ for (const issue of group) {
360
+ const lastKey = String(issue.path[issue.path.length - 1]);
361
+ const found = deep.atKeys(root, issue.path);
362
+ marks.set(lastKey, {
363
+ reason: describeCore(issue),
364
+ missing: !found.present,
365
+ });
366
+ }
367
+
368
+ const isRootParent = parentArr.length === 0;
369
+ const baseIndent = isRootParent ? " " : " ";
370
+ const viewLines = renderParentView(parent, marks, baseIndent, options);
371
+ if (isRootParent) blocks.push(viewLines.join("\n"));
372
+ else blocks.push([` at ${fmt.path(parentArr)}`, ...viewLines].join("\n"));
373
+ }
374
+
375
+ return blocks.join("\n\n");
376
+ };
377
+
378
+ const formatContextLine = (
379
+ context: Record<string, unknown>,
380
+ options: fmt.Options,
381
+ ): string => {
382
+ const entries = Object.entries(context);
383
+ if (entries.every(([, v]) => primitive.is(v)))
384
+ return entries
385
+ .map(([k, v]) => `${k}=${typeof v === "string" ? v : String(v)}`)
386
+ .join(", ");
387
+ return fmt.stringify(context, options);
388
+ };
389
+
390
+ interface FormatArgs {
391
+ issues: ReadonlyArray<z.core.$ZodIssue>;
392
+ input: unknown;
393
+ label: string;
394
+ context?: Record<string, unknown>;
395
+ formatOptions?: fmt.Options;
396
+ }
397
+
398
+ const format = ({
399
+ issues,
400
+ input,
401
+ label,
402
+ context,
403
+ formatOptions,
404
+ }: FormatArgs): string => {
405
+ const opts = formatOptions ?? {};
406
+ const flat = expandUnrecognizedKeys(flattenIssues(issues));
407
+ const count = flat.length === 1 ? "1 issue" : `${flat.length} issues`;
408
+ const parts: string[] = [`Failed to parse ${label} (${count})`];
409
+ parts.push(renderIssues(flat, input, opts));
410
+ if (context != null && Object.keys(context).length > 0)
411
+ parts.push(` context: ${formatContextLine(context, opts)}`);
412
+ return parts.join("\n\n");
413
+ };
414
+
415
+ export interface ParseErrorArgs {
416
+ issues: ReadonlyArray<z.core.$ZodIssue>;
417
+ input: unknown;
418
+ label: string;
419
+ context?: Record<string, unknown>;
420
+ cause?: unknown;
421
+ formatOptions?: fmt.Options;
422
+ }
423
+
424
+ /**
425
+ * An error thrown by `zod.parse` when a value fails to parse. It retains the original
426
+ * input, a human-readable label, and optional context so that callers and the status
427
+ * system can render a richer failure message than a raw `ZodError`.
428
+ *
429
+ * Extends the typed error system in `@/errors` so callers can match against it with
430
+ * `ParseError.matches(err)` rather than `instanceof`, which is robust across worker
431
+ * boundaries and network hops.
432
+ *
433
+ * Note that `err.issues.length` and the `(N issues)` count shown in `err.message` can
434
+ * differ: the message counts "leaves" after union/element flattening and
435
+ * unrecognized-keys expansion, while `err.issues` exposes the original zod array
436
+ * unchanged for programmatic consumers.
437
+ */
438
+ export class ParseError
439
+ extends errors.createTyped(PARSE_ERROR_TYPE)
440
+ implements status.Custom
441
+ {
442
+ readonly issues: ReadonlyArray<z.core.$ZodIssue>;
443
+ readonly input: unknown;
444
+ readonly label: string;
445
+ readonly context?: Record<string, unknown>;
446
+
447
+ constructor({ issues, input, label, context, cause, formatOptions }: ParseErrorArgs) {
448
+ super(format({ issues, input, label, context, formatOptions }), { cause });
449
+ this.issues = issues;
450
+ this.input = input;
451
+ this.label = label;
452
+ this.context = context;
453
+ }
454
+
455
+ toStatus(): Partial<status.Crude<z.ZodRecord, "error">> {
456
+ const details: Record<string, unknown> = {
457
+ input: fmt.value(this.input),
458
+ issues: this.issues,
459
+ };
460
+ if (this.context != null) details.context = this.context;
461
+ return {
462
+ message: `Failed to parse ${this.label}`,
463
+ description: this.message,
464
+ details,
465
+ };
466
+ }
467
+ }
468
+
469
+ interface ParseErrorPayload {
470
+ label: string;
471
+ context?: Record<string, unknown>;
472
+ issues: ReadonlyArray<unknown>;
473
+ input: unknown;
474
+ }
475
+
476
+ errors.register({
477
+ encode: (err) => {
478
+ if (!ParseError.matches(err)) return null;
479
+ const pe = err as ParseError;
480
+ const payload: ParseErrorPayload = {
481
+ label: pe.label,
482
+ context: pe.context,
483
+ issues: pe.issues,
484
+ input: fmt.value(pe.input),
485
+ };
486
+ return { type: PARSE_ERROR_TYPE, data: JSON.stringify(payload) };
487
+ },
488
+ decode: (payload) => {
489
+ if (payload.type !== PARSE_ERROR_TYPE) return null;
490
+ const parsed = JSON.parse(payload.data) as ParseErrorPayload;
491
+ return new ParseError({
492
+ issues: parsed.issues as ReadonlyArray<z.core.$ZodIssue>,
493
+ input: parsed.input,
494
+ label: parsed.label,
495
+ context: parsed.context,
496
+ });
497
+ },
498
+ });
499
+
500
+ /**
501
+ * Parses `value` against `schema`. On failure, throws a `ParseError` that retains the
502
+ * original input along with a human-readable label and optional context fields. The
503
+ * error's `message` is a pre-formatted breakdown suitable for logs and status display.
504
+ */
505
+ export const parse = <S extends z.ZodType>(
506
+ schema: S,
507
+ value: unknown,
508
+ options: ParseOptions = {},
509
+ ): z.infer<S> => {
510
+ const result = schema.safeParse(value);
511
+ if (result.success) return result.data;
512
+ throw new ParseError({
513
+ issues: result.error.issues,
514
+ input: value,
515
+ label: options.label ?? DEFAULT_LABEL,
516
+ context: options.context,
517
+ cause: result.error,
518
+ });
519
+ };