Skip to content

Commit

Permalink
feat: resolve dependencies without order
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 committed Mar 21, 2021
1 parent 82c987a commit f04e49f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 13 deletions.
21 changes: 14 additions & 7 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@ import { getType, isObject, unique } from './utils'
import type { InputObject, InputValue, JSValue, Schema } from './types'

export function resolveSchema (obj: InputObject) {
const schema = _resolveSchema(obj, obj, obj)
const schema = _resolveSchema(obj, obj)
// TODO: Create meta-schema fror superset of Schema interface
// schema.$schema = 'http://json-schema.org/schema#'
return schema
}

function _resolveSchema (input: InputValue, parent: InputObject, root: InputObject): Schema {
function _resolveSchema (input: InputValue, parent: InputObject, root?: InputObject): Schema {
// Node is plain value
if (!isObject(input)) {
return normalizeSchema({
Expand All @@ -22,23 +22,30 @@ function _resolveSchema (input: InputValue, parent: InputObject, root: InputObje
const schema: Schema = { ...node.$schema }

// Resolve children
let proxifiedNode = node
const getSchema = (key) => {
schema.properties = schema.properties || {}
if (!schema.properties[key]) {
schema.properties[key] = _resolveSchema(node[key], proxifiedNode, root || proxifiedNode)
}
return schema.properties[key]
}
proxifiedNode = new Proxy(node, { get: (_, key) => getSchema(key).default, set: () => false })

for (const key in node) {
// Ignore special keys
if (key === '$resolve' || key === '$schema' || key === '$default') {
continue
}
const resolved = _resolveSchema(node[key], node, root)
schema.properties = schema.properties || {}
schema.properties[key] = resolved
node[key] = resolved.default
getSchema(key)
}

// Infer default value from $resolve and $default
if ('$default' in node) {
schema.default = node.$default
}
if (typeof node.$resolve === 'function') {
schema.default = node.$resolve(schema.default, parent, root)
schema.default = node.$resolve(schema.default, parent, root || proxifiedNode)
}

// Infer type from default value
Expand Down
23 changes: 17 additions & 6 deletions test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ describe('resolveSchema', () => {
})
})

it('with $resolve (dependency)', () => {
it('with $resolve (dependency order-1)', () => {
const schema = resolveSchema({
foo: { $resolve: () => 'foo' },
bar: { $resolve: (val, parent) => parent.foo + (val || 'bar') }
Expand All @@ -90,15 +90,26 @@ describe('resolveSchema', () => {
})
})

it.skip('with $resolve (dependency)', () => {
it('with $resolve (dependency order-2)', () => {
const schema = resolveSchema({
bar: { $resolve: (val, parent) => parent.foo + (val || 'bar') },
foo: { $resolve: () => 'foo' }
nested: {
foo: { $resolve: (val, _parent, root) => root.rootDir + (val || 'bar') }
},
rootDir: { $resolve: () => 'root/' }
})
expect(schema).toMatchObject({
properties: {
bar: {
default: 'foobar'
rootDir: {
type: 'string',
default: 'root/'
},
nested: {
properties: {
foo: {
type: 'string',
default: 'root/bar'
}
}
}
}
})
Expand Down

0 comments on commit f04e49f

Please sign in to comment.