@scalar/json-magic 0.8.2 → 0.8.4

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 (84) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/bundle/index.d.ts +1 -0
  3. package/dist/bundle/index.d.ts.map +1 -1
  4. package/dist/bundle/index.js.map +1 -1
  5. package/dist/bundle/plugins/browser.js.map +1 -1
  6. package/dist/bundle/plugins/node.d.ts +1 -1
  7. package/dist/bundle/plugins/node.js +1 -1
  8. package/dist/bundle/plugins/node.js.map +1 -1
  9. package/dist/dereference/index.d.ts.map +1 -1
  10. package/dist/dereference/index.js.map +2 -2
  11. package/dist/diff/index.d.ts +1 -1
  12. package/dist/diff/index.d.ts.map +1 -1
  13. package/dist/diff/index.js +1 -1
  14. package/dist/diff/index.js.map +2 -2
  15. package/dist/helpers/escape-json-pointer.d.ts +1 -1
  16. package/dist/helpers/escape-json-pointer.js.map +1 -1
  17. package/dist/magic-proxy/index.d.ts.map +1 -1
  18. package/dist/magic-proxy/index.js.map +2 -2
  19. package/dist/magic-proxy/proxy.d.ts +0 -1
  20. package/dist/magic-proxy/proxy.d.ts.map +1 -1
  21. package/dist/magic-proxy/proxy.js +1 -2
  22. package/dist/magic-proxy/proxy.js.map +2 -2
  23. package/package.json +12 -13
  24. package/.turbo/turbo-build.log +0 -10
  25. package/esbuild.ts +0 -15
  26. package/src/bundle/bundle.test.ts +0 -2917
  27. package/src/bundle/bundle.ts +0 -916
  28. package/src/bundle/create-limiter.test.ts +0 -28
  29. package/src/bundle/create-limiter.ts +0 -52
  30. package/src/bundle/index.ts +0 -3
  31. package/src/bundle/plugins/browser.ts +0 -4
  32. package/src/bundle/plugins/fetch-urls/index.test.ts +0 -141
  33. package/src/bundle/plugins/fetch-urls/index.ts +0 -105
  34. package/src/bundle/plugins/node.ts +0 -5
  35. package/src/bundle/plugins/parse-json/index.test.ts +0 -24
  36. package/src/bundle/plugins/parse-json/index.ts +0 -32
  37. package/src/bundle/plugins/parse-yaml/index.test.ts +0 -26
  38. package/src/bundle/plugins/parse-yaml/index.ts +0 -34
  39. package/src/bundle/plugins/read-files/index.test.ts +0 -36
  40. package/src/bundle/plugins/read-files/index.ts +0 -58
  41. package/src/bundle/value-generator.test.ts +0 -165
  42. package/src/bundle/value-generator.ts +0 -143
  43. package/src/dereference/dereference.test.ts +0 -142
  44. package/src/dereference/dereference.ts +0 -84
  45. package/src/dereference/index.ts +0 -2
  46. package/src/diff/apply.test.ts +0 -262
  47. package/src/diff/apply.ts +0 -83
  48. package/src/diff/diff.test.ts +0 -328
  49. package/src/diff/diff.ts +0 -93
  50. package/src/diff/index.test.ts +0 -150
  51. package/src/diff/index.ts +0 -5
  52. package/src/diff/merge.test.ts +0 -1109
  53. package/src/diff/merge.ts +0 -136
  54. package/src/diff/trie.test.ts +0 -30
  55. package/src/diff/trie.ts +0 -113
  56. package/src/diff/utils.test.ts +0 -169
  57. package/src/diff/utils.ts +0 -111
  58. package/src/helpers/convert-to-local-ref.test.ts +0 -211
  59. package/src/helpers/convert-to-local-ref.ts +0 -43
  60. package/src/helpers/escape-json-pointer.test.ts +0 -13
  61. package/src/helpers/escape-json-pointer.ts +0 -8
  62. package/src/helpers/get-schemas.test.ts +0 -356
  63. package/src/helpers/get-schemas.ts +0 -80
  64. package/src/helpers/get-segments-from-path.test.ts +0 -17
  65. package/src/helpers/get-segments-from-path.ts +0 -17
  66. package/src/helpers/get-value-by-path.test.ts +0 -338
  67. package/src/helpers/get-value-by-path.ts +0 -44
  68. package/src/helpers/is-json-object.ts +0 -31
  69. package/src/helpers/is-object.test.ts +0 -27
  70. package/src/helpers/is-object.ts +0 -4
  71. package/src/helpers/is-yaml.ts +0 -18
  72. package/src/helpers/json-path-utils.test.ts +0 -57
  73. package/src/helpers/json-path-utils.ts +0 -50
  74. package/src/helpers/normalize.test.ts +0 -92
  75. package/src/helpers/normalize.ts +0 -35
  76. package/src/helpers/unescape-json-pointer.test.ts +0 -23
  77. package/src/helpers/unescape-json-pointer.ts +0 -9
  78. package/src/magic-proxy/index.ts +0 -2
  79. package/src/magic-proxy/proxy.test.ts +0 -1987
  80. package/src/magic-proxy/proxy.ts +0 -323
  81. package/src/types.ts +0 -1
  82. package/tsconfig.build.json +0 -12
  83. package/tsconfig.json +0 -16
  84. package/vite.config.ts +0 -8
