@scalar/json-magic 0.4.2 → 0.5.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.
Files changed (106) hide show
  1. package/.turbo/turbo-build.log +4 -4
  2. package/CHANGELOG.md +17 -0
  3. package/dist/bundle/bundle.d.ts +0 -10
  4. package/dist/bundle/bundle.d.ts.map +1 -1
  5. package/dist/bundle/bundle.js +27 -29
  6. package/dist/bundle/bundle.js.map +2 -2
  7. package/dist/bundle/plugins/fetch-urls/index.d.ts.map +1 -1
  8. package/dist/bundle/plugins/fetch-urls/index.js +2 -2
  9. package/dist/bundle/plugins/fetch-urls/index.js.map +2 -2
  10. package/dist/bundle/plugins/parse-json/index.d.ts.map +1 -1
  11. package/dist/bundle/plugins/parse-json/index.js +1 -1
  12. package/dist/bundle/plugins/parse-json/index.js.map +2 -2
  13. package/dist/bundle/plugins/parse-yaml/index.d.ts.map +1 -1
  14. package/dist/bundle/plugins/parse-yaml/index.js +1 -1
  15. package/dist/bundle/plugins/parse-yaml/index.js.map +2 -2
  16. package/dist/bundle/plugins/read-files/index.d.ts.map +1 -1
  17. package/dist/bundle/plugins/read-files/index.js +1 -1
  18. package/dist/bundle/plugins/read-files/index.js.map +2 -2
  19. package/dist/helpers/convert-to-local-ref.d.ts +10 -0
  20. package/dist/helpers/convert-to-local-ref.d.ts.map +1 -0
  21. package/dist/helpers/convert-to-local-ref.js +26 -0
  22. package/dist/helpers/convert-to-local-ref.js.map +7 -0
  23. package/dist/helpers/escape-json-pointer.d.ts.map +1 -0
  24. package/dist/{utils → helpers}/escape-json-pointer.js.map +1 -1
  25. package/dist/helpers/get-schemas.d.ts +21 -0
  26. package/dist/helpers/get-schemas.d.ts.map +1 -0
  27. package/dist/helpers/get-schemas.js +37 -0
  28. package/dist/helpers/get-schemas.js.map +7 -0
  29. package/dist/helpers/get-segments-from-path.d.ts.map +1 -0
  30. package/dist/{utils → helpers}/get-segments-from-path.js.map +1 -1
  31. package/dist/helpers/get-value-by-path.d.ts +24 -0
  32. package/dist/helpers/get-value-by-path.d.ts.map +1 -0
  33. package/dist/helpers/get-value-by-path.js +23 -0
  34. package/dist/helpers/get-value-by-path.js.map +7 -0
  35. package/dist/helpers/is-json-object.d.ts.map +1 -0
  36. package/dist/{utils → helpers}/is-json-object.js +1 -1
  37. package/dist/helpers/is-json-object.js.map +7 -0
  38. package/dist/helpers/is-object.d.ts.map +1 -0
  39. package/dist/{utils → helpers}/is-object.js.map +1 -1
  40. package/dist/helpers/is-yaml.d.ts.map +1 -0
  41. package/dist/{utils → helpers}/is-yaml.js.map +1 -1
  42. package/dist/{utils → helpers}/json-path-utils.d.ts +0 -11
  43. package/dist/helpers/json-path-utils.d.ts.map +1 -0
  44. package/dist/{utils → helpers}/json-path-utils.js +0 -9
  45. package/dist/helpers/json-path-utils.js.map +7 -0
  46. package/dist/helpers/normalize.d.ts.map +1 -0
  47. package/dist/{utils → helpers}/normalize.js.map +1 -1
  48. package/dist/helpers/unescape-json-pointer.d.ts.map +1 -0
  49. package/dist/{utils → helpers}/unescape-json-pointer.js.map +1 -1
  50. package/dist/magic-proxy/proxy.d.ts +35 -10
  51. package/dist/magic-proxy/proxy.d.ts.map +1 -1
  52. package/dist/magic-proxy/proxy.js +40 -20
  53. package/dist/magic-proxy/proxy.js.map +2 -2
  54. package/esbuild.ts +1 -0
  55. package/package.json +8 -3
  56. package/src/bundle/bundle.test.ts +462 -25
  57. package/src/bundle/bundle.ts +37 -36
  58. package/src/bundle/plugins/fetch-urls/index.ts +2 -2
  59. package/src/bundle/plugins/parse-json/index.ts +1 -1
  60. package/src/bundle/plugins/parse-yaml/index.ts +3 -2
  61. package/src/bundle/plugins/read-files/index.ts +1 -1
  62. package/src/helpers/convert-to-local-ref.test.ts +211 -0
  63. package/src/helpers/convert-to-local-ref.ts +43 -0
  64. package/src/helpers/get-schemas.test.ts +356 -0
  65. package/src/helpers/get-schemas.ts +80 -0
  66. package/src/helpers/get-value-by-path.test.ts +338 -0
  67. package/src/helpers/get-value-by-path.ts +44 -0
  68. package/src/{utils → helpers}/is-json-object.ts +1 -1
  69. package/src/{utils → helpers}/json-path-utils.ts +0 -19
  70. package/src/{utils → helpers}/normalize.test.ts +2 -1
  71. package/src/magic-proxy/proxy.test.ts +548 -0
  72. package/src/magic-proxy/proxy.ts +80 -31
  73. package/dist/utils/escape-json-pointer.d.ts.map +0 -1
  74. package/dist/utils/get-segments-from-path.d.ts.map +0 -1
  75. package/dist/utils/is-json-object.d.ts.map +0 -1
  76. package/dist/utils/is-json-object.js.map +0 -7
  77. package/dist/utils/is-object.d.ts.map +0 -1
  78. package/dist/utils/is-yaml.d.ts.map +0 -1
  79. package/dist/utils/json-path-utils.d.ts.map +0 -1
  80. package/dist/utils/json-path-utils.js.map +0 -7
  81. package/dist/utils/normalize.d.ts.map +0 -1
  82. package/dist/utils/unescape-json-pointer.d.ts.map +0 -1
  83. /package/dist/{utils → helpers}/escape-json-pointer.d.ts +0 -0
  84. /package/dist/{utils → helpers}/escape-json-pointer.js +0 -0
  85. /package/dist/{utils → helpers}/get-segments-from-path.d.ts +0 -0
  86. /package/dist/{utils → helpers}/get-segments-from-path.js +0 -0
  87. /package/dist/{utils → helpers}/is-json-object.d.ts +0 -0
  88. /package/dist/{utils → helpers}/is-object.d.ts +0 -0
  89. /package/dist/{utils → helpers}/is-object.js +0 -0
  90. /package/dist/{utils → helpers}/is-yaml.d.ts +0 -0
  91. /package/dist/{utils → helpers}/is-yaml.js +0 -0
  92. /package/dist/{utils → helpers}/normalize.d.ts +0 -0
  93. /package/dist/{utils → helpers}/normalize.js +0 -0
  94. /package/dist/{utils → helpers}/unescape-json-pointer.d.ts +0 -0
  95. /package/dist/{utils → helpers}/unescape-json-pointer.js +0 -0
  96. /package/src/{utils → helpers}/escape-json-pointer.test.ts +0 -0
  97. /package/src/{utils → helpers}/escape-json-pointer.ts +0 -0
  98. /package/src/{utils → helpers}/get-segments-from-path.test.ts +0 -0
  99. /package/src/{utils → helpers}/get-segments-from-path.ts +0 -0
  100. /package/src/{utils → helpers}/is-object.test.ts +0 -0
  101. /package/src/{utils → helpers}/is-object.ts +0 -0
  102. /package/src/{utils → helpers}/is-yaml.ts +0 -0
  103. /package/src/{utils → helpers}/json-path-utils.test.ts +0 -0
  104. /package/src/{utils → helpers}/normalize.ts +0 -0
  105. /package/src/{utils → helpers}/unescape-json-pointer.test.ts +0 -0
  106. /package/src/{utils → helpers}/unescape-json-pointer.ts +0 -0
