@veryfront/ext-schema-zod 0.1.1284 → 0.1.1285

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.
@@ -0,0 +1,12 @@
1
+ declare global {
2
+ interface Object {
3
+ /**
4
+ * Determines whether an object has a property with the specified name.
5
+ * @param o An object.
6
+ * @param v A property name.
7
+ */
8
+ hasOwn(o: object, v: PropertyKey): boolean;
9
+ }
10
+ }
11
+ export {};
12
+ //# sourceMappingURL=_dnt.polyfills.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"_dnt.polyfills.d.ts","sourceRoot":"","sources":["../src/_dnt.polyfills.ts"],"names":[],"mappings":"AAeA,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QACd;;;;WAIG;QACH,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;KAC5C;CACF;AAED,OAAO,EAAE,CAAC"}
@@ -0,0 +1,15 @@
1
+ // https://github.com/tc39/proposal-accessible-object-hasownproperty/blob/main/polyfill.js
2
+ if (!Object.hasOwn) {
3
+ Object.defineProperty(Object, "hasOwn", {
4
+ value: function (object, property) {
5
+ if (object == null) {
6
+ throw new TypeError("Cannot convert undefined or null to object");
7
+ }
8
+ return Object.prototype.hasOwnProperty.call(Object(object), property);
9
+ },
10
+ configurable: true,
11
+ enumerable: false,
12
+ writable: true,
13
+ });
14
+ }
15
+ export {};
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,EAUV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAqyBrC;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAiGlD"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,KAAK,EAUV,eAAe,EAIhB,MAAM,6BAA6B,CAAC;AAuzBrC;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAiGlD"}
package/esm/adapter.js CHANGED
@@ -14,7 +14,9 @@ import { Ajv2019 } from "ajv/dist/2019.js";
14
14
  import { Ajv2020 } from "ajv/dist/2020.js";
15
15
  import addFormatsModule from "ajv-formats";
16
16
  import { z } from "zod";
17
- import { isOptionalSchema, recordStaticJsonSchemaDefault, zodToJsonSchema } from "./json-schema.js";
17
+ import { isOptionalSchema, recordStaticJsonSchemaDefault, recordTransparentSchemaInput, zodToJsonSchema, } from "./json-schema.js";
18
+ import { preserveDeclaredObjectDataProperty } from "./object-data-properties.js";
19
+ import { preserveUnionCheckDiagnostics } from "./union-diagnostics.js";
18
20
  // Deno exposes the CommonJS default as a callable value at runtime while the
19
21
  // package declaration describes the imported value as a module namespace.
20
22
  const addFormats = addFormatsModule;
@@ -24,6 +26,8 @@ function toZod(schema) {
24
26
  }
25
27
  /** Wrap a zod schema as an opaque Schema<T> with chainables routed through zod. */
