@scalar/json-magic 0.4.3 → 0.5.1
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 +16 -0
- package/dist/bundle/bundle.d.ts +37 -10
- package/dist/bundle/bundle.d.ts.map +1 -1
- package/dist/bundle/bundle.js +40 -30
- package/dist/bundle/bundle.js.map +2 -2
- package/dist/bundle/index.d.ts +2 -2
- package/dist/bundle/index.d.ts.map +1 -1
- package/dist/bundle/index.js +3 -2
- package/dist/bundle/index.js.map +2 -2
- package/dist/bundle/plugins/fetch-urls/index.d.ts.map +1 -1
- package/dist/bundle/plugins/fetch-urls/index.js +2 -2
- package/dist/bundle/plugins/fetch-urls/index.js.map +2 -2
- package/dist/bundle/plugins/parse-json/index.d.ts.map +1 -1
- package/dist/bundle/plugins/parse-json/index.js +1 -1
- package/dist/bundle/plugins/parse-json/index.js.map +2 -2
- package/dist/bundle/plugins/parse-yaml/index.d.ts.map +1 -1
- package/dist/bundle/plugins/parse-yaml/index.js +1 -1
- package/dist/bundle/plugins/parse-yaml/index.js.map +2 -2
- package/dist/bundle/plugins/read-files/index.d.ts.map +1 -1
- package/dist/bundle/plugins/read-files/index.js +1 -1
- package/dist/bundle/plugins/read-files/index.js.map +2 -2
- package/dist/helpers/convert-to-local-ref.d.ts +10 -0
- package/dist/helpers/convert-to-local-ref.d.ts.map +1 -0
- package/dist/helpers/convert-to-local-ref.js +26 -0
- package/dist/helpers/convert-to-local-ref.js.map +7 -0
- package/dist/helpers/escape-json-pointer.d.ts.map +1 -0
- package/dist/{utils → helpers}/escape-json-pointer.js.map +1 -1
- package/dist/helpers/get-schemas.d.ts +21 -0
- package/dist/helpers/get-schemas.d.ts.map +1 -0
- package/dist/helpers/get-schemas.js +37 -0
- package/dist/helpers/get-schemas.js.map +7 -0
- package/dist/helpers/get-segments-from-path.d.ts.map +1 -0
- package/dist/{utils → helpers}/get-segments-from-path.js.map +1 -1
- package/dist/helpers/get-value-by-path.d.ts +24 -0
- package/dist/helpers/get-value-by-path.d.ts.map +1 -0
- package/dist/helpers/get-value-by-path.js +23 -0
- package/dist/helpers/get-value-by-path.js.map +7 -0
- package/dist/helpers/is-json-object.d.ts.map +1 -0
- package/dist/{utils → helpers}/is-json-object.js +1 -1
- package/dist/helpers/is-json-object.js.map +7 -0
- package/dist/helpers/is-object.d.ts.map +1 -0
- package/dist/{utils → helpers}/is-object.js.map +1 -1
- package/dist/helpers/is-yaml.d.ts.map +1 -0
- package/dist/{utils → helpers}/is-yaml.js.map +1 -1
- package/dist/{utils → helpers}/json-path-utils.d.ts +0 -11
- package/dist/helpers/json-path-utils.d.ts.map +1 -0
- package/dist/{utils → helpers}/json-path-utils.js +0 -9
- package/dist/helpers/json-path-utils.js.map +7 -0
- package/dist/helpers/normalize.d.ts.map +1 -0
- package/dist/{utils → helpers}/normalize.js.map +1 -1
- package/dist/helpers/unescape-json-pointer.d.ts.map +1 -0
- package/dist/{utils → helpers}/unescape-json-pointer.js.map +1 -1
- package/dist/magic-proxy/proxy.d.ts +35 -10
- package/dist/magic-proxy/proxy.d.ts.map +1 -1
- package/dist/magic-proxy/proxy.js +40 -20
- package/dist/magic-proxy/proxy.js.map +2 -2
- package/esbuild.ts +1 -0
- package/package.json +6 -1
- package/src/bundle/bundle.test.ts +533 -25
- package/src/bundle/bundle.ts +53 -37
- package/src/bundle/index.ts +3 -3
- package/src/bundle/plugins/fetch-urls/index.ts +2 -2
- package/src/bundle/plugins/parse-json/index.ts +1 -1
- package/src/bundle/plugins/parse-yaml/index.ts +3 -2
- package/src/bundle/plugins/read-files/index.ts +1 -1
- package/src/helpers/convert-to-local-ref.test.ts +211 -0
- package/src/helpers/convert-to-local-ref.ts +43 -0
- package/src/helpers/get-schemas.test.ts +356 -0
- package/src/helpers/get-schemas.ts +80 -0
- package/src/helpers/get-value-by-path.test.ts +338 -0
- package/src/helpers/get-value-by-path.ts +44 -0
- package/src/{utils → helpers}/is-json-object.ts +1 -1
- package/src/{utils → helpers}/json-path-utils.ts +0 -19
- package/src/{utils → helpers}/normalize.test.ts +2 -1
- package/src/magic-proxy/proxy.test.ts +548 -0
- package/src/magic-proxy/proxy.ts +80 -31
- package/dist/utils/escape-json-pointer.d.ts.map +0 -1
- package/dist/utils/get-segments-from-path.d.ts.map +0 -1
- package/dist/utils/is-json-object.d.ts.map +0 -1
- package/dist/utils/is-json-object.js.map +0 -7
- package/dist/utils/is-object.d.ts.map +0 -1
- package/dist/utils/is-yaml.d.ts.map +0 -1
- package/dist/utils/json-path-utils.d.ts.map +0 -1
- package/dist/utils/json-path-utils.js.map +0 -7
- package/dist/utils/normalize.d.ts.map +0 -1
- package/dist/utils/unescape-json-pointer.d.ts.map +0 -1
- /package/dist/{utils → helpers}/escape-json-pointer.d.ts +0 -0
- /package/dist/{utils → helpers}/escape-json-pointer.js +0 -0
- /package/dist/{utils → helpers}/get-segments-from-path.d.ts +0 -0
- /package/dist/{utils → helpers}/get-segments-from-path.js +0 -0
- /package/dist/{utils → helpers}/is-json-object.d.ts +0 -0
- /package/dist/{utils → helpers}/is-object.d.ts +0 -0
- /package/dist/{utils → helpers}/is-object.js +0 -0
- /package/dist/{utils → helpers}/is-yaml.d.ts +0 -0
- /package/dist/{utils → helpers}/is-yaml.js +0 -0
- /package/dist/{utils → helpers}/normalize.d.ts +0 -0
- /package/dist/{utils → helpers}/normalize.js +0 -0
- /package/dist/{utils → helpers}/unescape-json-pointer.d.ts +0 -0
- /package/dist/{utils → helpers}/unescape-json-pointer.js +0 -0
- /package/src/{utils → helpers}/escape-json-pointer.test.ts +0 -0
- /package/src/{utils → helpers}/escape-json-pointer.ts +0 -0
- /package/src/{utils → helpers}/get-segments-from-path.test.ts +0 -0
- /package/src/{utils → helpers}/get-segments-from-path.ts +0 -0
- /package/src/{utils → helpers}/is-object.test.ts +0 -0
- /package/src/{utils → helpers}/is-object.ts +0 -0
- /package/src/{utils → helpers}/is-yaml.ts +0 -0
- /package/src/{utils → helpers}/json-path-utils.test.ts +0 -0
- /package/src/{utils → helpers}/normalize.ts +0 -0
- /package/src/{utils → helpers}/unescape-json-pointer.test.ts +0 -0
- /package/src/{utils → helpers}/unescape-json-pointer.ts +0 -0
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto'
|
|
2
2
|
import fs from 'node:fs/promises'
|
|
3
|
+
import { setTimeout } from 'node:timers/promises'
|
|
4
|
+
|
|
5
|
+
import { consoleWarnSpy, resetConsoleSpies } from '@scalar/helpers/testing/console-spies'
|
|
3
6
|
import fastify, { type FastifyInstance } from 'fastify'
|
|
4
7
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
8
|
+
import YAML from 'yaml'
|
|
9
|
+
|
|
10
|
+
import { parseJson } from '@/bundle/plugins/parse-json'
|
|
11
|
+
import { parseYaml } from '@/bundle/plugins/parse-yaml'
|
|
12
|
+
import { getHash } from '@/bundle/value-generator'
|
|
13
|
+
|
|
5
14
|
import {
|
|
15
|
+
type LoaderPlugin,
|
|
6
16
|
bundle,
|
|
7
|
-
getNestedValue,
|
|
8
17
|
isLocalRef,
|
|
9
18
|
isRemoteUrl,
|
|
10
19
|
prefixInternalRef,
|
|
11
20
|
prefixInternalRefRecursive,
|
|
21
|
+
resolveAndCopyReferences,
|
|
12
22
|
setValueAtPath,
|
|
13
|
-
type LoaderPlugin,
|
|
14
23
|
} from './bundle'
|
|
15
24
|
import { fetchUrls } from './plugins/fetch-urls'
|
|
16
25
|
import { readFiles } from './plugins/read-files'
|
|
17
|
-
import { setTimeout } from 'node:timers/promises'
|
|
18
|
-
import { parseJson } from '@/bundle/plugins/parse-json'
|
|
19
|
-
import { parseYaml } from '@/bundle/plugins/parse-yaml'
|
|
20
|
-
import YAML from 'yaml'
|
|
21
|
-
import { getHash } from '@/bundle/value-generator'
|
|
22
|
-
import { consoleWarnSpy, resetConsoleSpies } from '@scalar/helpers/testing/console-spies'
|
|
23
26
|
|
|
24
27
|
describe('bundle', () => {
|
|
25
28
|
describe('external urls', () => {
|
|
@@ -1102,18 +1105,18 @@ describe('bundle', () => {
|
|
|
1102
1105
|
$ref: `${url}/external/document.json`,
|
|
1103
1106
|
},
|
|
1104
1107
|
b: {
|
|
1105
|
-
$ref: `${url}/chunk2
|
|
1108
|
+
$ref: `${url}/chunk2`,
|
|
1106
1109
|
$global: true,
|
|
1107
1110
|
},
|
|
1108
1111
|
a: {
|
|
1109
|
-
$ref: `${url}/chunk1
|
|
1112
|
+
$ref: `${url}/chunk1`,
|
|
1110
1113
|
$global: true,
|
|
1111
1114
|
},
|
|
1112
1115
|
entry: {
|
|
1113
1116
|
$ref: '#/a',
|
|
1114
1117
|
},
|
|
1115
1118
|
nonBundle: {
|
|
1116
|
-
$ref: `${url}/chunk1
|
|
1119
|
+
$ref: `${url}/chunk1`,
|
|
1117
1120
|
},
|
|
1118
1121
|
}
|
|
1119
1122
|
|
|
@@ -1145,7 +1148,7 @@ describe('bundle', () => {
|
|
|
1145
1148
|
$ref: '#/a',
|
|
1146
1149
|
},
|
|
1147
1150
|
nonBundle: {
|
|
1148
|
-
$ref: `http://localhost:${port}/chunk1
|
|
1151
|
+
$ref: `http://localhost:${port}/chunk1`,
|
|
1149
1152
|
},
|
|
1150
1153
|
'x-ext': {
|
|
1151
1154
|
[await getHash(`${url}/external/document.json`)]: {
|
|
@@ -1325,6 +1328,448 @@ describe('bundle', () => {
|
|
|
1325
1328
|
'x-ext': { e53b62c: { message: 'some resolved external reference' } },
|
|
1326
1329
|
})
|
|
1327
1330
|
})
|
|
1331
|
+
|
|
1332
|
+
it('does not modify external URLs when already defined by $id property', async () => {
|
|
1333
|
+
const url = `http://localhost:${port}`
|
|
1334
|
+
|
|
1335
|
+
const input = {
|
|
1336
|
+
$id: 'https://example.com/root',
|
|
1337
|
+
components: {
|
|
1338
|
+
schemas: {
|
|
1339
|
+
User: {
|
|
1340
|
+
$id: `${url}/schema`,
|
|
1341
|
+
type: 'object',
|
|
1342
|
+
properties: {
|
|
1343
|
+
name: { type: 'string' },
|
|
1344
|
+
},
|
|
1345
|
+
},
|
|
1346
|
+
},
|
|
1347
|
+
},
|
|
1348
|
+
paths: {
|
|
1349
|
+
'/users': {
|
|
1350
|
+
get: {
|
|
1351
|
+
responses: {
|
|
1352
|
+
'200': {
|
|
1353
|
+
description: 'Success',
|
|
1354
|
+
content: {
|
|
1355
|
+
'application/json': {
|
|
1356
|
+
schema: {
|
|
1357
|
+
$ref: `${url}/schema`,
|
|
1358
|
+
},
|
|
1359
|
+
},
|
|
1360
|
+
},
|
|
1361
|
+
},
|
|
1362
|
+
},
|
|
1363
|
+
},
|
|
1364
|
+
},
|
|
1365
|
+
},
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
await bundle(input, {
|
|
1369
|
+
plugins: [fetchUrls(), readFiles()],
|
|
1370
|
+
treeShake: false,
|
|
1371
|
+
})
|
|
1372
|
+
|
|
1373
|
+
// The $ref should remain unchanged because the schema is already defined locally with $id
|
|
1374
|
+
expect(input.paths['/users'].get.responses['200'].content['application/json'].schema.$ref).toBe(`${url}/schema`)
|
|
1375
|
+
|
|
1376
|
+
// The external schema should not be bundled into x-ext
|
|
1377
|
+
expect(input['x-ext']).toBeUndefined()
|
|
1378
|
+
|
|
1379
|
+
// The local schema with $id should remain unchanged
|
|
1380
|
+
expect(input.components.schemas.User).toEqual({
|
|
1381
|
+
$id: `${url}/schema`,
|
|
1382
|
+
type: 'object',
|
|
1383
|
+
properties: {
|
|
1384
|
+
name: { type: 'string' },
|
|
1385
|
+
},
|
|
1386
|
+
})
|
|
1387
|
+
})
|
|
1388
|
+
|
|
1389
|
+
it('does not modify external URLs when already defined by $anchor property', async () => {
|
|
1390
|
+
const input = {
|
|
1391
|
+
$id: 'https://example.com/root',
|
|
1392
|
+
components: {
|
|
1393
|
+
schemas: {
|
|
1394
|
+
User: {
|
|
1395
|
+
$anchor: 'user-schema',
|
|
1396
|
+
type: 'object',
|
|
1397
|
+
properties: {
|
|
1398
|
+
name: { type: 'string' },
|
|
1399
|
+
},
|
|
1400
|
+
},
|
|
1401
|
+
},
|
|
1402
|
+
},
|
|
1403
|
+
paths: {
|
|
1404
|
+
'/users': {
|
|
1405
|
+
get: {
|
|
1406
|
+
responses: {
|
|
1407
|
+
'200': {
|
|
1408
|
+
description: 'Success',
|
|
1409
|
+
content: {
|
|
1410
|
+
'application/json': {
|
|
1411
|
+
schema: {
|
|
1412
|
+
$ref: 'https://example.com/root/schema#user-schema',
|
|
1413
|
+
},
|
|
1414
|
+
},
|
|
1415
|
+
},
|
|
1416
|
+
},
|
|
1417
|
+
},
|
|
1418
|
+
},
|
|
1419
|
+
},
|
|
1420
|
+
},
|
|
1421
|
+
}
|
|
1422
|
+
|
|
1423
|
+
await bundle(input, {
|
|
1424
|
+
plugins: [fetchUrls(), readFiles()],
|
|
1425
|
+
treeShake: false,
|
|
1426
|
+
})
|
|
1427
|
+
|
|
1428
|
+
// The $ref should remain unchanged because the schema is already defined locally with $anchor
|
|
1429
|
+
expect(input.paths['/users'].get.responses['200'].content['application/json'].schema.$ref).toBe(
|
|
1430
|
+
'https://example.com/root/schema#user-schema',
|
|
1431
|
+
)
|
|
1432
|
+
|
|
1433
|
+
// The external schema should not be bundled into x-ext
|
|
1434
|
+
expect(input['x-ext']).toBeUndefined()
|
|
1435
|
+
|
|
1436
|
+
// The local schema with $anchor should remain unchanged
|
|
1437
|
+
expect(input.components.schemas.User).toEqual({
|
|
1438
|
+
$anchor: 'user-schema',
|
|
1439
|
+
type: 'object',
|
|
1440
|
+
properties: {
|
|
1441
|
+
name: { type: 'string' },
|
|
1442
|
+
},
|
|
1443
|
+
})
|
|
1444
|
+
})
|
|
1445
|
+
|
|
1446
|
+
it('does not modify external URLs when prefix is already defined by $id', async () => {
|
|
1447
|
+
const url = `http://localhost:${port}`
|
|
1448
|
+
|
|
1449
|
+
const input = {
|
|
1450
|
+
$id: `${url}/schema`,
|
|
1451
|
+
components: {
|
|
1452
|
+
schemas: {
|
|
1453
|
+
User: {
|
|
1454
|
+
type: 'object',
|
|
1455
|
+
properties: {
|
|
1456
|
+
name: { type: 'string' },
|
|
1457
|
+
},
|
|
1458
|
+
},
|
|
1459
|
+
},
|
|
1460
|
+
},
|
|
1461
|
+
paths: {
|
|
1462
|
+
'/users': {
|
|
1463
|
+
get: {
|
|
1464
|
+
responses: {
|
|
1465
|
+
'200': {
|
|
1466
|
+
description: 'Success',
|
|
1467
|
+
content: {
|
|
1468
|
+
'application/json': {
|
|
1469
|
+
schema: {
|
|
1470
|
+
$ref: `${url}/schema#/components/schemas/User`,
|
|
1471
|
+
},
|
|
1472
|
+
},
|
|
1473
|
+
},
|
|
1474
|
+
},
|
|
1475
|
+
},
|
|
1476
|
+
},
|
|
1477
|
+
},
|
|
1478
|
+
},
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
await bundle(input, {
|
|
1482
|
+
plugins: [fetchUrls(), readFiles()],
|
|
1483
|
+
treeShake: false,
|
|
1484
|
+
})
|
|
1485
|
+
|
|
1486
|
+
// The $ref should remain unchanged because the prefix is already defined locally with $id
|
|
1487
|
+
expect(input.paths['/users'].get.responses['200'].content['application/json'].schema.$ref).toBe(
|
|
1488
|
+
`${url}/schema#/components/schemas/User`,
|
|
1489
|
+
)
|
|
1490
|
+
|
|
1491
|
+
// The external schema should not be bundled into x-ext
|
|
1492
|
+
expect(input['x-ext']).toBeUndefined()
|
|
1493
|
+
|
|
1494
|
+
// The local schema should remain unchanged
|
|
1495
|
+
expect(input.components.schemas.User).toEqual({
|
|
1496
|
+
type: 'object',
|
|
1497
|
+
properties: {
|
|
1498
|
+
name: { type: 'string' },
|
|
1499
|
+
},
|
|
1500
|
+
})
|
|
1501
|
+
})
|
|
1502
|
+
|
|
1503
|
+
it('prioritizes $id when resolving refs', async () => {
|
|
1504
|
+
const input = {
|
|
1505
|
+
$id: 'https://example.com/root',
|
|
1506
|
+
a: {
|
|
1507
|
+
b: {
|
|
1508
|
+
c: {
|
|
1509
|
+
$ref: '/b',
|
|
1510
|
+
},
|
|
1511
|
+
},
|
|
1512
|
+
},
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
const fn = vi.fn()
|
|
1516
|
+
|
|
1517
|
+
await bundle(input, {
|
|
1518
|
+
treeShake: false,
|
|
1519
|
+
plugins: [
|
|
1520
|
+
{
|
|
1521
|
+
type: 'loader',
|
|
1522
|
+
validate: () => true,
|
|
1523
|
+
exec: async (value) => {
|
|
1524
|
+
fn(value)
|
|
1525
|
+
return {
|
|
1526
|
+
ok: true,
|
|
1527
|
+
data: {
|
|
1528
|
+
message: 'resolved value',
|
|
1529
|
+
},
|
|
1530
|
+
}
|
|
1531
|
+
},
|
|
1532
|
+
},
|
|
1533
|
+
],
|
|
1534
|
+
})
|
|
1535
|
+
|
|
1536
|
+
expect(input).toEqual({
|
|
1537
|
+
'$id': 'https://example.com/root',
|
|
1538
|
+
'a': {
|
|
1539
|
+
'b': {
|
|
1540
|
+
'c': {
|
|
1541
|
+
'$ref': '#/x-ext/69a42cc',
|
|
1542
|
+
},
|
|
1543
|
+
},
|
|
1544
|
+
},
|
|
1545
|
+
'x-ext': {
|
|
1546
|
+
'69a42cc': {
|
|
1547
|
+
'message': 'resolved value',
|
|
1548
|
+
},
|
|
1549
|
+
},
|
|
1550
|
+
})
|
|
1551
|
+
|
|
1552
|
+
expect(fn).toHaveBeenCalled()
|
|
1553
|
+
expect(fn).toHaveBeenCalledWith('https://example.com/b')
|
|
1554
|
+
})
|
|
1555
|
+
|
|
1556
|
+
it('prioritizes $id when resolving refs with origin #1', async () => {
|
|
1557
|
+
const url = `http://localhost:${port}`
|
|
1558
|
+
|
|
1559
|
+
const input = {
|
|
1560
|
+
$id: '/root',
|
|
1561
|
+
a: {
|
|
1562
|
+
b: {
|
|
1563
|
+
c: {
|
|
1564
|
+
$ref: '/b',
|
|
1565
|
+
},
|
|
1566
|
+
},
|
|
1567
|
+
},
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
const fn = vi.fn()
|
|
1571
|
+
|
|
1572
|
+
await bundle(input, {
|
|
1573
|
+
treeShake: false,
|
|
1574
|
+
origin: url,
|
|
1575
|
+
plugins: [
|
|
1576
|
+
{
|
|
1577
|
+
type: 'loader',
|
|
1578
|
+
validate: () => true,
|
|
1579
|
+
exec: async (value) => {
|
|
1580
|
+
fn(value)
|
|
1581
|
+
return {
|
|
1582
|
+
ok: true,
|
|
1583
|
+
data: {
|
|
1584
|
+
message: 'resolved value',
|
|
1585
|
+
},
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
},
|
|
1589
|
+
],
|
|
1590
|
+
})
|
|
1591
|
+
|
|
1592
|
+
expect(input).toEqual({
|
|
1593
|
+
'$id': '/root',
|
|
1594
|
+
'a': {
|
|
1595
|
+
'b': {
|
|
1596
|
+
'c': {
|
|
1597
|
+
'$ref': '#/x-ext/25c8e1f',
|
|
1598
|
+
},
|
|
1599
|
+
},
|
|
1600
|
+
},
|
|
1601
|
+
'x-ext': {
|
|
1602
|
+
'25c8e1f': {
|
|
1603
|
+
'message': 'resolved value',
|
|
1604
|
+
},
|
|
1605
|
+
},
|
|
1606
|
+
})
|
|
1607
|
+
|
|
1608
|
+
expect(fn).toHaveBeenCalled()
|
|
1609
|
+
expect(fn).toHaveBeenCalledWith('/b')
|
|
1610
|
+
})
|
|
1611
|
+
|
|
1612
|
+
it('prioritizes $id when resolving refs with origin #2', async () => {
|
|
1613
|
+
const url = `http://localhost:${port}`
|
|
1614
|
+
|
|
1615
|
+
const input = {
|
|
1616
|
+
$id: 'http://example.com/root',
|
|
1617
|
+
a: {
|
|
1618
|
+
b: {
|
|
1619
|
+
c: {
|
|
1620
|
+
$ref: '/b',
|
|
1621
|
+
},
|
|
1622
|
+
},
|
|
1623
|
+
},
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
const fn = vi.fn()
|
|
1627
|
+
|
|
1628
|
+
await bundle(url, {
|
|
1629
|
+
treeShake: false,
|
|
1630
|
+
origin: url,
|
|
1631
|
+
plugins: [
|
|
1632
|
+
{
|
|
1633
|
+
type: 'loader',
|
|
1634
|
+
validate: () => true,
|
|
1635
|
+
exec: async (value) => {
|
|
1636
|
+
fn(value)
|
|
1637
|
+
|
|
1638
|
+
if (value === url) {
|
|
1639
|
+
return {
|
|
1640
|
+
ok: true,
|
|
1641
|
+
data: input,
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1645
|
+
return {
|
|
1646
|
+
ok: true,
|
|
1647
|
+
data: {
|
|
1648
|
+
message: 'resolved value',
|
|
1649
|
+
},
|
|
1650
|
+
}
|
|
1651
|
+
},
|
|
1652
|
+
},
|
|
1653
|
+
],
|
|
1654
|
+
})
|
|
1655
|
+
|
|
1656
|
+
expect(input).toEqual({
|
|
1657
|
+
'$id': 'http://example.com/root',
|
|
1658
|
+
'a': {
|
|
1659
|
+
'b': {
|
|
1660
|
+
'c': {
|
|
1661
|
+
'$ref': '#/x-ext/943da6f',
|
|
1662
|
+
},
|
|
1663
|
+
},
|
|
1664
|
+
},
|
|
1665
|
+
'x-ext': {
|
|
1666
|
+
'943da6f': {
|
|
1667
|
+
'message': 'resolved value',
|
|
1668
|
+
},
|
|
1669
|
+
},
|
|
1670
|
+
})
|
|
1671
|
+
|
|
1672
|
+
expect(fn).toHaveBeenCalledTimes(2)
|
|
1673
|
+
expect(fn.mock.calls[0][0]).toBe(url)
|
|
1674
|
+
expect(fn.mock.calls[1][0]).toBe('http://example.com/b')
|
|
1675
|
+
})
|
|
1676
|
+
|
|
1677
|
+
it('correctly bundles when doing a partial bundle with $anchor on a different context', async () => {
|
|
1678
|
+
const input = {
|
|
1679
|
+
a: {
|
|
1680
|
+
b: {
|
|
1681
|
+
c: {
|
|
1682
|
+
$ref: '#/e/f',
|
|
1683
|
+
},
|
|
1684
|
+
},
|
|
1685
|
+
},
|
|
1686
|
+
e: {
|
|
1687
|
+
$id: 'https://example.com/e',
|
|
1688
|
+
$anchor: 'my-anchor',
|
|
1689
|
+
f: {
|
|
1690
|
+
$ref: '#my-anchor',
|
|
1691
|
+
},
|
|
1692
|
+
g: {
|
|
1693
|
+
$ref: 'http://example.com',
|
|
1694
|
+
},
|
|
1695
|
+
},
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
const fn = vi.fn()
|
|
1699
|
+
|
|
1700
|
+
await bundle(input.a, {
|
|
1701
|
+
treeShake: false,
|
|
1702
|
+
plugins: [
|
|
1703
|
+
{
|
|
1704
|
+
type: 'loader',
|
|
1705
|
+
validate: () => true,
|
|
1706
|
+
exec: async (value) => {
|
|
1707
|
+
fn(value)
|
|
1708
|
+
if (value === 'http://example.com') {
|
|
1709
|
+
return {
|
|
1710
|
+
ok: true,
|
|
1711
|
+
data: {
|
|
1712
|
+
message: 'resolved value',
|
|
1713
|
+
},
|
|
1714
|
+
}
|
|
1715
|
+
}
|
|
1716
|
+
return { ok: false }
|
|
1717
|
+
},
|
|
1718
|
+
},
|
|
1719
|
+
],
|
|
1720
|
+
root: input,
|
|
1721
|
+
urlMap: true,
|
|
1722
|
+
cache: new Map(),
|
|
1723
|
+
})
|
|
1724
|
+
|
|
1725
|
+
expect(input).toEqual({
|
|
1726
|
+
'a': {
|
|
1727
|
+
'b': {
|
|
1728
|
+
'c': {
|
|
1729
|
+
'$ref': '#/e/f',
|
|
1730
|
+
},
|
|
1731
|
+
},
|
|
1732
|
+
},
|
|
1733
|
+
'e': {
|
|
1734
|
+
'$anchor': 'my-anchor',
|
|
1735
|
+
'$id': 'https://example.com/e',
|
|
1736
|
+
'f': {
|
|
1737
|
+
'$ref': '#my-anchor',
|
|
1738
|
+
},
|
|
1739
|
+
'g': {
|
|
1740
|
+
'$ref': '#/x-ext/89dce6a',
|
|
1741
|
+
},
|
|
1742
|
+
},
|
|
1743
|
+
'x-ext': {
|
|
1744
|
+
'89dce6a': {
|
|
1745
|
+
'message': 'resolved value',
|
|
1746
|
+
},
|
|
1747
|
+
},
|
|
1748
|
+
'x-ext-urls': {
|
|
1749
|
+
'89dce6a': 'http://example.com',
|
|
1750
|
+
},
|
|
1751
|
+
})
|
|
1752
|
+
})
|
|
1753
|
+
|
|
1754
|
+
it('treats internal root pointers as internal references', async () => {
|
|
1755
|
+
resetConsoleSpies()
|
|
1756
|
+
|
|
1757
|
+
const input = {
|
|
1758
|
+
a: {
|
|
1759
|
+
$ref: '#/',
|
|
1760
|
+
},
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
await bundle(input, { plugins: [fetchUrls()], treeShake: false })
|
|
1764
|
+
|
|
1765
|
+
expect(input).toEqual({
|
|
1766
|
+
a: {
|
|
1767
|
+
$ref: '#/',
|
|
1768
|
+
},
|
|
1769
|
+
})
|
|
1770
|
+
|
|
1771
|
+
expect(consoleWarnSpy).toHaveBeenCalledTimes(0)
|
|
1772
|
+
})
|
|
1328
1773
|
})
|
|
1329
1774
|
|
|
1330
1775
|
describe('local files', () => {
|
|
@@ -1405,7 +1850,9 @@ describe('bundle', () => {
|
|
|
1405
1850
|
}
|
|
1406
1851
|
const bName = randomUUID()
|
|
1407
1852
|
|
|
1408
|
-
await fs.mkdir('./nested')
|
|
1853
|
+
await fs.mkdir('./nested').catch(() => {
|
|
1854
|
+
return
|
|
1855
|
+
})
|
|
1409
1856
|
await fs.writeFile(`./nested/${bName}`, JSON.stringify(b))
|
|
1410
1857
|
await fs.writeFile(`./nested/${cName}`, JSON.stringify(c))
|
|
1411
1858
|
|
|
@@ -1449,7 +1896,9 @@ describe('bundle', () => {
|
|
|
1449
1896
|
}
|
|
1450
1897
|
const bName = randomUUID()
|
|
1451
1898
|
|
|
1452
|
-
await fs.mkdir('./nested')
|
|
1899
|
+
await fs.mkdir('./nested').catch(() => {
|
|
1900
|
+
return
|
|
1901
|
+
})
|
|
1453
1902
|
await fs.writeFile(`./nested/${bName}`, JSON.stringify(b))
|
|
1454
1903
|
await fs.writeFile(`./nested/${cName}`, JSON.stringify(c))
|
|
1455
1904
|
|
|
@@ -2333,17 +2782,6 @@ describe('isLocalRef', () => {
|
|
|
2333
2782
|
})
|
|
2334
2783
|
})
|
|
2335
2784
|
|
|
2336
|
-
describe('getNestedValue', () => {
|
|
2337
|
-
it.each([
|
|
2338
|
-
[{ a: { b: { c: 'hello' } } }, ['a', 'b', 'c'], 'hello'],
|
|
2339
|
-
[{ a: { b: { c: 'hello' } } }, [], { a: { b: { c: 'hello' } } }],
|
|
2340
|
-
[{ foo: { bar: { baz: 42 } } }, ['foo', 'bar', 'baz'], 42],
|
|
2341
|
-
[{ foo: { bar: { baz: 42 } } }, ['foo', 'non-existing', 'baz'], undefined],
|
|
2342
|
-
])('gets nested value', (a, b, c) => {
|
|
2343
|
-
expect(getNestedValue(a, b)).toEqual(c)
|
|
2344
|
-
})
|
|
2345
|
-
})
|
|
2346
|
-
|
|
2347
2785
|
describe('prefixInternalRef', () => {
|
|
2348
2786
|
it.each([
|
|
2349
2787
|
['#/hello', ['prefix'], '#/prefix/hello'],
|
|
@@ -2385,3 +2823,73 @@ describe('setValueAtPath', () => {
|
|
|
2385
2823
|
expect(a).toEqual(d)
|
|
2386
2824
|
})
|
|
2387
2825
|
})
|
|
2826
|
+
|
|
2827
|
+
describe('resolveAndCopyReferences', () => {
|
|
2828
|
+
const source = {
|
|
2829
|
+
openapi: '3.1.1',
|
|
2830
|
+
info: {
|
|
2831
|
+
title: 'Example API',
|
|
2832
|
+
version: '1.0.0',
|
|
2833
|
+
},
|
|
2834
|
+
paths: {
|
|
2835
|
+
'/': {
|
|
2836
|
+
get: {
|
|
2837
|
+
responses: {
|
|
2838
|
+
'200': {
|
|
2839
|
+
content: {
|
|
2840
|
+
'application/json': {
|
|
2841
|
+
schema: {
|
|
2842
|
+
$ref: '#/components/schemas/User',
|
|
2843
|
+
},
|
|
2844
|
+
},
|
|
2845
|
+
},
|
|
2846
|
+
},
|
|
2847
|
+
},
|
|
2848
|
+
},
|
|
2849
|
+
},
|
|
2850
|
+
},
|
|
2851
|
+
components: {
|
|
2852
|
+
schemas: {
|
|
2853
|
+
User: {
|
|
2854
|
+
type: 'object',
|
|
2855
|
+
properties: {
|
|
2856
|
+
name: { type: 'string' },
|
|
2857
|
+
},
|
|
2858
|
+
},
|
|
2859
|
+
Person: {
|
|
2860
|
+
type: 'object',
|
|
2861
|
+
properties: {
|
|
2862
|
+
name: { type: 'string', default: 'John Doe' },
|
|
2863
|
+
},
|
|
2864
|
+
},
|
|
2865
|
+
},
|
|
2866
|
+
},
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2869
|
+
it('correctly resolves and copies local references, and leaves out the rest', async () => {
|
|
2870
|
+
const target = {}
|
|
2871
|
+
|
|
2872
|
+
resolveAndCopyReferences(target, source, '/paths/~1', '', '', true)
|
|
2873
|
+
|
|
2874
|
+
expect(target).toEqual({
|
|
2875
|
+
paths: {
|
|
2876
|
+
'/': {
|
|
2877
|
+
get: {
|
|
2878
|
+
responses: {
|
|
2879
|
+
'200': {
|
|
2880
|
+
content: {
|
|
2881
|
+
'application/json': { schema: { '$ref': '#/components/schemas/User' } },
|
|
2882
|
+
},
|
|
2883
|
+
},
|
|
2884
|
+
},
|
|
2885
|
+
},
|
|
2886
|
+
},
|
|
2887
|
+
},
|
|
2888
|
+
components: {
|
|
2889
|
+
schemas: {
|
|
2890
|
+
User: { type: 'object', properties: { name: { type: 'string' } } },
|
|
2891
|
+
},
|
|
2892
|
+
},
|
|
2893
|
+
})
|
|
2894
|
+
})
|
|
2895
|
+
})
|