exact-mirror 1.1.1 → 1.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exact-mirror",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Mirror exact value to TypeBox/OpenAPI model",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -23,7 +23,7 @@
23
23
  "elysia": "^1.4.28",
24
24
  "eslint": "9.6.0",
25
25
  "mitata": "^1.0.33",
26
- "tsup": "^8.1.0",
26
+ "tsdown": "^0.22.2",
27
27
  "tsx": "^4.19.2",
28
28
  "typebox": "^1.1.15",
29
29
  "typescript": "^6.0.0"
@@ -36,7 +36,7 @@
36
36
  ".": {
37
37
  "types": "./dist/index.d.ts",
38
38
  "import": "./dist/index.mjs",
39
- "require": "./dist/cjs/index.js"
39
+ "require": "./dist/index.js"
40
40
  }
41
41
  },
42
42
  "keywords": [
@@ -1,103 +0,0 @@
1
- import type { TSchema, TModule, Static } from 'typebox';
2
- import type { Compile, Validator } from 'typebox/compile';
3
- interface BaseSchema {
4
- '~kind': string;
5
- id?: string;
6
- $id?: string;
7
- type?: string;
8
- $schema?: string;
9
- const?: unknown[];
10
- pattern?: string;
11
- additionalItems?: boolean | AnySchema;
12
- items?: AnySchema | AnySchema[];
13
- required?: string[];
14
- additionalProperties?: boolean | AnySchema;
15
- definitions?: {
16
- [name: string]: AnySchema;
17
- };
18
- properties?: {
19
- [name: string]: AnySchema;
20
- };
21
- patternProperties?: {
22
- [name: string]: AnySchema;
23
- };
24
- dependencies?: {
25
- [name: string]: AnySchema | string[];
26
- };
27
- enum?: any[];
28
- allOf?: AnySchema[];
29
- anyOf?: AnySchema[];
30
- oneOf?: AnySchema[];
31
- not?: AnySchema;
32
- $ref?: string;
33
- $defs?: Record<string, AnySchema>;
34
- }
35
- type AnySchema = TSchema & BaseSchema;
36
- export declare const mergeObjectIntersection: (schema: AnySchema) => AnySchema;
37
- type MaybeArray<T> = T | T[];
38
- export interface Instruction<Emit extends boolean = false> {
39
- optionals: string[];
40
- optionalsInArray: string[][];
41
- parentIsOptional: boolean;
42
- array: number;
43
- unions: Validator<any>[][];
44
- unionKeys: Record<string, 1>;
45
- sanitize: MaybeArray<(v: string) => string> | undefined;
46
- fromUnion?: boolean;
47
- emit?: Emit;
48
- /**
49
- * TypeCompiler is required when using Union
50
- *
51
- * Left as opt-in to reduce bundle size
52
- * many end-user doesn't use Union
53
- *
54
- * @default undefined
55
- */
56
- Compile?: typeof Compile;
57
- typeCompilerWanred?: boolean;
58
- modules?: TModule<{}>;
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;
70
- recursion: number;
71
- /**
72
- * @default 8
73
- */
74
- recursionLimit: number;
75
- /**
76
- * If incorrect type is passed to Union value, should it be removed?
77
- *
78
- * If you check a value later, it's recommended to set this to `false`
79
- * otherwise, set this to true
80
- *
81
- * @default false
82
- */
83
- removeUnknownUnionType: boolean;
84
- }
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
- }
95
- export interface Manifest {
96
- source: string;
97
- externals: {
98
- unions: Validator<any, TSchema, unknown, unknown>[][];
99
- hof?: Record<string, Function>;
100
- };
101
- }
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>;
103
- export default createMirror;
package/dist/cjs/index.js DELETED
@@ -1,495 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- createMirror: () => createMirror,
24
- deepClone: () => deepClone,
25
- default: () => index_default,
26
- mergeObjectIntersection: () => mergeObjectIntersection
27
- });
28
- module.exports = __toCommonJS(index_exports);
29
- var Kind = "~kind";
30
- var Hint = "~hint";
31
- var isSpecialProperty = (name) => !/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
32
- var joinProperty = (v1, v2, isOptional = false) => {
33
- if (typeof v2 === "number") return `${v1}[${v2}]`;
34
- if (isSpecialProperty(v2))
35
- return `${v1}${isOptional ? "?." : ""}[${JSON.stringify(v2)}]`;
36
- return `${v1}${isOptional ? "?" : ""}.${v2}`;
37
- };
38
- var encodeProperty = (v) => isSpecialProperty(v) ? JSON.stringify(v) : v;
39
- var sanitize = (key, sanitize2 = 0, schema) => {
40
- if (schema.type !== "string" || schema.const || schema.trusted) return key;
41
- let hof = "";
42
- for (let i = sanitize2 - 1; i >= 0; i--) hof += `d.h${i}(`;
43
- return hof + key + ")".repeat(sanitize2);
44
- };
45
- var mergeObjectIntersection = (schema) => {
46
- if (!schema.allOf || Kind in schema && (schema[Kind] !== "Intersect" || schema.type !== "object"))
47
- return schema;
48
- const { allOf, ...newSchema } = schema;
49
- newSchema.properties = {};
50
- if (Kind in newSchema) newSchema[Kind] = "Object";
51
- for (const type of allOf) {
52
- if (type.type !== "object") continue;
53
- const { properties, required, type: _, [Kind]: __, ...rest } = type;
54
- if (required)
55
- newSchema.required = newSchema.required ? newSchema.required.concat(required) : required;
56
- Object.assign(newSchema, rest);
57
- for (const property in type.properties)
58
- newSchema.properties[property] = mergeObjectIntersection(
59
- type.properties[property]
60
- );
61
- }
62
- return newSchema;
63
- };
64
- var handleRecord = (schema, property, instruction) => {
65
- const child = schema.patternProperties["^(.*)$"] ?? schema.patternProperties[Object.keys(schema.patternProperties)[0]];
66
- if (!child) return property;
67
- const i = instruction.array;
68
- instruction.array++;
69
- let v = `(()=>{const ar${i}s=Object.keys(${property}),ar${i}v={};for(let i=0;i<ar${i}s.length;i++){const ar${i}p=${property}[ar${i}s[i]];ar${i}v[ar${i}s[i]]=${mirror(child, `ar${i}p`, instruction)}`;
70
- const optionals = instruction.optionalsInArray[i + 1];
71
- if (optionals) {
72
- for (let oi = 0; oi < optionals.length; oi++) {
73
- const target = `ar${i}v[ar${i}s[i]]${optionals[oi]}`;
74
- v += `;if(${target}===undefined)delete ${target}`;
75
- }
76
- instruction.optionalsInArray[i + 1] = [];
77
- }
78
- v += `}return ar${i}v})()`;
79
- return v;
80
- };
81
- var handleTuple = (schema, property, instruction) => {
82
- const i = instruction.array;
83
- instruction.array++;
84
- const isRoot = property === "v" && !instruction.fromUnion;
85
- let v = "";
86
- if (!isRoot) v = `(()=>{`;
87
- v += `const ar${i}v=[`;
88
- for (let i2 = 0; i2 < schema.length; i2++) {
89
- if (i2 !== 0) v += ",";
90
- v += mirror(
91
- schema[i2],
92
- joinProperty(
93
- property,
94
- i2,
95
- instruction.parentIsOptional || instruction.fromUnion
96
- ),
97
- instruction
98
- );
99
- }
100
- v += `];`;
101
- if (!isRoot) v += `return ar${i}v})()`;
102
- return v;
103
- };
104
- function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
105
- if (source === null || typeof source !== "object" || typeof source === "function")
106
- return source;
107
- if (weak.has(source)) return weak.get(source);
108
- if (Array.isArray(source)) {
109
- const copy = new Array(source.length);
110
- weak.set(source, copy);
111
- for (let i = 0; i < source.length; i++)
112
- copy[i] = deepClone(source[i], weak);
113
- return copy;
114
- }
115
- if (typeof source === "object") {
116
- const keys = Object.keys(source).concat(
117
- Object.getOwnPropertySymbols(source)
118
- );
119
- const cloned = {};
120
- for (const key of keys)
121
- cloned[key] = deepClone(source[key], weak);
122
- return cloned;
123
- }
124
- return source;
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
- };
179
- var handleUnion = (schemas, property, instruction) => {
180
- if (instruction.Compile === void 0) {
181
- if (!instruction.typeCompilerWanred) {
182
- console.warn(
183
- new Error(
184
- "[exact-mirror] TypeBox's TypeCompiler is required to use Union"
185
- )
186
- );
187
- instruction.typeCompilerWanred = true;
188
- }
189
- return property;
190
- }
191
- instruction.unionKeys[property] = 1;
192
- const ui = instruction.unions.length;
193
- const typeChecks = instruction.unions[ui] = [];
194
- let v = `(()=>{
195
- `;
196
- const unwrapRef = (type) => {
197
- if (!(Kind in type) || !type.$ref) return type;
198
- if (type[Kind] === "This")
199
- return deepClone(instruction.definitions[type.$ref]);
200
- return type;
201
- };
202
- let cleanThenCheck = "";
203
- for (let i = 0; i < schemas.length; i++) {
204
- let type = unwrapRef(schemas[i]);
205
- if (Array.isArray(type.anyOf))
206
- for (let i2 = 0; i2 < type.anyOf.length; i2++)
207
- type.anyOf[i2] = unwrapRef(type.anyOf[i2]);
208
- else if (type.items) {
209
- if (Array.isArray(type.items))
210
- for (let i2 = 0; i2 < type.items.length; i2++)
211
- type.items[i2] = unwrapRef(type.items[i2]);
212
- else type.items = unwrapRef(type.items);
213
- }
214
- typeChecks.push(
215
- instruction.Compile(
216
- instruction.cyclicDefs ? withDefs(type, instruction.cyclicDefs) : type
217
- )
218
- );
219
- v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
220
- type,
221
- property,
222
- {
223
- ...instruction,
224
- recursion: instruction.recursion + 1,
225
- parentIsOptional: true,
226
- fromUnion: true
227
- }
228
- )}}
229
- `;
230
- cleanThenCheck += (i ? "" : "let ") + "tmp=" + mirror(type, property, {
231
- ...instruction,
232
- recursion: instruction.recursion + 1,
233
- parentIsOptional: true,
234
- fromUnion: true
235
- }) + `
236
- if(d.unions[${ui}][${i}].Check(tmp))return tmp
237
- `;
238
- }
239
- if (cleanThenCheck) v += cleanThenCheck;
240
- v += `return ${instruction.removeUnknownUnionType ? "undefined" : property}`;
241
- return v + `})()`;
242
- };
243
- var mirror = (schema, property, instruction) => {
244
- if (!schema) return "";
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
- }
270
- if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
271
- return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
272
- if (instruction.recursion >= instruction.recursionLimit) return property;
273
- let v = "";
274
- if (schema.$id && Hint in schema)
275
- instruction.definitions[schema.$id] = schema;
276
- switch (schema.type) {
277
- case "object":
278
- if (schema[Kind] === "Record") {
279
- v = handleRecord(schema, property, instruction);
280
- break;
281
- }
282
- schema = mergeObjectIntersection(schema);
283
- if (!schema.properties) {
284
- v = property;
285
- break;
286
- }
287
- v += "{";
288
- if (schema.additionalProperties) v += `...${property},`;
289
- const keys = Object.keys(schema.properties);
290
- for (let i2 = 0; i2 < keys.length; i2++) {
291
- const key = keys[i2];
292
- let isOptional = (
293
- // all fields are optional
294
- !schema.required || // field is explicitly required
295
- schema.required && !schema.required.includes(key) || Array.isArray(schema.properties[key].anyOf)
296
- );
297
- const name = joinProperty(
298
- property,
299
- key,
300
- // If parent is a union, any property could be undefined
301
- instruction.parentIsOptional || instruction.fromUnion
302
- );
303
- if (isOptional) {
304
- const index = instruction.array;
305
- if (property.startsWith("ar")) {
306
- const dotIndex = name.indexOf(".");
307
- let refName;
308
- if (dotIndex >= 0) {
309
- refName = name.slice(dotIndex);
310
- } else {
311
- refName = name.slice(property.length);
312
- }
313
- if (refName.startsWith("?.")) {
314
- if (refName.charAt(2) === "[") {
315
- refName = refName.slice(2);
316
- } else {
317
- refName = refName.slice(1);
318
- }
319
- }
320
- const array = instruction.optionalsInArray;
321
- if (array[index]) {
322
- array[index].push(refName);
323
- } else {
324
- array[index] = [refName];
325
- }
326
- } else {
327
- instruction.optionals.push(name);
328
- }
329
- }
330
- const child = schema.properties[key];
331
- if (i2 !== 0) v += ",";
332
- v += `${encodeProperty(key)}:${isOptional ? `${name}===undefined?undefined:` : ""}${mirror(
333
- child,
334
- name,
335
- {
336
- ...instruction,
337
- recursion: instruction.recursion + 1,
338
- parentIsOptional: isOptional
339
- }
340
- )}`;
341
- }
342
- v += "}";
343
- break;
344
- case "array":
345
- if (!schema.items) {
346
- v = property;
347
- break;
348
- }
349
- if (
350
- // @ts-expect-error
351
- schema.items.type !== "object" && // @ts-expect-error
352
- schema.items.type !== "array"
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;
355
- if (Array.isArray(schema.items)) {
356
- v = handleTuple(schema.items, property, instruction);
357
- break;
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
- }
377
- }
378
- }
379
- const i = instruction.array;
380
- instruction.array++;
381
- let reference = property;
382
- if (isRoot) v = `const ar${i}v=new Array(${property}.length);`;
383
- else {
384
- reference = `ar${i}s`;
385
- v = `((${reference})=>{const ar${i}v=new Array(${reference}.length);`;
386
- }
387
- v += `for(let i=0;i<${reference}.length;i++){const ar${i}p=${reference}[i];ar${i}v[i]=${mirror(schema.items, `ar${i}p`, instruction)}`;
388
- const optionals = instruction.optionalsInArray[i + 1];
389
- if (optionals) {
390
- for (let oi = 0; oi < optionals.length; oi++) {
391
- const target = `ar${i}v[i]${optionals[oi]}`;
392
- v += `;if(${target}===undefined)delete ${target}`;
393
- }
394
- instruction.optionalsInArray[i + 1] = [];
395
- }
396
- v += `}`;
397
- if (!isRoot) v += `return ar${i}v})(${property})`;
398
- break;
399
- default:
400
- if (schema.$ref && schema.$ref in instruction.definitions)
401
- return mirror(
402
- instruction.definitions[schema.$ref],
403
- property,
404
- instruction
405
- );
406
- if (Array.isArray(schema.anyOf)) {
407
- v = handleUnion(schema.anyOf, property, instruction);
408
- break;
409
- }
410
- v = sanitize(property, instruction.sanitize?.length, schema);
411
- break;
412
- }
413
- if (!isRoot) return v;
414
- if (schema.type === "array") {
415
- v = `${v}const x=ar0v;`;
416
- } else {
417
- v = `const x=${v}
418
- `;
419
- }
420
- for (let i = 0; i < instruction.optionals.length; i++) {
421
- const key = instruction.optionals[i];
422
- const prop = key.slice(1);
423
- v += `if(${key}===undefined`;
424
- if (instruction.unionKeys[key]) v += `||x${prop}===undefined`;
425
- const shouldQuestion = prop.charCodeAt(0) !== 63 && schema.type !== "array";
426
- v += `)delete x${shouldQuestion ? prop.charCodeAt(0) === 91 ? "?." : "?" : ""}${prop}
427
- `;
428
- }
429
- return `${v}return x`;
430
- };
431
- var createMirror = (schema, {
432
- Compile,
433
- modules,
434
- definitions,
435
- sanitize: sanitize2,
436
- recursionLimit = 8,
437
- removeUnknownUnionType = false,
438
- emit
439
- } = {}) => {
440
- const unions = [];
441
- const cyclic = { groups: /* @__PURE__ */ new Map(), fns: [], count: 0 };
442
- if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
443
- const f = mirror(schema, "v", {
444
- optionals: [],
445
- optionalsInArray: [],
446
- array: 0,
447
- parentIsOptional: false,
448
- unions,
449
- unionKeys: {},
450
- Compile,
451
- modules,
452
- // @ts-ignore private property
453
- definitions: definitions ?? modules?.$defs ?? {},
454
- cyclic,
455
- sanitize: sanitize2,
456
- recursion: 0,
457
- recursionLimit,
458
- removeUnknownUnionType
459
- });
460
- const fns = cyclic.fns.length ? cyclic.fns.join("\n") + "\n" : "";
461
- if (!unions.length && !sanitize2?.length) {
462
- if (emit) return { source: fns + f, externals: void 0 };
463
- return Function("v", fns + f);
464
- }
465
- let hof;
466
- if (sanitize2?.length) {
467
- hof = {};
468
- for (let i = 0; i < sanitize2.length; i++) hof[`h${i}`] = sanitize2[i];
469
- }
470
- const source = `${fns}return function mirror(v){${f}}`;
471
- if (emit)
472
- return {
473
- source,
474
- externals: {
475
- unions,
476
- hof
477
- }
478
- };
479
- return Function(
480
- "d",
481
- source
482
- )(
483
- hof ? unions ? {
484
- unions,
485
- ...hof
486
- } : hof : unions ? { unions } : void 0
487
- );
488
- };
489
- var index_default = createMirror;
490
- // Annotate the CommonJS export names for ESM import in node:
491
- 0 && (module.exports = {
492
- createMirror,
493
- deepClone,
494
- mergeObjectIntersection
495
- });