Skip to content

Commit c58255c

Browse files
committed
Extracting runtime file.
1 parent 3b59809 commit c58255c

6 files changed

Lines changed: 88 additions & 86 deletions

File tree

zod-plugin/augmentation.ts

Lines changed: 2 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import * as R from "ramda";
2-
import { globalRegistry, z } from "zod";
3-
import { $EZBrandCheck } from "./brand-check";
4-
import { name } from "./package.json";
5-
import { Intact, Remap } from "./remap";
1+
import type { z } from "zod";
2+
import type { Intact, Remap } from "./remap";
63

74
declare module "zod/v4/core" {
85
interface GlobalMeta {
@@ -56,81 +53,3 @@ declare module "zod" {
5653
): z.ZodPipe<z.ZodPipe<this, z.ZodTransform>, z.ZodObject<U>>; // internal type simplified
5754
}
5855
}
59-
60-
const exampleSetter = function (this: z.ZodType, value: z.output<typeof this>) {
61-
const examples = globalRegistry.get(this)?.examples?.slice() || [];
62-
examples.push(value);
63-
return this.meta({ examples });
64-
};
65-
66-
const deprecationSetter = function (this: z.ZodType) {
67-
return this.meta({ deprecated: true });
68-
};
69-
70-
const labelSetter = function (this: z.ZodDefault, defaultLabel: string) {
71-
return this.meta({ default: defaultLabel });
72-
};
73-
74-
const brandSetter = function (
75-
this: z.ZodType,
76-
brand?: string | number | symbol,
77-
) {
78-
return this.check(new $EZBrandCheck({ brand, check: "$EZBrandCheck" }));
79-
};
80-
81-
type _Mapper = <T extends Record<string, unknown>>(
82-
subject: T,
83-
) => { [P in string | keyof T]: T[keyof T] };
84-
85-
const objectMapper = function (
86-
this: z.ZodObject,
87-
tool: Record<string, string> | _Mapper,
88-
) {
89-
const transformer =
90-
typeof tool === "function" ? tool : R.renameKeys(R.reject(R.isNil, tool)); // rejecting undefined
91-
const nextShape = transformer(
92-
R.map(R.invoker(0, "clone"), this._zod.def.shape), // immutable, changed from R.clone due to failure
93-
);
94-
const hasPassThrough = this._zod.def.catchall instanceof z.ZodUnknown;
95-
const output = (hasPassThrough ? z.looseObject : z.object)(nextShape); // proxies unknown keys when set to "passthrough"
96-
return this.transform(transformer).pipe(output);
97-
};
98-
99-
const pluginFlag = Symbol.for(name);
100-
101-
if (!(pluginFlag in globalThis)) {
102-
(globalThis as Record<symbol, unknown>)[pluginFlag] = true;
103-
for (const entry of Object.keys(z)) {
104-
if (!entry.startsWith("Zod")) continue;
105-
if (/(Success|Error|Function)$/.test(entry)) continue;
106-
const Cls = z[entry as keyof typeof z];
107-
if (typeof Cls !== "function") continue;
108-
Object.defineProperties(Cls.prototype, {
109-
["example" satisfies keyof z.ZodType]: {
110-
value: exampleSetter,
111-
writable: false,
112-
},
113-
["deprecated" satisfies keyof z.ZodType]: {
114-
value: deprecationSetter,
115-
writable: false,
116-
},
117-
["brand" satisfies keyof z.ZodType]: {
118-
set() {}, // this is required to override the existing method
119-
get() {
120-
return brandSetter.bind(this) as z.ZodType["brand"];
121-
},
122-
},
123-
});
124-
}
125-
126-
Object.defineProperty(
127-
z.ZodDefault.prototype,
128-
"label" satisfies keyof z.ZodDefault,
129-
{ value: labelSetter, writable: false },
130-
);
131-
Object.defineProperty(
132-
z.ZodObject.prototype,
133-
"remap" satisfies keyof z.ZodObject,
134-
{ value: objectMapper, writable: false },
135-
);
136-
}

