exact-mirror 0.0.9 → 0.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.
@@ -1,5 +1,5 @@
1
1
  import { TypeCompiler, type TypeCheck } from '@sinclair/typebox/compiler';
2
- import type { TAnySchema } from '@sinclair/typebox';
2
+ import type { TAnySchema, TModule } from '@sinclair/typebox';
3
3
  export declare const mergeObjectIntersection: (schema: TAnySchema) => TAnySchema;
4
4
  type MaybeArray<T> = T | T[];
5
5
  export interface Instruction {
@@ -20,7 +20,14 @@ export interface Instruction {
20
20
  */
21
21
  TypeCompiler?: typeof TypeCompiler;
22
22
  typeCompilerWanred?: boolean;
23
+ modules?: TModule<any, any>;
23
24
  definitions: Record<string, TAnySchema>;
25
+ recursion: number;
26
+ /**
27
+ * @default 8
28
+ */
29
+ recursionLimit: number;
24
30
  }
25
- export declare const createMirror: <T extends TAnySchema>(schema: T, { TypeCompiler, definitions, sanitize }?: Partial<Pick<Instruction, "TypeCompiler" | "definitions" | "sanitize">>) => ((v: T["static"]) => T["static"]);
31
+ export declare function deepClone<T>(source: T, weak?: WeakMap<object, any>): T;
32
+ export declare const createMirror: <T extends TAnySchema>(schema: T, { TypeCompiler, modules, definitions, sanitize, recursionLimit }?: Partial<Pick<Instruction, "TypeCompiler" | "definitions" | "sanitize" | "modules" | "recursionLimit">>) => ((v: T["static"]) => T["static"]);
26
33
  export default createMirror;
package/dist/cjs/index.js CHANGED
@@ -21,17 +21,19 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  createMirror: () => createMirror,
24
+ deepClone: () => deepClone,
24
25
  default: () => index_default,
25
26
  mergeObjectIntersection: () => mergeObjectIntersection
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
  var import_compiler = require("@sinclair/typebox/compiler");
29
30
  var Kind = Symbol.for("TypeBox.Kind");
31
+ var Hint = Symbol.for("TypeBox.Hint");
30
32
  var isSpecialProperty = (name) => /(\ |-|\t|\n)/.test(name);
31
33
  var joinProperty = (v1, v2, isOptional = false) => {
32
- if (typeof v2 === "number") return `${v1}?.[${v2}]`;
33
- if (isSpecialProperty(v2)) return `${v1}${true ? "?." : ""}["${v2}"]`;
34
- return `${v1}${true ? "?" : ""}.${v2}`;
34
+ if (typeof v2 === "number") return `${v1}[${v2}]`;
35
+ if (isSpecialProperty(v2)) return `${v1}${isOptional ? "?." : ""}["${v2}"]`;
36
+ return `${v1}${isOptional ? "?" : ""}.${v2}`;
35
37
  };
36
38
  var encodeProperty = (v) => isSpecialProperty(v) ? `"${v}"` : v;
37
39
  var sanitize = (key, sanitize2 = 0, schema) => {
@@ -85,11 +87,35 @@ var handleTuple = (schema, property, instruction) => {
85
87
  if (!isRoot) v += `return ar${i}v})()`;
86
88
  return v;
87
89
  };
90
+ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
91
+ if (source === null || typeof source !== "object" || typeof source === "function")
92
+ return source;
93
+ if (weak.has(source)) return weak.get(source);
94
+ if (Array.isArray(source)) {
95
+ const copy = new Array(source.length);
96
+ weak.set(source, copy);
97
+ for (let i = 0; i < source.length; i++)
98
+ copy[i] = deepClone(source[i], weak);
99
+ return copy;
100
+ }
101
+ if (typeof source === "object") {
102
+ const keys = Object.keys(source).concat(
103
+ Object.getOwnPropertySymbols(source)
104
+ );
105
+ const cloned = {};
106
+ for (const key of keys)
107
+ cloned[key] = deepClone(source[key], weak);
108
+ return cloned;
109
+ }
110
+ return source;
111
+ }
88
112
  var handleUnion = (schemas, property, instruction) => {
89
113
  if (instruction.TypeCompiler === void 0) {
90
114
  if (!instruction.typeCompilerWanred) {
91
115
  console.warn(
92
- new Error("TypeBox's TypeCompiler is required to use Union")
116
+ new Error(
117
+ "[exact-mirror] TypeBox's TypeCompiler is required to use Union"
118
+ )
93
119
  );
94
120
  instruction.typeCompilerWanred = true;
95
121
  }
@@ -100,13 +126,42 @@ var handleUnion = (schemas, property, instruction) => {
100
126
  const typeChecks = instruction.unions[ui] = [];
101
127
  let v = `(()=>{
102
128
  `;
129
+ const unwrapRef = (type) => {
130
+ if (!(Kind in type) || !type.$ref) return type;
131
+ if (type[Kind] === "This") {
132
+ return deepClone(instruction.definitions[type.$ref]);
133
+ } else if (type[Kind] === "Ref") {
134
+ if (!instruction.modules)
135
+ console.warn(
136
+ new Error(
137
+ "[exact-mirror] modules is required when using nested cyclic reference"
138
+ )
139
+ );
140
+ else
141
+ return instruction.modules.Import(
142
+ type.$ref
143
+ );
144
+ }
145
+ return type;
146
+ };
103
147
  for (let i = 0; i < schemas.length; i++) {
104
- typeChecks.push(import_compiler.TypeCompiler.Compile(schemas[i]));
148
+ let type = unwrapRef(schemas[i]);
149
+ if (Array.isArray(type.anyOf))
150
+ for (let i2 = 0; i2 < type.anyOf.length; i2++)
151
+ type.anyOf[i2] = unwrapRef(type.anyOf[i2]);
152
+ else if (type.items) {
153
+ if (Array.isArray(type.items))
154
+ for (let i2 = 0; i2 < type.items.length; i2++)
155
+ type.items[i2] = unwrapRef(type.items[i2]);
156
+ else type.items = unwrapRef(type.items);
157
+ }
158
+ typeChecks.push(import_compiler.TypeCompiler.Compile(type));
105
159
  v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
106
- schemas[i],
160
+ type,
107
161
  property,
108
162
  {
109
163
  ...instruction,
164
+ recursion: instruction.recursion + 1,
110
165
  parentIsOptional: true
111
166
  }
112
167
  )}}
@@ -123,10 +178,12 @@ var mirror = (schema, property, instruction) => {
123
178
  ...instruction,
124
179
  definitions: Object.assign(instruction.definitions, schema.$defs)
125
180
  });
126
- if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf) {
181
+ if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
127
182
  return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
128
- }
183
+ if (instruction.recursion >= instruction.recursionLimit) return property;
129
184
  let v = "";
