@scalar/json-magic 0.8.1 β†’ 0.8.3

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 (94) hide show
  1. package/CHANGELOG.md +22 -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/bundle/value-generator.d.ts +2 -2
  10. package/dist/bundle/value-generator.d.ts.map +1 -1
  11. package/dist/bundle/value-generator.js +3 -3
  12. package/dist/bundle/value-generator.js.map +2 -2
  13. package/dist/dereference/index.d.ts.map +1 -1
  14. package/dist/dereference/index.js.map +2 -2
  15. package/dist/diff/index.d.ts +1 -1
  16. package/dist/diff/index.d.ts.map +1 -1
  17. package/dist/diff/index.js +1 -1
  18. package/dist/diff/index.js.map +2 -2
  19. package/dist/helpers/escape-json-pointer.d.ts +1 -1
  20. package/dist/helpers/escape-json-pointer.js.map +1 -1
  21. package/dist/magic-proxy/index.d.ts.map +1 -1
  22. package/dist/magic-proxy/index.js.map +2 -2
  23. package/dist/magic-proxy/proxy.d.ts +0 -1
  24. package/dist/magic-proxy/proxy.d.ts.map +1 -1
  25. package/dist/magic-proxy/proxy.js +1 -2
  26. package/dist/magic-proxy/proxy.js.map +2 -2
  27. package/package.json +12 -14
  28. package/.turbo/turbo-build.log +0 -10
  29. package/dist/helpers/generate-hash.d.ts +0 -11
  30. package/dist/helpers/generate-hash.d.ts.map +0 -1
  31. package/dist/helpers/generate-hash.js +0 -16
  32. package/dist/helpers/generate-hash.js.map +0 -7
  33. package/esbuild.ts +0 -15
  34. package/src/bundle/bundle.test.ts +0 -2921
  35. package/src/bundle/bundle.ts +0 -916
  36. package/src/bundle/create-limiter.test.ts +0 -28
  37. package/src/bundle/create-limiter.ts +0 -52
  38. package/src/bundle/index.ts +0 -3
  39. package/src/bundle/plugins/browser.ts +0 -4
  40. package/src/bundle/plugins/fetch-urls/index.test.ts +0 -144
  41. package/src/bundle/plugins/fetch-urls/index.ts +0 -105
  42. package/src/bundle/plugins/node.ts +0 -5
  43. package/src/bundle/plugins/parse-json/index.test.ts +0 -24
  44. package/src/bundle/plugins/parse-json/index.ts +0 -32
  45. package/src/bundle/plugins/parse-yaml/index.test.ts +0 -26
  46. package/src/bundle/plugins/parse-yaml/index.ts +0 -34
  47. package/src/bundle/plugins/read-files/index.test.ts +0 -36
  48. package/src/bundle/plugins/read-files/index.ts +0 -58
  49. package/src/bundle/value-generator.test.ts +0 -165
  50. package/src/bundle/value-generator.ts +0 -143
  51. package/src/dereference/dereference.test.ts +0 -145
  52. package/src/dereference/dereference.ts +0 -84
  53. package/src/dereference/index.ts +0 -2
  54. package/src/diff/apply.test.ts +0 -262
  55. package/src/diff/apply.ts +0 -83
  56. package/src/diff/diff.test.ts +0 -328
  57. package/src/diff/diff.ts +0 -93
  58. package/src/diff/index.test.ts +0 -150
  59. package/src/diff/index.ts +0 -5
  60. package/src/diff/merge.test.ts +0 -1109
  61. package/src/diff/merge.ts +0 -136
  62. package/src/diff/trie.test.ts +0 -30
  63. package/src/diff/trie.ts +0 -113
  64. package/src/diff/utils.test.ts +0 -169
  65. package/src/diff/utils.ts +0 -111
  66. package/src/helpers/convert-to-local-ref.test.ts +0 -211
  67. package/src/helpers/convert-to-local-ref.ts +0 -43
  68. package/src/helpers/escape-json-pointer.test.ts +0 -13
  69. package/src/helpers/escape-json-pointer.ts +0 -8
  70. package/src/helpers/generate-hash.test.ts +0 -74
  71. package/src/helpers/generate-hash.ts +0 -29
  72. package/src/helpers/get-schemas.test.ts +0 -356
  73. package/src/helpers/get-schemas.ts +0 -80
  74. package/src/helpers/get-segments-from-path.test.ts +0 -17
  75. package/src/helpers/get-segments-from-path.ts +0 -17
  76. package/src/helpers/get-value-by-path.test.ts +0 -338
  77. package/src/helpers/get-value-by-path.ts +0 -44
  78. package/src/helpers/is-json-object.ts +0 -31
  79. package/src/helpers/is-object.test.ts +0 -27
  80. package/src/helpers/is-object.ts +0 -4
  81. package/src/helpers/is-yaml.ts +0 -18
  82. package/src/helpers/json-path-utils.test.ts +0 -57
  83. package/src/helpers/json-path-utils.ts +0 -50
  84. package/src/helpers/normalize.test.ts +0 -92
  85. package/src/helpers/normalize.ts +0 -35
  86. package/src/helpers/unescape-json-pointer.test.ts +0 -23
  87. package/src/helpers/unescape-json-pointer.ts +0 -9
  88. package/src/magic-proxy/index.ts +0 -2
  89. package/src/magic-proxy/proxy.test.ts +0 -1987
  90. package/src/magic-proxy/proxy.ts +0 -323
  91. package/src/types.ts +0 -1
  92. package/tsconfig.build.json +0 -12
  93. package/tsconfig.json +0 -16
  94. package/vite.config.ts +0 -8