zod-plugin/index.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { z } from "zod";
22
import * as entrypoint from "./index";
33

44
describe("Entrypoint", () => {
5-
test("Extended Zod prototypes", () => {
5+
test("Augmentation", () => {
66
expectTypeOf<z.ZodAny>()
77
.toHaveProperty("example")
88
.toEqualTypeOf<(value: any) => z.ZodAny>();

zod-plugin/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
import "./augmentation"; // side effects here
1+
import "./augmentation";
2+
import "./runtime"; // side effects here
23
export { getBrand } from "./helpers";

zod-plugin/runtime.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import * as R from "ramda";
2+
import { globalRegistry, z } from "zod";
3+
import { $EZBrandCheck } from "./brand-check";
4+
import { name } from "./package.json";
5+
6+
const exampleSetter = function (this: z.ZodType, value: z.output<typeof this>) {
7+
const examples = globalRegistry.get(this)?.examples?.slice() || [];
8+
examples.push(value);
9+
return this.meta({ examples });
10+
};
11+
12+
const deprecationSetter = function (this: z.ZodType) {
13+
return this.meta({ deprecated: true });
14+
};
15+
16+
const labelSetter = function (this: z.ZodDefault, defaultLabel: string) {
17+
return this.meta({ default: defaultLabel });
18+
};
19+
20+
const brandSetter = function (
21+
this: z.ZodType,
22+
brand?: string | number | symbol,
23+
) {
24+
return this.check(new $EZBrandCheck({ brand, check: "$EZBrandCheck" }));
25+
};
26+
27+
type _Mapper = <T extends Record<string, unknown>>(
28+
subject: T,
29+
) => { [P in string | keyof T]: T[keyof T] };
30+
31+
const objectMapper = function (
32+
this: z.ZodObject,
33+
tool: Record<string, string> | _Mapper,
34+
) {
35+
const transformer =
36+
typeof tool === "function" ? tool : R.renameKeys(R.reject(R.isNil, tool)); // rejecting undefined
37+
const nextShape = transformer(
38+
R.map(R.invoker(0, "clone"), this._zod.def.shape), // immutable, changed from R.clone due to failure
39+
);
40+
const hasPassThrough = this._zod.def.catchall instanceof z.ZodUnknown;
41+
const output = (hasPassThrough ? z.looseObject : z.object)(nextShape); // proxies unknown keys when set to "passthrough"
42+
return this.transform(transformer).pipe(output);
43+
};
44+
45+
const pluginFlag = Symbol.for(name);
46+
47+
if (!(pluginFlag in globalThis)) {
48+
(globalThis as Record<symbol, unknown>)[pluginFlag] = true;
49+
for (const entry of Object.keys(z)) {
50+
if (!entry.startsWith("Zod")) continue;
51+
if (/(Success|Error|Function)$/.test(entry)) continue;
52+
const Cls = z[entry as keyof typeof z];
53+
if (typeof Cls !== "function") continue;
54+
Object.defineProperties(Cls.prototype, {
55+
["example" satisfies keyof z.ZodType]: {
56+
value: exampleSetter,
57+
writable: false,
58+
},
59+
["deprecated" satisfies keyof z.ZodType]: {
60+
value: deprecationSetter,
61+
writable: false,
62+
},
63+
["brand" satisfies keyof z.ZodType]: {
64+
set() {}, // this is required to override the existing method
65+
get() {
66+
return brandSetter.bind(this) as z.ZodType["brand"];
67+
},
68+
},
69+
});
70+
}
71+
72+
Object.defineProperty(
73+
z.ZodDefault.prototype,
74+
"label" satisfies keyof z.ZodDefault,
75+
{ value: labelSetter, writable: false },
76+
);
77+
Object.defineProperty(
78+
z.ZodObject.prototype,
79+
"remap" satisfies keyof z.ZodObject,
80+
{ value: objectMapper, writable: false },
81+
);
82+
}

zod-plugin/vitest.setup.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
import "./augmentation";
1+
import "./runtime";

0 commit comments

Comments
 (0)