exact-mirror 1.0.2 → 1.1.1
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 +19 -0
- package/dist/cjs/index.js +122 -38
- package/dist/index.d.ts +19 -0
- package/dist/index.mjs +122 -38
- 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,6 +83,15 @@ 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
96
|
source: string;
|
|
78
97
|
externals: {
|
package/dist/cjs/index.js
CHANGED
|
@@ -28,13 +28,14 @@ __export(index_exports, {
|
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
29
|
var Kind = "~kind";
|
|
30
30
|
var Hint = "~hint";
|
|
31
|
-
var isSpecialProperty = (name) =>
|
|
31
|
+
var isSpecialProperty = (name) => !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
|
|
32
32
|
var joinProperty = (v1, v2, isOptional = false) => {
|
|
33
33
|
if (typeof v2 === "number") return `${v1}[${v2}]`;
|
|
34
|
-
if (isSpecialProperty(v2))
|
|
34
|
+
if (isSpecialProperty(v2))
|
|
35
|
+
return `${v1}${isOptional ? "?." : ""}[${JSON.stringify(v2)}]`;
|
|
35
36
|
return `${v1}${isOptional ? "?" : ""}.${v2}`;
|
|
36
37
|
};
|
|
37
|
-
var encodeProperty = (v) => isSpecialProperty(v) ?
|
|
38
|
+
var encodeProperty = (v) => isSpecialProperty(v) ? JSON.stringify(v) : v;
|
|
38
39
|
var sanitize = (key, sanitize2 = 0, schema) => {
|
|
39
40
|
if (schema.type !== "string" || schema.const || schema.trusted) return key;
|
|
40
41
|
let hof = "";
|
|
@@ -80,7 +81,7 @@ var handleRecord = (schema, property, instruction) => {
|
|
|
80
81
|
var handleTuple = (schema, property, instruction) => {
|
|
81
82
|
const i = instruction.array;
|
|
82
83
|
instruction.array++;
|
|
83
|
-
const isRoot = property === "v" && !instruction.
|
|
84
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
84
85
|
let v = "";
|
|
85
86
|
if (!isRoot) v = `(()=>{`;
|
|
86
87
|
v += `const ar${i}v=[`;
|
|
@@ -122,6 +123,59 @@ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
|
|
|
122
123
|
}
|
|
123
124
|
return source;
|
|
124
125
|
}
|
|
126
|
+
var handleCyclic = (schema, property, instruction) => {
|
|
127
|
+
const defs = schema.$defs;
|
|
128
|
+
let group = instruction.cyclic.groups.get(defs);
|
|
129
|
+
if (!group) {
|
|
130
|
+
group = { defs, names: {} };
|
|
131
|
+
instruction.cyclic.groups.set(defs, group);
|
|
132
|
+
for (const name in defs)
|
|
133
|
+
group.names[name] = `cy${instruction.cyclic.count++}`;
|
|
134
|
+
for (const name in defs)
|
|
135
|
+
instruction.cyclic.fns.push(
|
|
136
|
+
`function ${group.names[name]}(v){${mirror(defs[name], "v", {
|
|
137
|
+
...instruction,
|
|
138
|
+
cyclicDefs: group,
|
|
139
|
+
fromUnion: false,
|
|
140
|
+
parentIsOptional: false,
|
|
141
|
+
optionals: [],
|
|
142
|
+
optionalsInArray: [],
|
|
143
|
+
unionKeys: {},
|
|
144
|
+
array: 0,
|
|
145
|
+
recursion: 0
|
|
146
|
+
})}}`
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
const fn = group.names[schema.$ref];
|
|
150
|
+
if (!fn)
|
|
151
|
+
throw new Error(
|
|
152
|
+
`[exact-mirror] cyclic reference "${schema.$ref}" is not found in $defs`
|
|
153
|
+
);
|
|
154
|
+
return `(${property}==null?${property}:${fn}(${property}))`;
|
|
155
|
+
};
|
|
156
|
+
var withDefs = (type, group) => {
|
|
157
|
+
if (Kind in type) {
|
|
158
|
+
if (type[Kind] === "Cyclic") return type;
|
|
159
|
+
if (type[Kind] === "Ref" && type.$ref in group.defs)
|
|
160
|
+
return Object.defineProperty(
|
|
161
|
+
{ $defs: group.defs, $ref: type.$ref },
|
|
162
|
+
Kind,
|
|
163
|
+
{ value: "Cyclic" }
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
let entry = "~check";
|
|
167
|
+
while (entry in group.defs) entry += "~";
|
|
168
|
+
const def = Object.create(
|
|
169
|
+
Object.getPrototypeOf(type),
|
|
170
|
+
Object.getOwnPropertyDescriptors(type)
|
|
171
|
+
);
|
|
172
|
+
def.$id = entry;
|
|
173
|
+
return Object.defineProperty(
|
|
174
|
+
{ $defs: { ...group.defs, [entry]: def }, $ref: entry },
|
|
175
|
+
Kind,
|
|
176
|
+
{ value: "Cyclic" }
|
|
177
|
+
);
|
|
178
|
+
};
|
|
125
179
|
var handleUnion = (schemas, property, instruction) => {
|
|
126
180
|
if (instruction.Compile === void 0) {
|
|
127
181
|
if (!instruction.typeCompilerWanred) {
|
|
@@ -143,15 +197,6 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
143
197
|
if (!(Kind in type) || !type.$ref) return type;
|
|
144
198
|
if (type[Kind] === "This")
|
|
145
199
|
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
200
|
return type;
|
|
156
201
|
};
|
|
157
202
|
let cleanThenCheck = "";
|
|
@@ -166,7 +211,11 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
166
211
|
type.items[i2] = unwrapRef(type.items[i2]);
|
|
167
212
|
else type.items = unwrapRef(type.items);
|
|
168
213
|
}
|
|
169
|
-
typeChecks.push(
|
|
214
|
+
typeChecks.push(
|
|
215
|
+
instruction.Compile(
|
|
216
|
+
instruction.cyclicDefs ? withDefs(type, instruction.cyclicDefs) : type
|
|
217
|
+
)
|
|
218
|
+
);
|
|
170
219
|
v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
|
|
171
220
|
type,
|
|
172
221
|
property,
|
|
@@ -193,12 +242,31 @@ if(d.unions[${ui}][${i}].Check(tmp))return tmp
|
|
|
193
242
|
};
|
|
194
243
|
var mirror = (schema, property, instruction) => {
|
|
195
244
|
if (!schema) return "";
|
|
196
|
-
const isRoot = property === "v" && !instruction.
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
245
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
246
|
+
const optionalsLength = instruction.optionals.length;
|
|
247
|
+
try {
|
|
248
|
+
if (Kind in schema && schema[Kind] === "Cyclic") {
|
|
249
|
+
const call = handleCyclic(schema, property, instruction);
|
|
250
|
+
return isRoot ? `return ${call}` : call;
|
|
251
|
+
}
|
|
252
|
+
return mirrorNode(schema, property, instruction);
|
|
253
|
+
} catch (error) {
|
|
254
|
+
instruction.optionals.length = optionalsLength;
|
|
255
|
+
console.warn(
|
|
256
|
+
new Error(
|
|
257
|
+
"[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"
|
|
258
|
+
),
|
|
259
|
+
error
|
|
260
|
+
);
|
|
261
|
+
return isRoot ? "return v" : property;
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
var mirrorNode = (schema, property, instruction) => {
|
|
265
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
266
|
+
if (instruction.cyclicDefs && Kind in schema && schema[Kind] === "Ref" && schema.$ref && schema.$ref in instruction.cyclicDefs.names) {
|
|
267
|
+
const call = `(${property}==null?${property}:${instruction.cyclicDefs.names[schema.$ref]}(${property}))`;
|
|
268
|
+
return isRoot ? `return ${call}` : call;
|
|
269
|
+
}
|
|
202
270
|
if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
|
|
203
271
|
return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
|
|
204
272
|
if (instruction.recursion >= instruction.recursionLimit) return property;
|
|
@@ -212,6 +280,10 @@ var mirror = (schema, property, instruction) => {
|
|
|
212
280
|
break;
|
|
213
281
|
}
|
|
214
282
|
schema = mergeObjectIntersection(schema);
|
|
283
|
+
if (!schema.properties) {
|
|
284
|
+
v = property;
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
215
287
|
v += "{";
|
|
216
288
|
if (schema.additionalProperties) v += `...${property},`;
|
|
217
289
|
const keys = Object.keys(schema.properties);
|
|
@@ -270,29 +342,38 @@ var mirror = (schema, property, instruction) => {
|
|
|
270
342
|
v += "}";
|
|
271
343
|
break;
|
|
272
344
|
case "array":
|
|
345
|
+
if (!schema.items) {
|
|
346
|
+
v = property;
|
|
347
|
+
break;
|
|
348
|
+
}
|
|
273
349
|
if (
|
|
274
350
|
// @ts-expect-error
|
|
275
351
|
schema.items.type !== "object" && // @ts-expect-error
|
|
276
352
|
schema.items.type !== "array"
|
|
277
353
|
) {
|
|
354
|
+
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
355
|
if (Array.isArray(schema.items)) {
|
|
279
356
|
v = handleTuple(schema.items, property, instruction);
|
|
280
357
|
break;
|
|
281
|
-
} else if (
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
358
|
+
} else if (!cyclicItems) {
|
|
359
|
+
if (isRoot && !Array.isArray(schema.items.anyOf))
|
|
360
|
+
return "return v";
|
|
361
|
+
else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
|
|
362
|
+
v = mirror(
|
|
363
|
+
deepClone(
|
|
364
|
+
instruction.definitions[schema.items.$ref]
|
|
365
|
+
),
|
|
366
|
+
property,
|
|
367
|
+
{
|
|
368
|
+
...instruction,
|
|
369
|
+
parentIsOptional: true,
|
|
370
|
+
recursion: instruction.recursion + 1
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
else if (!Array.isArray(schema.items.anyOf)) {
|
|
374
|
+
v = property;
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
296
377
|
}
|
|
297
378
|
}
|
|
298
379
|
const i = instruction.array;
|
|
@@ -357,6 +438,7 @@ var createMirror = (schema, {
|
|
|
357
438
|
emit
|
|
358
439
|
} = {}) => {
|
|
359
440
|
const unions = [];
|
|
441
|
+
const cyclic = { groups: /* @__PURE__ */ new Map(), fns: [], count: 0 };
|
|
360
442
|
if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
|
|
361
443
|
const f = mirror(schema, "v", {
|
|
362
444
|
optionals: [],
|
|
@@ -369,21 +451,23 @@ var createMirror = (schema, {
|
|
|
369
451
|
modules,
|
|
370
452
|
// @ts-ignore private property
|
|
371
453
|
definitions: definitions ?? modules?.$defs ?? {},
|
|
454
|
+
cyclic,
|
|
372
455
|
sanitize: sanitize2,
|
|
373
456
|
recursion: 0,
|
|
374
457
|
recursionLimit,
|
|
375
458
|
removeUnknownUnionType
|
|
376
459
|
});
|
|
460
|
+
const fns = cyclic.fns.length ? cyclic.fns.join("\n") + "\n" : "";
|
|
377
461
|
if (!unions.length && !sanitize2?.length) {
|
|
378
|
-
if (emit) return { source: f, externals: void 0 };
|
|
379
|
-
return Function("v", f);
|
|
462
|
+
if (emit) return { source: fns + f, externals: void 0 };
|
|
463
|
+
return Function("v", fns + f);
|
|
380
464
|
}
|
|
381
465
|
let hof;
|
|
382
466
|
if (sanitize2?.length) {
|
|
383
467
|
hof = {};
|
|
384
468
|
for (let i = 0; i < sanitize2.length; i++) hof[`h${i}`] = sanitize2[i];
|
|
385
469
|
}
|
|
386
|
-
const source =
|
|
470
|
+
const source = `${fns}return function mirror(v){${f}}`;
|
|
387
471
|
if (emit)
|
|
388
472
|
return {
|
|
389
473
|
source,
|
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,6 +83,15 @@ 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
96
|
source: string;
|
|
78
97
|
externals: {
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
var Kind = "~kind";
|
|
3
3
|
var Hint = "~hint";
|
|
4
|
-
var isSpecialProperty = (name) =>
|
|
4
|
+
var isSpecialProperty = (name) => !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
|
|
5
5
|
var joinProperty = (v1, v2, isOptional = false) => {
|
|
6
6
|
if (typeof v2 === "number") return `${v1}[${v2}]`;
|
|
7
|
-
if (isSpecialProperty(v2))
|
|
7
|
+
if (isSpecialProperty(v2))
|
|
8
|
+
return `${v1}${isOptional ? "?." : ""}[${JSON.stringify(v2)}]`;
|
|
8
9
|
return `${v1}${isOptional ? "?" : ""}.${v2}`;
|
|
9
10
|
};
|
|
10
|
-
var encodeProperty = (v) => isSpecialProperty(v) ?
|
|
11
|
+
var encodeProperty = (v) => isSpecialProperty(v) ? JSON.stringify(v) : v;
|
|
11
12
|
var sanitize = (key, sanitize2 = 0, schema) => {
|
|
12
13
|
if (schema.type !== "string" || schema.const || schema.trusted) return key;
|
|
13
14
|
let hof = "";
|
|
@@ -53,7 +54,7 @@ var handleRecord = (schema, property, instruction) => {
|
|
|
53
54
|
var handleTuple = (schema, property, instruction) => {
|
|
54
55
|
const i = instruction.array;
|
|
55
56
|
instruction.array++;
|
|
56
|
-
const isRoot = property === "v" && !instruction.
|
|
57
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
57
58
|
let v = "";
|
|
58
59
|
if (!isRoot) v = `(()=>{`;
|
|
59
60
|
v += `const ar${i}v=[`;
|
|
@@ -95,6 +96,59 @@ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
|
|
|
95
96
|
}
|
|
96
97
|
return source;
|
|
97
98
|
}
|
|
99
|
+
var handleCyclic = (schema, property, instruction) => {
|
|
100
|
+
const defs = schema.$defs;
|
|
101
|
+
let group = instruction.cyclic.groups.get(defs);
|
|
102
|
+
if (!group) {
|
|
103
|
+
group = { defs, names: {} };
|
|
104
|
+
instruction.cyclic.groups.set(defs, group);
|
|
105
|
+
for (const name in defs)
|
|
106
|
+
group.names[name] = `cy${instruction.cyclic.count++}`;
|
|
107
|
+
for (const name in defs)
|
|
108
|
+
instruction.cyclic.fns.push(
|
|
109
|
+
`function ${group.names[name]}(v){${mirror(defs[name], "v", {
|
|
110
|
+
...instruction,
|
|
111
|
+
cyclicDefs: group,
|
|
112
|
+
fromUnion: false,
|
|
113
|
+
parentIsOptional: false,
|
|
114
|
+
optionals: [],
|
|
115
|
+
optionalsInArray: [],
|
|
116
|
+
unionKeys: {},
|
|
117
|
+
array: 0,
|
|
118
|
+
recursion: 0
|
|
119
|
+
})}}`
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const fn = group.names[schema.$ref];
|
|
123
|
+
if (!fn)
|
|
124
|
+
throw new Error(
|
|
125
|
+
`[exact-mirror] cyclic reference "${schema.$ref}" is not found in $defs`
|
|
126
|
+
);
|
|
127
|
+
return `(${property}==null?${property}:${fn}(${property}))`;
|
|
128
|
+
};
|
|
129
|
+
var withDefs = (type, group) => {
|
|
130
|
+
if (Kind in type) {
|
|
131
|
+
if (type[Kind] === "Cyclic") return type;
|
|
132
|
+
if (type[Kind] === "Ref" && type.$ref in group.defs)
|
|
133
|
+
return Object.defineProperty(
|
|
134
|
+
{ $defs: group.defs, $ref: type.$ref },
|
|
135
|
+
Kind,
|
|
136
|
+
{ value: "Cyclic" }
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
let entry = "~check";
|
|
140
|
+
while (entry in group.defs) entry += "~";
|
|
141
|
+
const def = Object.create(
|
|
142
|
+
Object.getPrototypeOf(type),
|
|
143
|
+
Object.getOwnPropertyDescriptors(type)
|
|
144
|
+
);
|
|
145
|
+
def.$id = entry;
|
|
146
|
+
return Object.defineProperty(
|
|
147
|
+
{ $defs: { ...group.defs, [entry]: def }, $ref: entry },
|
|
148
|
+
Kind,
|
|
149
|
+
{ value: "Cyclic" }
|
|
150
|
+
);
|
|
151
|
+
};
|
|
98
152
|
var handleUnion = (schemas, property, instruction) => {
|
|
99
153
|
if (instruction.Compile === void 0) {
|
|
100
154
|
if (!instruction.typeCompilerWanred) {
|
|
@@ -116,15 +170,6 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
116
170
|
if (!(Kind in type) || !type.$ref) return type;
|
|
117
171
|
if (type[Kind] === "This")
|
|
118
172
|
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
173
|
return type;
|
|
129
174
|
};
|
|
130
175
|
let cleanThenCheck = "";
|
|
@@ -139,7 +184,11 @@ var handleUnion = (schemas, property, instruction) => {
|
|
|
139
184
|
type.items[i2] = unwrapRef(type.items[i2]);
|
|
140
185
|
else type.items = unwrapRef(type.items);
|
|
141
186
|
}
|
|
142
|
-
typeChecks.push(
|
|
187
|
+
typeChecks.push(
|
|
188
|
+
instruction.Compile(
|
|
189
|
+
instruction.cyclicDefs ? withDefs(type, instruction.cyclicDefs) : type
|
|
190
|
+
)
|
|
191
|
+
);
|
|
143
192
|
v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
|
|
144
193
|
type,
|
|
145
194
|
property,
|
|
@@ -166,12 +215,31 @@ if(d.unions[${ui}][${i}].Check(tmp))return tmp
|
|
|
166
215
|
};
|
|
167
216
|
var mirror = (schema, property, instruction) => {
|
|
168
217
|
if (!schema) return "";
|
|
169
|
-
const isRoot = property === "v" && !instruction.
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
218
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
219
|
+
const optionalsLength = instruction.optionals.length;
|
|
220
|
+
try {
|
|
221
|
+
if (Kind in schema && schema[Kind] === "Cyclic") {
|
|
222
|
+
const call = handleCyclic(schema, property, instruction);
|
|
223
|
+
return isRoot ? `return ${call}` : call;
|
|
224
|
+
}
|
|
225
|
+
return mirrorNode(schema, property, instruction);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
instruction.optionals.length = optionalsLength;
|
|
228
|
+
console.warn(
|
|
229
|
+
new Error(
|
|
230
|
+
"[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"
|
|
231
|
+
),
|
|
232
|
+
error
|
|
233
|
+
);
|
|
234
|
+
return isRoot ? "return v" : property;
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
var mirrorNode = (schema, property, instruction) => {
|
|
238
|
+
const isRoot = property === "v" && !instruction.fromUnion;
|
|
239
|
+
if (instruction.cyclicDefs && Kind in schema && schema[Kind] === "Ref" && schema.$ref && schema.$ref in instruction.cyclicDefs.names) {
|
|
240
|
+
const call = `(${property}==null?${property}:${instruction.cyclicDefs.names[schema.$ref]}(${property}))`;
|
|
241
|
+
return isRoot ? `return ${call}` : call;
|
|
242
|
+
}
|
|
175
243
|
if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
|
|
176
244
|
return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
|
|
177
245
|
if (instruction.recursion >= instruction.recursionLimit) return property;
|
|
@@ -185,6 +253,10 @@ var mirror = (schema, property, instruction) => {
|
|
|
185
253
|
break;
|
|
186
254
|
}
|
|
187
255
|
schema = mergeObjectIntersection(schema);
|
|
256
|
+
if (!schema.properties) {
|
|
257
|
+
v = property;
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
188
260
|
v += "{";
|
|
189
261
|
if (schema.additionalProperties) v += `...${property},`;
|
|
190
262
|
const keys = Object.keys(schema.properties);
|
|
@@ -243,29 +315,38 @@ var mirror = (schema, property, instruction) => {
|
|
|
243
315
|
v += "}";
|
|
244
316
|
break;
|
|
245
317
|
case "array":
|
|
318
|
+
if (!schema.items) {
|
|
319
|
+
v = property;
|
|
320
|
+
break;
|
|
321
|
+
}
|
|
246
322
|
if (
|
|
247
323
|
// @ts-expect-error
|
|
248
324
|
schema.items.type !== "object" && // @ts-expect-error
|
|
249
325
|
schema.items.type !== "array"
|
|
250
326
|
) {
|
|
327
|
+
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
328
|
if (Array.isArray(schema.items)) {
|
|
252
329
|
v = handleTuple(schema.items, property, instruction);
|
|
253
330
|
break;
|
|
254
|
-
} else if (
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
331
|
+
} else if (!cyclicItems) {
|
|
332
|
+
if (isRoot && !Array.isArray(schema.items.anyOf))
|
|
333
|
+
return "return v";
|
|
334
|
+
else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
|
|
335
|
+
v = mirror(
|
|
336
|
+
deepClone(
|
|
337
|
+
instruction.definitions[schema.items.$ref]
|
|
338
|
+
),
|
|
339
|
+
property,
|
|
340
|
+
{
|
|
341
|
+
...instruction,
|
|
342
|
+
parentIsOptional: true,
|
|
343
|
+
recursion: instruction.recursion + 1
|
|
344
|
+
}
|
|
345
|
+
);
|
|
346
|
+
else if (!Array.isArray(schema.items.anyOf)) {
|
|
347
|
+
v = property;
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
269
350
|
}
|
|
270
351
|
}
|
|
271
352
|
const i = instruction.array;
|
|
@@ -330,6 +411,7 @@ var createMirror = (schema, {
|
|
|
330
411
|
emit
|
|
331
412
|
} = {}) => {
|
|
332
413
|
const unions = [];
|
|
414
|
+
const cyclic = { groups: /* @__PURE__ */ new Map(), fns: [], count: 0 };
|
|
333
415
|
if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
|
|
334
416
|
const f = mirror(schema, "v", {
|
|
335
417
|
optionals: [],
|
|
@@ -342,21 +424,23 @@ var createMirror = (schema, {
|
|
|
342
424
|
modules,
|
|
343
425
|
// @ts-ignore private property
|
|
344
426
|
definitions: definitions ?? modules?.$defs ?? {},
|
|
427
|
+
cyclic,
|
|
345
428
|
sanitize: sanitize2,
|
|
346
429
|
recursion: 0,
|
|
347
430
|
recursionLimit,
|
|
348
431
|
removeUnknownUnionType
|
|
349
432
|
});
|
|
433
|
+
const fns = cyclic.fns.length ? cyclic.fns.join("\n") + "\n" : "";
|
|
350
434
|
if (!unions.length && !sanitize2?.length) {
|
|
351
|
-
if (emit) return { source: f, externals: void 0 };
|
|
352
|
-
return Function("v", f);
|
|
435
|
+
if (emit) return { source: fns + f, externals: void 0 };
|
|
436
|
+
return Function("v", fns + f);
|
|
353
437
|
}
|
|
354
438
|
let hof;
|
|
355
439
|
if (sanitize2?.length) {
|
|
356
440
|
hof = {};
|
|
357
441
|
for (let i = 0; i < sanitize2.length; i++) hof[`h${i}`] = sanitize2[i];
|
|
358
442
|
}
|
|
359
|
-
const source =
|
|
443
|
+
const source = `${fns}return function mirror(v){${f}}`;
|
|
360
444
|
if (emit)
|
|
361
445
|
return {
|
|
362
446
|
source,
|