Skip to content

Commit db8b0cc

Browse files
committed
Add explorer to inspect information about the schema
1 parent 1a97669 commit db8b0cc

File tree

7 files changed

+85
-8
lines changed

7 files changed

+85
-8
lines changed

lib/explorer.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import pointer from 'json-pointer'
2+
3+
export class Explorer {
4+
constructor (schemas, baseURI) {
5+
this.schemas = schemas
6+
this.baseURI = baseURI
7+
}
8+
9+
// Get a ref from the schema
10+
get (ref, baseURI = this.baseURI) {
11+
const uri = new URL(ref, baseURI).href
12+
const [$id, path] = uri.split('#')
13+
const schema = this.schemas[$id]
14+
return this.proxy(path ? pointer.get(schema, path) : schema, uri)
15+
}
16+
17+
// Returns a proxy to the schema that resolves $refs
18+
proxy (schema, uri) {
19+
const self = this
20+
return new Proxy(schema, {
21+
get (target, property, receiver) {
22+
const value = target[property]
23+
24+
if (value !== null && typeof value === 'object') {
25+
// Schema returns an object for this property, proxy it as well
26+
return new Proxy(value, this)
27+
} else if (value !== undefined) {
28+
// Schema returns a value for this property, return it
29+
return value
30+
} else if (target.$ref) {
31+
// Schema includes a ref, so delegate to it
32+
return self.get(target.$ref, uri)[property]
33+
}
34+
}
35+
})
36+
}
37+
38+
// Returns a list of the functions defined in the schema
39+
get functions () {
40+
return this.get('#/definitions/function/properties')
41+
}
42+
}

lib/index.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1-
export { default as schemas } from '../schemas'
2-
export { default as validate } from './validate'
1+
import schemas, { BaseURI } from '../schemas'
2+
import { Explorer } from './explorer'
3+
4+
export const explorer = new Explorer(schemas, BaseURI)
5+
export { schemas }
36
export { default as examples } from '../examples'
7+
export { default as validate } from './validate'

lib/validate.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Ajv from 'ajv'
22
import addFormats from 'ajv-formats'
3-
import schemas from '../schemas'
3+
import schemas, { BaseURI } from '../schemas'
44

55
const ajv = new Ajv({
66
schemas: Object.values(schemas),
@@ -9,7 +9,7 @@ const ajv = new Ajv({
99
strict: true
1010
})
1111
addFormats(ajv)
12-
const validator = ajv.getSchema(schemas.default.$id)
12+
const validator = ajv.getSchema(BaseURI)
1313

1414
function coerceArgsToArray (object) {
1515
if (object && typeof object === 'object') {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"license": "MIT",
2121
"dependencies": {
2222
"ajv": "^8.12.0",
23-
"ajv-formats": "^2.1.1"
23+
"ajv-formats": "^2.1.1",
24+
"json-pointer": "^0.6.2"
2425
},
2526
"devDependencies": {
2627
"standard": "^17.0.0",

schemas/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const modules = import.meta.glob('./*.json', { eager: true, import: 'default' })
2-
const schemas = Object.fromEntries(Object.entries(modules).map(([path, module]) => {
3-
const name = path.split('/').pop().split('.').shift()
4-
return [name === 'schema' ? 'default' : name, module]
2+
const schemas = Object.fromEntries(Object.values(modules).map(module => {
3+
return [module.$id, module]
54
}))
65

6+
export const BaseURI = modules['./schema.json'].$id
77
export default schemas

test/explorer.test.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { describe, test, expect } from 'vitest'
2+
import { explorer } from '../lib'
3+
4+
describe('explorer', () => {
5+
test('resolves refs', () => {
6+
const schema = explorer.get('#')
7+
expect(schema.anyOf).not.toBeUndefined()
8+
})
9+
10+
describe('functions', () => {
11+
test('returns all functions with their schemas', () => {
12+
expect(Object.keys(explorer.functions)).toEqual(expect.arrayContaining([
13+
'All', 'Any', 'Boolean', 'Time'
14+
]))
15+
expect(explorer.functions.All.title).toEqual('All')
16+
})
17+
})
18+
})

yarn.lock

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,11 @@ for-each@^0.3.3:
916916
dependencies:
917917
is-callable "^1.1.3"
918918

919+
foreach@^2.0.4:
920+
version "2.0.6"
921+
resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.6.tgz#87bcc8a1a0e74000ff2bf9802110708cfb02eb6e"
922+
integrity sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==
923+
919924
fs.realpath@^1.0.0:
920925
version "1.0.0"
921926
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -1260,6 +1265,13 @@ json-parse-better-errors@^1.0.1:
12601265
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
12611266
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
12621267

1268+
json-pointer@^0.6.2:
1269+
version "0.6.2"
1270+
resolved "https://registry.yarnpkg.com/json-pointer/-/json-pointer-0.6.2.tgz#f97bd7550be5e9ea901f8c9264c9d436a22a93cd"
1271+
integrity sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==
1272+
dependencies:
1273+
foreach "^2.0.4"
1274+
12631275
json-schema-traverse@^0.4.1:
12641276
version "0.4.1"
12651277
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"

0 commit comments

Comments
 (0)