exact-mirror 1.0.1 → 1.1.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.
- package/dist/cjs/index.d.ts +24 -2
- package/dist/cjs/index.js +124 -37
- package/dist/index.d.ts +24 -2
- package/dist/index.mjs +124 -37
- package/package.json +1 -1
package/dist/cjs/index.d.ts
CHANGED
|
@@ -57,6 +57,16 @@ export interface Instruction<Emit extends boolean = false> {
|
|
|
57
57
|
typeCompilerWanred?: boolean;
|
|
58
58
|
modules?: TModule<{}>;
|
|
59
59
|
definitions: Record<string, AnySchema>;
|
|
60
|
+
/**
|
|
61
|
+
* Shared cyclic codegen state: generated per-definition mirror
|
|
62
|
+
* functions, grouped by `$defs` object identity
|
|
63
|
+
*/
|
|
64
|
+
cyclic: CyclicContext;
|
|
65
|
+
/**
|
|
66
|
+
* `$defs` group the current cyclic definition body is generated
|
|
67
|
+
* against, used to resolve `Ref` nodes to function calls
|
|
68
|
+
*/
|
|
69
|
+
cyclicDefs?: CyclicGroup;
|
|
60
70
|
recursion: number;
|
|
61
71
|
/**
|
|
62
72
|
* @default 8
|
|
@@ -73,9 +83,21 @@ export interface Instruction<Emit extends boolean = false> {
|
|
|
73
83
|
removeUnknownUnionType: boolean;
|
|
74
84
|
}
|
|
75
85
|
export declare function deepClone<T>(source: T, weak?: WeakMap<object, any>): T;
|
|
86
|
+
interface CyclicGroup {
|
|
87
|
+
defs: Record<string, AnySchema>;
|
|
88
|
+
names: Record<string, string>;
|
|
89
|
+
}
|
|
90
|
+
interface CyclicContext {
|
|
91
|
+
groups: Map<object, CyclicGroup>;
|
|
92
|
+
fns: string[];
|
|
93
|
+
count: number;
|
|
94
|
+
}
|
|
76
95
|
export interface Manifest {
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
source: string;
|
|
97
|
+
externals: {
|
|
98
|
+
unions: Validator<any, TSchema, unknown, unknown>[][];
|
|
99
|
+
hof?: Record<string, Function>;
|
|
100
|
+
};
|
|
79
101
|
}
|
|
80
102
|
export declare const createMirror: <T extends TSchema, Emit extends boolean = false>(schema: T, { Compile, modules, definitions, sanitize, recursionLimit, removeUnknownUnionType, emit }?: Partial<Pick<Instruction<Emit>, "Compile" | "definitions" | "sanitize" | "modules" | "recursionLimit" | "removeUnknownUnionType" | "emit">>) => Emit extends true ? Manifest : (v: Static<T>) => Static<T>;
|
|
81
103
|
export default createMirror;
|
package/dist/cjs/index.js
CHANGED
|
@@ -80,7 +80,7 @@ var handleRecord = (schema, property, instruction) => {
|
|
|
80
80
|
var handleTuple = (schema, property, instruction) => {
|
|
81
81
|
const i = instruction.array;
|
|
82
82
|
instruction.array++;
|
|
83
|
-
const isRoot = property === "v" && !instruction.
|
|
83
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
84
84
|
let v = "";
|
|
85
85
|
if (!isRoot) v = `(()=>{`;
|
|
86
86
|
v += `const ar${i}v=[`;
|
|
@@ -122,6 +122,59 @@ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
|
|
|
122
122
|
}
|
|
123
123
|
return source;
|
|
124
124
|
}
|
|
125
|
+
var handleCyclic = (schema, property, instruction) => {
|
|
126
|
+
const defs = schema.$defs;
|
|
127
|
+
let group = instruction.cyclic.groups.get(defs);
|
|
128
|
+
if (!group) {
|
|
129
|
+
group = { defs, names: {} };
|
|
130
|
+
instruction.cyclic.groups.set(defs, group);
|
|
131
|
+
for (const name in defs)
|
|
132
|
+
group.names[name] = `cy${instruction.cyclic.count++}`;
|
|
133
|
+
for (const name in defs)
|
|
134
|
+
instruction.cyclic.fns.push(
|
|
135
|
+
`function ${group.names[name]}(v){${mirror(defs[name], "v", {
|
|
136
|
+
...instruction,
|
|
137
|
+
cyclicDefs: group,
|
|
138
|
+
fromUnion: false,
|
|
139
|
+
parentIsOptional: false,
|
|
140
|
+
optionals: [],
|
|
141
|
+
optionalsInArray: [],
|
|
142
|
+
unionKeys: {},
|
|
143
|
+
array: 0,
|
|
144
|
+
recursion: 0
|
|
145
|
+
})}}`
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const fn = group.names[schema.$ref];
|
|
149
|
+
if (!fn)
|
|
150
|
+
throw new Error(
|
|
151
|
+
`[exact-mirror] cyclic reference "${schema.$ref}" is not found in $defs`
|
|
152
|
+
);
|
|
153
|
+
return `(${property}==null?${property}:${fn}(${property}))`;
|
|
154
|
+
};
|
|
155
|
+
var withDefs = (type, group) => {
|
|
156
|
+
if (Kind in type) {
|
|
157
|
+
if (type[Kind] === "Cyclic") return type;
|
|
158
|
+
if (type[Kind] === "Ref" && type.$ref in group.defs)
|
|
159
|
+
return Object.defineProperty(
|
|
160
|
+
{ $defs: group.defs, $ref: type.$ref },
|
|
161
|
+
Kind,
|
|
162
|
+
{ value: "Cyclic" }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
let entry = "~check";
|
|
166
|
+
while (entry in group.defs) entry += "~";
|
|
167
|
+
const def = Object.create(
|
|
168
|
+
Object.getPrototypeOf(type),
|
|
169
|
+
Object.getOwnPropertyDescriptors(type)
|
|
170
|
+
);
|
|
171
|
+
def.$id = entry;
|
|
172
|
+
return Object.defineProperty(
|
|
173
|
+
{ $defs: { ...group.defs, [entry]: def }, $ref: entry },
|
|
174
|
+
Kind,
|
|
175
|
+
{ value: "Cyclic" }
|
|
176
|
+
);
|
|
177
|
+
};
|
|
125
178
|
var handleUnion = (schemas, property, instruction) => {
|
|
126
179
|
if (instruction.Compile === void 0) {
|
|
127
180
|
if (!instruction.typeCompilerWanred) {
|
|
@@ -143,15 +196,6 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
143
196
|
if (!(Kind in type) || !type.$ref) return type;
|
|
144
197
|
if (type[Kind] === "This")
|
|
145
198
|
return deepClone(instruction.definitions[type.$ref]);
|
|
146
|
-
else if (type[Kind] === "Cyclic") {
|
|
147
|
-
if (!instruction.modules)
|
|
148
|
-
console.warn(
|
|
149
|
-
new Error(
|
|
150
|
-
"[exact-mirror] modules is required when using nested cyclic reference"
|
|
151
|
-
)
|
|
152
|
-
);
|
|
153
|
-
else return instruction.modules.$defs[type.$ref];
|
|
154
|
-
}
|
|
155
199
|
return type;
|
|
156
200
|
};
|
|
157
201
|
let cleanThenCheck = "";
|
|
@@ -166,7 +210,11 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
166
210
|
type.items[i2] = unwrapRef(type.items[i2]);
|
|
167
211
|
else type.items = unwrapRef(type.items);
|
|
168
212
|
}
|
|
169
|
-
typeChecks.push(
|
|
213
|
+
typeChecks.push(
|
|
214
|
+
instruction.Compile(
|
|
215
|
+
instruction.cyclicDefs ? withDefs(type, instruction.cyclicDefs) : type
|
|
216
|
+
)
|
|
217
|
+
);
|
|
170
218
|
v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
|
|
171
219
|
type,
|
|
172
220
|
property,
|
|
@@ -193,12 +241,31 @@ if(d.unions[${ui}][${i}].Check(tmp))return tmp
|
|
|
193
241
|
};
|
|
194
242
|
var mirror = (schema, property, instruction) => {
|
|
195
243
|
if (!schema) return "";
|
|
196
|
-
const isRoot = property === "v" && !instruction.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
244
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
245
|
+
const optionalsLength = instruction.optionals.length;
|
|
246
|
+
try {
|
|
247
|
+
if (Kind in schema && schema[Kind] === "Cyclic") {
|
|
248
|
+
const call = handleCyclic(schema, property, instruction);
|
|
249
|
+
return isRoot ? `return ${call}` : call;
|
|
250
|
+
}
|
|
251
|
+
return mirrorNode(schema, property, instruction);
|
|
252
|
+
} catch (error) {
|
|
253
|
+
instruction.optionals.length = optionalsLength;
|
|
254
|
+
console.warn(
|
|
255
|
+
new Error(
|
|
256
|
+
"[exact-mirror] failed to generate mirror for a schema node, the node is passed through as-is. Please report this issue to https://github.com/elysiajs/exact-mirror/issues"
|
|
257
|
+
),
|
|
258
|
+
error
|
|
259
|
+
);
|
|
260
|
+
return isRoot ? "return v" : property;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
var mirrorNode = (schema, property, instruction) => {
|
|
264
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
265
|
+
if (instruction.cyclicDefs && Kind in schema && schema[Kind] === "Ref" && schema.$ref && schema.$ref in instruction.cyclicDefs.names) {
|
|
266
|
+
const call = `(${property}==null?${property}:${instruction.cyclicDefs.names[schema.$ref]}(${property}))`;
|
|
267
|
+
return isRoot ? `return ${call}` : call;
|
|
268
|
+
}
|
|
202
269
|
if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
|
|
203
270
|
return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
|
|
204
271
|
if (instruction.recursion >= instruction.recursionLimit) return property;
|
|
@@ -212,6 +279,10 @@ var mirror = (schema, property, instruction) => {
|
|
|
212
279
|
break;
|
|
213
280
|
}
|
|
214
281
|
schema = mergeObjectIntersection(schema);
|
|
282
|
+
if (!schema.properties) {
|
|
283
|
+
v = property;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
215
286
|
v += "{";
|
|
216
287
|
if (schema.additionalProperties) v += `...${property},`;
|
|
217
288
|
const keys = Object.keys(schema.properties);
|
|
@@ -270,29 +341,38 @@ var mirror = (schema, property, instruction) => {
|
|
|
270
341
|
v += "}";
|
|
271
342
|
break;
|
|
272
343
|
case "array":
|
|
344
|
+
if (!schema.items) {
|
|
345
|
+
v = property;
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
273
348
|
if (
|
|
274
349
|
// @ts-expect-error
|
|
275
350
|
schema.items.type !== "object" && // @ts-expect-error
|
|
276
351
|
schema.items.type !== "array"
|
|
277
352
|
) {
|
|
353
|
+
const cyclicItems = instruction.cyclicDefs !== void 0 && !Array.isArray(schema.items) && Kind in schema.items && schema.items[Kind] === "Ref" && schema.items.$ref !== void 0 && schema.items.$ref in instruction.cyclicDefs.names;
|
|
278
354
|
if (Array.isArray(schema.items)) {
|
|
279
355
|
v = handleTuple(schema.items, property, instruction);
|
|
280
356
|
break;
|
|
281
|
-
} else if (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
357
|
+
} else if (!cyclicItems) {
|
|
358
|
+
if (isRoot && !Array.isArray(schema.items.anyOf))
|
|
359
|
+
return "return v";
|
|
360
|
+
else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
|
|
361
|
+
v = mirror(
|
|
362
|
+
deepClone(
|
|
363
|
+
instruction.definitions[schema.items.$ref]
|
|
364
|
+
),
|
|
365
|
+
property,
|
|
366
|
+
{
|
|
367
|
+
...instruction,
|
|
368
|
+
parentIsOptional: true,
|
|
369
|
+
recursion: instruction.recursion + 1
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
else if (!Array.isArray(schema.items.anyOf)) {
|
|
373
|
+
v = property;
|
|
374
|
+
break;
|
|
375
|
+
}
|
|
296
376
|
}
|
|
297
377
|
}
|
|
298
378
|
const i = instruction.array;
|
|
@@ -357,6 +437,7 @@ var createMirror = (schema, {
|
|
|
357
437
|
emit
|
|
358
438
|
} = {}) => {
|
|
359
439
|
const unions = [];
|
|
440
|
+
const cyclic = { groups: /* @__PURE__ */ new Map(), fns: [], count: 0 };
|
|
360
441
|
if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
|
|
361
442
|
const f = mirror(schema, "v", {
|
|
362
443
|
optionals: [],
|
|
@@ -369,28 +450,34 @@ var createMirror = (schema, {
|
|
|
369
450
|
modules,
|
|
370
451
|
// @ts-ignore private property
|
|
371
452
|
definitions: definitions ?? modules?.$defs ?? {},
|
|
453
|
+
cyclic,
|
|
372
454
|
sanitize: sanitize2,
|
|
373
455
|
recursion: 0,
|
|
374
456
|
recursionLimit,
|
|
375
457
|
removeUnknownUnionType
|
|
376
458
|
});
|
|
459
|
+
const fns = cyclic.fns.length ? cyclic.fns.join("\n") + "\n" : "";
|
|
377
460
|
if (!unions.length && !sanitize2?.length) {
|
|
378
|
-
if (emit) return {
|
|
379
|
-
return Function("v", f);
|
|
461
|
+
if (emit) return { source: fns + f, externals: void 0 };
|
|
462
|
+
return Function("v", fns + f);
|
|
380
463
|
}
|
|
381
464
|
let hof;
|
|
382
465
|
if (sanitize2?.length) {
|
|
383
466
|
hof = {};
|
|
384
467
|
for (let i = 0; i < sanitize2.length; i++) hof[`h${i}`] = sanitize2[i];
|
|
385
468
|
}
|
|
469
|
+
const source = `${fns}return function mirror(v){${f}}`;
|
|
386
470
|
if (emit)
|
|
387
471
|
return {
|
|
388
|
-
|
|
389
|
-
|
|
472
|
+
source,
|
|
473
|
+
externals: {
|
|
474
|
+
unions,
|
|
475
|
+
hof
|
|
476
|
+
}
|
|
390
477
|
};
|
|
391
478
|
return Function(
|
|
392
479
|
"d",
|
|
393
|
-
|
|
480
|
+
source
|
|
394
481
|
)(
|
|
395
482
|
hof ? unions ? {
|
|
396
483
|
unions,
|
package/dist/index.d.ts
CHANGED
|
@@ -57,6 +57,16 @@ export interface Instruction<Emit extends boolean = false> {
|
|
|
57
57
|
typeCompilerWanred?: boolean;
|
|
58
58
|
modules?: TModule<{}>;
|
|
59
59
|
definitions: Record<string, AnySchema>;
|
|
60
|
+
/**
|
|
61
|
+
* Shared cyclic codegen state: generated per-definition mirror
|
|
62
|
+
* functions, grouped by `$defs` object identity
|
|
63
|
+
*/
|
|
64
|
+
cyclic: CyclicContext;
|
|
65
|
+
/**
|
|
66
|
+
* `$defs` group the current cyclic definition body is generated
|
|
67
|
+
* against, used to resolve `Ref` nodes to function calls
|
|
68
|
+
*/
|
|
69
|
+
cyclicDefs?: CyclicGroup;
|
|
60
70
|
recursion: number;
|
|
61
71
|
/**
|
|
62
72
|
* @default 8
|
|
@@ -73,9 +83,21 @@ export interface Instruction<Emit extends boolean = false> {
|
|
|
73
83
|
removeUnknownUnionType: boolean;
|
|
74
84
|
}
|
|
75
85
|
export declare function deepClone<T>(source: T, weak?: WeakMap<object, any>): T;
|
|
86
|
+
interface CyclicGroup {
|
|
87
|
+
defs: Record<string, AnySchema>;
|
|
88
|
+
names: Record<string, string>;
|
|
89
|
+
}
|
|
90
|
+
interface CyclicContext {
|
|
91
|
+
groups: Map<object, CyclicGroup>;
|
|
92
|
+
fns: string[];
|
|
93
|
+
count: number;
|
|
94
|
+
}
|
|
76
95
|
export interface Manifest {
|
|
77
|
-
|
|
78
|
-
|
|
96
|
+
source: string;
|
|
97
|
+
externals: {
|
|
98
|
+
unions: Validator<any, TSchema, unknown, unknown>[][];
|
|
99
|
+
hof?: Record<string, Function>;
|
|
100
|
+
};
|
|
79
101
|
}
|
|
80
102
|
export declare const createMirror: <T extends TSchema, Emit extends boolean = false>(schema: T, { Compile, modules, definitions, sanitize, recursionLimit, removeUnknownUnionType, emit }?: Partial<Pick<Instruction<Emit>, "Compile" | "definitions" | "sanitize" | "modules" | "recursionLimit" | "removeUnknownUnionType" | "emit">>) => Emit extends true ? Manifest : (v: Static<T>) => Static<T>;
|
|
81
103
|
export default createMirror;
|
package/dist/index.mjs
CHANGED
|
@@ -53,7 +53,7 @@ var handleRecord = (schema, property, instruction) => {
|
|
|
53
53
|
var handleTuple = (schema, property, instruction) => {
|
|
54
54
|
const i = instruction.array;
|
|
55
55
|
instruction.array++;
|
|
56
|
-
const isRoot = property === "v" && !instruction.
|
|
56
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
57
57
|
let v = "";
|
|
58
58
|
if (!isRoot) v = `(()=>{`;
|
|
59
59
|
v += `const ar${i}v=[`;
|
|
@@ -95,6 +95,59 @@ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
|
|
|
95
95
|
}
|
|
96
96
|
return source;
|
|
97
97
|
}
|
|
98
|
+
var handleCyclic = (schema, property, instruction) => {
|
|
99
|
+
const defs = schema.$defs;
|
|
100
|
+
let group = instruction.cyclic.groups.get(defs);
|
|
101
|
+
if (!group) {
|
|
102
|
+
group = { defs, names: {} };
|
|
103
|
+
instruction.cyclic.groups.set(defs, group);
|
|
104
|
+
for (const name in defs)
|
|
105
|
+
group.names[name] = `cy${instruction.cyclic.count++}`;
|
|
106
|
+
for (const name in defs)
|
|
107
|
+
instruction.cyclic.fns.push(
|
|
108
|
+
`function ${group.names[name]}(v){${mirror(defs[name], "v", {
|
|
109
|
+
...instruction,
|
|
110
|
+
cyclicDefs: group,
|
|
111
|
+
fromUnion: false,
|
|
112
|
+
parentIsOptional: false,
|
|
113
|
+
optionals: [],
|
|
114
|
+
optionalsInArray: [],
|
|
115
|
+
unionKeys: {},
|
|
116
|
+
array: 0,
|
|
117
|
+
recursion: 0
|
|
118
|
+
})}}`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const fn = group.names[schema.$ref];
|
|
122
|
+
if (!fn)
|
|
123
|
+
throw new Error(
|
|
124
|
+
`[exact-mirror] cyclic reference "${schema.$ref}" is not found in $defs`
|
|
125
|
+
);
|
|
126
|
+
return `(${property}==null?${property}:${fn}(${property}))`;
|
|
127
|
+
};
|
|
128
|
+
var withDefs = (type, group) => {
|
|
129
|
+
if (Kind in type) {
|
|
130
|
+
if (type[Kind] === "Cyclic") return type;
|
|
131
|
+
if (type[Kind] === "Ref" && type.$ref in group.defs)
|
|
132
|
+
return Object.defineProperty(
|
|
133
|
+
{ $defs: group.defs, $ref: type.$ref },
|
|
134
|
+
Kind,
|
|
135
|
+
{ value: "Cyclic" }
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
let entry = "~check";
|
|
139
|
+
while (entry in group.defs) entry += "~";
|
|
140
|
+
const def = Object.create(
|
|
141
|
+
Object.getPrototypeOf(type),
|
|
142
|
+
Object.getOwnPropertyDescriptors(type)
|
|
143
|
+
);
|
|
144
|
+
def.$id = entry;
|
|
145
|
+
return Object.defineProperty(
|
|
146
|
+
{ $defs: { ...group.defs, [entry]: def }, $ref: entry },
|
|
147
|
+
Kind,
|
|
148
|
+
{ value: "Cyclic" }
|
|
149
|
+
);
|
|
150
|
+
};
|
|
98
151
|
var handleUnion = (schemas, property, instruction) => {
|
|
99
152
|
if (instruction.Compile === void 0) {
|
|
100
153
|
if (!instruction.typeCompilerWanred) {
|
|
@@ -116,15 +169,6 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
116
169
|
if (!(Kind in type) || !type.$ref) return type;
|
|
117
170
|
if (type[Kind] === "This")
|
|
118
171
|
return deepClone(instruction.definitions[type.$ref]);
|
|
119
|
-
else if (type[Kind] === "Cyclic") {
|
|
120
|
-
if (!instruction.modules)
|
|
121
|
-
console.warn(
|
|
122
|
-
new Error(
|
|
123
|
-
"[exact-mirror] modules is required when using nested cyclic reference"
|
|
124
|
-
)
|
|
125
|
-
);
|
|
126
|
-
else return instruction.modules.$defs[type.$ref];
|
|
127
|
-
}
|
|
128
172
|
return type;
|
|
129
173
|
};
|
|
130
174
|
let cleanThenCheck = "";
|
|
@@ -139,7 +183,11 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
139
183
|
type.items[i2] = unwrapRef(type.items[i2]);
|
|
140
184
|
else type.items = unwrapRef(type.items);
|
|
141
185
|
}
|
|
142
|
-
typeChecks.push(
|
|
186
|
+
typeChecks.push(
|
|
187
|
+
instruction.Compile(
|
|
188
|
+
instruction.cyclicDefs ? withDefs(type, instruction.cyclicDefs) : type
|
|
189
|
+
)
|
|
190
|
+
);
|
|
143
191
|
v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
|
|
144
192
|
type,
|
|
145
193
|
property,
|
|
@@ -166,12 +214,31 @@ if(d.unions[${ui}][${i}].Check(tmp))return tmp
|
|
|
166
214
|
};
|
|
167
215
|
var mirror = (schema, property, instruction) => {
|
|
168
216
|
if (!schema) return "";
|
|
169
|
-
const isRoot = property === "v" && !instruction.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
217
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
218
|
+
const optionalsLength = instruction.optionals.length;
|
|
219
|
+
try {
|
|
220
|
+
if (Kind in schema && schema[Kind] === "Cyclic") {
|
|
221
|
+
const call = handleCyclic(schema, property, instruction);
|
|
222
|
+
return isRoot ? `return ${call}` : call;
|
|
223
|
+
}
|
|
224
|
+
return mirrorNode(schema, property, instruction);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
instruction.optionals.length = optionalsLength;
|
|
227
|
+
console.warn(
|
|
228
|
+
new Error(
|
|
229
|
+
"[exact-mirror] failed to generate mirror for a schema node, the node is passed through as-is. Please report this issue to https://github.com/elysiajs/exact-mirror/issues"
|
|
230
|
+
),
|
|
231
|
+
error
|
|
232
|
+
);
|
|
233
|
+
return isRoot ? "return v" : property;
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
var mirrorNode = (schema, property, instruction) => {
|
|
237
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
238
|
+
if (instruction.cyclicDefs && Kind in schema && schema[Kind] === "Ref" && schema.$ref && schema.$ref in instruction.cyclicDefs.names) {
|
|
239
|
+
const call = `(${property}==null?${property}:${instruction.cyclicDefs.names[schema.$ref]}(${property}))`;
|
|
240
|
+
return isRoot ? `return ${call}` : call;
|
|
241
|
+
}
|
|
175
242
|
if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
|
|
176
243
|
return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
|
|
177
244
|
if (instruction.recursion >= instruction.recursionLimit) return property;
|
|
@@ -185,6 +252,10 @@ var mirror = (schema, property, instruction) => {
|
|
|
185
252
|
break;
|
|
186
253
|
}
|
|
187
254
|
schema = mergeObjectIntersection(schema);
|
|
255
|
+
if (!schema.properties) {
|
|
256
|
+
v = property;
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
188
259
|
v += "{";
|
|
189
260
|
if (schema.additionalProperties) v += `...${property},`;
|
|
190
261
|
const keys = Object.keys(schema.properties);
|
|
@@ -243,29 +314,38 @@ var mirror = (schema, property, instruction) => {
|
|
|
243
314
|
v += "}";
|
|
244
315
|
break;
|
|
245
316
|
case "array":
|
|
317
|
+
if (!schema.items) {
|
|
318
|
+
v = property;
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
246
321
|
if (
|
|
247
322
|
// @ts-expect-error
|
|
248
323
|
schema.items.type !== "object" && // @ts-expect-error
|
|
249
324
|
schema.items.type !== "array"
|
|
250
325
|
) {
|
|
326
|
+
const cyclicItems = instruction.cyclicDefs !== void 0 && !Array.isArray(schema.items) && Kind in schema.items && schema.items[Kind] === "Ref" && schema.items.$ref !== void 0 && schema.items.$ref in instruction.cyclicDefs.names;
|
|
251
327
|
if (Array.isArray(schema.items)) {
|
|
252
328
|
v = handleTuple(schema.items, property, instruction);
|
|
253
329
|
break;
|
|
254
|
-
} else if (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
330
|
+
} else if (!cyclicItems) {
|
|
331
|
+
if (isRoot && !Array.isArray(schema.items.anyOf))
|
|
332
|
+
return "return v";
|
|
333
|
+
else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
|
|
334
|
+
v = mirror(
|
|
335
|
+
deepClone(
|
|
336
|
+
instruction.definitions[schema.items.$ref]
|
|
337
|
+
),
|
|
338
|
+
property,
|
|
339
|
+
{
|
|
340
|
+
...instruction,
|
|
341
|
+
parentIsOptional: true,
|
|
342
|
+
recursion: instruction.recursion + 1
|
|
343
|
+
}
|
|
344
|
+
);
|
|
345
|
+
else if (!Array.isArray(schema.items.anyOf)) {
|
|
346
|
+
v = property;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
269
349
|
}
|
|
270
350
|
}
|
|
271
351
|
const i = instruction.array;
|
|
@@ -330,6 +410,7 @@ var createMirror = (schema, {
|
|
|
330
410
|
emit
|
|
331
411
|
} = {}) => {
|
|
332
412
|
const unions = [];
|
|
413
|
+
const cyclic = { groups: /* @__PURE__ */ new Map(), fns: [], count: 0 };
|
|
333
414
|
if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
|
|
334
415
|
const f = mirror(schema, "v", {
|
|
335
416
|
optionals: [],
|
|
@@ -342,28 +423,34 @@ var createMirror = (schema, {
|
|
|
342
423
|
modules,
|
|
343
424
|
// @ts-ignore private property
|
|
344
425
|
definitions: definitions ?? modules?.$defs ?? {},
|
|
426
|
+
cyclic,
|
|
345
427
|
sanitize: sanitize2,
|
|
346
428
|
recursion: 0,
|
|
347
429
|
recursionLimit,
|
|
348
430
|
removeUnknownUnionType
|
|
349
431
|
});
|
|
432
|
+
const fns = cyclic.fns.length ? cyclic.fns.join("\n") + "\n" : "";
|
|
350
433
|
if (!unions.length && !sanitize2?.length) {
|
|
351
|
-
if (emit) return {
|
|
352
|
-
return Function("v", f);
|
|
434
|
+
if (emit) return { source: fns + f, externals: void 0 };
|
|
435
|
+
return Function("v", fns + f);
|
|
353
436
|
}
|
|
354
437
|
let hof;
|
|
355
438
|
if (sanitize2?.length) {
|
|
356
439
|
hof = {};
|
|
357
440
|
for (let i = 0; i < sanitize2.length; i++) hof[`h${i}`] = sanitize2[i];
|
|
358
441
|
}
|
|
442
|
+
const source = `${fns}return function mirror(v){${f}}`;
|
|
359
443
|
if (emit)
|
|
360
444
|
return {
|
|
361
|
-
|
|
362
|
-
|
|
445
|
+
source,
|
|
446
|
+
externals: {
|
|
447
|
+
unions,
|
|
448
|
+
hof
|
|
449
|
+
}
|
|
363
450
|
};
|
|
364
451
|
return Function(
|
|
365
452
|
"d",
|
|
366
|
-
|
|
453
|
+
source
|
|
367
454
|
)(
|
|
368
455
|
hof ? unions ? {
|
|
369
456
|
unions,
|