185
+ if (schema.$id && Hint in schema)
186
+ instruction.definitions[schema.$id] = schema;
130
187
  switch (schema.type) {
131
188
  case "object":
132
189
  if (schema[Kind] === "Record") {
@@ -165,6 +222,7 @@ var mirror = (schema, property, instruction) => {
165
222
  name,
166
223
  {
167
224
  ...instruction,
225
+ recursion: instruction.recursion + 1,
168
226
  parentIsOptional: isOptional
169
227
  }
170
228
  )}`;
@@ -173,11 +231,24 @@ var mirror = (schema, property, instruction) => {
173
231
  break;
174
232
  case "array":
175
233
  if (schema.items.type !== "object" && schema.items.type !== "array") {
176
- if (Array.isArray(schema.items))
234
+ if (Array.isArray(schema.items)) {
177
235
  v = handleTuple(schema.items, property, instruction);
178
- else if (isRoot) return "return v";
179
- else v = property;
180
- break;
236
+ break;
237
+ } else if (isRoot) return "return v";
238
+ else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
239
+ v = mirror(
240
+ deepClone(instruction.definitions[schema.items.$ref]),
241
+ property,
242
+ {
243
+ ...instruction,
244
+ parentIsOptional: true,
245
+ recursion: instruction.recursion + 1
246
+ }
247
+ );
248
+ else {
249
+ v = property;
250
+ break;
251
+ }
181
252
  }
182
253
  const i = instruction.array;
183
254
  instruction.array++;
@@ -228,8 +299,10 @@ var mirror = (schema, property, instruction) => {
228
299
  };
229
300
  var createMirror = (schema, {
230
301
  TypeCompiler: TypeCompiler2,
231
- definitions = {},
232
- sanitize: sanitize2
302
+ modules,
303
+ definitions,
304
+ sanitize: sanitize2,
305
+ recursionLimit = 8
233
306
  } = {}) => {
234
307
  const unions = [];
235
308
  if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
@@ -241,8 +314,12 @@ var createMirror = (schema, {
241
314
  unions,
242
315
  unionKeys: {},
243
316
  TypeCompiler: TypeCompiler2,
244
- definitions,
245
- sanitize: sanitize2
317
+ modules,
318
+ // @ts-ignore private property
319
+ definitions: definitions ?? modules?.$defs ?? {},
320
+ sanitize: sanitize2,
321
+ recursion: 0,
322
+ recursionLimit
246
323
  });
247
324
  if (!unions.length && !sanitize2?.length) return Function("v", f);
248
325
  let hof;
@@ -262,5 +339,6 @@ var index_default = createMirror;
262
339
  // Annotate the CommonJS export names for ESM import in node:
263
340
  0 && (module.exports = {
264
341
  createMirror,
342
+ deepClone,
265
343
  mergeObjectIntersection
266
344
  });
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { TypeCompiler, type TypeCheck } from '@sinclair/typebox/compiler';
2
- import type { TAnySchema } from '@sinclair/typebox';
2
+ import type { TAnySchema, TModule } from '@sinclair/typebox';
3
3
  export declare const mergeObjectIntersection: (schema: TAnySchema) => TAnySchema;
4
4
  type MaybeArray<T> = T | T[];
5
5
  export interface Instruction {
@@ -20,7 +20,14 @@ export interface Instruction {
20
20
  */
21
21
  TypeCompiler?: typeof TypeCompiler;
22
22
  typeCompilerWanred?: boolean;
23
+ modules?: TModule<any, any>;
23
24
  definitions: Record<string, TAnySchema>;
25
+ recursion: number;
26
+ /**
27
+ * @default 8
28
+ */
29
+ recursionLimit: number;
24
30
  }
25
- export declare const createMirror: <T extends TAnySchema>(schema: T, { TypeCompiler, definitions, sanitize }?: Partial<Pick<Instruction, "TypeCompiler" | "definitions" | "sanitize">>) => ((v: T["static"]) => T["static"]);
31
+ export declare function deepClone<T>(source: T, weak?: WeakMap<object, any>): T;
32
+ export declare const createMirror: <T extends TAnySchema>(schema: T, { TypeCompiler, modules, definitions, sanitize, recursionLimit }?: Partial<Pick<Instruction, "TypeCompiler" | "definitions" | "sanitize" | "modules" | "recursionLimit">>) => ((v: T["static"]) => T["static"]);
26
33
  export default createMirror;
package/dist/index.mjs CHANGED
@@ -1,11 +1,12 @@
1
1
  // src/index.ts
2
2
  import { TypeCompiler } from "@sinclair/typebox/compiler";
3
3
  var Kind = Symbol.for("TypeBox.Kind");
4
+ var Hint = Symbol.for("TypeBox.Hint");
4
5
  var isSpecialProperty = (name) => /(\ |-|\t|\n)/.test(name);
5
6
  var joinProperty = (v1, v2, isOptional = false) => {
6
- if (typeof v2 === "number") return `${v1}?.[${v2}]`;
7
- if (isSpecialProperty(v2)) return `${v1}${true ? "?." : ""}["${v2}"]`;
8
- return `${v1}${true ? "?" : ""}.${v2}`;
7
+ if (typeof v2 === "number") return `${v1}[${v2}]`;
8
+ if (isSpecialProperty(v2)) return `${v1}${isOptional ? "?." : ""}["${v2}"]`;
9
+ return `${v1}${isOptional ? "?" : ""}.${v2}`;
9
10
  };
10
11
  var encodeProperty = (v) => isSpecialProperty(v) ? `"${v}"` : v;
11
12
  var sanitize = (key, sanitize2 = 0, schema) => {
@@ -59,11 +60,35 @@ var handleTuple = (schema, property, instruction) => {
59
60
  if (!isRoot) v += `return ar${i}v})()`;
60
61
  return v;
61
62
  };
63
+ function deepClone(source, weak = /* @__PURE__ */ new WeakMap()) {
64
+ if (source === null || typeof source !== "object" || typeof source === "function")
65
+ return source;
66
+ if (weak.has(source)) return weak.get(source);
67
+ if (Array.isArray(source)) {
68
+ const copy = new Array(source.length);
69
+ weak.set(source, copy);
70
+ for (let i = 0; i < source.length; i++)
71
+ copy[i] = deepClone(source[i], weak);
72
+ return copy;
73
+ }
74
+ if (typeof source === "object") {
75
+ const keys = Object.keys(source).concat(
76
+ Object.getOwnPropertySymbols(source)
77
+ );
78
+ const cloned = {};
79
+ for (const key of keys)
80
+ cloned[key] = deepClone(source[key], weak);
81
+ return cloned;
82
+ }
83
+ return source;
84
+ }
62
85
  var handleUnion = (schemas, property, instruction) => {
63
86
  if (instruction.TypeCompiler === void 0) {
64
87
  if (!instruction.typeCompilerWanred) {
65
88
  console.warn(
66
- new Error("TypeBox's TypeCompiler is required to use Union")
89
+ new Error(
90
+ "[exact-mirror] TypeBox's TypeCompiler is required to use Union"
91
+ )
67
92
  );
68
93
  instruction.typeCompilerWanred = true;
69
94
  }
@@ -74,13 +99,42 @@ var handleUnion = (schemas, property, instruction) => {
74
99
  const typeChecks = instruction.unions[ui] = [];
75
100
  let v = `(()=>{
76
101
  `;
102
+ const unwrapRef = (type) => {
103
+ if (!(Kind in type) || !type.$ref) return type;
104
+ if (type[Kind] === "This") {
105
+ return deepClone(instruction.definitions[type.$ref]);
106
+ } else if (type[Kind] === "Ref") {
107
+ if (!instruction.modules)
108
+ console.warn(
109
+ new Error(
110
+ "[exact-mirror] modules is required when using nested cyclic reference"
111
+ )
112
+ );
113
+ else
114
+ return instruction.modules.Import(
115
+ type.$ref
116
+ );
117
+ }
118
+ return type;
119
+ };
77
120
  for (let i = 0; i < schemas.length; i++) {
78
- typeChecks.push(TypeCompiler.Compile(schemas[i]));
121
+ let type = unwrapRef(schemas[i]);
122
+ if (Array.isArray(type.anyOf))
123
+ for (let i2 = 0; i2 < type.anyOf.length; i2++)
124
+ type.anyOf[i2] = unwrapRef(type.anyOf[i2]);
125
+ else if (type.items) {
126
+ if (Array.isArray(type.items))
127
+ for (let i2 = 0; i2 < type.items.length; i2++)
128
+ type.items[i2] = unwrapRef(type.items[i2]);
129
+ else type.items = unwrapRef(type.items);
130
+ }
131
+ typeChecks.push(TypeCompiler.Compile(type));
79
132
  v += `if(d.unions[${ui}][${i}].Check(${property})){return ${mirror(
80
- schemas[i],
133
+ type,
81
134
  property,
82
135
  {
83
136
  ...instruction,
137
+ recursion: instruction.recursion + 1,
84
138
  parentIsOptional: true
85
139
  }
86
140
  )}}
@@ -97,10 +151,12 @@ var mirror = (schema, property, instruction) => {
97
151
  ...instruction,
98
152
  definitions: Object.assign(instruction.definitions, schema.$defs)
99
153
  });
100
- if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf) {
154
+ if (isRoot && schema.type !== "object" && schema.type !== "array" && !schema.anyOf)
101
155
  return `return ${sanitize("v", instruction.sanitize?.length, schema)}`;
102
- }
156
+ if (instruction.recursion >= instruction.recursionLimit) return property;
103
157
  let v = "";