26
28
  function wrap(zs) {
29
+ preserveDeclaredObjectDataProperty(zs);
30
+ preserveUnionCheckDiagnostics(zs);
27
31
  // The wrapper fakes the full Schema<T> surface; unsupported chainables on
28
32
  // unsuitable kinds (e.g. calling `.email()` on a number) throw at runtime
29
33
  // just like zod would.
@@ -104,6 +108,14 @@ function wrap(zs) {
104
108
  s.__zod = zs;
105
109
  return s;
106
110
  }
111
+ // An unconstrained input stage preserves omission for unknown/any/custom fields.
112
+ // The actual validator stays outside optional(), so required refinements still
113
+ // run. A validation pipeline also keeps opaque promises synchronous.
114
+ function withMissingInputValidation(schema) {
115
+ const input = z.unknown().optional().pipe(schema);
116
+ recordTransparentSchemaInput(input, schema);
117
+ return input;
118
+ }
107
119
  function toZodShape(shape) {
108
120
  const out = {};
109
121
  for (const [key, value] of Object.entries(shape)) {
@@ -678,10 +690,10 @@ export function createZodAdapter() {
678
690
  boolean: () => wrap(z.boolean()),
679
691
  date: () => wrap(z.date()),
680
692
  null: () => wrap(z.null()),
681
- unknown: () => wrap(z.unknown()),
693
+ unknown: () => wrap(withMissingInputValidation(z.unknown())),
682
694
  bigint: () => wrap(z.bigint()),
683
695
  // deno-lint-ignore no-explicit-any -- contract mirrors zod's `any` constructor
684
- any: () => wrap(z.any()),
696
+ any: () => wrap(withMissingInputValidation(z.any())),
685
697
  function: () =>
686
698
  // zod 4's z.function() is callable without args/returns and produces a
687
699
  // schema accepting any function. We wrap it as Schema<AnyFunction>.
@@ -709,7 +721,7 @@ export function createZodAdapter() {
709
721
  // contract uses a slimmer `new`-able shape; bridge with a single cast
710
722
  // through unknown.
711
723
  wrap(z.instanceof(ctor)),
712
- custom: (check, message) => wrap(z.custom(check, message)),
724
+ custom: (check, message) => wrap(withMissingInputValidation(z.custom(check, message))),
713
725
  coerce,
714
726
  validate: (schema, data) => schema.safeParse(data),
715
727
  compileJsonSchema,
package/esm/index.d.ts CHANGED
@@ -12,6 +12,7 @@
12
12
  *
13
13
  * @module extensions/ext-schema-zod
14
14
  */
15
+ import "./_dnt.polyfills.js";
15
16
  import type { ExtensionFactory } from "veryfront/extensions";
16
17
  declare const extZod: ExtensionFactory;
17
18
  export default extZod;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,QAAA,MAAM,MAAM,EAAE,gBAiBb,CAAC;AAEF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,qBAAqB,CAAC;AAG7B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,QAAA,MAAM,MAAM,EAAE,gBAiBb,CAAC;AAEF,eAAe,MAAM,CAAC;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
package/esm/index.js CHANGED
@@ -12,6 +12,7 @@
12
12
  *
13
13
  * @module extensions/ext-schema-zod
14
14
  */
15
+ import "./_dnt.polyfills.js";
15
16
  import { createZodAdapter } from "./adapter.js";
16
17
  const extZod = () => {
17
18
  const impl = createZodAdapter();
@@ -10,6 +10,8 @@
10
10
  */
11
11
  import type { z } from "zod";
12
12
  import type { JsonSchema } from "veryfront/extensions/schema";
13
+ /** Identity input stages do not change the public schema's metadata. */
14
+ export declare function recordTransparentSchemaInput(schema: z.ZodTypeAny, represented: z.ZodTypeAny): void;
13
15
  /** Record a literal default without evaluating Zod's possibly dynamic getter. */
14
16
  export declare function recordStaticJsonSchemaDefault(schema: z.ZodTypeAny, value: unknown): void;
15
17
  export declare function zodToJsonSchema(schema: z.ZodTypeAny): JsonSchema;
@@ -1 +1 @@
1
- {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAqO9D,iFAAiF;AACjF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAOxF;AAmLD,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,UAAU,CAMhE;AAgBD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,OAAO,CAE9D"}
1
+ {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAC7B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAwO9D,wEAAwE;AACxE,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,CAAC,CAAC,UAAU,EACpB,WAAW,EAAE,CAAC,CAAC,UAAU,GACxB,IAAI,CAON;AAMD,iFAAiF;AACjF,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAOxF;AAmLD,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,UAAU,CAMhE;AAgBD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,GAAG,OAAO,CAE9D"}
@@ -16,6 +16,7 @@ function assertConversionDepth(depth) {
16
16
  }
17
17
  }
18
18
  const STATIC_DEFAULT_VALUE = Symbol("veryfront.staticJsonSchemaDefault");
19
+ const TRANSPARENT_INPUT_SCHEMA = Symbol("veryfront.transparentInputSchema");
19
20
  const LITERAL_TYPE_MAP = {
20
21
  string: "string",
21
22
  number: "number",
@@ -138,7 +139,7 @@ function originatesFromCustomSchema(schema) {
138
139
  if (tag !== "pipe" && tag !== "ZodEffects")
139
140
  return false;
140
141
  const def = getDef(current);
141
- const input = def.schema ?? def.in;
142
+ const input = getTransparentInputSchema(def) ?? def.schema ?? def.in;
142
143
  if (!input || input === current)
143
144
  return false;
144
145
  current = input;
@@ -147,9 +148,24 @@ function originatesFromCustomSchema(schema) {
147
148
  return false;
148
149
  }
149
150
  function representedPipeSchema(def) {
151
+ const transparent = getTransparentInputSchema(def);
152
+ if (transparent)
153
+ return transparent;
150
154
  const input = def.schema ?? def.in;
151
155
  return input && originatesFromCustomSchema(input) && def.out ? def.out : input;
152
156
  }
157
+ /** Identity input stages do not change the public schema's metadata. */
158
+ export function recordTransparentSchemaInput(schema, represented) {
159
+ Object.defineProperty(getDef(schema), TRANSPARENT_INPUT_SCHEMA, {
160
+ configurable: true,
161
+ enumerable: true,
162
+ value: represented,
163
+ writable: false,
164
+ });
165
+ }
166
+ function getTransparentInputSchema(def) {
167
+ return Object.getOwnPropertyDescriptor(def, TRANSPARENT_INPUT_SCHEMA)?.value;
168
+ }
153
169
  /** Record a literal default without evaluating Zod's possibly dynamic getter. */
154
170
  export function recordStaticJsonSchemaDefault(schema, value) {
155
171
  Object.defineProperty(getDef(schema), STATIC_DEFAULT_VALUE, {
@@ -604,7 +620,7 @@ function hasDefaultSchema(schema) {
604
620
  case "optional":
605
621
  case "ZodEffects":
606
622
  case "pipe": {
607
- const inner = def.innerType ?? def.schema ?? def.in;
623
+ const inner = getTransparentInputSchema(def) ?? def.innerType ?? def.schema ?? def.in;
608
624
  if (!inner || inner === current)
609
625
  return false;
610
626
  current = inner;
@@ -0,0 +1,4 @@
1
+ import type { z } from "zod";
2
+ /** Preserve declared data without restoring unsafe unknown-key assignment. */
3
+ export declare function preserveDeclaredObjectDataProperty(schema: z.ZodType): void;
4
+ //# sourceMappingURL=object-data-properties.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object-data-properties.d.ts","sourceRoot":"","sources":["../src/object-data-properties.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA+E7B,8EAA8E;AAC9E,wBAAgB,kCAAkC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CAsC1E"}
@@ -0,0 +1,98 @@
1
+ const DATA_KEY = "__proto__";
2
+ const patched = new WeakSet();
3
+ const HasOwn = Object.hasOwn;
4
+ const DefineProperty = Object.defineProperty;
5
+ const Get = Reflect.get;
6
+ const Apply = Reflect.apply;
7
+ const IsArray = Array.isArray;
8
+ const NativePromise = Promise;
9
+ const PromiseThen = Promise.prototype.then;
10
+ function isSchemaObjectData(value) {
11
+ return value !== null && typeof value === "object" && !IsArray(value);
12
+ }
13
+ function continueParse(result, next) {
14
+ return result instanceof NativePromise
15
+ ? Apply(PromiseThen, result, [next])
16
+ : next(result);
17
+ }
18
+ function mergeDeclaredData(parent, child, field, present, output) {
19
+ for (let index = 0; index < child.issues.length; index++) {
20
+ const issue = child.issues[index];
21
+ parent.issues[parent.issues.length] = {
22
+ ...issue,
23
+ path: [DATA_KEY, ...(issue.path ?? [])],
24
+ };
25
+ }
26
+ // Ordinary fields retain values for non-aborting refinements; their issues
27
+ // still make validation fail. Defining data never calls the prototype setter.
28
+ if (present || child.value !== undefined ||
29
+ field._zod.optin === "defaulted" && field._zod.optout !== "optional") {
30
+ const descriptor = {
31
+ __proto__: null,
32
+ configurable: true,
33
+ enumerable: true,
34
+ writable: true,
35
+ value: child.value,
36
+ };
37
+ DefineProperty(output, DATA_KEY, descriptor);
38
+ }
39
+ return parent;
40
+ }
41
+ function parseDeclaredData(parent, input, field, context) {
42
+ const output = parent.value;
43
+ if (!isSchemaObjectData(output)) {
44
+ throw new TypeError("Object schema parser returned an invalid output");
45
+ }
46
+ const present = HasOwn(input, DATA_KEY);
47
+ const parsed = field._zod.run({
48
+ value: present ? Get(input, DATA_KEY, input) : undefined,
49
+ issues: [],
50
+ }, context);
51
+ return continueParse(parsed, (child) => mergeDeclaredData(parent, child, field, present, output));
52
+ }
53
+ /** Preserve declared data without restoring unsafe unknown-key assignment. */
54
+ export function preserveDeclaredObjectDataProperty(schema) {
55
+ if (schema._zod.def.type !== "object" || patched.has(schema))
56
+ return;
57
+ const object = schema;
58
+ const shape = object._zod.def.shape;
59
+ if (!HasOwn(shape, DATA_KEY))
60
+ return;
61
+ const field = shape[DATA_KEY];
62
+ let delegate = object._zod.parse;
63
+ const directRun = object._zod.run === delegate;
64
+ // Zod4.6 skips this name even in a declared shape. Validate it through its
65
+ // actual field parser, then define an own data property before object checks.
66
+ // No shared prototype or global parser changes; wrap() patches each clone.
67
+ const parse = (payload, context) => {
68
+ const input = payload.value;
69
+ const issueCount = payload.issues.length;
70
+ const result = delegate(payload, context);
71
+ if (!isSchemaObjectData(input))
72
+ return result;
73
+ return continueParse(result, (parent) => {
74
+ if (parent.memo || context.abortEarly && parent.issues.length > issueCount)
75
+ return parent;
76
+ return parseDeclaredData(parent, input, field, context);
77
+ });
78
+ };
79
+ // The memoizer replaces its parser from inside the first call. Keep this
80
+ // instance's augmentation installed even during reentrant validation, while
81
+ // allowing that replacement to become the delegate for subsequent calls.
82
+ const descriptor = {
83
+ __proto__: null,
84
+ configurable: true,
85
+ enumerable: true,
86
+ get: () => parse,
87
+ set(next) {
88
+ if (typeof next !== "function")
89
+ throw new TypeError("Object schema parser is unavailable");
90
+ if (next !== parse)
91
+ delegate = next;
92
+ },
93
+ };
94
+ DefineProperty(object._zod, "parse", descriptor);
95
+ if (directRun)
96
+ object._zod.run = parse;
97
+ patched.add(schema);
98
+ }
@@ -0,0 +1,4 @@
1
+ import { z } from "zod";
2
+ /** Adapt upstream #6662 for eager collection bounds without changing custom type errors. */
3
+ export declare function preserveUnionCheckDiagnostics(schema: z.ZodType): void;
4
+ //# sourceMappingURL=union-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"union-diagnostics.d.ts","sourceRoot":"","sources":["../src/union-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAmDxB,4FAA4F;AAC5F,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,IAAI,CA4BrE"}
@@ -0,0 +1,63 @@
1
+ import { z } from "zod";
2
+ const patched = new WeakSet();
3
+ function isCollectionSizeRefusal(issue) {
4
+ return issue.code === "too_big" &&
5
+ (issue.origin === "array" || issue.origin === "set" || issue.origin === "map");
6
+ }
7
+ function selectUnionResult(results, final, union, context) {
8
+ for (const result of results) {
9
+ if (result.issues.length === 0) {
10
+ final.value = result.value;
11
+ return final;
12
+ }
13
+ }
14
+ let matched = results.filter((result) => !z.core.util.aborted(result));
15
+ if (matched.length === 0) {
16
+ // Only eager collection caps need the fallback. A failed custom type
17
+ // predicate must retain its enclosing union's original error boundary.
18
+ matched = results.filter((result) => !result.aborted &&
19
+ result.issues.every((issue) => issue.continue === true || issue.continue === false && isCollectionSizeRefusal(issue)) && result.issues.some(isCollectionSizeRefusal));
20
+ }
21
+ if (matched.length === 1) {
22
+ final.value = matched[0].value;
23
+ return matched[0];
24
+ }
25
+ final.issues.push({
26
+ code: "invalid_union",
27
+ input: final.value,
28
+ inst: union,
29
+ errors: results.map((result) => result.issues.map((issue) => z.core.util.finalizeIssue(issue, context, z.core.config()))),
30
+ });
31
+ return final;
32
+ }
33
+ /** Adapt upstream #6662 for eager collection bounds without changing custom type errors. */
34
+ export function preserveUnionCheckDiagnostics(schema) {
35
+ const def = schema._zod.def;
36
+ if (def.type !== "union" || "discriminator" in def || "exclusive" in def || patched.has(schema))
37
+ return;
38
+ const union = schema;
39
+ const options = union._zod.def.options;
40
+ const previous = union._zod.parse;
41
+ const directRun = union._zod.run === previous;
42
+ const parse = (payload, context) => {
43
+ if (options.length === 1)
44
+ return options[0]._zod.run(payload, context);
45
+ const results = [];
46
+ let asynchronous = false;
47
+ for (const option of options) {
48
+ const result = option._zod.run({ value: payload.value, issues: [] }, context);
49
+ if (result instanceof Promise)
50
+ asynchronous = true;
51
+ else if (result.issues.length === 0)
52
+ return result;
53
+ results.push(result);
54
+ }
55
+ return asynchronous
56
+ ? Promise.all(results).then((resolved) => selectUnionResult(resolved, payload, union, context))
57
+ : selectUnionResult(results, payload, union, context);
58
+ };
59
+ union._zod.parse = parse;
60
+ if (directRun)
61
+ union._zod.run = parse;
62
+ patched.add(schema);
63
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veryfront/ext-schema-zod",
3
- "version": "0.1.1284",
3
+ "version": "0.1.1285",
4
4
  "description": "Veryfront first-party extension package for ext-schema-zod",
5
5
  "keywords": [
6
6
  "veryfront",
@@ -44,10 +44,10 @@
44
44
  "dependencies": {
45
45
  "ajv": "8.18.0",
46
46
  "ajv-formats": "3.0.1",
47
- "zod": "4.3.6"
47
+ "zod": "4.6.7"
48
48
  },
49
49
  "peerDependencies": {
50
- "veryfront": "^0.1.1284"
50
+ "veryfront": "^0.1.1285"
51
51
  },
52
52
  "type": "module",
53
53
  "types": "./esm/index.d.ts",
@@ -57,5 +57,5 @@
57
57
  "NOTICE",
58
58
  "README.md"
59
59
  ],
60
- "gitHead": "ee34c936d96f979a54dc2f32def75772677f4cfd"
60
+ "gitHead": "2bac963100515224f14213021beb42e128b201ea"
61
61
  }