@@ -0,0 +1,26 @@
1
+ const convertToLocalRef = (ref, currentContext, schemas) => {
2
+ const [baseUrl, pathOrAnchor] = ref.split("#", 2);
3
+ if (baseUrl) {
4
+ if (!schemas.has(baseUrl)) {
5
+ return void 0;
6
+ }
7
+ if (!pathOrAnchor) {
8
+ return schemas.get(baseUrl);
9
+ }
10
+ if (pathOrAnchor.startsWith("/")) {
11
+ return `${schemas.get(baseUrl)}${pathOrAnchor}`;
12
+ }
13
+ return schemas.get(`${baseUrl}#${pathOrAnchor}`);
14
+ }
15
+ if (pathOrAnchor) {
16
+ if (pathOrAnchor.startsWith("/")) {
17
+ return pathOrAnchor.slice(1);
18
+ }
19
+ return schemas.get(`${currentContext}#${pathOrAnchor}`);
20
+ }
21
+ return void 0;
22
+ };
23
+ export {
24
+ convertToLocalRef
25
+ };
26
+ //# sourceMappingURL=convert-to-local-ref.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/helpers/convert-to-local-ref.ts"],
4
+ "sourcesContent": ["/**\n * Translates a JSON Reference ($ref) to a local object path within the root schema.\n *\n * @param ref - The JSON Reference string (e.g., \"#/foo/bar\", \"other.json#/baz\", \"other.json#anchor\")\n * @param currentContext - The current base context (usually the $id of the current schema or parent)\n * @param schemas - A map of schema identifiers ($id, $anchor) to their local object paths\n * @returns The local object path as a string, or undefined if the reference cannot be resolved\n */\nexport const convertToLocalRef = (\n ref: string,\n currentContext: string,\n schemas: Map<string, string>,\n): string | undefined => {\n // Split the reference into base URL and path/anchor (e.g., \"foo.json#/bar\" => [\"foo.json\", \"/bar\"])\n const [baseUrl, pathOrAnchor] = ref.split('#', 2)\n\n if (baseUrl) {\n if (!schemas.has(baseUrl)) {\n return undefined\n }\n\n if (!pathOrAnchor) {\n return schemas.get(baseUrl)\n }\n\n // If the pathOrAnchor is a JSON pointer, we need to append it to the baseUrl\n if (pathOrAnchor.startsWith('/')) {\n return `${schemas.get(baseUrl)}${pathOrAnchor}`\n }\n\n // If the pathOrAnchor is an anchor, we need to return the anchor\n return schemas.get(`${baseUrl}#${pathOrAnchor}`)\n }\n\n if (pathOrAnchor) {\n if (pathOrAnchor.startsWith('/')) {\n return pathOrAnchor.slice(1)\n }\n return schemas.get(`${currentContext}#${pathOrAnchor}`)\n }\n\n return undefined\n}\n"],
5
+ "mappings": "AAQO,MAAM,oBAAoB,CAC/B,KACA,gBACA,YACuB;AAEvB,QAAM,CAAC,SAAS,YAAY,IAAI,IAAI,MAAM,KAAK,CAAC;AAEhD,MAAI,SAAS;AACX,QAAI,CAAC,QAAQ,IAAI,OAAO,GAAG;AACzB,aAAO;AAAA,IACT;AAEA,QAAI,CAAC,cAAc;AACjB,aAAO,QAAQ,IAAI,OAAO;AAAA,IAC5B;AAGA,QAAI,aAAa,WAAW,GAAG,GAAG;AAChC,aAAO,GAAG,QAAQ,IAAI,OAAO,CAAC,GAAG,YAAY;AAAA,IAC/C;AAGA,WAAO,QAAQ,IAAI,GAAG,OAAO,IAAI,YAAY,EAAE;AAAA,EACjD;AAEA,MAAI,cAAc;AAChB,QAAI,aAAa,WAAW,GAAG,GAAG;AAChC,aAAO,aAAa,MAAM,CAAC;AAAA,IAC7B;AACA,WAAO,QAAQ,IAAI,GAAG,cAAc,IAAI,YAAY,EAAE;AAAA,EACxD;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escape-json-pointer.d.ts","sourceRoot":"","sources":["../../src/helpers/escape-json-pointer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,UAE5C"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/escape-json-pointer.ts"],
3
+ "sources": ["../../src/helpers/escape-json-pointer.ts"],
4
4
  "sourcesContent": ["/**\n * Escapes a JSON pointer string.\n *\n * Example: `/foo/bar~baz` -> `/foo~1bar~0baz`\n */\nexport function escapeJsonPointer(str: string) {\n return str.replace(/~/g, '~0').replace(/\\//g, '~1')\n}\n"],
5
5
  "mappings": "AAKO,SAAS,kBAAkB,KAAa;AAC7C,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;",
6
6
  "names": []
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Retrieves the $id property from the input object if it exists and is a string.
3
+ *
4
+ * @param input - The object to extract the $id from.
5
+ * @returns The $id string if present, otherwise undefined.
6
+ */
7
+ export declare const getId: (input: unknown) => string | undefined;
8
+ /**
9
+ * Recursively traverses the input object to collect all schemas identified by $id and $anchor properties.
10
+ *
11
+ * - If an object has a $id property, it is added to the map with its $id as the key.
12
+ * - If an object has a $anchor property, it is added to the map with a key composed of the current base and the anchor.
13
+ * - The function performs a depth-first search (DFS) through all nested objects.
14
+ *
15
+ * @param input - The input object to traverse.
16
+ * @param base - The current base URI, used for resolving anchors.
17
+ * @param map - The map collecting found schemas.
18
+ * @returns A map of schema identifiers to their corresponding objects.
19
+ */
20
+ export declare const getSchemas: (input: unknown, base?: string, segments?: string[], map?: Map<string, string>, visited?: WeakSet<object>) => Map<string, string>;
21
+ //# sourceMappingURL=get-schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-schemas.d.ts","sourceRoot":"","sources":["../../src/helpers/get-schemas.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,KAAK,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAK/C,CAAA;AAYD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,OAAO,EACd,OAAM,MAAW,EACjB,WAAU,MAAM,EAAO,EACvB,yBAA+B,EAC/B,yBAAuB,wBAuCxB,CAAA"}
@@ -0,0 +1,37 @@
1
+ const getId = (input) => {
2
+ if (input && typeof input === "object" && input["$id"] && typeof input["$id"] === "string") {
3
+ return input["$id"];
4
+ }
5
+ return void 0;
6
+ };
7
+ const getPath = (segments) => {
8
+ return segments.join("/");
9
+ };
10
+ const getSchemas = (input, base = "", segments = [], map = /* @__PURE__ */ new Map(), visited = /* @__PURE__ */ new WeakSet()) => {
11
+ if (typeof input !== "object" || input === null) {
12
+ return map;
13
+ }
14
+ if (visited.has(input)) {
15
+ return map;
16
+ }
17
+ visited.add(input);
18
+ const id = getId(input);
19
+ if (id) {
20
+ map.set(id, getPath(segments));
21
+ }
22
+ const newBase = id ?? base;
23
+ if (input["$anchor"] && typeof input["$anchor"] === "string") {
24
+ map.set(`${newBase}#${input["$anchor"]}`, getPath(segments));
25
+ }
26
+ for (const key in input) {
27
+ if (typeof input[key] === "object" && input[key] !== null) {
28
+ getSchemas(input[key], newBase, [...segments, key], map, visited);
29
+ }
30
+ }
31
+ return map;
32
+ };
33
+ export {
34
+ getId,
35
+ getSchemas
36
+ };
37
+ //# sourceMappingURL=get-schemas.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/helpers/get-schemas.ts"],
4
+ "sourcesContent": ["/**\n * Retrieves the $id property from the input object if it exists and is a string.\n *\n * @param input - The object to extract the $id from.\n * @returns The $id string if present, otherwise undefined.\n */\nexport const getId = (input: unknown): string | undefined => {\n if (input && typeof input === 'object' && input['$id'] && typeof input['$id'] === 'string') {\n return input['$id']\n }\n return undefined\n}\n\n/**\n * Joins an array of path segments into a single string separated by '/'.\n *\n * @param segments - The array of path segments.\n * @returns The joined path string.\n */\nconst getPath = (segments: string[]): string => {\n return segments.join('/')\n}\n\n/**\n * Recursively traverses the input object to collect all schemas identified by $id and $anchor properties.\n *\n * - If an object has a $id property, it is added to the map with its $id as the key.\n * - If an object has a $anchor property, it is added to the map with a key composed of the current base and the anchor.\n * - The function performs a depth-first search (DFS) through all nested objects.\n *\n * @param input - The input object to traverse.\n * @param base - The current base URI, used for resolving anchors.\n * @param map - The map collecting found schemas.\n * @returns A map of schema identifiers to their corresponding objects.\n */\nexport const getSchemas = (\n input: unknown,\n base: string = '',\n segments: string[] = [],\n map = new Map<string, string>(),\n visited = new WeakSet(),\n) => {\n // Only process non-null objects\n if (typeof input !== 'object' || input === null) {\n return map\n }\n\n // If the object has already been visited, return the map\n if (visited.has(input)) {\n return map\n }\n\n // Add the object to the visited set\n visited.add(input)\n\n // Attempt to get $id from the current object\n const id = getId(input)\n\n // If $id exists, add the object to the map with $id as the key\n if (id) {\n map.set(id, getPath(segments))\n }\n\n // Update the base for nested anchors\n const newBase = id ?? base\n\n // If $anchor exists, add the object to the map with base#anchor as the key\n if (input['$anchor'] && typeof input['$anchor'] === 'string') {\n map.set(`${newBase}#${input['$anchor']}`, getPath(segments))\n }\n\n // Recursively traverse all properties (DFS)\n for (const key in input) {\n if (typeof input[key] === 'object' && input[key] !== null) {\n getSchemas(input[key], newBase, [...segments, key], map, visited)\n }\n }\n\n return map\n}\n"],
5
+ "mappings": "AAMO,MAAM,QAAQ,CAAC,UAAuC;AAC3D,MAAI,SAAS,OAAO,UAAU,YAAY,MAAM,KAAK,KAAK,OAAO,MAAM,KAAK,MAAM,UAAU;AAC1F,WAAO,MAAM,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAQA,MAAM,UAAU,CAAC,aAA+B;AAC9C,SAAO,SAAS,KAAK,GAAG;AAC1B;AAcO,MAAM,aAAa,CACxB,OACA,OAAe,IACf,WAAqB,CAAC,GACtB,MAAM,oBAAI,IAAoB,GAC9B,UAAU,oBAAI,QAAQ,MACnB;AAEH,MAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,WAAO;AAAA,EACT;AAGA,MAAI,QAAQ,IAAI,KAAK,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,UAAQ,IAAI,KAAK;AAGjB,QAAM,KAAK,MAAM,KAAK;AAGtB,MAAI,IAAI;AACN,QAAI,IAAI,IAAI,QAAQ,QAAQ,CAAC;AAAA,EAC/B;AAGA,QAAM,UAAU,MAAM;AAGtB,MAAI,MAAM,SAAS,KAAK,OAAO,MAAM,SAAS,MAAM,UAAU;AAC5D,QAAI,IAAI,GAAG,OAAO,IAAI,MAAM,SAAS,CAAC,IAAI,QAAQ,QAAQ,CAAC;AAAA,EAC7D;AAGA,aAAW,OAAO,OAAO;AACvB,QAAI,OAAO,MAAM,GAAG,MAAM,YAAY,MAAM,GAAG,MAAM,MAAM;AACzD,iBAAW,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,UAAU,GAAG,GAAG,KAAK,OAAO;AAAA,IAClE;AAAA,EACF;AAEA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-segments-from-path.d.ts","sourceRoot":"","sources":["../../src/helpers/get-segments-from-path.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,YAW/C"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/get-segments-from-path.ts"],
3
+ "sources": ["../../src/helpers/get-segments-from-path.ts"],
4
4
  "sourcesContent": ["import { unescapeJsonPointer } from './unescape-json-pointer'\n\n/**\n * Translate `/paths/~1test` to `['paths', '/test']`\n */\nexport function getSegmentsFromPath(path: string) {\n return (\n // /paths/~1test\n path\n // ['', 'paths', '~1test']\n .split('/')\n // ['paths', '~test']\n .slice(1)\n // ['paths', '/test']\n .map(unescapeJsonPointer)\n )\n}\n"],
5
5
  "mappings": "AAAA,SAAS,2BAA2B;AAK7B,SAAS,oBAAoB,MAAc;AAChD;AAAA;AAAA,IAEE,KAEG,MAAM,GAAG,EAET,MAAM,CAAC,EAEP,IAAI,mBAAmB;AAAA;AAE9B;",
6
6
  "names": []
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Traverses an object using an array of string segments (path keys) and returns
3
+ * the value at the specified path along with its context (id if available).
4
+ *
5
+ * @param target - The root object to traverse.
6
+ * @param segments - An array of string keys representing the path to traverse.
7
+ * @returns An object containing the final context (id or previous context) and the value at the path.
8
+ *
9
+ * @example
10
+ * const obj = {
11
+ * foo: {
12
+ * bar: {
13
+ * baz: 42
14
+ * }
15
+ * }
16
+ * };
17
+ * // Returns: { context: '', value: 42 }
18
+ * getValueByPath(obj, ['foo', 'bar', 'baz']);
19
+ */
20
+ export declare function getValueByPath(target: unknown, segments: string[]): {
21
+ context: string;
22
+ value: any;
23
+ };
24
+ //# sourceMappingURL=get-value-by-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-value-by-path.d.ts","sourceRoot":"","sources":["../../src/helpers/get-value-by-path.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAsBnG"}
@@ -0,0 +1,23 @@
1
+ import { getId } from "../helpers/get-schemas.js";
2
+ function getValueByPath(target, segments) {
3
+ return segments.reduce(
4
+ (acc, key) => {
5
+ if (acc.value === void 0) {
6
+ return { context: "", value: void 0 };
7
+ }
8
+ if (typeof acc.value !== "object" || acc.value === null) {
9
+ return { context: "", value: void 0 };
10
+ }
11
+ const id = getId(acc.value);
12
+ return { context: id ?? acc.context, value: acc.value?.[key] };
13
+ },
14
+ {
15
+ context: "",
16
+ value: target
17
+ }
18
+ );
19
+ }
20
+ export {
21
+ getValueByPath
22
+ };
23
+ //# sourceMappingURL=get-value-by-path.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/helpers/get-value-by-path.ts"],
4
+ "sourcesContent": ["import { getId } from '@/helpers/get-schemas'\n\n/**\n * Traverses an object using an array of string segments (path keys) and returns\n * the value at the specified path along with its context (id if available).\n *\n * @param target - The root object to traverse.\n * @param segments - An array of string keys representing the path to traverse.\n * @returns An object containing the final context (id or previous context) and the value at the path.\n *\n * @example\n * const obj = {\n * foo: {\n * bar: {\n * baz: 42\n * }\n * }\n * };\n * // Returns: { context: '', value: 42 }\n * getValueByPath(obj, ['foo', 'bar', 'baz']);\n */\nexport function getValueByPath(target: unknown, segments: string[]): { context: string; value: any } {\n return segments.reduce<{ context: string; value: unknown }>(\n (acc, key) => {\n // If the accumulator is undefined, the path does not exist\n if (acc.value === undefined) {\n return { context: '', value: undefined }\n }\n // If the accumulator is not an object or is null, stop traversal\n if (typeof acc.value !== 'object' || acc.value === null) {\n return { context: '', value: undefined }\n }\n // Attempt to get the id from the current value for context tracking\n const id = getId(acc.value)\n\n // Return the next context and value for the next iteration\n return { context: id ?? acc.context, value: acc.value?.[key] }\n },\n {\n context: '',\n value: target,\n },\n )\n}\n"],
5
+ "mappings": "AAAA,SAAS,aAAa;AAqBf,SAAS,eAAe,QAAiB,UAAqD;AACnG,SAAO,SAAS;AAAA,IACd,CAAC,KAAK,QAAQ;AAEZ,UAAI,IAAI,UAAU,QAAW;AAC3B,eAAO,EAAE,SAAS,IAAI,OAAO,OAAU;AAAA,MACzC;AAEA,UAAI,OAAO,IAAI,UAAU,YAAY,IAAI,UAAU,MAAM;AACvD,eAAO,EAAE,SAAS,IAAI,OAAO,OAAU;AAAA,MACzC;AAEA,YAAM,KAAK,MAAM,IAAI,KAAK;AAG1B,aAAO,EAAE,SAAS,MAAM,IAAI,SAAS,OAAO,IAAI,QAAQ,GAAG,EAAE;AAAA,IAC/D;AAAA,IACA;AAAA,MACE,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-json-object.d.ts","sourceRoot":"","sources":["../../src/helpers/is-json-object.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,WAYzC"}
@@ -1,4 +1,4 @@
1
- import { isObject } from "../utils/is-object.js";
1
+ import { isObject } from "../helpers/is-object.js";
2
2
  function isJsonObject(value) {
3
3
  if (!/^\s*(\{)/.test(value.slice(0, 500))) {
4
4
  return false;
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/helpers/is-json-object.ts"],
4
+ "sourcesContent": ["import { isObject } from '@/helpers/is-object'\n\n/**\n * Determines if a string represents a valid JSON object (i.e., a plain object, not an array, primitive, or null).\n * The function first checks if the string appears to start with an opening curly brace (ignoring leading whitespace),\n * which is a quick heuristic to rule out arrays, primitives, and most invalid JSON. If this check passes,\n * it attempts to parse the string with JSON.parse. The result is then checked to ensure it is a plain object\n * (not an array, null, or primitive) using the isObject utility.\n *\n * @param value - The string to evaluate\n * @returns true if the string is valid JSON and parses to a plain object, false otherwise\n *\n * @example\n * isJsonObject('{\"foo\": \"bar\"}') // true\n * isJsonObject('[1,2,3]') // false\n * isJsonObject('not json') // false\n * isJsonObject('42') // false\n */\nexport function isJsonObject(value: string) {\n // Quickly rule out anything that doesn't start with an object brace\n if (!/^\\s*(\\{)/.test(value.slice(0, 500))) {\n return false\n }\n\n try {\n const val = JSON.parse(value)\n return isObject(val)\n } catch {\n return false\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,gBAAgB;AAkBlB,SAAS,aAAa,OAAe;AAE1C,MAAI,CAAC,WAAW,KAAK,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG;AACzC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,KAAK,MAAM,KAAK;AAC5B,WAAO,SAAS,GAAG;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-object.d.ts","sourceRoot":"","sources":["../../src/helpers/is-object.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,QAAQ,GAAI,KAAK,GAAG,KAAG,GAAG,IAAI,MAAwE,CAAA"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/is-object.ts"],
3
+ "sources": ["../../src/helpers/is-object.ts"],
4
4
  "sourcesContent": ["/**\n * Check if the given value is an object\n */\nexport const isObject = (obj: any): obj is object => typeof obj === 'object' && !Array.isArray(obj) && obj !== null\n"],
5
5
  "mappings": "AAGO,MAAM,WAAW,CAAC,QAA4B,OAAO,QAAQ,YAAY,CAAC,MAAM,QAAQ,GAAG,KAAK,QAAQ;",
6
6
  "names": []
@@ -0,0 +1 @@
1
+ {"version":3,"file":"is-yaml.d.ts","sourceRoot":"","sources":["../../src/helpers/is-yaml.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE7C"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/is-yaml.ts"],
3
+ "sources": ["../../src/helpers/is-yaml.ts"],
4
4
  "sourcesContent": ["/**\n * Checks if a string appears to be YAML content.\n * This function uses a simple heuristic: it looks for a line that starts with an optional dash,\n * followed by a key (alphanumeric or dash), a colon, and a value, and then at least one more line.\n * This is not a full YAML parser, but works for basic detection.\n *\n * @param value - The string to check\n * @returns true if the string looks like YAML, false otherwise\n *\n * @example\n * isYaml('openapi: 3.0.0\\ninfo:\\n title: Example') // true\n * isYaml('{\"openapi\": \"3.0.0\", \"info\": {\"title\": \"Example\"}}') // false\n * isYaml('- name: value\\n- name: value2') // true\n * isYaml('type: object') // false (only one line)\n */\nexport function isYaml(value: string): boolean {\n return /^\\s*(?:-\\s*)?[\\w\\-]+\\s*:\\s*.+\\n.*/.test(value)\n}\n"],
5
5
  "mappings": "AAeO,SAAS,OAAO,OAAwB;AAC7C,SAAO,oCAAoC,KAAK,KAAK;AACvD;",
6
6
  "names": []
@@ -9,17 +9,6 @@
9
9
  * ```
10
10
  */
11
11
  export declare function parseJsonPointer(pointer: string): string[];
12
- /**
13
- * Retrieves a nested value from the source document using a path array
14
- *
15
- * @example
16
- * ```ts
17
- * getValueByPath(document, ['components', 'schemas', 'User'])
18
- *
19
- * { id: '123', name: 'John Doe' }
20
- * ```
21
- */
22
- export declare function getValueByPath<R = unknown>(obj: any, pointer: string[]): R;
23
12
  /**
24
13
  * Creates a nested path in an object from an array of path segments.
25
14
  * Only creates intermediate objects/arrays if they don't already exist.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-path-utils.d.ts","sourceRoot":"","sources":["../../src/helpers/json-path-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAWlE"}
@@ -1,14 +1,6 @@
1
1
  function parseJsonPointer(pointer) {
2
2
  return pointer.split("/").filter((segment, index) => (index !== 0 || segment !== "#") && segment);
3
3
  }
4
- function getValueByPath(obj, pointer) {
5
- return pointer.reduce((acc, part) => {
6
- if (acc === void 0 || acc === null) {
7
- return void 0;
8
- }
9
- return acc[part];
10
- }, obj);
11
- }
12
4
  function createPathFromSegments(obj, segments) {
13
5
  return segments.reduce((acc, part) => {
14
6
  if (acc[part] === void 0) {
@@ -23,7 +15,6 @@ function createPathFromSegments(obj, segments) {
23
15
  }
24
16
  export {
25
17
  createPathFromSegments,
26
- getValueByPath,
27
18
  parseJsonPointer
28
19
  };
29
20
  //# sourceMappingURL=json-path-utils.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/helpers/json-path-utils.ts"],
4
+ "sourcesContent": ["/**\n * Parses a JSON Pointer string into an array of path segments\n *\n * @example\n * ```ts\n * parseJsonPointer('#/components/schemas/User')\n *\n * ['components', 'schemas', 'User']\n * ```\n */\nexport function parseJsonPointer(pointer: string): string[] {\n return (\n pointer\n // Split on '/'\n .split('/')\n // Remove the leading '#' if present\n .filter((segment, index) => (index !== 0 || segment !== '#') && segment)\n )\n}\n\n/**\n * Creates a nested path in an object from an array of path segments.\n * Only creates intermediate objects/arrays if they don't already exist.\n *\n * @param obj - The target object to create the path in\n * @param segments - Array of path segments to create\n * @returns The final nested object/array at the end of the path\n *\n * @example\n * ```ts\n * const obj = {}\n * createPathFromSegments(obj, ['components', 'schemas', 'User'])\n * // Creates: { components: { schemas: { User: {} } } }\n *\n * createPathFromSegments(obj, ['items', '0', 'name'])\n * // Creates: { items: [{ name: {} }] }\n * ```\n */\nexport function createPathFromSegments(obj: any, segments: string[]) {\n return segments.reduce((acc, part) => {\n if (acc[part] === undefined) {\n if (isNaN(Number(part))) {\n acc[part] = {}\n } else {\n acc[part] = []\n }\n }\n return acc[part]\n }, obj)\n}\n"],
5
+ "mappings": "AAUO,SAAS,iBAAiB,SAA2B;AAC1D,SACE,QAEG,MAAM,GAAG,EAET,OAAO,CAAC,SAAS,WAAW,UAAU,KAAK,YAAY,QAAQ,OAAO;AAE7E;AAoBO,SAAS,uBAAuB,KAAU,UAAoB;AACnE,SAAO,SAAS,OAAO,CAAC,KAAK,SAAS;AACpC,QAAI,IAAI,IAAI,MAAM,QAAW;AAC3B,UAAI,MAAM,OAAO,IAAI,CAAC,GAAG;AACvB,YAAI,IAAI,IAAI,CAAC;AAAA,MACf,OAAO;AACL,YAAI,IAAI,IAAI,CAAC;AAAA,MACf;AAAA,IACF;AACA,WAAO,IAAI,IAAI;AAAA,EACjB,GAAG,GAAG;AACR;",
6
+ "names": []
7
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/helpers/normalize.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,GAAG,OA4BrC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/normalize.ts"],
3
+ "sources": ["../../src/helpers/normalize.ts"],
4
4
  "sourcesContent": ["import { parse } from 'yaml'\n\n/**\n * Normalize a string (YAML, JSON, object) to a JavaScript datatype.\n */\nexport function normalize(content: any) {\n if (content === null) {\n return undefined\n }\n\n if (typeof content === 'string') {\n if (content.trim() === '') {\n return undefined\n }\n\n try {\n return JSON.parse(content)\n } catch (_error) {\n // Does it look like YAML?\n const hasColon = /^[^:]+:/.test(content)\n const isJson = content.slice(0, 50).trimStart().startsWith('{')\n\n if (!hasColon || isJson) {\n return undefined\n }\n\n return parse(content, {\n maxAliasCount: 10000,\n })\n }\n }\n\n return content\n}\n"],
5
5
  "mappings": "AAAA,SAAS,aAAa;AAKf,SAAS,UAAU,SAAc;AACtC,MAAI,YAAY,MAAM;AACpB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,YAAY,UAAU;AAC/B,QAAI,QAAQ,KAAK,MAAM,IAAI;AACzB,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,SAAS,QAAQ;AAEf,YAAM,WAAW,UAAU,KAAK,OAAO;AACvC,YAAM,SAAS,QAAQ,MAAM,GAAG,EAAE,EAAE,UAAU,EAAE,WAAW,GAAG;AAE9D,UAAI,CAAC,YAAY,QAAQ;AACvB,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,SAAS;AAAA,QACpB,eAAe;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;",
6
6
  "names": []
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unescape-json-pointer.d.ts","sourceRoot":"","sources":["../../src/helpers/unescape-json-pointer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,UAE9C"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../src/utils/unescape-json-pointer.ts"],
3
+ "sources": ["../../src/helpers/unescape-json-pointer.ts"],
4
4
  "sourcesContent": ["/**\n * Unescape JSON pointer\n *\n * Examples:\n * /foo~1bar~0baz -> /foo/bar~baz\n */\nexport function unescapeJsonPointer(uri: string) {\n return decodeURI(uri.replace(/~1/g, '/').replace(/~0/g, '~'))\n}\n"],
5
5
  "mappings": "AAMO,SAAS,oBAAoB,KAAa;AAC/C,SAAO,UAAU,IAAI,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,GAAG,CAAC;AAC9D;",
6
6
  "names": []
@@ -3,16 +3,16 @@ import type { UnknownObject } from '../types.js';
3
3
  * Creates a "magic" proxy for a given object or array, enabling transparent access to
4
4
  * JSON Reference ($ref) values as if they were directly present on the object.
5
5
  *
6
- * - If an object contains a `$ref` property, accessing the special `$ref-value` property
7
- * will resolve and return the referenced value from the root object.
8
- * - All nested objects and arrays are recursively wrapped in proxies, so reference resolution
9
- * works at any depth.
10
- * - Properties starting with an underscore (_) are hidden and will not be accessible through
11
- * the proxy (returns undefined on access, false on 'in' checks, excluded from enumeration).
6
+ * Features:
7
+ * - If an object contains a `$ref` property, accessing the special `$ref-value` property will resolve and return the referenced value from the root object.
8
+ * - All nested objects and arrays are recursively wrapped in proxies, so reference resolution works at any depth.
9
+ * - Properties starting with an underscore (_) are considered internal and are hidden by default: they return undefined on access, are excluded from enumeration, and `'in'` checks return false. This can be overridden with the `showInternal` option.
12
10
  * - Setting, deleting, and enumerating properties works as expected, including for proxied references.
11
+ * - Ensures referential stability by caching proxies for the same target object.
13
12
  *
14
13
  * @param target - The object or array to wrap in a magic proxy
15
- * @param root - The root object for resolving local JSON references (defaults to target)
14
+ * @param options - Optional settings (e.g., showInternal to expose internal properties)
15
+ * @param args - Internal arguments for advanced usage (root object, proxy/cache maps, current context)
16
16
  * @returns A proxied version of the input object/array with magic $ref-value support
17
17
  *
18
18
  * @example
@@ -37,9 +37,34 @@ import type { UnknownObject } from '../types.js';
37
37
  * proxy.refObj.extra = 'hello'
38
38
  * delete proxy.refObj.extra
39
39
  */
40
- export declare const createMagicProxy: <T extends Record<keyof T & symbol, unknown>, S extends UnknownObject>(target: T, options?: {
41
- showInternal?: boolean;
42
- }, root?: S | T, cache?: Map<string, unknown>, proxyCache?: WeakMap<object, T>) => T;
40
+ export declare const createMagicProxy: <T extends Record<keyof T & symbol, unknown>, S extends UnknownObject>(target: T, options?: Partial<{
41
+ showInternal: boolean;
42
+ }>, args?: {
43
+ /**
44
+ * The root object for resolving local JSON references.
45
+ */
46
+ root: S | T;
47
+ /**
48
+ * Cache to store already created proxies for target objects to ensure referential stability.
49
+ *
50
+ * It is helpful when dealing with reactive frameworks like Vue,
51
+ */
52
+ proxyCache: WeakMap<object, T>;
53
+ /**
54
+ * Cache to store resolved JSON references.
55
+ */
56
+ cache: Map<string, unknown>;
57
+ /**
58
+ * Map of all schemas by their $id or $anchor for cross-document reference resolution.
59
+ */
60
+ schemas: Map<string, string>;
61
+ /**
62
+ * The current JSON path context within the root object.
63
+ *
64
+ * Used to resolve $anchor references correctly.
65
+ */
66
+ currentContext: string;
67
+ }) => T;
43
68
  /**
44
69
  * Gets the raw (non-proxied) version of an object created by createMagicProxy.
45
70
  * This is useful when you need to access the original object without the magic proxy wrapper.
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/magic-proxy/proxy.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAW5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,aAAa,EACnG,QAAQ,CAAC,EACT,UAAU;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,EACpC,OAAM,CAAC,GAAG,CAAU,EACpB,4BAAkC,EAClC,+BAAqC,MAsLtC,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAUnC"}
1
+ {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/magic-proxy/proxy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAQ5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,SAAS,aAAa,EACnG,QAAQ,CAAC,EACT,UAAU,OAAO,CAAC;IAAE,YAAY,EAAE,OAAO,CAAA;CAAE,CAAC,EAC5C,OAAM;IACJ;;OAEG;IACH,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;IACX;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IAC9B;;OAEG;IACH,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC3B;;OAEG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAA;CAOvB,MAyMF,CAAA;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAUnC"}
@@ -1,17 +1,24 @@
1
- import { isLocalRef } from "../bundle/bundle.js";
2
- import { getSegmentsFromPath } from "../utils/get-segments-from-path.js";
3
- import { isObject } from "../utils/is-object.js";
4
- import { createPathFromSegments, getValueByPath, parseJsonPointer } from "../utils/json-path-utils.js";
1
+ import { convertToLocalRef } from "../helpers/convert-to-local-ref.js";
2
+ import { getId, getSchemas } from "../helpers/get-schemas.js";
3
+ import { getValueByPath } from "../helpers/get-value-by-path.js";
4
+ import { isObject } from "../helpers/is-object.js";
5
+ import { createPathFromSegments, parseJsonPointer } from "../helpers/json-path-utils.js";
5
6
  const isMagicProxy = Symbol("isMagicProxy");
6
7
  const magicProxyTarget = Symbol("magicProxyTarget");
7
8
  const REF_VALUE = "$ref-value";
8
9
  const REF_KEY = "$ref";
9
- const createMagicProxy = (target, options, root = target, cache = /* @__PURE__ */ new Map(), proxyCache = /* @__PURE__ */ new WeakMap()) => {
10
+ const createMagicProxy = (target, options, args = {
11
+ root: target,
12
+ proxyCache: /* @__PURE__ */ new WeakMap(),
13
+ cache: /* @__PURE__ */ new Map(),
14
+ schemas: getSchemas(target),
15
+ currentContext: ""
16
+ }) => {
10
17
  if (!isObject(target) && !Array.isArray(target)) {
11
18
  return target;
12
19
  }
13
- if (proxyCache.has(target)) {
14
- return proxyCache.get(target);
20
+ if (args.proxyCache.has(target)) {
21
+ return args.proxyCache.get(target);
15
22
  }
16
23
  const handler = {
17
24
  /**
@@ -29,21 +36,29 @@ const createMagicProxy = (target, options, root = target, cache = /* @__PURE__ *
29
36
  if (prop === magicProxyTarget) {
30
37
  return target2;
31
38
  }
32
- const ref = Reflect.get(target2, REF_KEY, receiver);
33
39
  if (typeof prop === "string" && prop.startsWith("_") && !options?.showInternal) {
34
40
  return void 0;
35
41
  }
36
- if (prop === REF_VALUE && typeof ref === "string" && isLocalRef(ref)) {
37
- if (cache.has(ref)) {
38
- return cache.get(ref);
42
+ const ref = Reflect.get(target2, REF_KEY, receiver);
43
+ const id = getId(target2);
44
+ if (prop === REF_VALUE && typeof ref === "string") {
45
+ if (args.cache.has(ref)) {
46
+ return args.cache.get(ref);
39
47
  }
40
- const resolvedValue = getValueByPath(root, parseJsonPointer(ref));
41
- const proxiedValue = createMagicProxy(resolvedValue, options, root, cache);
42
- cache.set(ref, proxiedValue);
48
+ const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas);
49
+ if (path === void 0) {
50
+ return void 0;
51
+ }
52
+ const resolvedValue = getValueByPath(args.root, parseJsonPointer(`#/${path}`));
53
+ const proxiedValue = createMagicProxy(resolvedValue.value, options, {
54
+ ...args,
55
+ currentContext: resolvedValue.context
56
+ });
57
+ args.cache.set(ref, proxiedValue);
43
58
  return proxiedValue;
44
59
  }
45
60
  const value = Reflect.get(target2, prop, receiver);
46
- return createMagicProxy(value, options, root, cache, proxyCache);
61
+ return createMagicProxy(value, options, { ...args, currentContext: id ?? args.currentContext });
47
62
  },
48
63
  /**
49
64
  * Proxy "set" trap for magic proxy.
@@ -58,14 +73,19 @@ const createMagicProxy = (target, options, root = target, cache = /* @__PURE__ *
58
73
  if (typeof prop === "string" && prop.startsWith("_") && !options?.showInternal) {
59
74
  return true;
60
75
  }
61
- if (prop === REF_VALUE && typeof ref === "string" && isLocalRef(ref)) {
62
- const segments = getSegmentsFromPath(ref);
76
+ if (prop === REF_VALUE && typeof ref === "string") {
77
+ const id = getId(target2);
78
+ const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas);
79
+ if (path === void 0) {
80
+ return void 0;
81
+ }
82
+ const segments = parseJsonPointer(`#/${path}`);
63
83
  if (segments.length === 0) {
64
84
  return false;
65
85
  }
66
- const getParentNode = () => getValueByPath(root, segments.slice(0, -1));
86
+ const getParentNode = () => getValueByPath(args.root, segments.slice(0, -1)).value;
67
87
  if (getParentNode() === void 0) {
68
- createPathFromSegments(root, segments.slice(0, -1));
88
+ createPathFromSegments(args.root, segments.slice(0, -1));
69
89
  console.warn(
70
90
  `Trying to set $ref-value for invalid reference: ${ref}
71
91
 
@@ -144,7 +164,7 @@ Please fix your input file to fix this issue.`
144
164
  }
145
165
  };
146
166
  const proxied = new Proxy(target, handler);
147
- proxyCache.set(target, proxied);
167
+ args.proxyCache.set(target, proxied);
148
168
  return proxied;
149
169
  };
150
170
  function getRaw(obj) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/magic-proxy/proxy.ts"],
4
- "sourcesContent": ["import { isLocalRef } from '@/bundle/bundle'\nimport type { UnknownObject } from '@/types'\nimport { getSegmentsFromPath } from '@/utils/get-segments-from-path'\nimport { isObject } from '@/utils/is-object'\nimport { createPathFromSegments, getValueByPath, parseJsonPointer } from '@/utils/json-path-utils'\n\nconst isMagicProxy = Symbol('isMagicProxy')\nconst magicProxyTarget = Symbol('magicProxyTarget')\n\nconst REF_VALUE = '$ref-value'\nconst REF_KEY = '$ref'\n\n/**\n * Creates a \"magic\" proxy for a given object or array, enabling transparent access to\n * JSON Reference ($ref) values as if they were directly present on the object.\n *\n * - If an object contains a `$ref` property, accessing the special `$ref-value` property\n * will resolve and return the referenced value from the root object.\n * - All nested objects and arrays are recursively wrapped in proxies, so reference resolution\n * works at any depth.\n * - Properties starting with an underscore (_) are hidden and will not be accessible through\n * the proxy (returns undefined on access, false on 'in' checks, excluded from enumeration).\n * - Setting, deleting, and enumerating properties works as expected, including for proxied references.\n *\n * @param target - The object or array to wrap in a magic proxy\n * @param root - The root object for resolving local JSON references (defaults to target)\n * @returns A proxied version of the input object/array with magic $ref-value support\n *\n * @example\n * const input = {\n * definitions: {\n * foo: { bar: 123 }\n * },\n * refObj: { $ref: '#/definitions/foo' },\n * _internal: 'hidden property'\n * }\n * const proxy = createMagicProxy(input)\n *\n * // Accessing proxy.refObj['$ref-value'] will resolve to { bar: 123 }\n * console.log(proxy.refObj['$ref-value']) // { bar: 123 }\n *\n * // Properties starting with underscore are hidden\n * console.log(proxy._internal) // undefined\n * console.log('_internal' in proxy) // false\n * console.log(Object.keys(proxy)) // ['definitions', 'refObj'] (no '_internal')\n *\n * // Setting and deleting properties works as expected\n * proxy.refObj.extra = 'hello'\n * delete proxy.refObj.extra\n */\nexport const createMagicProxy = <T extends Record<keyof T & symbol, unknown>, S extends UnknownObject>(\n target: T,\n options?: { showInternal?: boolean },\n root: S | T = target,\n cache = new Map<string, unknown>(),\n proxyCache = new WeakMap<object, T>(),\n) => {\n if (!isObject(target) && !Array.isArray(target)) {\n return target\n }\n\n // Return existing proxy for the same target to ensure referential stability\n if (proxyCache.has(target)) {\n return proxyCache.get(target)\n }\n\n const handler: ProxyHandler<T> = {\n /**\n * Proxy \"get\" trap for magic proxy.\n * - If accessing the special isMagicProxy symbol, return true to identify proxy.\n * - If accessing the magicProxyTarget symbol, return the original target object.\n * - Hide properties starting with underscore by returning undefined.\n * - If accessing \"$ref-value\" and the object has a local $ref, resolve and return the referenced value as a new magic proxy.\n * - For all other properties, recursively wrap the returned value in a magic proxy (if applicable).\n */\n get(target, prop, receiver) {\n if (prop === isMagicProxy) {\n // Used to identify if an object is a magic proxy\n return true\n }\n\n if (prop === magicProxyTarget) {\n // Used to retrieve the original target object from the proxy\n return target\n }\n\n const ref = Reflect.get(target, REF_KEY, receiver)\n\n // Hide properties starting with underscore - these are considered internal/private properties\n // and should not be accessible through the magic proxy interface\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return undefined\n }\n\n // If accessing \"$ref-value\" and $ref is a local reference, resolve and return the referenced value\n if (prop === REF_VALUE && typeof ref === 'string' && isLocalRef(ref)) {\n // Check cache first for performance optimization\n if (cache.has(ref)) {\n return cache.get(ref)\n }\n\n // Resolve the reference and create a new magic proxy\n const resolvedValue = getValueByPath(root, parseJsonPointer(ref))\n const proxiedValue = createMagicProxy(resolvedValue, options, root, cache)\n\n // Store in cache for future lookups\n cache.set(ref, proxiedValue)\n return proxiedValue\n }\n\n // For all other properties, recursively wrap the value in a magic proxy\n const value = Reflect.get(target, prop, receiver)\n return createMagicProxy(value as T, options, root, cache, proxyCache)\n },\n /**\n * Proxy \"set\" trap for magic proxy.\n * Allows setting properties on the proxied object.\n * This will update the underlying target object.\n *\n * Note: it will not update if the property starts with an underscore (_)\n * Those will be considered private properties by the proxy\n */\n set(target, prop, newValue, receiver) {\n const ref = Reflect.get(target, REF_KEY, receiver)\n\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return true\n }\n\n if (prop === REF_VALUE && typeof ref === 'string' && isLocalRef(ref)) {\n const segments = getSegmentsFromPath(ref)\n\n if (segments.length === 0) {\n return false // Can not set top level $ref-value\n }\n\n // Get the parent node or create it if it does not exist\n const getParentNode = () => getValueByPath(root, segments.slice(0, -1))\n\n if (getParentNode() === undefined) {\n createPathFromSegments(root, segments.slice(0, -1))\n\n // In this case the ref is pointing to an invalid path, so we warn the user\n console.warn(\n `Trying to set $ref-value for invalid reference: ${ref}\\n\\nPlease fix your input file to fix this issue.`,\n )\n }\n\n // Set the value on the parent node\n getParentNode()[segments.at(-1)] = newValue\n return true\n }\n\n return Reflect.set(target, prop, newValue, receiver)\n },\n /**\n * Proxy \"deleteProperty\" trap for magic proxy.\n * Allows deleting properties from the proxied object.\n * This will update the underlying target object.\n */\n deleteProperty(target, prop) {\n return Reflect.deleteProperty(target, prop)\n },\n /**\n * Proxy \"has\" trap for magic proxy.\n * - Pretend that \"$ref-value\" exists if \"$ref\" exists on the target.\n * This allows expressions like `\"$ref-value\" in obj` to return true for objects with a $ref,\n * even though \"$ref-value\" is a virtual property provided by the proxy.\n * - Hide properties starting with underscore by returning false.\n * - For all other properties, defer to the default Reflect.has behavior.\n */\n has(target, prop) {\n // Hide properties starting with underscore\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return false\n }\n\n // Pretend that \"$ref-value\" exists if \"$ref\" exists\n if (prop === REF_VALUE && REF_KEY in target) {\n return true\n }\n return Reflect.has(target, prop)\n },\n /**\n * Proxy \"ownKeys\" trap for magic proxy.\n * - Returns the list of own property keys for the proxied object.\n * - If the object has a \"$ref\" property, ensures that \"$ref-value\" is also included in the keys,\n * even though \"$ref-value\" is a virtual property provided by the proxy.\n * This allows Object.keys, Reflect.ownKeys, etc. to include \"$ref-value\" for objects with $ref.\n * - Filters out properties starting with underscore.\n */\n ownKeys(target) {\n const keys = Reflect.ownKeys(target)\n\n // Filter out properties starting with underscore\n const filteredKeys = keys.filter(\n (key) => typeof key !== 'string' || !(key.startsWith('_') && !options?.showInternal),\n )\n\n if (REF_KEY in target && !filteredKeys.includes(REF_VALUE)) {\n filteredKeys.push(REF_VALUE)\n }\n return filteredKeys\n },\n\n /**\n * Proxy \"getOwnPropertyDescriptor\" trap for magic proxy.\n * - For the virtual \"$ref-value\" property, returns a descriptor that makes it appear as a regular property.\n * - Hide properties starting with underscore by returning undefined.\n * - For all other properties, delegates to the default Reflect.getOwnPropertyDescriptor behavior.\n * - This ensures that Object.getOwnPropertyDescriptor and similar methods work correctly with the virtual property.\n */\n getOwnPropertyDescriptor(target, prop) {\n // Hide properties starting with underscore\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return undefined\n }\n\n const ref = Reflect.get(target, REF_KEY)\n\n if (prop === REF_VALUE && typeof ref === 'string') {\n return {\n configurable: true,\n enumerable: true,\n value: undefined,\n writable: false,\n }\n }\n\n // Otherwise, delegate to the default behavior\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n }\n\n const proxied = new Proxy<T>(target, handler)\n proxyCache.set(target, proxied)\n return proxied\n}\n\n/**\n * Gets the raw (non-proxied) version of an object created by createMagicProxy.\n * This is useful when you need to access the original object without the magic proxy wrapper.\n *\n * @param obj - The magic proxy object to get the raw version of\n * @returns The raw version of the object\n * @example\n * const proxy = createMagicProxy({ foo: { $ref: '#/bar' } })\n * const raw = getRaw(proxy) // { foo: { $ref: '#/bar' } }\n */\nexport function getRaw<T>(obj: T): T {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n\n if ((obj as T & { [isMagicProxy]: boolean | undefined })[isMagicProxy]) {\n return (obj as T & { [magicProxyTarget]: T })[magicProxyTarget]\n }\n\n return obj\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { convertToLocalRef } from '@/helpers/convert-to-local-ref'\nimport { getId, getSchemas } from '@/helpers/get-schemas'\nimport { getValueByPath } from '@/helpers/get-value-by-path'\nimport { isObject } from '@/helpers/is-object'\nimport { createPathFromSegments, parseJsonPointer } from '@/helpers/json-path-utils'\nimport type { UnknownObject } from '@/types'\n\nconst isMagicProxy = Symbol('isMagicProxy')\nconst magicProxyTarget = Symbol('magicProxyTarget')\n\nconst REF_VALUE = '$ref-value'\nconst REF_KEY = '$ref'\n\n/**\n * Creates a \"magic\" proxy for a given object or array, enabling transparent access to\n * JSON Reference ($ref) values as if they were directly present on the object.\n *\n * Features:\n * - If an object contains a `$ref` property, accessing the special `$ref-value` property will resolve and return the referenced value from the root object.\n * - All nested objects and arrays are recursively wrapped in proxies, so reference resolution works at any depth.\n * - Properties starting with an underscore (_) are considered internal and are hidden by default: they return undefined on access, are excluded from enumeration, and `'in'` checks return false. This can be overridden with the `showInternal` option.\n * - Setting, deleting, and enumerating properties works as expected, including for proxied references.\n * - Ensures referential stability by caching proxies for the same target object.\n *\n * @param target - The object or array to wrap in a magic proxy\n * @param options - Optional settings (e.g., showInternal to expose internal properties)\n * @param args - Internal arguments for advanced usage (root object, proxy/cache maps, current context)\n * @returns A proxied version of the input object/array with magic $ref-value support\n *\n * @example\n * const input = {\n * definitions: {\n * foo: { bar: 123 }\n * },\n * refObj: { $ref: '#/definitions/foo' },\n * _internal: 'hidden property'\n * }\n * const proxy = createMagicProxy(input)\n *\n * // Accessing proxy.refObj['$ref-value'] will resolve to { bar: 123 }\n * console.log(proxy.refObj['$ref-value']) // { bar: 123 }\n *\n * // Properties starting with underscore are hidden\n * console.log(proxy._internal) // undefined\n * console.log('_internal' in proxy) // false\n * console.log(Object.keys(proxy)) // ['definitions', 'refObj'] (no '_internal')\n *\n * // Setting and deleting properties works as expected\n * proxy.refObj.extra = 'hello'\n * delete proxy.refObj.extra\n */\nexport const createMagicProxy = <T extends Record<keyof T & symbol, unknown>, S extends UnknownObject>(\n target: T,\n options?: Partial<{ showInternal: boolean }>,\n args: {\n /**\n * The root object for resolving local JSON references.\n */\n root: S | T\n /**\n * Cache to store already created proxies for target objects to ensure referential stability.\n *\n * It is helpful when dealing with reactive frameworks like Vue,\n */\n proxyCache: WeakMap<object, T>\n /**\n * Cache to store resolved JSON references.\n */\n cache: Map<string, unknown>\n /**\n * Map of all schemas by their $id or $anchor for cross-document reference resolution.\n */\n schemas: Map<string, string>\n /**\n * The current JSON path context within the root object.\n *\n * Used to resolve $anchor references correctly.\n */\n currentContext: string\n } = {\n root: target,\n proxyCache: new WeakMap(),\n cache: new Map(),\n schemas: getSchemas(target),\n currentContext: '',\n },\n) => {\n if (!isObject(target) && !Array.isArray(target)) {\n return target\n }\n\n // Return existing proxy for the same target to ensure referential stability\n if (args.proxyCache.has(target)) {\n return args.proxyCache.get(target)\n }\n\n const handler: ProxyHandler<T> = {\n /**\n * Proxy \"get\" trap for magic proxy.\n * - If accessing the special isMagicProxy symbol, return true to identify proxy.\n * - If accessing the magicProxyTarget symbol, return the original target object.\n * - Hide properties starting with underscore by returning undefined.\n * - If accessing \"$ref-value\" and the object has a local $ref, resolve and return the referenced value as a new magic proxy.\n * - For all other properties, recursively wrap the returned value in a magic proxy (if applicable).\n */\n get(target, prop, receiver) {\n if (prop === isMagicProxy) {\n // Used to identify if an object is a magic proxy\n return true\n }\n\n if (prop === magicProxyTarget) {\n // Used to retrieve the original target object from the proxy\n return target\n }\n\n // Hide properties starting with underscore - these are considered internal/private properties\n // and should not be accessible through the magic proxy interface\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return undefined\n }\n\n // Get the $ref value of the current target (if any)\n const ref = Reflect.get(target, REF_KEY, receiver)\n // Get the identifier ($id) of the current target for context tracking\n const id = getId(target)\n\n // If accessing \"$ref-value\" and $ref is a local reference, resolve and return the referenced value\n if (prop === REF_VALUE && typeof ref === 'string') {\n // Check cache first for performance optimization\n if (args.cache.has(ref)) {\n return args.cache.get(ref)\n }\n\n const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas)\n\n if (path === undefined) {\n return undefined\n }\n\n // Resolve the reference and create a new magic proxy\n const resolvedValue = getValueByPath(args.root, parseJsonPointer(`#/${path}`))\n const proxiedValue = createMagicProxy(resolvedValue.value, options, {\n ...args,\n currentContext: resolvedValue.context,\n })\n\n // Store in cache for future lookups\n args.cache.set(ref, proxiedValue)\n return proxiedValue\n }\n\n // For all other properties, recursively wrap the value in a magic proxy\n const value = Reflect.get(target, prop, receiver)\n return createMagicProxy(value as T, options, { ...args, currentContext: id ?? args.currentContext })\n },\n /**\n * Proxy \"set\" trap for magic proxy.\n * Allows setting properties on the proxied object.\n * This will update the underlying target object.\n *\n * Note: it will not update if the property starts with an underscore (_)\n * Those will be considered private properties by the proxy\n */\n set(target, prop, newValue, receiver) {\n const ref = Reflect.get(target, REF_KEY, receiver)\n\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return true\n }\n\n if (prop === REF_VALUE && typeof ref === 'string') {\n const id = getId(target)\n const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas)\n\n if (path === undefined) {\n return undefined\n }\n\n const segments = parseJsonPointer(`#/${path}`)\n\n if (segments.length === 0) {\n return false // Can not set top level $ref-value\n }\n\n // Get the parent node or create it if it does not exist\n const getParentNode = () => getValueByPath(args.root, segments.slice(0, -1)).value\n\n if (getParentNode() === undefined) {\n createPathFromSegments(args.root, segments.slice(0, -1))\n\n // In this case the ref is pointing to an invalid path, so we warn the user\n console.warn(\n `Trying to set $ref-value for invalid reference: ${ref}\\n\\nPlease fix your input file to fix this issue.`,\n )\n }\n\n // Set the value on the parent node\n getParentNode()[segments.at(-1)] = newValue\n return true\n }\n\n return Reflect.set(target, prop, newValue, receiver)\n },\n /**\n * Proxy \"deleteProperty\" trap for magic proxy.\n * Allows deleting properties from the proxied object.\n * This will update the underlying target object.\n */\n deleteProperty(target, prop) {\n return Reflect.deleteProperty(target, prop)\n },\n /**\n * Proxy \"has\" trap for magic proxy.\n * - Pretend that \"$ref-value\" exists if \"$ref\" exists on the target.\n * This allows expressions like `\"$ref-value\" in obj` to return true for objects with a $ref,\n * even though \"$ref-value\" is a virtual property provided by the proxy.\n * - Hide properties starting with underscore by returning false.\n * - For all other properties, defer to the default Reflect.has behavior.\n */\n has(target, prop) {\n // Hide properties starting with underscore\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return false\n }\n\n // Pretend that \"$ref-value\" exists if \"$ref\" exists\n if (prop === REF_VALUE && REF_KEY in target) {\n return true\n }\n return Reflect.has(target, prop)\n },\n /**\n * Proxy \"ownKeys\" trap for magic proxy.\n * - Returns the list of own property keys for the proxied object.\n * - If the object has a \"$ref\" property, ensures that \"$ref-value\" is also included in the keys,\n * even though \"$ref-value\" is a virtual property provided by the proxy.\n * This allows Object.keys, Reflect.ownKeys, etc. to include \"$ref-value\" for objects with $ref.\n * - Filters out properties starting with underscore.\n */\n ownKeys(target) {\n const keys = Reflect.ownKeys(target)\n\n // Filter out properties starting with underscore\n const filteredKeys = keys.filter(\n (key) => typeof key !== 'string' || !(key.startsWith('_') && !options?.showInternal),\n )\n\n if (REF_KEY in target && !filteredKeys.includes(REF_VALUE)) {\n filteredKeys.push(REF_VALUE)\n }\n return filteredKeys\n },\n\n /**\n * Proxy \"getOwnPropertyDescriptor\" trap for magic proxy.\n * - For the virtual \"$ref-value\" property, returns a descriptor that makes it appear as a regular property.\n * - Hide properties starting with underscore by returning undefined.\n * - For all other properties, delegates to the default Reflect.getOwnPropertyDescriptor behavior.\n * - This ensures that Object.getOwnPropertyDescriptor and similar methods work correctly with the virtual property.\n */\n getOwnPropertyDescriptor(target, prop) {\n // Hide properties starting with underscore\n if (typeof prop === 'string' && prop.startsWith('_') && !options?.showInternal) {\n return undefined\n }\n\n const ref = Reflect.get(target, REF_KEY)\n\n if (prop === REF_VALUE && typeof ref === 'string') {\n return {\n configurable: true,\n enumerable: true,\n value: undefined,\n writable: false,\n }\n }\n\n // Otherwise, delegate to the default behavior\n return Reflect.getOwnPropertyDescriptor(target, prop)\n },\n }\n\n const proxied = new Proxy<T>(target, handler)\n args.proxyCache.set(target, proxied)\n return proxied\n}\n\n/**\n * Gets the raw (non-proxied) version of an object created by createMagicProxy.\n * This is useful when you need to access the original object without the magic proxy wrapper.\n *\n * @param obj - The magic proxy object to get the raw version of\n * @returns The raw version of the object\n * @example\n * const proxy = createMagicProxy({ foo: { $ref: '#/bar' } })\n * const raw = getRaw(proxy) // { foo: { $ref: '#/bar' } }\n */\nexport function getRaw<T>(obj: T): T {\n if (typeof obj !== 'object' || obj === null) {\n return obj\n }\n\n if ((obj as T & { [isMagicProxy]: boolean | undefined })[isMagicProxy]) {\n return (obj as T & { [magicProxyTarget]: T })[magicProxyTarget]\n }\n\n return obj\n}\n"],
5
+ "mappings": "AAAA,SAAS,yBAAyB;AAClC,SAAS,OAAO,kBAAkB;AAClC,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,wBAAwB,wBAAwB;AAGzD,MAAM,eAAe,OAAO,cAAc;AAC1C,MAAM,mBAAmB,OAAO,kBAAkB;AAElD,MAAM,YAAY;AAClB,MAAM,UAAU;AAwCT,MAAM,mBAAmB,CAC9B,QACA,SACA,OAyBI;AAAA,EACF,MAAM;AAAA,EACN,YAAY,oBAAI,QAAQ;AAAA,EACxB,OAAO,oBAAI,IAAI;AAAA,EACf,SAAS,WAAW,MAAM;AAAA,EAC1B,gBAAgB;AAClB,MACG;AACH,MAAI,CAAC,SAAS,MAAM,KAAK,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC/C,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,WAAW,IAAI,MAAM,GAAG;AAC/B,WAAO,KAAK,WAAW,IAAI,MAAM;AAAA,EACnC;AAEA,QAAM,UAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAS/B,IAAIA,SAAQ,MAAM,UAAU;AAC1B,UAAI,SAAS,cAAc;AAEzB,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,kBAAkB;AAE7B,eAAOA;AAAA,MACT;AAIA,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG,KAAK,CAAC,SAAS,cAAc;AAC9E,eAAO;AAAA,MACT;AAGA,YAAM,MAAM,QAAQ,IAAIA,SAAQ,SAAS,QAAQ;AAEjD,YAAM,KAAK,MAAMA,OAAM;AAGvB,UAAI,SAAS,aAAa,OAAO,QAAQ,UAAU;AAEjD,YAAI,KAAK,MAAM,IAAI,GAAG,GAAG;AACvB,iBAAO,KAAK,MAAM,IAAI,GAAG;AAAA,QAC3B;AAEA,cAAM,OAAO,kBAAkB,KAAK,MAAM,KAAK,gBAAgB,KAAK,OAAO;AAE3E,YAAI,SAAS,QAAW;AACtB,iBAAO;AAAA,QACT;AAGA,cAAM,gBAAgB,eAAe,KAAK,MAAM,iBAAiB,KAAK,IAAI,EAAE,CAAC;AAC7E,cAAM,eAAe,iBAAiB,cAAc,OAAO,SAAS;AAAA,UAClE,GAAG;AAAA,UACH,gBAAgB,cAAc;AAAA,QAChC,CAAC;AAGD,aAAK,MAAM,IAAI,KAAK,YAAY;AAChC,eAAO;AAAA,MACT;AAGA,YAAM,QAAQ,QAAQ,IAAIA,SAAQ,MAAM,QAAQ;AAChD,aAAO,iBAAiB,OAAY,SAAS,EAAE,GAAG,MAAM,gBAAgB,MAAM,KAAK,eAAe,CAAC;AAAA,IACrG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,IAAIA,SAAQ,MAAM,UAAU,UAAU;AACpC,YAAM,MAAM,QAAQ,IAAIA,SAAQ,SAAS,QAAQ;AAEjD,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG,KAAK,CAAC,SAAS,cAAc;AAC9E,eAAO;AAAA,MACT;AAEA,UAAI,SAAS,aAAa,OAAO,QAAQ,UAAU;AACjD,cAAM,KAAK,MAAMA,OAAM;AACvB,cAAM,OAAO,kBAAkB,KAAK,MAAM,KAAK,gBAAgB,KAAK,OAAO;AAE3E,YAAI,SAAS,QAAW;AACtB,iBAAO;AAAA,QACT;AAEA,cAAM,WAAW,iBAAiB,KAAK,IAAI,EAAE;AAE7C,YAAI,SAAS,WAAW,GAAG;AACzB,iBAAO;AAAA,QACT;AAGA,cAAM,gBAAgB,MAAM,eAAe,KAAK,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE;AAE7E,YAAI,cAAc,MAAM,QAAW;AACjC,iCAAuB,KAAK,MAAM,SAAS,MAAM,GAAG,EAAE,CAAC;AAGvD,kBAAQ;AAAA,YACN,mDAAmD,GAAG;AAAA;AAAA;AAAA,UACxD;AAAA,QACF;AAGA,sBAAc,EAAE,SAAS,GAAG,EAAE,CAAC,IAAI;AACnC,eAAO;AAAA,MACT;AAEA,aAAO,QAAQ,IAAIA,SAAQ,MAAM,UAAU,QAAQ;AAAA,IACrD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,eAAeA,SAAQ,MAAM;AAC3B,aAAO,QAAQ,eAAeA,SAAQ,IAAI;AAAA,IAC5C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,IAAIA,SAAQ,MAAM;AAEhB,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG,KAAK,CAAC,SAAS,cAAc;AAC9E,eAAO;AAAA,MACT;AAGA,UAAI,SAAS,aAAa,WAAWA,SAAQ;AAC3C,eAAO;AAAA,MACT;AACA,aAAO,QAAQ,IAAIA,SAAQ,IAAI;AAAA,IACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,QAAQA,SAAQ;AACd,YAAM,OAAO,QAAQ,QAAQA,OAAM;AAGnC,YAAM,eAAe,KAAK;AAAA,QACxB,CAAC,QAAQ,OAAO,QAAQ,YAAY,EAAE,IAAI,WAAW,GAAG,KAAK,CAAC,SAAS;AAAA,MACzE;AAEA,UAAI,WAAWA,WAAU,CAAC,aAAa,SAAS,SAAS,GAAG;AAC1D,qBAAa,KAAK,SAAS;AAAA,MAC7B;AACA,aAAO;AAAA,IACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IASA,yBAAyBA,SAAQ,MAAM;AAErC,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,GAAG,KAAK,CAAC,SAAS,cAAc;AAC9E,eAAO;AAAA,MACT;AAEA,YAAM,MAAM,QAAQ,IAAIA,SAAQ,OAAO;AAEvC,UAAI,SAAS,aAAa,OAAO,QAAQ,UAAU;AACjD,eAAO;AAAA,UACL,cAAc;AAAA,UACd,YAAY;AAAA,UACZ,OAAO;AAAA,UACP,UAAU;AAAA,QACZ;AAAA,MACF;AAGA,aAAO,QAAQ,yBAAyBA,SAAQ,IAAI;AAAA,IACtD;AAAA,EACF;AAEA,QAAM,UAAU,IAAI,MAAS,QAAQ,OAAO;AAC5C,OAAK,WAAW,IAAI,QAAQ,OAAO;AACnC,SAAO;AACT;AAYO,SAAS,OAAU,KAAW;AACnC,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,WAAO;AAAA,EACT;AAEA,MAAK,IAAoD,YAAY,GAAG;AACtE,WAAQ,IAAsC,gBAAgB;AAAA,EAChE;AAEA,SAAO;AACT;",
6
6
  "names": ["target"]
7
7
  }
package/esbuild.ts CHANGED
@@ -9,5 +9,6 @@ await build({
9
9
  'src/dereference/index.ts',
10
10
  'src/bundle/plugins/node.ts',
11
11
  'src/bundle/plugins/browser.ts',
12
+ 'src/helpers/escape-json-pointer.ts',
12
13
  ],
13
14
  })