@@ -1,323 +0,0 @@
1
- import { convertToLocalRef } from '@/helpers/convert-to-local-ref'
2
- import { getId, getSchemas } from '@/helpers/get-schemas'
3
- import { getValueByPath } from '@/helpers/get-value-by-path'
4
- import { isObject } from '@/helpers/is-object'
5
- import { createPathFromSegments, parseJsonPointer } from '@/helpers/json-path-utils'
6
- import type { UnknownObject } from '@/types'
7
-
8
- const isMagicProxy = Symbol('isMagicProxy')
9
- const magicProxyTarget = Symbol('magicProxyTarget')
10
-
11
- const REF_VALUE = '$ref-value'
12
- const REF_KEY = '$ref'
13
-
14
- /**
15
- * Creates a "magic" proxy for a given object or array, enabling transparent access to
16
- * JSON Reference ($ref) values as if they were directly present on the object.
17
- *
18
- * Features:
19
- * - If an object contains a `$ref` property, accessing the special `$ref-value` property will resolve and return the referenced value from the root object.
20
- * - All nested objects and arrays are recursively wrapped in proxies, so reference resolution works at any depth.
21
- * - Properties starting with `__scalar_` 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.
22
- * - Setting, deleting, and enumerating properties works as expected, including for proxied references.
23
- * - Ensures referential stability by caching proxies for the same target object.
24
- *
25
- * @param target - The object or array to wrap in a magic proxy
26
- * @param options - Optional settings (e.g., showInternal to expose internal properties)
27
- * @param args - Internal arguments for advanced usage (root object, proxy/cache maps, current context)
28
- * @returns A proxied version of the input object/array with magic $ref-value support
29
- *
30
- * @example
31
- * const input = {
32
- * definitions: {
33
- * foo: { bar: 123 }
34
- * },
35
- * refObj: { $ref: '#/definitions/foo' },
36
- * __scalar_internal: 'hidden property'
37
- * }
38
- * const proxy = createMagicProxy(input)
39
- *
40
- * // Accessing proxy.refObj['$ref-value'] will resolve to { bar: 123 }
41
- * console.log(proxy.refObj['$ref-value']) // { bar: 123 }
42
- *
43
- * // Properties starting with __scalar_ are hidden
44
- * console.log(proxy.__scalar_internal) // undefined
45
- * console.log('__scalar_internal' in proxy) // false
46
- * console.log(Object.keys(proxy)) // ['definitions', 'refObj'] (no '__scalar_internal')
47
- *
48
- * // Setting and deleting properties works as expected
49
- * proxy.refObj.extra = 'hello'
50
- * delete proxy.refObj.extra
51
- */
52
- export const createMagicProxy = <T extends Record<keyof T & symbol, unknown>, S extends UnknownObject>(
53
- target: T,
54
- options?: Partial<{ showInternal: boolean }>,
55
- args: {
56
- /**
57
- * The root object for resolving local JSON references.
58
- */
59
- root: S | T
60
- /**
61
- * Cache to store already created proxies for target objects to ensure referential stability.
62
- *
63
- * It is helpful when dealing with reactive frameworks like Vue,
64
- */
65
- proxyCache: WeakMap<object, T>
66
- /**
67
- * Cache to store resolved JSON references.
68
- */
69
- cache: Map<string, unknown>
70
- /**
71
- * Map of all schemas by their $id or $anchor for cross-document reference resolution.
72
- */
73
- schemas: Map<string, string>
74
- /**
75
- * The current JSON path context within the root object.
76
- *
77
- * Used to resolve $anchor references correctly.
78
- */
79
- currentContext: string
80
- } = {
81
- root: target,
82
- proxyCache: new WeakMap(),
83
- cache: new Map(),
84
- schemas: getSchemas(target),
85
- currentContext: '',
86
- },
87
- ) => {
88
- if (!isObject(target) && !Array.isArray(target)) {
89
- return target
90
- }
91
-
92
- // Return existing proxy for the same target to ensure referential stability
93
- if (args.proxyCache.has(target)) {
94
- return args.proxyCache.get(target)
95
- }
96
-
97
- const handler: ProxyHandler<T> = {
98
- /**
99
- * Proxy "get" trap for magic proxy.
100
- * - If accessing the special isMagicProxy symbol, return true to identify proxy.
101
- * - If accessing the magicProxyTarget symbol, return the original target object.
102
- * - Hide properties starting with __scalar_ by returning undefined.
103
- * - If accessing "$ref-value" and the object has a local $ref, resolve and return the referenced value as a new magic proxy.
104
- * - For all other properties, recursively wrap the returned value in a magic proxy (if applicable).
105
- */
106
- get(target, prop, receiver) {
107
- if (prop === isMagicProxy) {
108
- // Used to identify if an object is a magic proxy
109
- return true
110
- }
111
-
112
- if (prop === magicProxyTarget) {
113
- // Used to retrieve the original target object from the proxy
114
- return target
115
- }
116
-
117
- // Hide properties starting with __scalar_ - these are considered internal/private properties
118
- // and should not be accessible through the magic proxy interface
119
- if (typeof prop === 'string' && prop.startsWith('__scalar_') && !options?.showInternal) {
120
- return undefined
121
- }
122
-
123
- // Get the $ref value of the current target (if any)
124
- const ref = Reflect.get(target, REF_KEY, receiver)
125
- // Get the identifier ($id) of the current target for context tracking
126
- const id = getId(target)
127
-
128
- // If accessing "$ref-value" and $ref is a local reference, resolve and return the referenced value
129
- if (prop === REF_VALUE && typeof ref === 'string') {
130
- // Check cache first for performance optimization
131
- if (args.cache.has(ref)) {
132
- return args.cache.get(ref)
133
- }
134
-
135
- const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas)
136
-
137
- if (path === undefined) {
138
- return undefined
139
- }
140
-
141
- // Resolve the reference and create a new magic proxy
142
- const resolvedValue = getValueByPath(args.root, parseJsonPointer(`#/${path}`))
143
- // Return early if the value is already a magic proxy
144
- if (isMagicProxyObject(resolvedValue.value)) {
145
- return resolvedValue.value
146
- }
147
- const proxiedValue = createMagicProxy(resolvedValue.value, options, {
148
- ...args,
149
- currentContext: resolvedValue.context,
150
- })
151
-
152
- // Store in cache for future lookups
153
- args.cache.set(ref, proxiedValue)
154
- return proxiedValue
155
- }
156
-
157
- // For all other properties, recursively wrap the value in a magic proxy
158
- const value = Reflect.get(target, prop, receiver)
159
-
160
- // Return early if the value is already a magic proxy
161
- if (isMagicProxyObject(value)) {
162
- return value
163
- }
164
-
165
- return createMagicProxy(value as T, options, { ...args, currentContext: id ?? args.currentContext })
166
- },
167
- /**
168
- * Proxy "set" trap for magic proxy.
169
- * Allows setting properties on the proxied object.
170
- * This will update the underlying target object.
171
- *
172
- * Note: it will not update if the property starts with __scalar_
173
- * Those will be considered private properties by the proxy
174
- */
175
- set(target, prop, newValue, receiver) {
176
- const ref = Reflect.get(target, REF_KEY, receiver)
177
-
178
- if (typeof prop === 'string' && prop.startsWith('__scalar_') && !options?.showInternal) {
179
- return true
180
- }
181
-
182
- if (prop === REF_VALUE && typeof ref === 'string') {
183
- const id = getId(target)
184
- const path = convertToLocalRef(ref, id ?? args.currentContext, args.schemas)
185
-
186
- if (path === undefined) {
187
- return undefined
188
- }
189
-
190
- const segments = parseJsonPointer(`#/${path}`)
191
-
192
- if (segments.length === 0) {
193
- return false // Can not set top level $ref-value
194
- }
195
-
196
- // Get the parent node or create it if it does not exist
197
- const getParentNode = () => getValueByPath(args.root, segments.slice(0, -1)).value
198
-
199
- if (getParentNode() === undefined) {
200
- createPathFromSegments(args.root, segments.slice(0, -1))
201
-
202
- // In this case the ref is pointing to an invalid path, so we warn the user
203
- console.warn(
204
- `Trying to set $ref-value for invalid reference: ${ref}\n\nPlease fix your input file to fix this issue.`,
205
- )
206
- }
207
-
208
- // Set the value on the parent node
209
- getParentNode()[segments.at(-1)] = newValue
210
- return true
211
- }
212
-
213
- return Reflect.set(target, prop, newValue, receiver)
214
- },
215
- /**
216
- * Proxy "deleteProperty" trap for magic proxy.
217
- * Allows deleting properties from the proxied object.
218
- * This will update the underlying target object.
219
- */
220
- deleteProperty(target, prop) {
221
- return Reflect.deleteProperty(target, prop)
222
- },
223
- /**
224
- * Proxy "has" trap for magic proxy.
225
- * - Pretend that "$ref-value" exists if "$ref" exists on the target.
226
- * This allows expressions like `"$ref-value" in obj` to return true for objects with a $ref,
227
- * even though "$ref-value" is a virtual property provided by the proxy.
228
- * - Hide properties starting with __scalar_ by returning false.
229
- * - For all other properties, defer to the default Reflect.has behavior.
230
- */
231
- has(target, prop) {
232
- // Hide properties starting with __scalar_
233
- if (typeof prop === 'string' && prop.startsWith('__scalar_') && !options?.showInternal) {
234
- return false
235
- }
236
-
237
- // Pretend that "$ref-value" exists if "$ref" exists
238
- if (prop === REF_VALUE && REF_KEY in target) {
239
- return true
240
- }
241
- return Reflect.has(target, prop)
242
- },
243
- /**
244
- * Proxy "ownKeys" trap for magic proxy.
245
- * - Returns the list of own property keys for the proxied object.
246
- * - If the object has a "$ref" property, ensures that "$ref-value" is also included in the keys,
247
- * even though "$ref-value" is a virtual property provided by the proxy.
248
- * This allows Object.keys, Reflect.ownKeys, etc. to include "$ref-value" for objects with $ref.
249
- * - Filters out properties starting with __scalar_.
250
- */
251
- ownKeys(target) {
252
- const keys = Reflect.ownKeys(target)
253
-
254
- // Filter out properties starting with __scalar_
255
- const filteredKeys = keys.filter(
256
- (key) => typeof key !== 'string' || !(key.startsWith('__scalar_') && !options?.showInternal),
257
- )
258
-
259
- if (REF_KEY in target && !filteredKeys.includes(REF_VALUE)) {
260
- filteredKeys.push(REF_VALUE)
261
- }
262
- return filteredKeys
263
- },
264
-
265
- /**
266
- * Proxy "getOwnPropertyDescriptor" trap for magic proxy.
267
- * - For the virtual "$ref-value" property, returns a descriptor that makes it appear as a regular property.
268
- * - Hide properties starting with __scalar_ by returning undefined.
269
- * - For all other properties, delegates to the default Reflect.getOwnPropertyDescriptor behavior.
270
- * - This ensures that Object.getOwnPropertyDescriptor and similar methods work correctly with the virtual property.
271
- */
272
- getOwnPropertyDescriptor(target, prop) {
273
- // Hide properties starting with __scalar_
274
- if (typeof prop === 'string' && prop.startsWith('__scalar_') && !options?.showInternal) {
275
- return undefined
276
- }
277
-
278
- const ref = Reflect.get(target, REF_KEY)
279
-
280
- if (prop === REF_VALUE && typeof ref === 'string') {
281
- return {
282
- configurable: true,
283
- enumerable: true,
284
- value: undefined,
285
- writable: false,
286
- }
287
- }
288
-
289
- // Otherwise, delegate to the default behavior
290
- return Reflect.getOwnPropertyDescriptor(target, prop)
291
- },
292
- }
293
-
294
- const proxied = new Proxy<T>(target, handler)
295
- args.proxyCache.set(target, proxied)
296
- return proxied
297
- }
298
-
299
- export const isMagicProxyObject = (obj: unknown): boolean => {
300
- return typeof obj === 'object' && obj !== null && (obj as { [isMagicProxy]: boolean })[isMagicProxy] === true
301
- }
302
-
303
- /**
304
- * Gets the raw (non-proxied) version of an object created by createMagicProxy.
305
- * This is useful when you need to access the original object without the magic proxy wrapper.
306
- *
307
- * @param obj - The magic proxy object to get the raw version of
308
- * @returns The raw version of the object
309
- * @example
310
- * const proxy = createMagicProxy({ foo: { $ref: '#/bar' } })
311
- * const raw = getRaw(proxy) // { foo: { $ref: '#/bar' } }
312
- */
313
- export function getRaw<T>(obj: T): T {
314
- if (typeof obj !== 'object' || obj === null) {
315
- return obj
316
- }
317
-
318
- if ((obj as T & { [isMagicProxy]: boolean | undefined })[isMagicProxy]) {
319
- return (obj as T & { [magicProxyTarget]: T })[magicProxyTarget]
320
- }
321
-
322
- return obj
323
- }
package/src/types.ts DELETED
@@ -1 +0,0 @@
1
- export type UnknownObject = Record<string, unknown>
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "include": ["src"],
4
- "exclude": ["**/*.test.ts"],
5
- "compilerOptions": {
6
- "skipLibCheck": true,
7
- "declaration": true,
8
- "declarationMap": true,
9
- "emitDeclarationOnly": true,
10
- "outDir": "dist/"
11
- }
12
- }
package/tsconfig.json DELETED
@@ -1,16 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- /** We need to remove these :) */
5
- "strictNullChecks": false,
6
- "noImplicitAny": false,
7
- "useUnknownInCatchVariables": false,
8
- "exactOptionalPropertyTypes": false,
9
- "allowJs": true,
10
- "paths": {
11
- "@/*": ["./src/*"],
12
- "@test/*": ["./test/*"]
13
- }
14
- },
15
- "include": ["src", "tests", "rollup.config.ts"]
16
- }
package/vite.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { alias } from '@scalar/build-tooling/vite'
2
- import { defineConfig } from 'vite'
3
-
4
- export default defineConfig({
5
- resolve: {
6
- alias: alias(import.meta.url),
7
- },
8
- })