158
+ if (schema.$id && Hint in schema)
159
+ instruction.definitions[schema.$id] = schema;
104
160
  switch (schema.type) {
105
161
  case "object":
106
162
  if (schema[Kind] === "Record") {
@@ -139,6 +195,7 @@ var mirror = (schema, property, instruction) => {
139
195
  name,
140
196
  {
141
197
  ...instruction,
198
+ recursion: instruction.recursion + 1,
142
199
  parentIsOptional: isOptional
143
200
  }
144
201
  )}`;
@@ -147,11 +204,24 @@ var mirror = (schema, property, instruction) => {
147
204
  break;
148
205
  case "array":
149
206
  if (schema.items.type !== "object" && schema.items.type !== "array") {
150
- if (Array.isArray(schema.items))
207
+ if (Array.isArray(schema.items)) {
151
208
  v = handleTuple(schema.items, property, instruction);
152
- else if (isRoot) return "return v";
153
- else v = property;
154
- break;
209
+ break;
210
+ } else if (isRoot) return "return v";
211
+ else if (Kind in schema.items && schema.items.$ref && (schema.items[Kind] === "Ref" || schema.items[Kind] === "This"))
212
+ v = mirror(
213
+ deepClone(instruction.definitions[schema.items.$ref]),
214
+ property,
215
+ {
216
+ ...instruction,
217
+ parentIsOptional: true,
218
+ recursion: instruction.recursion + 1
219
+ }
220
+ );
221
+ else {
222
+ v = property;
223
+ break;
224
+ }
155
225
  }
156
226
  const i = instruction.array;
157
227
  instruction.array++;
@@ -202,8 +272,10 @@ var mirror = (schema, property, instruction) => {
202
272
  };
203
273
  var createMirror = (schema, {
204
274
  TypeCompiler: TypeCompiler2,
205
- definitions = {},
206
- sanitize: sanitize2
275
+ modules,
276
+ definitions,
277
+ sanitize: sanitize2,
278
+ recursionLimit = 8
207
279
  } = {}) => {
208
280
  const unions = [];
209
281
  if (typeof sanitize2 === "function") sanitize2 = [sanitize2];
@@ -215,8 +287,12 @@ var createMirror = (schema, {
215
287
  unions,
216
288
  unionKeys: {},
217
289
  TypeCompiler: TypeCompiler2,
218
- definitions,
219
- sanitize: sanitize2
290
+ modules,
291
+ // @ts-ignore private property
292
+ definitions: definitions ?? modules?.$defs ?? {},
293
+ sanitize: sanitize2,
294
+ recursion: 0,
295
+ recursionLimit
220
296
  });
221
297
  if (!unions.length && !sanitize2?.length) return Function("v", f);
222
298
  let hof;
@@ -235,6 +311,7 @@ var createMirror = (schema, {
235
311
  var index_default = createMirror;
236
312
  export {
237
313
  createMirror,
314
+ deepClone,
238
315
  index_default as default,
239
316
  mergeObjectIntersection
240
317
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "exact-mirror",
3
- "version": "0.0.9",
3
+ "version": "0.1.1",
4
4
  "description": "Mirror exact value to TypeBox/OpenAPI model",
5
5
  "license": "MIT",
6
6
  "scripts": {