@scalar/json-magic 0.8.1 β 0.8.2
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 -4
- package/CHANGELOG.md +9 -0
- package/dist/bundle/value-generator.d.ts +2 -2
- package/dist/bundle/value-generator.d.ts.map +1 -1
- package/dist/bundle/value-generator.js +3 -3
- package/dist/bundle/value-generator.js.map +2 -2
- package/package.json +3 -4
- package/src/bundle/bundle.test.ts +126 -130
- package/src/bundle/plugins/fetch-urls/index.test.ts +0 -3
- package/src/bundle/value-generator.ts +4 -4
- package/src/dereference/dereference.test.ts +8 -11
- package/vite.config.ts +1 -1
- package/dist/helpers/generate-hash.d.ts +0 -11
- package/dist/helpers/generate-hash.d.ts.map +0 -1
- package/dist/helpers/generate-hash.js +0 -16
- package/dist/helpers/generate-hash.js.map +0 -7
- package/src/helpers/generate-hash.test.ts +0 -74
- package/src/helpers/generate-hash.ts +0 -29
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
> @scalar/json-magic@0.8.
|
|
2
|
+
> @scalar/json-magic@0.8.2 build /home/runner/work/scalar/scalar/packages/json-magic
|
|
3
3
|
> scalar-build-esbuild
|
|
4
4
|
|
|
5
|
-
[34m@scalar/json-magic: Build completed in
|
|
5
|
+
[34m@scalar/json-magic: Build completed in 42.51ms[39m
|
|
6
6
|
|
|
7
|
-
> @scalar/json-magic@0.8.
|
|
7
|
+
> @scalar/json-magic@0.8.2 types:build /home/runner/work/scalar/scalar/packages/json-magic
|
|
8
8
|
> scalar-types-build
|
|
9
9
|
|
|
10
|
-
[32mTypes build completed in
|
|
10
|
+
[32mTypes build completed in 2.81s[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# @scalar/json-magic
|
|
2
2
|
|
|
3
|
+
## 0.8.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#7392](https://github.com/scalar/scalar/pull/7392) [`d86f1d6`](https://github.com/scalar/scalar/commit/d86f1d6911ecbca70b011a2a0efb6d6e0eca59bb) Thanks [@amritk](https://github.com/amritk)! - fix: move away from wasm hashing algo
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`d86f1d6`](https://github.com/scalar/scalar/commit/d86f1d6911ecbca70b011a2a0efb6d6e0eca59bb), [`cded2d6`](https://github.com/scalar/scalar/commit/cded2d6c087418c3c44731d344d0827a87b78b74)]:
|
|
10
|
+
- @scalar/helpers@0.1.2
|
|
11
|
+
|
|
3
12
|
## 0.8.1
|
|
4
13
|
|
|
5
14
|
### Patch Changes
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
* @returns A Promise that resolves to a 7-character hexadecimal hash with at least one letter
|
|
12
12
|
* @example
|
|
13
13
|
* // Returns "2ae91d7"
|
|
14
|
-
*
|
|
14
|
+
* getHash("https://example.com/schema.json")
|
|
15
15
|
*/
|
|
16
|
-
export declare function getHash(value: string):
|
|
16
|
+
export declare function getHash(value: string): string;
|
|
17
17
|
/**
|
|
18
18
|
* Generates a unique compressed value for a string, handling collisions by recursively compressing
|
|
19
19
|
* until a unique value is found. This is used to create unique identifiers for external
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"value-generator.d.ts","sourceRoot":"","sources":["../../src/bundle/value-generator.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,
|
|
1
|
+
{"version":3,"file":"value-generator.d.ts","sourceRoot":"","sources":["../../src/bundle/value-generator.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAO7C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,EACrD,KAAK,EAAE,MAAM,EACb,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACzC,mBAAmB,CAAC,EAAE,MAAM,EAC5B,KAAK,SAAI,mBAoBV;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,2BAA2B,GACtC,UAAU,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,EACrD,mBAAmB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAMvC;;;;;;;;;;;;OAYG;sBACqB,MAAM;CAqBjC,CAAA"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { generateHash } from "
|
|
2
|
-
|
|
3
|
-
const hashHex =
|
|
1
|
+
import { generateHash } from "@scalar/helpers/string/generate-hash";
|
|
2
|
+
function getHash(value) {
|
|
3
|
+
const hashHex = generateHash(value);
|
|
4
4
|
const hash = hashHex.substring(0, 7);
|
|
5
5
|
return hash.match(/^\d+$/) ? "a" + hash.substring(1) : hash;
|
|
6
6
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/bundle/value-generator.ts"],
|
|
4
|
-
"sourcesContent": ["import { generateHash } from '
|
|
5
|
-
"mappings": "AAAA,SAAS,oBAAoB;
|
|
4
|
+
"sourcesContent": ["import { generateHash } from '@scalar/helpers/string/generate-hash'\n\n/**\n * Generates a short hash from a string value using xxhash.\n *\n * This function is used to create unique identifiers for external references\n * while keeping the hash length manageable. It uses xxhash-wasm instead of\n * crypto.subtle because crypto.subtle is only available in secure contexts (HTTPS) or on localhost.\n * Returns the first 7 characters of the hash string.\n * If the hash would be all numbers, it ensures at least one letter is included.\n *\n * @param value - The string to hash\n * @returns A Promise that resolves to a 7-character hexadecimal hash with at least one letter\n * @example\n * // Returns \"2ae91d7\"\n * getHash(\"https://example.com/schema.json\")\n */\nexport function getHash(value: string): string {\n // Hash the data using xxhash\n const hashHex = generateHash(value)\n\n // Return first 7 characters of the hash, ensuring at least one letter\n const hash = hashHex.substring(0, 7)\n return hash.match(/^\\d+$/) ? 'a' + hash.substring(1) : hash\n}\n\n/**\n * Generates a unique compressed value for a string, handling collisions by recursively compressing\n * until a unique value is found. This is used to create unique identifiers for external\n * references in the bundled OpenAPI document.\n *\n * @param compress - Function that generates a compressed value from a string\n * @param value - The original string value to compress\n * @param compressedToValue - Object mapping compressed values to their original values\n * @param prevCompressedValue - Optional previous compressed value to use as input for generating a new value\n * @param depth - Current recursion depth to prevent infinite loops\n * @returns A unique compressed value that doesn't conflict with existing values\n *\n * @example\n * const valueMap = {}\n * // First call generates compressed value for \"example.com/schema.json\"\n * const value1 = await generateUniqueValue(compress, \"example.com/schema.json\", valueMap)\n * // Returns something like \"2ae91d7\"\n *\n * // Second call with same value returns same compressed value\n * const value2 = await generateUniqueValue(compress, \"example.com/schema.json\", valueMap)\n * // Returns same value as value1\n *\n * // Call with different value generates new unique compressed value\n * const value3 = await generateUniqueValue(compress, \"example.com/other.json\", valueMap)\n * // Returns different value like \"3bf82e9\"\n */\nexport async function generateUniqueValue(\n compress: (value: string) => Promise<string> | string,\n value: string,\n compressedToValue: Record<string, string>,\n prevCompressedValue?: string,\n depth = 0,\n) {\n // Prevent infinite recursion by limiting depth\n const MAX_DEPTH = 100\n\n if (depth >= MAX_DEPTH) {\n throw 'Can not generate unique compressed values'\n }\n\n // Compress the value, using previous compressed value if provided\n const compressedValue = await compress(prevCompressedValue ?? value)\n\n // Handle collision by recursively trying with compressed value as input\n if (compressedToValue[compressedValue] !== undefined && compressedToValue[compressedValue] !== value) {\n return generateUniqueValue(compress, value, compressedToValue, compressedValue, depth + 1)\n }\n\n // Store mapping and return unique compressed value\n compressedToValue[compressedValue] = value\n return compressedValue\n}\n\n/**\n * Factory function that creates a value generator with caching capabilities.\n * The generator maintains a bidirectional mapping between original values and their compressed forms.\n *\n * @param compress - Function that generates a compressed value from a string\n * @param compressedToValue - Initial mapping of compressed values to their original values\n * @returns An object with a generate method that produces unique compressed values\n *\n * @example\n * const compress = (value) => value.substring(0, 6) // Simple compression example\n * const initialMap = { 'abc123': 'example.com/schema.json' }\n * const generator = uniqueValueGeneratorFactory(compress, initialMap)\n *\n * // Generate compressed value for new string\n * const compressed = await generator.generate('example.com/other.json')\n * // Returns something like 'example'\n *\n * // Generate compressed value for existing string\n * const cached = await generator.generate('example.com/schema.json')\n * // Returns 'abc123' from cache\n */\nexport const uniqueValueGeneratorFactory = (\n compress: (value: string) => Promise<string> | string,\n compressedToValue: Record<string, string>,\n) => {\n // Create a reverse mapping from original values to their compressed forms\n const valueToCompressed = Object.fromEntries(Object.entries(compressedToValue).map(([key, value]) => [value, key]))\n\n return {\n /**\n * Generates a unique compressed value for the given input string.\n * First checks if a compressed value already exists in the cache.\n * If not, generates a new unique compressed value and stores it in the cache.\n *\n * @param value - The original string value to compress\n * @returns A Promise that resolves to the compressed string value\n *\n * @example\n * const generator = uniqueValueGeneratorFactory(compress, {})\n * const compressed = await generator.generate('example.com/schema.json')\n * // Returns a unique compressed value like 'example'\n */\n generate: async (value: string) => {\n // Check if we already have a compressed value for this input\n const cache = valueToCompressed[value]\n if (cache) {\n return cache\n }\n\n // Generate a new unique compressed value\n const generatedValue = await generateUniqueValue(compress, value, compressedToValue)\n\n // Ensure the generated string contains at least one non-numeric character\n // This prevents the `setValueAtPath` function from interpreting the value as an array index\n // by forcing it to be treated as an object property name\n const compressedValue = generatedValue.match(/^\\d+$/) ? `a${generatedValue}` : generatedValue\n\n // Store the new mapping in our cache\n valueToCompressed[value] = compressedValue\n\n return compressedValue\n },\n }\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAiBtB,SAAS,QAAQ,OAAuB;AAE7C,QAAM,UAAU,aAAa,KAAK;AAGlC,QAAM,OAAO,QAAQ,UAAU,GAAG,CAAC;AACnC,SAAO,KAAK,MAAM,OAAO,IAAI,MAAM,KAAK,UAAU,CAAC,IAAI;AACzD;AA4BA,eAAsB,oBACpB,UACA,OACA,mBACA,qBACA,QAAQ,GACR;AAEA,QAAM,YAAY;AAElB,MAAI,SAAS,WAAW;AACtB,UAAM;AAAA,EACR;AAGA,QAAM,kBAAkB,MAAM,SAAS,uBAAuB,KAAK;AAGnE,MAAI,kBAAkB,eAAe,MAAM,UAAa,kBAAkB,eAAe,MAAM,OAAO;AACpG,WAAO,oBAAoB,UAAU,OAAO,mBAAmB,iBAAiB,QAAQ,CAAC;AAAA,EAC3F;AAGA,oBAAkB,eAAe,IAAI;AACrC,SAAO;AACT;AAuBO,MAAM,8BAA8B,CACzC,UACA,sBACG;AAEH,QAAM,oBAAoB,OAAO,YAAY,OAAO,QAAQ,iBAAiB,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;AAElH,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAcL,UAAU,OAAO,UAAkB;AAEjC,YAAM,QAAQ,kBAAkB,KAAK;AACrC,UAAI,OAAO;AACT,eAAO;AAAA,MACT;AAGA,YAAM,iBAAiB,MAAM,oBAAoB,UAAU,OAAO,iBAAiB;AAKnF,YAAM,kBAAkB,eAAe,MAAM,OAAO,IAAI,IAAI,cAAc,KAAK;AAG/E,wBAAkB,KAAK,IAAI;AAE3B,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"url": "git+https://github.com/scalar/scalar.git",
|
|
11
11
|
"directory": "packages/json-magic"
|
|
12
12
|
},
|
|
13
|
-
"version": "0.8.
|
|
13
|
+
"version": "0.8.2",
|
|
14
14
|
"engines": {
|
|
15
15
|
"node": ">=20"
|
|
16
16
|
},
|
|
@@ -58,14 +58,13 @@
|
|
|
58
58
|
}
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"xxhash-wasm": "^1.1.0",
|
|
62
61
|
"yaml": "2.8.0",
|
|
63
|
-
"@scalar/helpers": "0.1.
|
|
62
|
+
"@scalar/helpers": "0.1.2"
|
|
64
63
|
},
|
|
65
64
|
"devDependencies": {
|
|
66
65
|
"fastify": "^5.3.3",
|
|
67
66
|
"vite": "7.1.11",
|
|
68
|
-
"@scalar/build-tooling": "0.
|
|
67
|
+
"@scalar/build-tooling": "0.3.0"
|
|
69
68
|
},
|
|
70
69
|
"scripts": {
|
|
71
70
|
"build": "scalar-build-esbuild",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto'
|
|
2
2
|
import fs from 'node:fs/promises'
|
|
3
|
-
import { setTimeout } from 'node:timers/promises'
|
|
4
3
|
|
|
5
4
|
import { consoleWarnSpy, resetConsoleSpies } from '@scalar/helpers/testing/console-spies'
|
|
6
5
|
import fastify, { type FastifyInstance } from 'fastify'
|
|
@@ -35,7 +34,6 @@ describe('bundle', () => {
|
|
|
35
34
|
|
|
36
35
|
return async () => {
|
|
37
36
|
await server.close()
|
|
38
|
-
await setTimeout(100)
|
|
39
37
|
}
|
|
40
38
|
})
|
|
41
39
|
|
|
@@ -69,7 +67,7 @@ describe('bundle', () => {
|
|
|
69
67
|
|
|
70
68
|
expect(input).toEqual({
|
|
71
69
|
'x-ext': {
|
|
72
|
-
[
|
|
70
|
+
[getHash(url)]: {
|
|
73
71
|
...external,
|
|
74
72
|
},
|
|
75
73
|
},
|
|
@@ -79,7 +77,7 @@ describe('bundle', () => {
|
|
|
79
77
|
},
|
|
80
78
|
},
|
|
81
79
|
d: {
|
|
82
|
-
$ref: `#/x-ext/${
|
|
80
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
83
81
|
},
|
|
84
82
|
})
|
|
85
83
|
})
|
|
@@ -126,13 +124,13 @@ describe('bundle', () => {
|
|
|
126
124
|
|
|
127
125
|
expect(input).toEqual({
|
|
128
126
|
'x-ext': {
|
|
129
|
-
[
|
|
127
|
+
[getHash(`${url}/chunk1`)]: {
|
|
130
128
|
...chunk1,
|
|
131
129
|
b: {
|
|
132
|
-
$ref: `#/x-ext/${
|
|
130
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk2`)}`,
|
|
133
131
|
},
|
|
134
132
|
},
|
|
135
|
-
[
|
|
133
|
+
[getHash(`${url}/chunk2`)]: {
|
|
136
134
|
...chunk2,
|
|
137
135
|
internal: '#/nested/key',
|
|
138
136
|
},
|
|
@@ -140,7 +138,7 @@ describe('bundle', () => {
|
|
|
140
138
|
a: {
|
|
141
139
|
b: {
|
|
142
140
|
c: {
|
|
143
|
-
$ref: `#/x-ext/${
|
|
141
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
144
142
|
},
|
|
145
143
|
},
|
|
146
144
|
},
|
|
@@ -170,13 +168,13 @@ describe('bundle', () => {
|
|
|
170
168
|
|
|
171
169
|
expect(input).toEqual({
|
|
172
170
|
'x-ext': {
|
|
173
|
-
[
|
|
171
|
+
[getHash(url)]: {
|
|
174
172
|
a: 'a',
|
|
175
173
|
},
|
|
176
174
|
},
|
|
177
175
|
a: {
|
|
178
176
|
b: {
|
|
179
|
-
$ref: `#/x-ext/${
|
|
177
|
+
$ref: `#/x-ext/${getHash(url)}`,
|
|
180
178
|
},
|
|
181
179
|
},
|
|
182
180
|
})
|
|
@@ -209,16 +207,16 @@ describe('bundle', () => {
|
|
|
209
207
|
|
|
210
208
|
expect(input).toEqual({
|
|
211
209
|
'x-ext': {
|
|
212
|
-
[
|
|
210
|
+
[getHash(url)]: {
|
|
213
211
|
a: 'a',
|
|
214
212
|
b: 'b',
|
|
215
213
|
},
|
|
216
214
|
},
|
|
217
215
|
a: {
|
|
218
|
-
$ref: `#/x-ext/${
|
|
216
|
+
$ref: `#/x-ext/${getHash(url)}/a`,
|
|
219
217
|
},
|
|
220
218
|
b: {
|
|
221
|
-
$ref: `#/x-ext/${
|
|
219
|
+
$ref: `#/x-ext/${getHash(url)}/b`,
|
|
222
220
|
},
|
|
223
221
|
})
|
|
224
222
|
|
|
@@ -255,17 +253,17 @@ describe('bundle', () => {
|
|
|
255
253
|
|
|
256
254
|
expect(input).toEqual({
|
|
257
255
|
'x-ext': {
|
|
258
|
-
[
|
|
256
|
+
[getHash(`${url}/nested/another-file.json`)]: {
|
|
259
257
|
c: 'c',
|
|
260
258
|
},
|
|
261
|
-
[
|
|
259
|
+
[getHash(`${url}/nested/chunk1.json`)]: {
|
|
262
260
|
b: {
|
|
263
|
-
$ref: `#/x-ext/${
|
|
261
|
+
$ref: `#/x-ext/${getHash(`${url}/nested/another-file.json`)}`,
|
|
264
262
|
},
|
|
265
263
|
},
|
|
266
264
|
},
|
|
267
265
|
a: {
|
|
268
|
-
$ref: `#/x-ext/${
|
|
266
|
+
$ref: `#/x-ext/${getHash(`${url}/nested/chunk1.json`)}`,
|
|
269
267
|
},
|
|
270
268
|
})
|
|
271
269
|
})
|
|
@@ -299,17 +297,17 @@ describe('bundle', () => {
|
|
|
299
297
|
|
|
300
298
|
expect(input).toEqual({
|
|
301
299
|
'x-ext': {
|
|
302
|
-
[
|
|
300
|
+
[getHash(`${url}/top-level`)]: {
|
|
303
301
|
c: 'c',
|
|
304
302
|
},
|
|
305
|
-
[
|
|
303
|
+
[getHash(`${url}/nested/chunk1.json`)]: {
|
|
306
304
|
b: {
|
|
307
|
-
$ref: `#/x-ext/${
|
|
305
|
+
$ref: `#/x-ext/${getHash(`${url}/top-level`)}`,
|
|
308
306
|
},
|
|
309
307
|
},
|
|
310
308
|
},
|
|
311
309
|
a: {
|
|
312
|
-
$ref: `#/x-ext/${
|
|
310
|
+
$ref: `#/x-ext/${getHash(`${url}/nested/chunk1.json`)}`,
|
|
313
311
|
},
|
|
314
312
|
})
|
|
315
313
|
})
|
|
@@ -345,17 +343,17 @@ describe('bundle', () => {
|
|
|
345
343
|
|
|
346
344
|
expect(output).toEqual({
|
|
347
345
|
'x-ext': {
|
|
348
|
-
[
|
|
346
|
+
[getHash(`${url}/top-level`)]: {
|
|
349
347
|
c: 'c',
|
|
350
348
|
},
|
|
351
|
-
[
|
|
349
|
+
[getHash(`${url}/nested/chunk1.json`)]: {
|
|
352
350
|
b: {
|
|
353
|
-
$ref: `#/x-ext/${
|
|
351
|
+
$ref: `#/x-ext/${getHash(`${url}/top-level`)}`,
|
|
354
352
|
},
|
|
355
353
|
},
|
|
356
354
|
},
|
|
357
355
|
a: {
|
|
358
|
-
$ref: `#/x-ext/${
|
|
356
|
+
$ref: `#/x-ext/${getHash(`${url}/nested/chunk1.json`)}`,
|
|
359
357
|
},
|
|
360
358
|
})
|
|
361
359
|
})
|
|
@@ -395,21 +393,21 @@ describe('bundle', () => {
|
|
|
395
393
|
|
|
396
394
|
expect(output).toEqual({
|
|
397
395
|
'x-ext': {
|
|
398
|
-
[
|
|
396
|
+
[getHash(`${url}/top-level`)]: {
|
|
399
397
|
c: 'c',
|
|
400
398
|
},
|
|
401
|
-
[
|
|
399
|
+
[getHash(`${url}/nested/chunk1.json`)]: {
|
|
402
400
|
b: {
|
|
403
|
-
$ref: `#/x-ext/${
|
|
401
|
+
$ref: `#/x-ext/${getHash(`${url}/top-level`)}`,
|
|
404
402
|
},
|
|
405
403
|
},
|
|
406
404
|
},
|
|
407
405
|
'x-ext-urls': {
|
|
408
|
-
[
|
|
409
|
-
[
|
|
406
|
+
[getHash(`${url}/top-level`)]: `${url}/top-level`,
|
|
407
|
+
[getHash(`${url}/nested/chunk1.json`)]: `${url}/nested/chunk1.json`,
|
|
410
408
|
},
|
|
411
409
|
a: {
|
|
412
|
-
$ref: `#/x-ext/${
|
|
410
|
+
$ref: `#/x-ext/${getHash(`${url}/nested/chunk1.json`)}`,
|
|
413
411
|
},
|
|
414
412
|
})
|
|
415
413
|
})
|
|
@@ -466,13 +464,13 @@ describe('bundle', () => {
|
|
|
466
464
|
a: {
|
|
467
465
|
b: {
|
|
468
466
|
c: {
|
|
469
|
-
$ref: `#/x-ext/${
|
|
467
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
470
468
|
},
|
|
471
469
|
d: {
|
|
472
470
|
e: {
|
|
473
471
|
f: {
|
|
474
472
|
g: {
|
|
475
|
-
$ref: `#/x-ext/${
|
|
473
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
476
474
|
},
|
|
477
475
|
},
|
|
478
476
|
},
|
|
@@ -480,18 +478,18 @@ describe('bundle', () => {
|
|
|
480
478
|
},
|
|
481
479
|
},
|
|
482
480
|
'x-ext': {
|
|
483
|
-
[
|
|
481
|
+
[getHash(`${url}/chunk1`)]: {
|
|
484
482
|
a: {
|
|
485
483
|
hello: 'hello',
|
|
486
484
|
},
|
|
487
485
|
b: {
|
|
488
|
-
$ref: `#/x-ext/${
|
|
486
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk2`)}`,
|
|
489
487
|
},
|
|
490
488
|
},
|
|
491
|
-
[
|
|
489
|
+
[getHash(`${url}/chunk2`)]: {
|
|
492
490
|
a: 'a',
|
|
493
491
|
b: {
|
|
494
|
-
$ref: `#/x-ext/${
|
|
492
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
495
493
|
},
|
|
496
494
|
},
|
|
497
495
|
},
|
|
@@ -528,11 +526,11 @@ describe('bundle', () => {
|
|
|
528
526
|
expect(input).toEqual({
|
|
529
527
|
a: [
|
|
530
528
|
{
|
|
531
|
-
$ref: `#/x-ext/${
|
|
529
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
532
530
|
},
|
|
533
531
|
],
|
|
534
532
|
'x-ext': {
|
|
535
|
-
[
|
|
533
|
+
[getHash(`${url}/chunk1`)]: {
|
|
536
534
|
a: {
|
|
537
535
|
hello: 'hello',
|
|
538
536
|
},
|
|
@@ -586,20 +584,20 @@ describe('bundle', () => {
|
|
|
586
584
|
$ref: `${url}/chunk1#`,
|
|
587
585
|
},
|
|
588
586
|
b: {
|
|
589
|
-
$ref: `#/x-ext/${
|
|
587
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
590
588
|
},
|
|
591
589
|
c: {
|
|
592
590
|
$ref: `${url}/chunk1#`,
|
|
593
591
|
},
|
|
594
592
|
'x-ext': {
|
|
595
|
-
[
|
|
593
|
+
[getHash(`${url}/chunk1`)]: {
|
|
596
594
|
a: {
|
|
597
595
|
hello: 'hello',
|
|
598
596
|
},
|
|
599
597
|
},
|
|
600
598
|
},
|
|
601
599
|
'x-ext-urls': {
|
|
602
|
-
[
|
|
600
|
+
[getHash(`${url}/chunk1`)]: `${url}/chunk1`,
|
|
603
601
|
},
|
|
604
602
|
})
|
|
605
603
|
|
|
@@ -616,20 +614,20 @@ describe('bundle', () => {
|
|
|
616
614
|
$ref: `${url}/chunk1#`,
|
|
617
615
|
},
|
|
618
616
|
b: {
|
|
619
|
-
$ref: `#/x-ext/${
|
|
617
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
620
618
|
},
|
|
621
619
|
c: {
|
|
622
|
-
$ref: `#/x-ext/${
|
|
620
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
623
621
|
},
|
|
624
622
|
'x-ext': {
|
|
625
|
-
[
|
|
623
|
+
[getHash(`${url}/chunk1`)]: {
|
|
626
624
|
a: {
|
|
627
625
|
hello: 'hello',
|
|
628
626
|
},
|
|
629
627
|
},
|
|
630
628
|
},
|
|
631
629
|
'x-ext-urls': {
|
|
632
|
-
[
|
|
630
|
+
[getHash(`${url}/chunk1`)]: `${url}/chunk1`,
|
|
633
631
|
},
|
|
634
632
|
})
|
|
635
633
|
|
|
@@ -679,13 +677,13 @@ describe('bundle', () => {
|
|
|
679
677
|
$ref: `${url}/chunk1#`,
|
|
680
678
|
},
|
|
681
679
|
b: {
|
|
682
|
-
$ref: `#/x-ext/${
|
|
680
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
683
681
|
},
|
|
684
682
|
c: {
|
|
685
683
|
$ref: `${url}/chunk1#`,
|
|
686
684
|
},
|
|
687
685
|
'x-ext': {
|
|
688
|
-
[
|
|
686
|
+
[getHash(`${url}/chunk1`)]: {
|
|
689
687
|
a: {
|
|
690
688
|
hello: 'hello',
|
|
691
689
|
},
|
|
@@ -693,7 +691,7 @@ describe('bundle', () => {
|
|
|
693
691
|
},
|
|
694
692
|
// It should still inject the mappings on the output document
|
|
695
693
|
'x-ext-urls': {
|
|
696
|
-
[
|
|
694
|
+
[getHash(`${url}/chunk1`)]: `${url}/chunk1`,
|
|
697
695
|
},
|
|
698
696
|
})
|
|
699
697
|
})
|
|
@@ -733,14 +731,14 @@ describe('bundle', () => {
|
|
|
733
731
|
|
|
734
732
|
expect(input).toEqual({
|
|
735
733
|
a: {
|
|
736
|
-
$ref: `#/x-ext/${
|
|
734
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/a/b`,
|
|
737
735
|
},
|
|
738
736
|
'x-ext': {
|
|
739
|
-
[
|
|
737
|
+
[getHash(`${url}/chunk1`)]: {
|
|
740
738
|
a: {
|
|
741
739
|
b: {
|
|
742
740
|
g: {
|
|
743
|
-
$ref: `#/x-ext/${
|
|
741
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/d/e`,
|
|
744
742
|
},
|
|
745
743
|
hello: 'hello',
|
|
746
744
|
},
|
|
@@ -804,20 +802,20 @@ describe('bundle', () => {
|
|
|
804
802
|
|
|
805
803
|
expect(input).toEqual({
|
|
806
804
|
a: {
|
|
807
|
-
$ref: `#/x-ext/${
|
|
805
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/a`,
|
|
808
806
|
},
|
|
809
807
|
'x-ext': {
|
|
810
|
-
[
|
|
808
|
+
[getHash(`${url}/chunk1`)]: {
|
|
811
809
|
a: {
|
|
812
810
|
b: {
|
|
813
811
|
g: {
|
|
814
|
-
$ref: `#/x-ext/${
|
|
812
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/d/e`,
|
|
815
813
|
},
|
|
816
814
|
hello: 'hello',
|
|
817
815
|
},
|
|
818
816
|
c: 'c',
|
|
819
817
|
'external': {
|
|
820
|
-
$ref: `#/x-ext/${
|
|
818
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk2`)}/a/b`,
|
|
821
819
|
},
|
|
822
820
|
},
|
|
823
821
|
d: {
|
|
@@ -826,7 +824,7 @@ describe('bundle', () => {
|
|
|
826
824
|
},
|
|
827
825
|
},
|
|
828
826
|
},
|
|
829
|
-
[
|
|
827
|
+
[getHash(`${url}/chunk2`)]: {
|
|
830
828
|
a: {
|
|
831
829
|
b: {
|
|
832
830
|
hello: 'hello',
|
|
@@ -871,20 +869,20 @@ describe('bundle', () => {
|
|
|
871
869
|
|
|
872
870
|
expect(input).toEqual({
|
|
873
871
|
a: {
|
|
874
|
-
$ref: `#/x-ext/${
|
|
872
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/a`,
|
|
875
873
|
},
|
|
876
874
|
'x-ext': {
|
|
877
|
-
[
|
|
875
|
+
[getHash(`${url}/chunk1`)]: {
|
|
878
876
|
a: {
|
|
879
877
|
b: {
|
|
880
878
|
g: {
|
|
881
|
-
$ref: `#/x-ext/${
|
|
879
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/a/external`,
|
|
882
880
|
},
|
|
883
881
|
hello: 'hello',
|
|
884
882
|
},
|
|
885
883
|
c: 'c',
|
|
886
884
|
external: {
|
|
887
|
-
$ref: `#/x-ext/${
|
|
885
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}/a/b`,
|
|
888
886
|
},
|
|
889
887
|
},
|
|
890
888
|
},
|
|
@@ -951,11 +949,11 @@ describe('bundle', () => {
|
|
|
951
949
|
expect(input).toEqual({
|
|
952
950
|
a: {
|
|
953
951
|
$global: true,
|
|
954
|
-
$ref: `#/x-ext/${
|
|
952
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
955
953
|
},
|
|
956
954
|
b: {
|
|
957
955
|
$global: true,
|
|
958
|
-
$ref: `#/x-ext/${
|
|
956
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk2`)}`,
|
|
959
957
|
},
|
|
960
958
|
c: {
|
|
961
959
|
$global: true,
|
|
@@ -973,19 +971,19 @@ describe('bundle', () => {
|
|
|
973
971
|
},
|
|
974
972
|
},
|
|
975
973
|
'x-ext': {
|
|
976
|
-
[
|
|
974
|
+
[getHash(`${url}/chunk1`)]: {
|
|
977
975
|
description: 'Chunk 1',
|
|
978
976
|
someRef: {
|
|
979
977
|
$ref: '#/components/User',
|
|
980
978
|
},
|
|
981
979
|
},
|
|
982
|
-
[
|
|
980
|
+
[getHash(`${url}/chunk2`)]: {
|
|
983
981
|
description: 'Chunk 2',
|
|
984
982
|
},
|
|
985
983
|
},
|
|
986
984
|
'x-ext-urls': {
|
|
987
|
-
[
|
|
988
|
-
[
|
|
985
|
+
[getHash(`${url}/chunk2`)]: `${url}/chunk2`,
|
|
986
|
+
[getHash(`${url}/chunk1`)]: `${url}/chunk1`,
|
|
989
987
|
},
|
|
990
988
|
})
|
|
991
989
|
})
|
|
@@ -1031,7 +1029,7 @@ describe('bundle', () => {
|
|
|
1031
1029
|
|
|
1032
1030
|
expect(input).toEqual({
|
|
1033
1031
|
a: {
|
|
1034
|
-
$ref: `#/x-ext/${
|
|
1032
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
1035
1033
|
},
|
|
1036
1034
|
b: {
|
|
1037
1035
|
a: 'a',
|
|
@@ -1043,14 +1041,14 @@ describe('bundle', () => {
|
|
|
1043
1041
|
$ref: `${url}/chunk2#`,
|
|
1044
1042
|
},
|
|
1045
1043
|
'x-ext': {
|
|
1046
|
-
[
|
|
1044
|
+
[getHash(`${url}/chunk1`)]: {
|
|
1047
1045
|
a: {
|
|
1048
1046
|
hello: 'hello',
|
|
1049
1047
|
},
|
|
1050
1048
|
},
|
|
1051
1049
|
},
|
|
1052
1050
|
'x-ext-urls': {
|
|
1053
|
-
[
|
|
1051
|
+
[getHash(`${url}/chunk1`)]: 'http://localhost:7289/chunk1',
|
|
1054
1052
|
},
|
|
1055
1053
|
})
|
|
1056
1054
|
})
|
|
@@ -1134,14 +1132,14 @@ describe('bundle', () => {
|
|
|
1134
1132
|
expect(input).toEqual({
|
|
1135
1133
|
a: {
|
|
1136
1134
|
$global: true,
|
|
1137
|
-
$ref: `#/x-ext/${
|
|
1135
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk1`)}`,
|
|
1138
1136
|
},
|
|
1139
1137
|
b: {
|
|
1140
1138
|
$global: true,
|
|
1141
|
-
$ref: `#/x-ext/${
|
|
1139
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk2`)}`,
|
|
1142
1140
|
},
|
|
1143
1141
|
c: {
|
|
1144
|
-
$ref: `#/x-ext/${
|
|
1142
|
+
$ref: `#/x-ext/${getHash(`${url}/external/document.json`)}`,
|
|
1145
1143
|
},
|
|
1146
1144
|
|
|
1147
1145
|
entry: {
|
|
@@ -1151,34 +1149,34 @@ describe('bundle', () => {
|
|
|
1151
1149
|
$ref: `http://localhost:${port}/chunk1`,
|
|
1152
1150
|
},
|
|
1153
1151
|
'x-ext': {
|
|
1154
|
-
[
|
|
1152
|
+
[getHash(`${url}/external/document.json`)]: {
|
|
1155
1153
|
external: 'external',
|
|
1156
1154
|
someChunk: {
|
|
1157
|
-
$ref: `#/x-ext/${
|
|
1155
|
+
$ref: `#/x-ext/${getHash(`${url}/chunk3`)}`,
|
|
1158
1156
|
$global: true,
|
|
1159
1157
|
},
|
|
1160
1158
|
},
|
|
1161
|
-
[
|
|
1159
|
+
[getHash(`${url}/chunk1`)]: {
|
|
1162
1160
|
chunk1: 'chunk1',
|
|
1163
1161
|
someRef: {
|
|
1164
1162
|
$ref: '#/b',
|
|
1165
1163
|
},
|
|
1166
1164
|
},
|
|
1167
|
-
[
|
|
1165
|
+
[getHash(`${url}/chunk2`)]: {
|
|
1168
1166
|
chunk2: 'chunk2',
|
|
1169
1167
|
someRef: {
|
|
1170
1168
|
$ref: '#/c',
|
|
1171
1169
|
},
|
|
1172
1170
|
},
|
|
1173
|
-
[
|
|
1171
|
+
[getHash(`${url}/chunk3`)]: {
|
|
1174
1172
|
chunk3: 'chunk3',
|
|
1175
1173
|
},
|
|
1176
1174
|
},
|
|
1177
1175
|
'x-ext-urls': {
|
|
1178
|
-
[
|
|
1179
|
-
[
|
|
1180
|
-
[
|
|
1181
|
-
[
|
|
1176
|
+
[getHash(`${url}/chunk1`)]: `${url}/chunk1`,
|
|
1177
|
+
[getHash(`${url}/chunk2`)]: `${url}/chunk2`,
|
|
1178
|
+
[getHash(`${url}/chunk3`)]: `${url}/chunk3`,
|
|
1179
|
+
[getHash(`${url}/external/document.json`)]: `${url}/external/document.json`,
|
|
1182
1180
|
},
|
|
1183
1181
|
})
|
|
1184
1182
|
})
|
|
@@ -1296,10 +1294,10 @@ describe('bundle', () => {
|
|
|
1296
1294
|
|
|
1297
1295
|
expect(result).toEqual({
|
|
1298
1296
|
'a': {
|
|
1299
|
-
'$ref': '#/x-ext/
|
|
1297
|
+
'$ref': '#/x-ext/814f1d7',
|
|
1300
1298
|
},
|
|
1301
1299
|
'x-ext': {
|
|
1302
|
-
'
|
|
1300
|
+
'814f1d7': {
|
|
1303
1301
|
'message': 'some resolved external reference',
|
|
1304
1302
|
},
|
|
1305
1303
|
},
|
|
@@ -1324,8 +1322,8 @@ describe('bundle', () => {
|
|
|
1324
1322
|
})
|
|
1325
1323
|
|
|
1326
1324
|
expect(result).toEqual({
|
|
1327
|
-
a: { '$ref': '#/x-ext/
|
|
1328
|
-
'x-ext': { '
|
|
1325
|
+
a: { '$ref': '#/x-ext/220f104' },
|
|
1326
|
+
'x-ext': { '220f104': { message: 'some resolved external reference' } },
|
|
1329
1327
|
})
|
|
1330
1328
|
})
|
|
1331
1329
|
|
|
@@ -1543,12 +1541,12 @@ describe('bundle', () => {
|
|
|
1543
1541
|
'a': {
|
|
1544
1542
|
'b': {
|
|
1545
1543
|
'c': {
|
|
1546
|
-
'$ref': '#/x-ext/
|
|
1544
|
+
'$ref': '#/x-ext/ce08d76',
|
|
1547
1545
|
},
|
|
1548
1546
|
},
|
|
1549
1547
|
},
|
|
1550
1548
|
'x-ext': {
|
|
1551
|
-
'
|
|
1549
|
+
'ce08d76': {
|
|
1552
1550
|
'message': 'resolved value',
|
|
1553
1551
|
},
|
|
1554
1552
|
},
|
|
@@ -1599,12 +1597,12 @@ describe('bundle', () => {
|
|
|
1599
1597
|
'a': {
|
|
1600
1598
|
'b': {
|
|
1601
1599
|
'c': {
|
|
1602
|
-
'$ref': '#/x-ext/
|
|
1600
|
+
'$ref': '#/x-ext/b9d44e3',
|
|
1603
1601
|
},
|
|
1604
1602
|
},
|
|
1605
1603
|
},
|
|
1606
1604
|
'x-ext': {
|
|
1607
|
-
'
|
|
1605
|
+
'b9d44e3': {
|
|
1608
1606
|
'message': 'resolved value',
|
|
1609
1607
|
},
|
|
1610
1608
|
},
|
|
@@ -1665,12 +1663,12 @@ describe('bundle', () => {
|
|
|
1665
1663
|
'a': {
|
|
1666
1664
|
'b': {
|
|
1667
1665
|
'c': {
|
|
1668
|
-
'$ref': '#/x-ext/
|
|
1666
|
+
'$ref': '#/x-ext/c3654f1',
|
|
1669
1667
|
},
|
|
1670
1668
|
},
|
|
1671
1669
|
},
|
|
1672
1670
|
'x-ext': {
|
|
1673
|
-
'
|
|
1671
|
+
'c3654f1': {
|
|
1674
1672
|
'message': 'resolved value',
|
|
1675
1673
|
},
|
|
1676
1674
|
},
|
|
@@ -1744,16 +1742,16 @@ describe('bundle', () => {
|
|
|
1744
1742
|
'$ref': '#my-anchor',
|
|
1745
1743
|
},
|
|
1746
1744
|
'g': {
|
|
1747
|
-
'$ref': '#/x-ext/
|
|
1745
|
+
'$ref': '#/x-ext/e71bf65',
|
|
1748
1746
|
},
|
|
1749
1747
|
},
|
|
1750
1748
|
'x-ext': {
|
|
1751
|
-
'
|
|
1749
|
+
'e71bf65': {
|
|
1752
1750
|
'message': 'resolved value',
|
|
1753
1751
|
},
|
|
1754
1752
|
},
|
|
1755
1753
|
'x-ext-urls': {
|
|
1756
|
-
'
|
|
1754
|
+
'e71bf65': 'http://example.com',
|
|
1757
1755
|
},
|
|
1758
1756
|
})
|
|
1759
1757
|
})
|
|
@@ -1798,12 +1796,12 @@ describe('bundle', () => {
|
|
|
1798
1796
|
|
|
1799
1797
|
expect(input).toEqual({
|
|
1800
1798
|
'x-ext': {
|
|
1801
|
-
[
|
|
1799
|
+
[getHash(chunk1Path)]: {
|
|
1802
1800
|
...chunk1,
|
|
1803
1801
|
},
|
|
1804
1802
|
},
|
|
1805
1803
|
a: {
|
|
1806
|
-
$ref: `#/x-ext/${
|
|
1804
|
+
$ref: `#/x-ext/${getHash(chunk1Path)}/a`,
|
|
1807
1805
|
},
|
|
1808
1806
|
})
|
|
1809
1807
|
})
|
|
@@ -1831,15 +1829,15 @@ describe('bundle', () => {
|
|
|
1831
1829
|
|
|
1832
1830
|
expect(input).toEqual({
|
|
1833
1831
|
'x-ext': {
|
|
1834
|
-
[
|
|
1832
|
+
[getHash(chunk1Path)]: {
|
|
1835
1833
|
...chunk1,
|
|
1836
1834
|
},
|
|
1837
|
-
[
|
|
1838
|
-
a: { $ref: `#/x-ext/${
|
|
1835
|
+
[getHash(chunk2Path)]: {
|
|
1836
|
+
a: { $ref: `#/x-ext/${getHash(chunk1Path)}` },
|
|
1839
1837
|
},
|
|
1840
1838
|
},
|
|
1841
1839
|
a: {
|
|
1842
|
-
$ref: `#/x-ext/${
|
|
1840
|
+
$ref: `#/x-ext/${getHash(chunk2Path)}`,
|
|
1843
1841
|
},
|
|
1844
1842
|
})
|
|
1845
1843
|
})
|
|
@@ -1877,15 +1875,15 @@ describe('bundle', () => {
|
|
|
1877
1875
|
|
|
1878
1876
|
expect(input).toEqual({
|
|
1879
1877
|
'x-ext': {
|
|
1880
|
-
[
|
|
1878
|
+
[getHash(`nested/${cName}`)]: {
|
|
1881
1879
|
c: 'c',
|
|
1882
1880
|
},
|
|
1883
|
-
[
|
|
1884
|
-
b: { $ref: `#/x-ext/${
|
|
1881
|
+
[getHash(`nested/${bName}`)]: {
|
|
1882
|
+
b: { $ref: `#/x-ext/${getHash(`nested/${cName}`)}` },
|
|
1885
1883
|
},
|
|
1886
1884
|
},
|
|
1887
1885
|
a: {
|
|
1888
|
-
$ref: `#/x-ext/${
|
|
1886
|
+
$ref: `#/x-ext/${getHash(`nested/${bName}`)}`,
|
|
1889
1887
|
},
|
|
1890
1888
|
})
|
|
1891
1889
|
})
|
|
@@ -1926,10 +1924,10 @@ describe('bundle', () => {
|
|
|
1926
1924
|
|
|
1927
1925
|
expect(result).toEqual({
|
|
1928
1926
|
'b': {
|
|
1929
|
-
'$ref': `#/x-ext/${
|
|
1927
|
+
'$ref': `#/x-ext/${getHash(`nested/${cName}`)}`,
|
|
1930
1928
|
},
|
|
1931
1929
|
'x-ext': {
|
|
1932
|
-
[
|
|
1930
|
+
[getHash(`nested/${cName}`)]: {
|
|
1933
1931
|
'c': 'c',
|
|
1934
1932
|
},
|
|
1935
1933
|
},
|
|
@@ -1971,12 +1969,12 @@ describe('bundle', () => {
|
|
|
1971
1969
|
|
|
1972
1970
|
expect(result).toEqual({
|
|
1973
1971
|
'x-ext': {
|
|
1974
|
-
[
|
|
1972
|
+
[getHash(chunk1Path)]: {
|
|
1975
1973
|
...chunk1,
|
|
1976
1974
|
},
|
|
1977
1975
|
},
|
|
1978
1976
|
a: {
|
|
1979
|
-
$ref: `#/x-ext/${
|
|
1977
|
+
$ref: `#/x-ext/${getHash(chunk1Path)}/a`,
|
|
1980
1978
|
},
|
|
1981
1979
|
})
|
|
1982
1980
|
})
|
|
@@ -1992,7 +1990,6 @@ describe('bundle', () => {
|
|
|
1992
1990
|
|
|
1993
1991
|
return async () => {
|
|
1994
1992
|
await server.close()
|
|
1995
|
-
await setTimeout(100)
|
|
1996
1993
|
}
|
|
1997
1994
|
})
|
|
1998
1995
|
|
|
@@ -2029,12 +2026,12 @@ describe('bundle', () => {
|
|
|
2029
2026
|
|
|
2030
2027
|
expect(result).toEqual({
|
|
2031
2028
|
'x-ext': {
|
|
2032
|
-
[
|
|
2029
|
+
[getHash(chunk1Path)]: {
|
|
2033
2030
|
...chunk1,
|
|
2034
2031
|
},
|
|
2035
2032
|
},
|
|
2036
2033
|
a: {
|
|
2037
|
-
$ref: `#/x-ext/${
|
|
2034
|
+
$ref: `#/x-ext/${getHash(chunk1Path)}/a`,
|
|
2038
2035
|
},
|
|
2039
2036
|
})
|
|
2040
2037
|
})
|
|
@@ -2071,7 +2068,6 @@ describe('bundle', () => {
|
|
|
2071
2068
|
|
|
2072
2069
|
return async () => {
|
|
2073
2070
|
await server.close()
|
|
2074
|
-
await setTimeout(100)
|
|
2075
2071
|
}
|
|
2076
2072
|
})
|
|
2077
2073
|
|
|
@@ -2113,12 +2109,12 @@ describe('bundle', () => {
|
|
|
2113
2109
|
|
|
2114
2110
|
expect(input).toEqual({
|
|
2115
2111
|
'x-ext': {
|
|
2116
|
-
[
|
|
2112
|
+
[getHash(url)]: {
|
|
2117
2113
|
...external,
|
|
2118
2114
|
},
|
|
2119
2115
|
},
|
|
2120
2116
|
'x-ext-urls': {
|
|
2121
|
-
[
|
|
2117
|
+
[getHash(url)]: url,
|
|
2122
2118
|
},
|
|
2123
2119
|
a: {
|
|
2124
2120
|
b: {
|
|
@@ -2133,7 +2129,7 @@ describe('bundle', () => {
|
|
|
2133
2129
|
},
|
|
2134
2130
|
d: {
|
|
2135
2131
|
e: {
|
|
2136
|
-
$ref: `#/x-ext/${
|
|
2132
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
2137
2133
|
},
|
|
2138
2134
|
},
|
|
2139
2135
|
})
|
|
@@ -2180,12 +2176,12 @@ describe('bundle', () => {
|
|
|
2180
2176
|
|
|
2181
2177
|
expect(input).toEqual({
|
|
2182
2178
|
'x-ext': {
|
|
2183
|
-
[
|
|
2179
|
+
[getHash(url)]: {
|
|
2184
2180
|
...external,
|
|
2185
2181
|
},
|
|
2186
2182
|
},
|
|
2187
2183
|
'x-ext-urls': {
|
|
2188
|
-
[
|
|
2184
|
+
[getHash(url)]: url,
|
|
2189
2185
|
},
|
|
2190
2186
|
a: {
|
|
2191
2187
|
b: {
|
|
@@ -2200,7 +2196,7 @@ describe('bundle', () => {
|
|
|
2200
2196
|
},
|
|
2201
2197
|
d: {
|
|
2202
2198
|
e: {
|
|
2203
|
-
$ref: `#/x-ext/${
|
|
2199
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
2204
2200
|
},
|
|
2205
2201
|
},
|
|
2206
2202
|
})
|
|
@@ -2217,12 +2213,12 @@ describe('bundle', () => {
|
|
|
2217
2213
|
// because we are reusing the same hash set
|
|
2218
2214
|
expect(input).toEqual({
|
|
2219
2215
|
'x-ext': {
|
|
2220
|
-
[
|
|
2216
|
+
[getHash(url)]: {
|
|
2221
2217
|
...external,
|
|
2222
2218
|
},
|
|
2223
2219
|
},
|
|
2224
2220
|
'x-ext-urls': {
|
|
2225
|
-
[
|
|
2221
|
+
[getHash(url)]: url,
|
|
2226
2222
|
},
|
|
2227
2223
|
a: {
|
|
2228
2224
|
b: {
|
|
@@ -2237,7 +2233,7 @@ describe('bundle', () => {
|
|
|
2237
2233
|
},
|
|
2238
2234
|
d: {
|
|
2239
2235
|
e: {
|
|
2240
|
-
$ref: `#/x-ext/${
|
|
2236
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
2241
2237
|
},
|
|
2242
2238
|
},
|
|
2243
2239
|
})
|
|
@@ -2251,19 +2247,19 @@ describe('bundle', () => {
|
|
|
2251
2247
|
|
|
2252
2248
|
expect(input).toEqual({
|
|
2253
2249
|
'x-ext': {
|
|
2254
|
-
[
|
|
2250
|
+
[getHash(url)]: {
|
|
2255
2251
|
...external,
|
|
2256
2252
|
},
|
|
2257
2253
|
},
|
|
2258
2254
|
'x-ext-urls': {
|
|
2259
|
-
[
|
|
2255
|
+
[getHash(url)]: url,
|
|
2260
2256
|
},
|
|
2261
2257
|
a: {
|
|
2262
2258
|
b: {
|
|
2263
2259
|
c: {
|
|
2264
2260
|
d: {
|
|
2265
2261
|
e: {
|
|
2266
|
-
$ref: `#/x-ext/${
|
|
2262
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
2267
2263
|
},
|
|
2268
2264
|
},
|
|
2269
2265
|
},
|
|
@@ -2271,7 +2267,7 @@ describe('bundle', () => {
|
|
|
2271
2267
|
},
|
|
2272
2268
|
d: {
|
|
2273
2269
|
e: {
|
|
2274
|
-
$ref: `#/x-ext/${
|
|
2270
|
+
$ref: `#/x-ext/${getHash(url)}/prop`,
|
|
2275
2271
|
},
|
|
2276
2272
|
},
|
|
2277
2273
|
})
|
|
@@ -2439,9 +2435,9 @@ describe('bundle', () => {
|
|
|
2439
2435
|
expect(exec).toHaveBeenLastCalledWith('hello')
|
|
2440
2436
|
|
|
2441
2437
|
expect(result).toEqual({
|
|
2442
|
-
$ref: '#/x-ext/
|
|
2438
|
+
$ref: '#/x-ext/f265832',
|
|
2443
2439
|
'x-ext': {
|
|
2444
|
-
'
|
|
2440
|
+
'f265832': {
|
|
2445
2441
|
message: 'Resolved document',
|
|
2446
2442
|
},
|
|
2447
2443
|
},
|
|
@@ -2638,13 +2634,13 @@ describe('bundle', () => {
|
|
|
2638
2634
|
|
|
2639
2635
|
expect(onResolveStart).toHaveBeenCalledTimes(2)
|
|
2640
2636
|
expect(onResolveStart).nthCalledWith(1, { $ref: 'some-value' })
|
|
2641
|
-
expect(onResolveStart).nthCalledWith(2, { $ref: '#/x-ext/
|
|
2637
|
+
expect(onResolveStart).nthCalledWith(2, { $ref: '#/x-ext/908a515' })
|
|
2642
2638
|
|
|
2643
2639
|
expect(onResolveError).toHaveBeenCalledTimes(1)
|
|
2644
2640
|
expect(onResolveError).lastCalledWith({ $ref: 'some-value' })
|
|
2645
2641
|
|
|
2646
2642
|
expect(onResolveSuccess).toHaveBeenCalledTimes(1)
|
|
2647
|
-
expect(onResolveSuccess).lastCalledWith({ $ref: '#/x-ext/
|
|
2643
|
+
expect(onResolveSuccess).lastCalledWith({ $ref: '#/x-ext/908a515' })
|
|
2648
2644
|
})
|
|
2649
2645
|
|
|
2650
2646
|
it('correctly provides the parent node in different levels', async () => {
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises'
|
|
2
|
-
|
|
3
1
|
import { type FastifyInstance, fastify } from 'fastify'
|
|
4
2
|
import { assert, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
5
3
|
|
|
@@ -16,7 +14,6 @@ describe('fetchUrl', () => {
|
|
|
16
14
|
|
|
17
15
|
return async () => {
|
|
18
16
|
await server.close()
|
|
19
|
-
await setTimeout(100)
|
|
20
17
|
}
|
|
21
18
|
})
|
|
22
19
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { generateHash } from '
|
|
1
|
+
import { generateHash } from '@scalar/helpers/string/generate-hash'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Generates a short hash from a string value using xxhash.
|
|
@@ -13,11 +13,11 @@ import { generateHash } from '@/helpers/generate-hash'
|
|
|
13
13
|
* @returns A Promise that resolves to a 7-character hexadecimal hash with at least one letter
|
|
14
14
|
* @example
|
|
15
15
|
* // Returns "2ae91d7"
|
|
16
|
-
*
|
|
16
|
+
* getHash("https://example.com/schema.json")
|
|
17
17
|
*/
|
|
18
|
-
export
|
|
18
|
+
export function getHash(value: string): string {
|
|
19
19
|
// Hash the data using xxhash
|
|
20
|
-
const hashHex =
|
|
20
|
+
const hashHex = generateHash(value)
|
|
21
21
|
|
|
22
22
|
// Return first 7 characters of the hash, ensuring at least one letter
|
|
23
23
|
const hash = hashHex.substring(0, 7)
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { setTimeout } from 'node:timers/promises'
|
|
2
|
-
|
|
3
1
|
import { type FastifyInstance, fastify } from 'fastify'
|
|
4
|
-
import {
|
|
2
|
+
import { beforeEach, describe, expect, it } from 'vitest'
|
|
5
3
|
|
|
6
4
|
import { dereference } from '@/dereference/dereference'
|
|
7
5
|
|
|
@@ -68,11 +66,10 @@ describe('dereference', () => {
|
|
|
68
66
|
|
|
69
67
|
beforeEach(() => {
|
|
70
68
|
server = fastify({ logger: false })
|
|
71
|
-
})
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
70
|
+
return async () => {
|
|
71
|
+
await server.close()
|
|
72
|
+
}
|
|
76
73
|
})
|
|
77
74
|
|
|
78
75
|
it('should dereference JSON pointers asynchronously', async () => {
|
|
@@ -101,7 +98,7 @@ describe('dereference', () => {
|
|
|
101
98
|
success: true,
|
|
102
99
|
data: {
|
|
103
100
|
profile: {
|
|
104
|
-
'$ref': '#/x-ext/
|
|
101
|
+
'$ref': '#/x-ext/f053c6d',
|
|
105
102
|
'$ref-value': {
|
|
106
103
|
name: 'Jane Doe',
|
|
107
104
|
age: 25,
|
|
@@ -112,17 +109,17 @@ describe('dereference', () => {
|
|
|
112
109
|
},
|
|
113
110
|
},
|
|
114
111
|
address: {
|
|
115
|
-
'$ref': '#/x-ext/
|
|
112
|
+
'$ref': '#/x-ext/f053c6d/address',
|
|
116
113
|
'$ref-value': {
|
|
117
114
|
city: 'Los Angeles',
|
|
118
115
|
street: 'Sunset Boulevard',
|
|
119
116
|
},
|
|
120
117
|
},
|
|
121
118
|
'x-ext': {
|
|
122
|
-
'
|
|
119
|
+
'f053c6d': userProfile,
|
|
123
120
|
},
|
|
124
121
|
'x-ext-urls': {
|
|
125
|
-
'
|
|
122
|
+
'f053c6d': `${url}/users`,
|
|
126
123
|
},
|
|
127
124
|
},
|
|
128
125
|
})
|
package/vite.config.ts
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate a hash from a string using the xxhash algorithm
|
|
3
|
-
*
|
|
4
|
-
* We cannot use crypto.subtle because it is only available in secure contexts (HTTPS) or on localhost.
|
|
5
|
-
* So this is just a wrapper around the xxhash-wasm library instead.
|
|
6
|
-
*
|
|
7
|
-
* @param input - The string to hash
|
|
8
|
-
* @returns A Promise that resolves to the hash of the input string
|
|
9
|
-
*/
|
|
10
|
-
export declare const generateHash: (input: string) => Promise<string>;
|
|
11
|
-
//# sourceMappingURL=generate-hash.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generate-hash.d.ts","sourceRoot":"","sources":["../../src/helpers/generate-hash.ts"],"names":[],"mappings":"AAgBA;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAU,OAAO,MAAM,KAAG,OAAO,CAAC,MAAM,CAGhE,CAAA"}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import xxhash from "xxhash-wasm";
|
|
2
|
-
let hasherInstance = null;
|
|
3
|
-
const getHasher = async () => {
|
|
4
|
-
if (!hasherInstance) {
|
|
5
|
-
hasherInstance = await xxhash();
|
|
6
|
-
}
|
|
7
|
-
return hasherInstance;
|
|
8
|
-
};
|
|
9
|
-
const generateHash = async (input) => {
|
|
10
|
-
const { h64ToString } = await getHasher();
|
|
11
|
-
return h64ToString(input);
|
|
12
|
-
};
|
|
13
|
-
export {
|
|
14
|
-
generateHash
|
|
15
|
-
};
|
|
16
|
-
//# sourceMappingURL=generate-hash.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/helpers/generate-hash.ts"],
|
|
4
|
-
"sourcesContent": ["import xxhash from 'xxhash-wasm'\n\nlet hasherInstance: Awaited<ReturnType<typeof xxhash>> | null = null\n\n/**\n * Initialize the xxhash hasher instance lazily\n *\n * This is just a workaround because we cannot use top level await in a UMD module (standalone references)\n */\nconst getHasher = async () => {\n if (!hasherInstance) {\n hasherInstance = await xxhash()\n }\n return hasherInstance\n}\n\n/**\n * Generate a hash from a string using the xxhash algorithm\n *\n * We cannot use crypto.subtle because it is only available in secure contexts (HTTPS) or on localhost.\n * So this is just a wrapper around the xxhash-wasm library instead.\n *\n * @param input - The string to hash\n * @returns A Promise that resolves to the hash of the input string\n */\nexport const generateHash = async (input: string): Promise<string> => {\n const { h64ToString } = await getHasher()\n return h64ToString(input)\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAO,YAAY;AAEnB,IAAI,iBAA4D;AAOhE,MAAM,YAAY,YAAY;AAC5B,MAAI,CAAC,gBAAgB;AACnB,qBAAiB,MAAM,OAAO;AAAA,EAChC;AACA,SAAO;AACT;AAWO,MAAM,eAAe,OAAO,UAAmC;AACpE,QAAM,EAAE,YAAY,IAAI,MAAM,UAAU;AACxC,SAAO,YAAY,KAAK;AAC1B;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -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
|
-
}
|