@scalar/json-magic 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +4 -3
- package/CHANGELOG.md +22 -0
- package/README.md +21 -3
- package/dist/bundle/bundle.d.ts +84 -14
- package/dist/bundle/bundle.d.ts.map +1 -1
- package/dist/bundle/bundle.js +56 -15
- package/dist/bundle/bundle.js.map +3 -3
- package/dist/bundle/index.d.ts +2 -1
- package/dist/bundle/index.d.ts.map +1 -1
- package/dist/bundle/index.js.map +2 -2
- package/dist/bundle/plugins/fetch-urls/index.d.ts +2 -2
- package/dist/bundle/plugins/fetch-urls/index.d.ts.map +1 -1
- package/dist/bundle/plugins/fetch-urls/index.js +1 -0
- package/dist/bundle/plugins/fetch-urls/index.js.map +2 -2
- package/dist/bundle/plugins/parse-json/index.d.ts +2 -2
- package/dist/bundle/plugins/parse-json/index.d.ts.map +1 -1
- package/dist/bundle/plugins/parse-json/index.js +1 -0
- package/dist/bundle/plugins/parse-json/index.js.map +2 -2
- package/dist/bundle/plugins/parse-yaml/index.d.ts +2 -2
- package/dist/bundle/plugins/parse-yaml/index.d.ts.map +1 -1
- package/dist/bundle/plugins/parse-yaml/index.js +1 -0
- package/dist/bundle/plugins/parse-yaml/index.js.map +2 -2
- package/dist/bundle/plugins/read-files/index.d.ts +2 -2
- package/dist/bundle/plugins/read-files/index.d.ts.map +1 -1
- package/dist/bundle/plugins/read-files/index.js +1 -0
- package/dist/bundle/plugins/read-files/index.js.map +2 -2
- package/dist/diff/apply.d.ts +1 -1
- package/dist/diff/apply.d.ts.map +1 -1
- package/dist/diff/apply.js.map +2 -2
- package/dist/diff/diff.d.ts +2 -2
- package/dist/diff/diff.d.ts.map +1 -1
- package/dist/diff/diff.js.map +2 -2
- package/dist/diff/merge.d.ts +3 -3
- package/dist/diff/merge.d.ts.map +1 -1
- package/dist/diff/merge.js.map +2 -2
- package/dist/magic-proxy/proxy.d.ts +23 -42
- package/dist/magic-proxy/proxy.d.ts.map +1 -1
- package/dist/magic-proxy/proxy.js +103 -80
- package/dist/magic-proxy/proxy.js.map +3 -3
- package/dist/utils/is-object.d.ts +1 -1
- package/dist/utils/is-object.d.ts.map +1 -1
- package/dist/utils/is-object.js.map +2 -2
- package/package.json +11 -10
- package/src/bundle/bundle.test.ts +594 -44
- package/src/bundle/bundle.ts +167 -32
- package/src/bundle/index.ts +2 -1
- package/src/bundle/plugins/fetch-urls/index.ts +3 -2
- package/src/bundle/plugins/parse-json/index.ts +3 -2
- package/src/bundle/plugins/parse-yaml/index.ts +3 -2
- package/src/bundle/plugins/read-files/index.ts +4 -2
- package/src/dereference/dereference.test.ts +26 -18
- package/src/diff/apply.ts +8 -3
- package/src/diff/diff.ts +3 -3
- package/src/diff/merge.ts +6 -6
- package/src/magic-proxy/proxy.test.ts +1095 -100
- package/src/magic-proxy/proxy.ts +150 -171
- package/src/utils/is-object.ts +1 -1
|
@@ -1,145 +1,1140 @@
|
|
|
1
|
-
import { createMagicProxy } from './proxy'
|
|
1
|
+
import { createMagicProxy, getRaw } from './proxy'
|
|
2
2
|
import { describe, expect, it } from 'vitest'
|
|
3
3
|
|
|
4
4
|
describe('createMagicProxy', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
5
|
+
describe('get', () => {
|
|
6
|
+
it('should correctly proxy internal refs', () => {
|
|
7
|
+
const input = {
|
|
8
|
+
a: 'hello',
|
|
9
|
+
b: {
|
|
10
|
+
'$ref': '#/a',
|
|
11
|
+
},
|
|
12
|
+
}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
const result = createMagicProxy(input)
|
|
15
|
+
expect(result.b).toEqual({ $ref: '#/a', '$ref-value': 'hello' })
|
|
16
|
+
})
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
18
|
+
it('should correctly proxy deep nested refs', () => {
|
|
19
|
+
const input = {
|
|
20
|
+
a: {
|
|
21
|
+
b: {
|
|
22
|
+
c: {
|
|
23
|
+
d: {
|
|
24
|
+
prop: 'hello',
|
|
25
|
+
},
|
|
26
|
+
e: {
|
|
27
|
+
'$ref': '#/a/b/c/d',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
}
|
|
17
33
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
34
|
+
const result = createMagicProxy(input) as any
|
|
35
|
+
expect(result.a.b.c.e['$ref-value'].prop).toBe('hello')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('should correctly proxy multi refs', () => {
|
|
39
|
+
const input = {
|
|
40
|
+
a: {
|
|
41
|
+
b: {
|
|
42
|
+
c: {
|
|
43
|
+
prop: 'hello',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
e: {
|
|
48
|
+
f: {
|
|
49
|
+
$ref: '#/a/b/c/prop',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
d: {
|
|
53
|
+
$ref: '#/e/f',
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const result = createMagicProxy(input)
|
|
58
|
+
|
|
59
|
+
expect(result.d).toEqual({
|
|
60
|
+
$ref: '#/e/f',
|
|
61
|
+
'$ref-value': {
|
|
62
|
+
$ref: '#/a/b/c/prop',
|
|
63
|
+
'$ref-value': 'hello',
|
|
64
|
+
},
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should preserve information about the ref when the ref is resolved', () => {
|
|
69
|
+
const input = {
|
|
70
|
+
a: {
|
|
71
|
+
b: {
|
|
72
|
+
c: {
|
|
73
|
+
d: {
|
|
74
|
+
prop: 'hello',
|
|
75
|
+
},
|
|
76
|
+
e: {
|
|
77
|
+
'$ref': '#/a/b/c/d',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const result = createMagicProxy(input)
|
|
85
|
+
expect(result.a.b.c.e).toEqual({
|
|
86
|
+
'$ref': '#/a/b/c/d',
|
|
87
|
+
'$ref-value': {
|
|
88
|
+
prop: 'hello',
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('should resolve the references inside an array', () => {
|
|
94
|
+
const input = {
|
|
95
|
+
$defs: {
|
|
96
|
+
a: {
|
|
97
|
+
b: {
|
|
24
98
|
prop: 'hello',
|
|
25
99
|
},
|
|
26
|
-
|
|
27
|
-
|
|
100
|
+
c: {
|
|
101
|
+
someOtherProp: 'world',
|
|
28
102
|
},
|
|
29
103
|
},
|
|
30
104
|
},
|
|
31
|
-
|
|
32
|
-
|
|
105
|
+
a: {
|
|
106
|
+
b: [
|
|
107
|
+
{
|
|
108
|
+
$ref: '#/$defs/a/b',
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
$ref: '#/$defs/a/c',
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const result = createMagicProxy(input)
|
|
118
|
+
expect(JSON.stringify(result.a)).toEqual(
|
|
119
|
+
JSON.stringify({
|
|
120
|
+
'b': [
|
|
121
|
+
{ '$ref': '#/$defs/a/b', '$ref-value': { 'prop': 'hello' } },
|
|
122
|
+
{ '$ref': '#/$defs/a/c', '$ref-value': { 'someOtherProp': 'world' } },
|
|
123
|
+
],
|
|
124
|
+
}),
|
|
125
|
+
)
|
|
126
|
+
})
|
|
33
127
|
|
|
34
|
-
|
|
35
|
-
|
|
128
|
+
it('should return undefined if the ref is an external ref', () => {
|
|
129
|
+
const input = {
|
|
130
|
+
a: 'hello',
|
|
131
|
+
b: {
|
|
132
|
+
$ref: 'https://example.com/document.json/#',
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const result = createMagicProxy(input)
|
|
137
|
+
expect(result).toEqual({
|
|
138
|
+
a: 'hello',
|
|
139
|
+
b: {
|
|
140
|
+
$ref: 'https://example.com/document.json/#',
|
|
141
|
+
'$ref-value': undefined,
|
|
142
|
+
},
|
|
143
|
+
})
|
|
144
|
+
})
|
|
36
145
|
})
|
|
37
146
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
147
|
+
describe('set', () => {
|
|
148
|
+
it('sets properties on the target object', () => {
|
|
149
|
+
const input: any = {
|
|
150
|
+
a: 'hello',
|
|
41
151
|
b: {
|
|
42
|
-
|
|
43
|
-
|
|
152
|
+
$ref: '#/a',
|
|
153
|
+
},
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const result = createMagicProxy(input)
|
|
157
|
+
result.c = 'world'
|
|
158
|
+
|
|
159
|
+
expect(result.c).toBe('world')
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('sets properties on nested objects', () => {
|
|
163
|
+
const input: any = {
|
|
164
|
+
a: {
|
|
165
|
+
b: {
|
|
166
|
+
c: 'hello',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const result = createMagicProxy(input)
|
|
172
|
+
result.a.b.d = 'world'
|
|
173
|
+
|
|
174
|
+
expect(result.a.b.d).toBe('world')
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
it('sets properties on objects with refs', () => {
|
|
178
|
+
const input: any = {
|
|
179
|
+
a: {
|
|
180
|
+
b: {
|
|
181
|
+
c: 'hello',
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
d: {
|
|
185
|
+
$ref: '#/a/b',
|
|
186
|
+
},
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const result = createMagicProxy(input)
|
|
190
|
+
result.d.e = 'world'
|
|
191
|
+
|
|
192
|
+
expect(result.d.e).toBe('world')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('sets properties on arrays', () => {
|
|
196
|
+
const input = {
|
|
197
|
+
items: [{ name: 'item1' }, { name: 'item2' }],
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const result = createMagicProxy(input)
|
|
201
|
+
result.items[2] = { name: 'item3' }
|
|
202
|
+
|
|
203
|
+
expect(result.items[2].name).toBe('item3')
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
it('sets properties on array elements with refs', () => {
|
|
207
|
+
const input: any = {
|
|
208
|
+
$defs: {
|
|
209
|
+
item: { name: 'default' },
|
|
210
|
+
},
|
|
211
|
+
items: [{ $ref: '#/$defs/item' }],
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const result = createMagicProxy(input)
|
|
215
|
+
result.items[0].id = 123
|
|
216
|
+
|
|
217
|
+
expect(input.items[0].id).toBe(123)
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
it('overwrites existing properties', () => {
|
|
221
|
+
const input = {
|
|
222
|
+
a: 'hello',
|
|
223
|
+
b: {
|
|
224
|
+
c: 'world',
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const result = createMagicProxy(input)
|
|
229
|
+
result.a = 'updated'
|
|
230
|
+
result.b.c = 'updated'
|
|
231
|
+
|
|
232
|
+
expect(result.a).toBe('updated')
|
|
233
|
+
expect(result.b.c).toBe('updated')
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
it('sets properties on the root object', () => {
|
|
237
|
+
const input: any = {
|
|
238
|
+
a: 'hello',
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const result = createMagicProxy(input)
|
|
242
|
+
result.rootProperty = 'root value'
|
|
243
|
+
|
|
244
|
+
expect(result.rootProperty).toBe('root value')
|
|
245
|
+
})
|
|
246
|
+
|
|
247
|
+
it('sets properties that are accessed via ref-value', () => {
|
|
248
|
+
const input: any = {
|
|
249
|
+
a: {
|
|
250
|
+
b: {
|
|
251
|
+
c: 'hello',
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
d: {
|
|
255
|
+
$ref: '#/a/b',
|
|
256
|
+
},
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
const result = createMagicProxy(input)
|
|
260
|
+
const refValue = result.d['$ref-value']
|
|
261
|
+
refValue.newProp = 'new value'
|
|
262
|
+
|
|
263
|
+
expect(refValue.newProp).toBe('new value')
|
|
264
|
+
expect(input.a.b.newProp).toBe('new value')
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('sets properties on deeply nested refs', () => {
|
|
268
|
+
const input: any = {
|
|
269
|
+
a: {
|
|
270
|
+
b: {
|
|
271
|
+
c: {
|
|
272
|
+
d: {
|
|
273
|
+
e: 'hello',
|
|
274
|
+
},
|
|
275
|
+
},
|
|
44
276
|
},
|
|
45
277
|
},
|
|
46
|
-
},
|
|
47
|
-
e: {
|
|
48
278
|
f: {
|
|
49
|
-
$ref: '#/a/b/c/
|
|
279
|
+
$ref: '#/a/b/c/d',
|
|
50
280
|
},
|
|
51
|
-
}
|
|
52
|
-
d: {
|
|
53
|
-
$ref: '#/e/f',
|
|
54
|
-
},
|
|
55
|
-
}
|
|
281
|
+
}
|
|
56
282
|
|
|
57
|
-
|
|
283
|
+
const result = createMagicProxy(input)
|
|
284
|
+
result.f['$ref-value'].g = 'world'
|
|
58
285
|
|
|
59
|
-
|
|
60
|
-
|
|
286
|
+
expect(result.f['$ref-value'].g).toBe('world')
|
|
287
|
+
expect(input.a.b.c.d.g).toBe('world')
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('correctly writes on the referenced value', () => {
|
|
291
|
+
const input = {
|
|
292
|
+
a: {
|
|
293
|
+
b: {
|
|
294
|
+
hello: 'hi',
|
|
295
|
+
},
|
|
296
|
+
},
|
|
297
|
+
c: {
|
|
298
|
+
$ref: '#/a/b',
|
|
299
|
+
},
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
const proxied = createMagicProxy(input)
|
|
303
|
+
|
|
304
|
+
proxied.c['$ref-value'].hello = 'new value'
|
|
305
|
+
|
|
306
|
+
expect(input).toEqual({
|
|
307
|
+
a: {
|
|
308
|
+
b: {
|
|
309
|
+
hello: 'new value',
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
c: {
|
|
313
|
+
$ref: '#/a/b',
|
|
314
|
+
},
|
|
315
|
+
})
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it('sets properties on the referenced value #1', () => {
|
|
319
|
+
const input = {
|
|
320
|
+
a: {
|
|
321
|
+
$ref: '#/b',
|
|
322
|
+
},
|
|
323
|
+
b: {
|
|
324
|
+
hello: 'world',
|
|
325
|
+
},
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const proxied = createMagicProxy(input)
|
|
329
|
+
|
|
330
|
+
proxied.a['$ref-value'] = 'new value'
|
|
331
|
+
|
|
332
|
+
expect(proxied).toEqual({
|
|
333
|
+
a: {
|
|
334
|
+
$ref: '#/b',
|
|
335
|
+
'$ref-value': 'new value',
|
|
336
|
+
},
|
|
337
|
+
b: 'new value',
|
|
338
|
+
})
|
|
339
|
+
})
|
|
61
340
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
341
|
+
it('sets properties on the referenced value #2', () => {
|
|
342
|
+
const input = {
|
|
343
|
+
a: {
|
|
344
|
+
$ref: '#/b/c',
|
|
345
|
+
},
|
|
65
346
|
b: {
|
|
66
347
|
c: {
|
|
67
|
-
|
|
68
|
-
prop: 'hello',
|
|
69
|
-
},
|
|
70
|
-
e: {
|
|
71
|
-
'$ref': '#/a/b/c/d',
|
|
72
|
-
},
|
|
348
|
+
hello: 'world',
|
|
73
349
|
},
|
|
74
350
|
},
|
|
75
|
-
}
|
|
76
|
-
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const proxied = createMagicProxy(input)
|
|
354
|
+
|
|
355
|
+
proxied.a['$ref-value'] = {
|
|
356
|
+
message: 'this is the new value',
|
|
357
|
+
}
|
|
77
358
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
359
|
+
expect(proxied).toEqual({
|
|
360
|
+
a: {
|
|
361
|
+
$ref: '#/b/c',
|
|
362
|
+
'$ref-value': {
|
|
363
|
+
'message': 'this is the new value',
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
'b': {
|
|
367
|
+
'c': {
|
|
368
|
+
'message': 'this is the new value',
|
|
369
|
+
},
|
|
370
|
+
},
|
|
371
|
+
})
|
|
82
372
|
})
|
|
83
|
-
})
|
|
84
373
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
374
|
+
it('throws an error when trying set rewrite a referenced value which is the root of the document', () => {
|
|
375
|
+
const input = {
|
|
376
|
+
a: {
|
|
377
|
+
$ref: '#',
|
|
378
|
+
},
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const proxied = createMagicProxy(input)
|
|
382
|
+
|
|
383
|
+
expect(() => {
|
|
384
|
+
proxied.a['$ref-value'] = 'new value'
|
|
385
|
+
}).toThrowError("'set' on proxy: trap returned falsish for property '$ref-value'")
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
// TODO: might change this behavior in the future
|
|
389
|
+
// so we allow setting the $ref-value for invalid refs by creating the path
|
|
390
|
+
it('throws when trying to update an invalid ref where the parent node does not exists', () => {
|
|
391
|
+
const input = {
|
|
392
|
+
a: {
|
|
393
|
+
$ref: '#/non-existent/some-path',
|
|
394
|
+
},
|
|
88
395
|
b: {
|
|
89
396
|
c: {
|
|
90
|
-
|
|
91
|
-
|
|
397
|
+
hello: 'world',
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const proxied = createMagicProxy(input)
|
|
403
|
+
|
|
404
|
+
expect(() => {
|
|
405
|
+
proxied.a['$ref-value'] = 'new value'
|
|
406
|
+
}).toThrowError("'set' on proxy: trap returned falsish for property '$ref-value'")
|
|
407
|
+
})
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
describe('has', () => {
|
|
411
|
+
it('returns true for $ref-value when $ref exists', () => {
|
|
412
|
+
const input = {
|
|
413
|
+
a: 'hello',
|
|
414
|
+
b: {
|
|
415
|
+
$ref: '#/a',
|
|
416
|
+
},
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const result = createMagicProxy(input)
|
|
420
|
+
expect('$ref-value' in result.b).toBe(true)
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
it('returns false for $ref-value when $ref does not exist', () => {
|
|
424
|
+
const input = {
|
|
425
|
+
a: 'hello',
|
|
426
|
+
b: {
|
|
427
|
+
c: 'world',
|
|
428
|
+
},
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const result = createMagicProxy(input)
|
|
432
|
+
expect('$ref-value' in result.b).toBe(false)
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
it('returns true for existing properties', () => {
|
|
436
|
+
const input = {
|
|
437
|
+
a: 'hello',
|
|
438
|
+
b: {
|
|
439
|
+
c: 'world',
|
|
440
|
+
},
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
const result = createMagicProxy(input)
|
|
444
|
+
expect('a' in result).toBe(true)
|
|
445
|
+
expect('b' in result).toBe(true)
|
|
446
|
+
expect('c' in result.b).toBe(true)
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
it('returns false for non-existent properties', () => {
|
|
450
|
+
const input = {
|
|
451
|
+
a: 'hello',
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const result = createMagicProxy(input)
|
|
455
|
+
expect('nonExistent' in result).toBe(false)
|
|
456
|
+
expect('$ref-value' in result).toBe(false)
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
it('handles nested objects with refs', () => {
|
|
460
|
+
const input = {
|
|
461
|
+
a: {
|
|
462
|
+
b: {
|
|
463
|
+
c: 'hello',
|
|
464
|
+
},
|
|
465
|
+
},
|
|
466
|
+
d: {
|
|
467
|
+
$ref: '#/a/b',
|
|
468
|
+
},
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
const result = createMagicProxy(input)
|
|
472
|
+
expect('$ref-value' in result.d).toBe(true)
|
|
473
|
+
expect('c' in result.a.b).toBe(true)
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
it('handles arrays with refs', () => {
|
|
477
|
+
const input = {
|
|
478
|
+
items: [{ name: 'item1' }, { $ref: '#/items/0' }],
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const result = createMagicProxy(input)
|
|
482
|
+
expect('$ref-value' in result.items[1]).toBe(true)
|
|
483
|
+
expect('name' in result.items[0]).toBe(true)
|
|
484
|
+
})
|
|
485
|
+
|
|
486
|
+
it('handles deeply nested refs', () => {
|
|
487
|
+
const input = {
|
|
488
|
+
a: {
|
|
489
|
+
b: {
|
|
490
|
+
c: {
|
|
491
|
+
d: {
|
|
492
|
+
e: 'hello',
|
|
493
|
+
},
|
|
92
494
|
},
|
|
93
|
-
|
|
94
|
-
|
|
495
|
+
},
|
|
496
|
+
},
|
|
497
|
+
f: {
|
|
498
|
+
$ref: '#/a/b/c/d',
|
|
499
|
+
},
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
const result = createMagicProxy(input)
|
|
503
|
+
expect('$ref-value' in result.f).toBe(true)
|
|
504
|
+
})
|
|
505
|
+
|
|
506
|
+
it('handles objects with both $ref and other properties', () => {
|
|
507
|
+
const input = {
|
|
508
|
+
a: {
|
|
509
|
+
b: {
|
|
510
|
+
c: 'hello',
|
|
511
|
+
},
|
|
512
|
+
},
|
|
513
|
+
d: {
|
|
514
|
+
$ref: '#/a/b',
|
|
515
|
+
extraProp: 'extra',
|
|
516
|
+
},
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const result = createMagicProxy(input)
|
|
520
|
+
expect('$ref-value' in result.d).toBe(true)
|
|
521
|
+
expect('extraProp' in result.d).toBe(true)
|
|
522
|
+
expect('$ref' in result.d).toBe(true)
|
|
523
|
+
})
|
|
524
|
+
|
|
525
|
+
it('handles external refs', () => {
|
|
526
|
+
const input = {
|
|
527
|
+
a: 'hello',
|
|
528
|
+
b: {
|
|
529
|
+
$ref: 'https://example.com/document.json/#',
|
|
530
|
+
},
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
const result = createMagicProxy(input)
|
|
534
|
+
expect('$ref-value' in result.b).toBe(true)
|
|
535
|
+
})
|
|
536
|
+
|
|
537
|
+
it('handles empty objects', () => {
|
|
538
|
+
const input = {}
|
|
539
|
+
|
|
540
|
+
const result = createMagicProxy(input)
|
|
541
|
+
expect('$ref-value' in result).toBe(false)
|
|
542
|
+
expect('anyProperty' in result).toBe(false)
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
it('handles null and undefined values', () => {
|
|
546
|
+
const input = {
|
|
547
|
+
a: null,
|
|
548
|
+
b: undefined,
|
|
549
|
+
c: {
|
|
550
|
+
$ref: '#/a',
|
|
551
|
+
},
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
const result = createMagicProxy(input)
|
|
555
|
+
expect('$ref-value' in result.c).toBe(true)
|
|
556
|
+
expect('a' in result).toBe(true)
|
|
557
|
+
expect('b' in result).toBe(true)
|
|
558
|
+
})
|
|
559
|
+
})
|
|
560
|
+
|
|
561
|
+
describe('delete', () => {
|
|
562
|
+
it('deletes properties from the target object', () => {
|
|
563
|
+
const input = {
|
|
564
|
+
a: 'hello',
|
|
565
|
+
b: 'world',
|
|
566
|
+
c: 'test',
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const result = createMagicProxy(input)
|
|
570
|
+
delete result.b
|
|
571
|
+
|
|
572
|
+
expect('b' in result).toBe(false)
|
|
573
|
+
expect(result.a).toBe('hello')
|
|
574
|
+
expect(result.c).toBe('test')
|
|
575
|
+
})
|
|
576
|
+
|
|
577
|
+
it('deletes properties from nested objects', () => {
|
|
578
|
+
const input = {
|
|
579
|
+
a: {
|
|
580
|
+
b: 'hello',
|
|
581
|
+
c: 'world',
|
|
582
|
+
d: 'test',
|
|
583
|
+
},
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const result = createMagicProxy(input)
|
|
587
|
+
delete result.a.c
|
|
588
|
+
|
|
589
|
+
expect('c' in result.a).toBe(false)
|
|
590
|
+
expect(result.a.b).toBe('hello')
|
|
591
|
+
expect(result.a.d).toBe('test')
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
it('deletes properties from objects with refs', () => {
|
|
595
|
+
const input = {
|
|
596
|
+
a: {
|
|
597
|
+
b: 'hello',
|
|
598
|
+
c: 'world',
|
|
599
|
+
},
|
|
600
|
+
d: {
|
|
601
|
+
$ref: '#/a',
|
|
602
|
+
extraProp: 'extra',
|
|
603
|
+
},
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
const result = createMagicProxy(input)
|
|
607
|
+
delete result.d.extraProp
|
|
608
|
+
|
|
609
|
+
expect('extraProp' in result.d).toBe(false)
|
|
610
|
+
expect('$ref' in result.d).toBe(true)
|
|
611
|
+
expect('$ref-value' in result.d).toBe(true)
|
|
612
|
+
})
|
|
613
|
+
|
|
614
|
+
it('deletes properties from ref-value objects', () => {
|
|
615
|
+
const input = {
|
|
616
|
+
a: {
|
|
617
|
+
b: {
|
|
618
|
+
c: 'hello',
|
|
619
|
+
d: 'world',
|
|
620
|
+
},
|
|
621
|
+
},
|
|
622
|
+
e: {
|
|
623
|
+
$ref: '#/a/b',
|
|
624
|
+
},
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
const result = createMagicProxy(input)
|
|
628
|
+
delete result.e['$ref-value'].d
|
|
629
|
+
|
|
630
|
+
expect('d' in result.e['$ref-value']).toBe(false)
|
|
631
|
+
expect(result.e['$ref-value'].c).toBe('hello')
|
|
632
|
+
expect(input.a.b.d).toBeUndefined()
|
|
633
|
+
})
|
|
634
|
+
|
|
635
|
+
it('deletes array elements', () => {
|
|
636
|
+
const input = {
|
|
637
|
+
items: ['a', 'b', 'c', 'd'],
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
const result = createMagicProxy(input)
|
|
641
|
+
delete result.items[1]
|
|
642
|
+
|
|
643
|
+
expect(result.items[1]).toBeUndefined()
|
|
644
|
+
expect(result.items[0]).toBe('a')
|
|
645
|
+
expect(result.items[2]).toBe('c')
|
|
646
|
+
expect(result.items[3]).toBe('d')
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
it('deletes properties from array elements with refs', () => {
|
|
650
|
+
const input = {
|
|
651
|
+
$defs: {
|
|
652
|
+
item: { name: 'default', id: 123, type: 'test' },
|
|
653
|
+
},
|
|
654
|
+
items: [{ $ref: '#/$defs/item' }],
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const result = createMagicProxy(input)
|
|
658
|
+
delete result.items[0]['$ref-value'].type
|
|
659
|
+
|
|
660
|
+
expect('type' in result.items[0]['$ref-value']).toBe(false)
|
|
661
|
+
expect(result.items[0]['$ref-value'].name).toBe('default')
|
|
662
|
+
expect(result.items[0]['$ref-value'].id).toBe(123)
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
it('deletes deeply nested properties', () => {
|
|
666
|
+
const input = {
|
|
667
|
+
a: {
|
|
668
|
+
b: {
|
|
669
|
+
c: {
|
|
670
|
+
d: {
|
|
671
|
+
e: 'hello',
|
|
672
|
+
f: 'world',
|
|
673
|
+
},
|
|
95
674
|
},
|
|
96
|
-
|
|
97
|
-
|
|
675
|
+
},
|
|
676
|
+
},
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const result = createMagicProxy(input)
|
|
680
|
+
delete result.a.b.c.d.f
|
|
681
|
+
|
|
682
|
+
expect('f' in result.a.b.c.d).toBe(false)
|
|
683
|
+
expect(result.a.b.c.d.e).toBe('hello')
|
|
684
|
+
})
|
|
685
|
+
|
|
686
|
+
it('deletes properties from deeply nested refs', () => {
|
|
687
|
+
const input = {
|
|
688
|
+
a: {
|
|
689
|
+
b: {
|
|
690
|
+
c: {
|
|
691
|
+
d: {
|
|
692
|
+
e: 'hello',
|
|
693
|
+
f: 'world',
|
|
694
|
+
},
|
|
98
695
|
},
|
|
99
696
|
},
|
|
100
697
|
},
|
|
101
|
-
|
|
102
|
-
|
|
698
|
+
g: {
|
|
699
|
+
$ref: '#/a/b/c/d',
|
|
700
|
+
},
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
const result = createMagicProxy(input)
|
|
704
|
+
delete result.g['$ref-value'].f
|
|
103
705
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
706
|
+
expect('f' in result.g['$ref-value']).toBe(false)
|
|
707
|
+
expect(result.g['$ref-value'].e).toBe('hello')
|
|
708
|
+
expect(input.a.b.c.d.f).toBeUndefined()
|
|
709
|
+
})
|
|
710
|
+
|
|
711
|
+
it('deletes root level properties', () => {
|
|
712
|
+
const input: any = {
|
|
713
|
+
rootProp: 'root value',
|
|
714
|
+
nestedProp: 'nested value',
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const result = createMagicProxy(input)
|
|
718
|
+
delete result.rootProp
|
|
719
|
+
|
|
720
|
+
expect('rootProp' in result).toBe(false)
|
|
721
|
+
expect(result.nestedProp).toBe('nested value')
|
|
722
|
+
})
|
|
723
|
+
|
|
724
|
+
it('deletes properties that do not exist', () => {
|
|
725
|
+
const input: any = {
|
|
726
|
+
a: 'hello',
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
const result = createMagicProxy(input)
|
|
730
|
+
const deleteResult = delete result.nonExistent
|
|
731
|
+
|
|
732
|
+
expect(deleteResult).toBe(true)
|
|
733
|
+
expect('nonExistent' in result).toBe(false)
|
|
734
|
+
})
|
|
735
|
+
|
|
736
|
+
it('deletes properties from objects with multiple refs', () => {
|
|
737
|
+
const input = {
|
|
738
|
+
a: {
|
|
739
|
+
b: {
|
|
740
|
+
c: 'hello',
|
|
741
|
+
d: 'world',
|
|
742
|
+
},
|
|
743
|
+
},
|
|
744
|
+
e: {
|
|
745
|
+
$ref: '#/a/b',
|
|
746
|
+
},
|
|
747
|
+
f: {
|
|
748
|
+
$ref: '#/e',
|
|
749
|
+
},
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const result = createMagicProxy(input)
|
|
753
|
+
delete result.f['$ref-value']['$ref-value'].d
|
|
754
|
+
|
|
755
|
+
expect('d' in result.f['$ref-value']['$ref-value']).toBe(false)
|
|
756
|
+
expect(result.f['$ref-value']['$ref-value'].c).toBe('hello')
|
|
757
|
+
expect(input.a.b.d).toBeUndefined()
|
|
758
|
+
})
|
|
759
|
+
|
|
760
|
+
it('deletes properties from external refs', () => {
|
|
761
|
+
const input = {
|
|
762
|
+
a: 'hello',
|
|
763
|
+
b: {
|
|
764
|
+
$ref: 'https://example.com/document.json/#',
|
|
765
|
+
localProp: 'local',
|
|
766
|
+
},
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
const result = createMagicProxy(input)
|
|
770
|
+
delete result.b.localProp
|
|
771
|
+
|
|
772
|
+
expect('localProp' in result.b).toBe(false)
|
|
773
|
+
expect('$ref' in result.b).toBe(true)
|
|
774
|
+
expect('$ref-value' in result.b).toBe(true)
|
|
775
|
+
})
|
|
776
|
+
|
|
777
|
+
it('deletes properties from empty objects', () => {
|
|
778
|
+
const input: any = {}
|
|
779
|
+
|
|
780
|
+
const result = createMagicProxy(input)
|
|
781
|
+
const deleteResult = delete result.anyProperty
|
|
782
|
+
|
|
783
|
+
expect(deleteResult).toBe(true)
|
|
784
|
+
expect('anyProperty' in result).toBe(false)
|
|
785
|
+
})
|
|
786
|
+
|
|
787
|
+
it('deletes properties from objects with null and undefined values', () => {
|
|
788
|
+
const input = {
|
|
789
|
+
a: null,
|
|
790
|
+
b: undefined,
|
|
791
|
+
c: {
|
|
792
|
+
d: null,
|
|
793
|
+
e: undefined,
|
|
794
|
+
},
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
const result = createMagicProxy(input)
|
|
798
|
+
delete result.a
|
|
799
|
+
delete result.c.d
|
|
800
|
+
|
|
801
|
+
expect('a' in result).toBe(false)
|
|
802
|
+
expect('d' in result.c).toBe(false)
|
|
803
|
+
expect('b' in result).toBe(true)
|
|
804
|
+
expect('e' in result.c).toBe(true)
|
|
805
|
+
})
|
|
806
|
+
|
|
807
|
+
it('deletes properties from arrays with mixed content', () => {
|
|
808
|
+
const input: any = {
|
|
809
|
+
items: [{ name: 'item1', id: 1 }, { $ref: '#/items/0' }, 'string item', { name: 'item2', id: 2 }],
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
const result = createMagicProxy(input)
|
|
813
|
+
delete result.items[0].id
|
|
814
|
+
delete result.items[1]['$ref-value'].name
|
|
815
|
+
|
|
816
|
+
expect('id' in result.items[0]).toBe(false)
|
|
817
|
+
expect('name' in result.items[1]['$ref-value']).toBe(false)
|
|
818
|
+
expect(result.items[0].name).toBe(undefined)
|
|
819
|
+
expect(result.items[2]).toBe('string item')
|
|
820
|
+
})
|
|
821
|
+
|
|
822
|
+
it('deletes properties from objects with both direct and ref properties', () => {
|
|
823
|
+
const input = {
|
|
824
|
+
a: {
|
|
825
|
+
b: {
|
|
826
|
+
c: 'hello',
|
|
827
|
+
d: 'world',
|
|
828
|
+
},
|
|
829
|
+
},
|
|
830
|
+
e: {
|
|
831
|
+
$ref: '#/a/b',
|
|
832
|
+
directProp: 'direct',
|
|
833
|
+
},
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
const result = createMagicProxy(input)
|
|
837
|
+
delete result.e.directProp
|
|
838
|
+
delete result.e['$ref-value'].d
|
|
839
|
+
|
|
840
|
+
expect('directProp' in result.e).toBe(false)
|
|
841
|
+
expect('d' in result.e['$ref-value']).toBe(false)
|
|
842
|
+
expect('$ref' in result.e).toBe(true)
|
|
843
|
+
expect(result.e['$ref-value'].c).toBe('hello')
|
|
108
844
|
})
|
|
109
845
|
})
|
|
110
846
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
847
|
+
describe('ownKeys', () => {
|
|
848
|
+
it('returns original keys when no $ref exists', () => {
|
|
849
|
+
const input = {
|
|
850
|
+
a: 'hello',
|
|
851
|
+
b: 'world',
|
|
852
|
+
c: 'test',
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const result = createMagicProxy(input)
|
|
856
|
+
const keys = Object.keys(result)
|
|
857
|
+
|
|
858
|
+
expect(keys).toEqual(['a', 'b', 'c'])
|
|
859
|
+
})
|
|
860
|
+
|
|
861
|
+
it('includes $ref-value when $ref exists', () => {
|
|
862
|
+
const input = {
|
|
863
|
+
a: 'hello',
|
|
864
|
+
b: {
|
|
865
|
+
$ref: '#/a',
|
|
866
|
+
},
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
const result = createMagicProxy(input)
|
|
870
|
+
const keys = Object.keys(result.b)
|
|
871
|
+
|
|
872
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
873
|
+
})
|
|
874
|
+
|
|
875
|
+
it('does not duplicate $ref-value if it already exists', () => {
|
|
876
|
+
const input = {
|
|
877
|
+
a: 'hello',
|
|
878
|
+
b: {
|
|
879
|
+
$ref: '#/a',
|
|
880
|
+
'$ref-value': 'existing',
|
|
881
|
+
},
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
const result = createMagicProxy(input)
|
|
885
|
+
const keys = Object.keys(result.b)
|
|
886
|
+
|
|
887
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
888
|
+
})
|
|
889
|
+
|
|
890
|
+
it('handles nested objects with refs', () => {
|
|
891
|
+
const input = {
|
|
114
892
|
a: {
|
|
115
893
|
b: {
|
|
116
|
-
|
|
894
|
+
c: 'hello',
|
|
117
895
|
},
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
896
|
+
},
|
|
897
|
+
d: {
|
|
898
|
+
$ref: '#/a/b',
|
|
899
|
+
extraProp: 'extra',
|
|
900
|
+
},
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
const result = createMagicProxy(input)
|
|
904
|
+
const keys = Object.keys(result.d)
|
|
905
|
+
|
|
906
|
+
expect(keys).toEqual(['$ref', 'extraProp', '$ref-value'])
|
|
907
|
+
})
|
|
908
|
+
|
|
909
|
+
it('handles arrays with refs', () => {
|
|
910
|
+
const input = {
|
|
911
|
+
items: [{ name: 'item1' }, { $ref: '#/items/0' }, { name: 'item2', id: 2 }],
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
const result = createMagicProxy(input)
|
|
915
|
+
const keys = Object.keys(result.items[1])
|
|
916
|
+
|
|
917
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
918
|
+
})
|
|
919
|
+
|
|
920
|
+
it('handles deeply nested refs', () => {
|
|
921
|
+
const input = {
|
|
922
|
+
a: {
|
|
923
|
+
b: {
|
|
924
|
+
c: {
|
|
925
|
+
d: {
|
|
926
|
+
e: 'hello',
|
|
927
|
+
},
|
|
928
|
+
},
|
|
929
|
+
},
|
|
930
|
+
},
|
|
931
|
+
f: {
|
|
932
|
+
$ref: '#/a/b/c/d',
|
|
933
|
+
},
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
const result = createMagicProxy(input)
|
|
937
|
+
const keys = Object.keys(result.f)
|
|
938
|
+
|
|
939
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
940
|
+
})
|
|
941
|
+
|
|
942
|
+
it('handles objects with multiple refs', () => {
|
|
943
|
+
const input = {
|
|
944
|
+
a: {
|
|
945
|
+
b: {
|
|
946
|
+
c: 'hello',
|
|
947
|
+
},
|
|
948
|
+
},
|
|
949
|
+
d: {
|
|
950
|
+
$ref: '#/a/b',
|
|
951
|
+
},
|
|
952
|
+
e: {
|
|
953
|
+
$ref: '#/d',
|
|
954
|
+
},
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
const result = createMagicProxy(input)
|
|
958
|
+
const dKeys = Object.keys(result.d)
|
|
959
|
+
const eKeys = Object.keys(result.e)
|
|
960
|
+
|
|
961
|
+
expect(dKeys).toEqual(['$ref', '$ref-value'])
|
|
962
|
+
expect(eKeys).toEqual(['$ref', '$ref-value'])
|
|
963
|
+
})
|
|
964
|
+
|
|
965
|
+
it('handles external refs', () => {
|
|
966
|
+
const input = {
|
|
967
|
+
a: 'hello',
|
|
968
|
+
b: {
|
|
969
|
+
$ref: 'https://example.com/document.json/#',
|
|
970
|
+
},
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
const result = createMagicProxy(input)
|
|
974
|
+
const keys = Object.keys(result.b)
|
|
975
|
+
|
|
976
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
977
|
+
})
|
|
978
|
+
|
|
979
|
+
it('handles empty objects', () => {
|
|
980
|
+
const input = {}
|
|
981
|
+
|
|
982
|
+
const result = createMagicProxy(input)
|
|
983
|
+
const keys = Object.keys(result)
|
|
984
|
+
|
|
985
|
+
expect(keys).toEqual([])
|
|
986
|
+
})
|
|
987
|
+
|
|
988
|
+
it('handles objects with only $ref', () => {
|
|
989
|
+
const input = {
|
|
990
|
+
a: {
|
|
991
|
+
$ref: '#/b',
|
|
992
|
+
},
|
|
993
|
+
b: 'hello',
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
const result = createMagicProxy(input)
|
|
997
|
+
const keys = Object.keys(result.a)
|
|
998
|
+
|
|
999
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
1000
|
+
})
|
|
1001
|
+
|
|
1002
|
+
it('handles objects with null and undefined values', () => {
|
|
1003
|
+
const input = {
|
|
1004
|
+
a: null,
|
|
1005
|
+
b: undefined,
|
|
1006
|
+
c: {
|
|
1007
|
+
$ref: '#/a',
|
|
1008
|
+
},
|
|
1009
|
+
d: {
|
|
1010
|
+
$ref: '#/b',
|
|
1011
|
+
},
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
const result = createMagicProxy(input)
|
|
1015
|
+
const cKeys = Object.keys(result.c)
|
|
1016
|
+
const dKeys = Object.keys(result.d)
|
|
1017
|
+
|
|
1018
|
+
expect(cKeys).toEqual(['$ref', '$ref-value'])
|
|
1019
|
+
expect(dKeys).toEqual(['$ref', '$ref-value'])
|
|
1020
|
+
})
|
|
1021
|
+
|
|
1022
|
+
it('handles arrays with mixed content', () => {
|
|
1023
|
+
const input = {
|
|
1024
|
+
items: [{ name: 'item1' }, { $ref: '#/items/0' }, 'string item', { name: 'item2', id: 2 }],
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
const result = createMagicProxy(input)
|
|
1028
|
+
const item0Keys = Object.keys(result.items[0])
|
|
1029
|
+
const item1Keys = Object.keys(result.items[1])
|
|
1030
|
+
|
|
1031
|
+
expect(item0Keys).toEqual(['name'])
|
|
1032
|
+
expect(item1Keys).toEqual(['$ref', '$ref-value'])
|
|
1033
|
+
})
|
|
1034
|
+
|
|
1035
|
+
it('handles objects with both direct and ref properties', () => {
|
|
1036
|
+
const input = {
|
|
1037
|
+
a: {
|
|
1038
|
+
b: {
|
|
1039
|
+
c: 'hello',
|
|
1040
|
+
},
|
|
1041
|
+
},
|
|
1042
|
+
d: {
|
|
1043
|
+
$ref: '#/a/b',
|
|
1044
|
+
directProp: 'direct',
|
|
1045
|
+
anotherProp: 'another',
|
|
1046
|
+
},
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
const result = createMagicProxy(input)
|
|
1050
|
+
const keys = Object.keys(result.d)
|
|
1051
|
+
|
|
1052
|
+
expect(keys).toEqual(['$ref', 'directProp', 'anotherProp', '$ref-value'])
|
|
1053
|
+
})
|
|
1054
|
+
|
|
1055
|
+
it('handles objects with symbol keys', () => {
|
|
1056
|
+
const symbolKey = Symbol('test')
|
|
1057
|
+
const input = {
|
|
1058
|
+
[symbolKey]: 'symbol value',
|
|
1059
|
+
a: 'hello',
|
|
1060
|
+
b: {
|
|
1061
|
+
$ref: '#/a',
|
|
1062
|
+
},
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
const result = createMagicProxy(input)
|
|
1066
|
+
const keys = Object.keys(result)
|
|
1067
|
+
const ownKeys = Object.getOwnPropertySymbols(result)
|
|
1068
|
+
|
|
1069
|
+
expect(keys).toEqual(['a', 'b'])
|
|
1070
|
+
expect(ownKeys).toEqual([symbolKey])
|
|
1071
|
+
})
|
|
1072
|
+
|
|
1073
|
+
it('handles objects with non-enumerable properties', () => {
|
|
1074
|
+
const input = {
|
|
1075
|
+
a: 'hello',
|
|
1076
|
+
b: {
|
|
1077
|
+
$ref: '#/a',
|
|
1078
|
+
},
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
Object.defineProperty(input.b, 'nonEnumerable', {
|
|
1082
|
+
value: 'test',
|
|
1083
|
+
enumerable: false,
|
|
1084
|
+
})
|
|
1085
|
+
|
|
1086
|
+
const result = createMagicProxy(input)
|
|
1087
|
+
const keys = Object.keys(result.b)
|
|
1088
|
+
const ownKeys = Reflect.ownKeys(result.b)
|
|
1089
|
+
|
|
1090
|
+
expect(keys).toEqual(['$ref', '$ref-value'])
|
|
1091
|
+
expect(ownKeys).toContain('nonEnumerable')
|
|
1092
|
+
expect(ownKeys).toContain('$ref')
|
|
1093
|
+
expect(ownKeys).toContain('$ref-value')
|
|
1094
|
+
})
|
|
1095
|
+
|
|
1096
|
+
it('handles objects with getter properties', () => {
|
|
1097
|
+
const input = {
|
|
1098
|
+
a: 'hello',
|
|
1099
|
+
b: {
|
|
1100
|
+
$ref: '#/a',
|
|
1101
|
+
},
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
Object.defineProperty(input.b, 'getterProp', {
|
|
1105
|
+
get() {
|
|
1106
|
+
return 'getter value'
|
|
1107
|
+
},
|
|
1108
|
+
enumerable: true,
|
|
1109
|
+
})
|
|
1110
|
+
|
|
1111
|
+
const result = createMagicProxy(input)
|
|
1112
|
+
const keys = Object.keys(result.b)
|
|
1113
|
+
|
|
1114
|
+
expect(keys).toEqual(['$ref', 'getterProp', '$ref-value'])
|
|
1115
|
+
})
|
|
1116
|
+
})
|
|
1117
|
+
|
|
1118
|
+
describe('getRaw', () => {
|
|
1119
|
+
it('should get the raw version of the document', () => {
|
|
1120
|
+
const input = {
|
|
1121
|
+
a: 'hello',
|
|
1122
|
+
b: {
|
|
1123
|
+
$ref: '#/a',
|
|
1124
|
+
},
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
const proxied = createMagicProxy(input)
|
|
1128
|
+
|
|
1129
|
+
expect(proxied).toEqual({
|
|
1130
|
+
a: 'hello',
|
|
1131
|
+
b: {
|
|
1132
|
+
$ref: '#/a',
|
|
1133
|
+
'$ref-value': 'hello',
|
|
1134
|
+
},
|
|
1135
|
+
})
|
|
1136
|
+
|
|
1137
|
+
expect(getRaw(proxied)).toEqual(input)
|
|
1138
|
+
})
|
|
144
1139
|
})
|
|
145
1140
|
})
|