@@ -1,211 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import { convertToLocalRef } from './convert-to-local-ref'
4
-
5
- describe('convertToLocalRef', () => {
6
- const schemas = new Map([
7
- ['https://example.com/schema1.json', '/components/schemas/Schema1'],
8
- ['https://example.com/schema2.json', '/components/schemas/Schema2'],
9
- ['https://example.com/schema1.json#anchor1', '/components/schemas/Schema1/definitions/Anchor1'],
10
- ['https://example.com/schema2.json#anchor2', '/components/schemas/Schema2/definitions/Anchor2'],
11
- ['https://example.com/current.json#currentAnchor', '/components/schemas/Current/definitions/CurrentAnchor'],
12
- ])
13
-
14
- const currentContext = 'https://example.com/current.json'
15
-
16
- describe('external references with baseUrl', () => {
17
- it('should resolve external reference without path or anchor', () => {
18
- const result = convertToLocalRef('https://example.com/schema1.json', currentContext, schemas)
19
-
20
- expect(result).toBe('/components/schemas/Schema1')
21
- })
22
-
23
- it('should resolve external reference with JSON pointer path', () => {
24
- const result = convertToLocalRef('https://example.com/schema1.json#/definitions/User', currentContext, schemas)
25
-
26
- expect(result).toBe('/components/schemas/Schema1/definitions/User')
27
- })
28
-
29
- it('should resolve external reference with anchor', () => {
30
- const result = convertToLocalRef('https://example.com/schema1.json#anchor1', currentContext, schemas)
31
-
32
- expect(result).toBe('/components/schemas/Schema1/definitions/Anchor1')
33
- })
34
-
35
- it('should return undefined for external reference not in schemas', () => {
36
- const result = convertToLocalRef('https://example.com/unknown.json', currentContext, schemas)
37
-
38
- expect(result).toBeUndefined()
39
- })
40
-
41
- it('should return undefined for external reference with unknown anchor', () => {
42
- const result = convertToLocalRef('https://example.com/schema1.json#unknownAnchor', currentContext, schemas)
43
-
44
- expect(result).toBeUndefined()
45
- })
46
- })
47
-
48
- describe('local references without baseUrl', () => {
49
- it('should resolve local JSON pointer path', () => {
50
- const result = convertToLocalRef('#/definitions/User', currentContext, schemas)
51
-
52
- expect(result).toBe('definitions/User')
53
- })
54
-
55
- it('should resolve local JSON pointer path with multiple segments', () => {
56
- const result = convertToLocalRef('#/components/schemas/User/properties/name', currentContext, schemas)
57
-
58
- expect(result).toBe('components/schemas/User/properties/name')
59
- })
60
-
61
- it('should resolve local anchor reference', () => {
62
- const result = convertToLocalRef('#currentAnchor', currentContext, schemas)
63
-
64
- expect(result).toBe('/components/schemas/Current/definitions/CurrentAnchor')
65
- })
66
-
67
- it('should return undefined for local anchor not in schemas', () => {
68
- const result = convertToLocalRef('#unknownAnchor', currentContext, schemas)
69
-
70
- expect(result).toBeUndefined()
71
- })
72
- })
73
-
74
- describe('edge cases', () => {
75
- it('should return undefined for empty reference', () => {
76
- const result = convertToLocalRef('', currentContext, schemas)
77
-
78
- expect(result).toBeUndefined()
79
- })
80
-
81
- it('should return undefined for reference with only hash', () => {
82
- const result = convertToLocalRef('#', currentContext, schemas)
83
-
84
- expect(result).toBeUndefined()
85
- })
86
-
87
- it('should return undefined for reference with only baseUrl and hash', () => {
88
- const result = convertToLocalRef('https://example.com/schema1.json#', currentContext, schemas)
89
-
90
- expect(result).toBe('/components/schemas/Schema1')
91
- })
92
-
93
- it('should handle empty currentContext', () => {
94
- const result = convertToLocalRef('#anchor', '', schemas)
95
-
96
- expect(result).toBeUndefined()
97
- })
98
-
99
- it('should handle empty schemas map', () => {
100
- const emptySchemas = new Map()
101
- const result = convertToLocalRef('https://example.com/schema1.json', currentContext, emptySchemas)
102
-
103
- expect(result).toBeUndefined()
104
- })
105
- })
106
-
107
- describe('complex scenarios', () => {
108
- it('should handle nested JSON pointer paths', () => {
109
- const result = convertToLocalRef(
110
- 'https://example.com/schema1.json#/definitions/User/properties/address/properties/street',
111
- currentContext,
112
- schemas,
113
- )
114
-
115
- expect(result).toBe('/components/schemas/Schema1/definitions/User/properties/address/properties/street')
116
- })
117
-
118
- it('should handle anchor with special characters', () => {
119
- const schemasWithSpecialChars = new Map([
120
- ['https://example.com/schema1.json', '/components/schemas/Schema1'],
121
- [
122
- 'https://example.com/schema1.json#anchor-with-dashes',
123
- '/components/schemas/Schema1/definitions/AnchorWithDashes',
124
- ],
125
- [
126
- 'https://example.com/schema1.json#anchor_with_underscores',
127
- '/components/schemas/Schema1/definitions/AnchorWithUnderscores',
128
- ],
129
- ])
130
-
131
- const result1 = convertToLocalRef(
132
- 'https://example.com/schema1.json#anchor-with-dashes',
133
- currentContext,
134
- schemasWithSpecialChars,
135
- )
136
-
137
- const result2 = convertToLocalRef(
138
- 'https://example.com/schema1.json#anchor_with_underscores',
139
- currentContext,
140
- schemasWithSpecialChars,
141
- )
142
-
143
- expect(result1).toBe('/components/schemas/Schema1/definitions/AnchorWithDashes')
144
- expect(result2).toBe('/components/schemas/Schema1/definitions/AnchorWithUnderscores')
145
- })
146
-
147
- it('should handle different schema contexts', () => {
148
- const differentContext = 'https://example.com/different.json'
149
- const schemasWithDifferentContext = new Map([
150
- [
151
- 'https://example.com/different.json#differentAnchor',
152
- '/components/schemas/Different/definitions/DifferentAnchor',
153
- ],
154
- ])
155
-
156
- const result = convertToLocalRef('#differentAnchor', differentContext, schemasWithDifferentContext)
157
-
158
- expect(result).toBe('/components/schemas/Different/definitions/DifferentAnchor')
159
- })
160
- })
161
-
162
- describe('real-world examples', () => {
163
- it('should handle OpenAPI component references', () => {
164
- const openApiSchemas = new Map([
165
- ['https://api.example.com/schemas/user.json', '/components/schemas/User'],
166
- ['https://api.example.com/schemas/user.json#/properties/id', '/components/schemas/User/properties/id'],
167
- ['https://api.example.com/schemas/user.json#userProfile', '/components/schemas/User/definitions/UserProfile'],
168
- ])
169
-
170
- const result1 = convertToLocalRef(
171
- 'https://api.example.com/schemas/user.json',
172
- 'https://api.example.com/openapi.json',
173
- openApiSchemas,
174
- )
175
-
176
- const result2 = convertToLocalRef(
177
- 'https://api.example.com/schemas/user.json#/properties/name',
178
- 'https://api.example.com/openapi.json',
179
- openApiSchemas,
180
- )
181
-
182
- const result3 = convertToLocalRef(
183
- 'https://api.example.com/schemas/user.json#userProfile',
184
- 'https://api.example.com/openapi.json',
185
- openApiSchemas,
186
- )
187
-
188
- expect(result1).toBe('/components/schemas/User')
189
- expect(result2).toBe('/components/schemas/User/properties/name')
190
- expect(result3).toBe('/components/schemas/User/definitions/UserProfile')
191
- })
192
-
193
- it('should handle local component references in OpenAPI', () => {
194
- const openApiSchemas = new Map([
195
- ['https://api.example.com/openapi.json#userSchema', '/components/schemas/User'],
196
- ['https://api.example.com/openapi.json#addressSchema', '/components/schemas/Address'],
197
- ])
198
-
199
- const result1 = convertToLocalRef('#userSchema', 'https://api.example.com/openapi.json', openApiSchemas)
200
-
201
- const result2 = convertToLocalRef(
202
- '#/components/schemas/User/properties/name',
203
- 'https://api.example.com/openapi.json',
204
- openApiSchemas,
205
- )
206
-
207
- expect(result1).toBe('/components/schemas/User')
208
- expect(result2).toBe('components/schemas/User/properties/name')
209
- })
210
- })
211
- })
@@ -1,43 +0,0 @@
1
- /**
2
- * Translates a JSON Reference ($ref) to a local object path within the root schema.
3
- *
4
- * @param ref - The JSON Reference string (e.g., "#/foo/bar", "other.json#/baz", "other.json#anchor")
5
- * @param currentContext - The current base context (usually the $id of the current schema or parent)
6
- * @param schemas - A map of schema identifiers ($id, $anchor) to their local object paths
7
- * @returns The local object path as a string, or undefined if the reference cannot be resolved
8
- */
9
- export const convertToLocalRef = (
10
- ref: string,
11
- currentContext: string,
12
- schemas: Map<string, string>,
13
- ): string | undefined => {
14
- // Split the reference into base URL and path/anchor (e.g., "foo.json#/bar" => ["foo.json", "/bar"])
15
- const [baseUrl, pathOrAnchor] = ref.split('#', 2)
16
-
17
- if (baseUrl) {
18
- if (!schemas.has(baseUrl)) {
19
- return undefined
20
- }
21
-
22
- if (!pathOrAnchor) {
23
- return schemas.get(baseUrl)
24
- }
25
-
26
- // If the pathOrAnchor is a JSON pointer, we need to append it to the baseUrl
27
- if (pathOrAnchor.startsWith('/')) {
28
- return `${schemas.get(baseUrl)}${pathOrAnchor}`
29
- }
30
-
31
- // If the pathOrAnchor is an anchor, we need to return the anchor
32
- return schemas.get(`${baseUrl}#${pathOrAnchor}`)
33
- }
34
-
35
- if (pathOrAnchor) {
36
- if (pathOrAnchor.startsWith('/')) {
37
- return pathOrAnchor.slice(1)
38
- }
39
- return schemas.get(`${currentContext}#${pathOrAnchor}`)
40
- }
41
-
42
- return undefined
43
- }
@@ -1,13 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import { escapeJsonPointer } from './escape-json-pointer'
4
-
5
- describe('escapeJsonPointer', () => {
6
- it('should escape a slash', () => {
7
- expect(escapeJsonPointer('application/json')).toBe('application~1json')
8
- })
9
-
10
- it('should escape multiple slashes', () => {
11
- expect(escapeJsonPointer('/api/users/{id}/reports')).toBe('~1api~1users~1{id}~1reports')
12
- })
13
- })
@@ -1,8 +0,0 @@
1
- /**
2
- * Escapes a JSON pointer string.
3
- *
4
- * Example: `/foo/bar~baz` -> `/foo~1bar~0baz`
5
- */
6
- export function escapeJsonPointer(str: string) {
7
- return str.replace(/~/g, '~0').replace(/\//g, '~1')
8
- }
@@ -1,74 +0,0 @@
1
- import { describe, expect, it } from 'vitest'
2
-
3
- import { generateHash } from './generate-hash'
4
-
5
- describe('generateHash', () => {
6
- it('generates a hash from a simple string', async () => {
7
- const result = await generateHash('hello world')
8
-
9
- // Should return a non-empty string
10
- expect(result).toBeTruthy()
11
- expect(typeof result).toBe('string')
12
- expect(result.length).toBeGreaterThan(0)
13
- })
14
-
15
- it('produces consistent hashes for the same input', async () => {
16
- const input = 'consistent-test-string'
17
- const hash1 = await generateHash(input)
18
- const hash2 = await generateHash(input)
19
- const hash3 = await generateHash(input)
20
-
21
- // Same input should always produce the same hash
22
- expect(hash1).toBe(hash2)
23
- expect(hash2).toBe(hash3)
24
- })
25
-
26
- it('produces different hashes for different inputs', async () => {
27
- const hash1 = await generateHash('first string')
28
- const hash2 = await generateHash('second string')
29
- const hash3 = await generateHash('first strinG') // Case-sensitive
30
-
31
- // Different inputs should produce different hashes
32
- expect(hash1).not.toBe(hash2)
33
- expect(hash1).not.toBe(hash3)
34
- expect(hash2).not.toBe(hash3)
35
- })
36
-
37
- it('handles empty string', async () => {
38
- const result = await generateHash('')
39
-
40
- // Should handle empty strings without throwing
41
- expect(result).toBeTruthy()
42
- expect(typeof result).toBe('string')
43
-
44
- // Empty string should produce a consistent hash
45
- const result2 = await generateHash('')
46
- expect(result).toBe(result2)
47
- })
48
-
49
- it('handles special characters and unicode', async () => {
50
- const inputs = [
51
- 'πŸš€ emoji test',
52
- 'special chars: !@#$%^&*()',
53
- 'unicode: γ“γ‚“γ«γ‘γ―δΈ–η•Œ',
54
- 'newlines\nand\ttabs',
55
- 'mixed: πŸ‘Ύ special!@# unicode: δ½ ε₯½',
56
- ]
57
-
58
- const hashes = await Promise.all(inputs.map((input) => generateHash(input)))
59
-
60
- // All should produce valid hashes
61
- hashes.forEach((hash) => {
62
- expect(hash).toBeTruthy()
63
- expect(typeof hash).toBe('string')
64
- })
65
-
66
- // All should be unique
67
- const uniqueHashes = new Set(hashes)
68
- expect(uniqueHashes.size).toBe(inputs.length)
69
-
70
- // Should be consistent on repeated calls
71
- const repeatedHash = await generateHash('πŸš€ emoji test')
72
- expect(repeatedHash).toBe(hashes[0])
73
- })
74
- })
@@ -1,29 +0,0 @@
1
- import xxhash from 'xxhash-wasm'
2
-
3
- let hasherInstance: Awaited<ReturnType<typeof xxhash>> | null = null
4
-
5
- /**
6
- * Initialize the xxhash hasher instance lazily
7
- *
8
- * This is just a workaround because we cannot use top level await in a UMD module (standalone references)
9
- */
10
- const getHasher = async () => {
11
- if (!hasherInstance) {
12
- hasherInstance = await xxhash()
13
- }
14
- return hasherInstance
15
- }
16
-
17
- /**
18
- * Generate a hash from a string using the xxhash algorithm
19
- *
20
- * We cannot use crypto.subtle because it is only available in secure contexts (HTTPS) or on localhost.
21
- * So this is just a wrapper around the xxhash-wasm library instead.
22
- *
23
- * @param input - The string to hash
24
- * @returns A Promise that resolves to the hash of the input string
25
- */
26
- export const generateHash = async (input: string): Promise<string> => {
27
- const { h64ToString } = await getHasher()
28
- return h64ToString(input)
29
- }