Skip to content

Commit

Permalink
feat!: allow async $resolve (#50)
Browse files Browse the repository at this point in the history
Breaking change: `resolveSchema` and `applyDefaults` returns a Promise now.

Breaking change: `get` function passed to `$resolve` also returns a Promise.
  • Loading branch information
pi0 authored Sep 12, 2022
1 parent 40a4035 commit bf5fb1c
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 46 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ const defaultPlanet = {
```js
import { resolveSchema } from 'untyped'

const schema = resolveSchema(defaultPlanet)
const schema = await resolveSchema(defaultPlanet)
```

Output:
Expand Down Expand Up @@ -92,7 +92,7 @@ Output:
```js
import { resolveSchema, generateTypes } from 'untyped'

const types = generateTypes(resolveSchema(defaultPlanet))
const types = generateTypes(await resolveSchema(defaultPlanet))
```

Output:
Expand Down Expand Up @@ -120,7 +120,7 @@ interface Untyped {
```js
import { resolveSchema, generateMarkdown } from 'untyped'

const markdown = generateMarkdown(resolveSchema(defaultPlanet))
const markdown = generateMarkdown(await resolveSchema(defaultPlanet))
```

Output:
Expand Down
16 changes: 8 additions & 8 deletions src/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ interface _ResolveCtx {
resolveCache: Record<string, Schema>
}

export function resolveSchema (obj: InputObject, defaults?: InputObject) {
const schema = _resolveSchema(obj, '', {
export async function resolveSchema (obj: InputObject, defaults?: InputObject) {
const schema = await _resolveSchema(obj, '', {
root: obj,
defaults,
resolveCache: {}
Expand All @@ -18,7 +18,7 @@ export function resolveSchema (obj: InputObject, defaults?: InputObject) {
return schema
}

function _resolveSchema (input: InputValue, id: string, ctx: _ResolveCtx): Schema {
async function _resolveSchema (input: InputValue, id: string, ctx: _ResolveCtx): Promise<Schema> {
// Check cache
if (id in ctx.resolveCache) {
return ctx.resolveCache[id]
Expand Down Expand Up @@ -55,7 +55,7 @@ function _resolveSchema (input: InputValue, id: string, ctx: _ResolveCtx): Schem
}
schema.properties = schema.properties || {}
if (!schema.properties[key]) {
schema.properties[key] = _resolveSchema(node[key], joinPath(id, key), ctx)
schema.properties[key] = await _resolveSchema(node[key], joinPath(id, key), ctx)
}
}

Expand All @@ -67,8 +67,8 @@ function _resolveSchema (input: InputValue, id: string, ctx: _ResolveCtx): Schem
schema.default = node.$default
}
if (typeof node.$resolve === 'function') {
schema.default = node.$resolve(schema.default, (key) => {
return _resolveSchema(getValue(ctx.root, key), key, ctx).default
schema.default = await node.$resolve(schema.default, async (key) => {
return (await _resolveSchema(getValue(ctx.root, key), key, ctx)).default
})
}
if (ctx.defaults) {
Expand All @@ -87,8 +87,8 @@ function _resolveSchema (input: InputValue, id: string, ctx: _ResolveCtx): Schem
return schema
}

export function applyDefaults (ref: InputObject, input: InputObject) {
resolveSchema(ref, input)
export async function applyDefaults (ref: InputObject, input: InputObject) {
await resolveSchema(ref, input)
return input
}

Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export type JSType =
'array'

// eslint-disable-next-line no-use-before-define
export type ResolveFn = ((value: any, get: (key: string) => any) => JSValue)
export type ResolveFn = ((value: any, get: (key: string) => any) => JSValue | Promise<JSValue>)

export interface TypeDescriptor {
/** Used internally to handle schema types */
Expand Down
4 changes: 2 additions & 2 deletions test/defaults.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { describe, it, expect } from 'vitest'
import { applyDefaults } from '../src'

describe('applyDefaults', () => {
it('basic', () => {
it('basic', async () => {
const ref = {
name: 'default',
empty: {},
Expand All @@ -20,7 +20,7 @@ describe('applyDefaults', () => {
}
}

const applied = applyDefaults(ref, input)
const applied = await applyDefaults(ref, input)

expect(applied).toMatchObject({
name: 'custom',
Expand Down
36 changes: 18 additions & 18 deletions test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { describe, it, expect } from 'vitest'
import { resolveSchema } from '../src'

describe('resolveSchema', () => {
it('direct value', () => {
const schema = resolveSchema({
it('direct value', async () => {
const schema = await resolveSchema({
foo: 'bar',
empty: {}
})
Expand All @@ -22,8 +22,8 @@ describe('resolveSchema', () => {
})
})

it('nested value', () => {
const schema = resolveSchema({
it('nested value', async () => {
const schema = await resolveSchema({
foo: { bar: 123 }
})
expect(schema).toMatchObject({
Expand All @@ -41,8 +41,8 @@ describe('resolveSchema', () => {
})
})

it('with $default', () => {
const schema = resolveSchema({
it('with $default', async () => {
const schema = await resolveSchema({
foo: { $default: 'bar' }
})
expect(schema).toMatchObject({
Expand All @@ -55,8 +55,8 @@ describe('resolveSchema', () => {
})
})

it('with $schema', () => {
const schema = resolveSchema({
it('with $schema', async () => {
const schema = await resolveSchema({
foo: { $schema: { title: 'this is foo' } }
})
expect(schema).toMatchObject({
Expand All @@ -68,8 +68,8 @@ describe('resolveSchema', () => {
})
})

it('with $resolve', () => {
const schema = resolveSchema({
it('with $resolve', async () => {
const schema = await resolveSchema({
foo: { $default: '123', $resolve: val => parseInt(val) }
})
expect(schema).toMatchObject({
Expand All @@ -82,10 +82,10 @@ describe('resolveSchema', () => {
})
})

it('with $resolve (dependency order-1)', () => {
const schema = resolveSchema({
it('with $resolve (dependency order-1)', async () => {
const schema = await resolveSchema({
foo: { $resolve: () => 'foo' },
bar: { $resolve: (val, get) => get('foo') + (val || 'bar') }
bar: { $resolve: async (val, get) => await get('foo') + (val || 'bar') }
})
expect(schema).toMatchObject({
properties: {
Expand All @@ -96,10 +96,10 @@ describe('resolveSchema', () => {
})
})

it('with $resolve (dependency order-2)', () => {
const schema = resolveSchema({
it('with $resolve (dependency order-2)', async () => {
const schema = await resolveSchema({
nested: {
foo: { $resolve: (val, get) => get('rootDir') + (val || 'bar') }
foo: { $resolve: async (val, get) => await get('rootDir') + (val || 'bar') }
},
rootDir: { $resolve: () => 'root/' }
})
Expand All @@ -121,8 +121,8 @@ describe('resolveSchema', () => {
})
})

it('array', () => {
const schema = resolveSchema({
it('array', async () => {
const schema = await resolveSchema({
empty: [],
numbers: [1, 2, 3],
mixed: [true, 123],
Expand Down
24 changes: 12 additions & 12 deletions test/types.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { describe, it, expect } from 'vitest'
import { resolveSchema, generateTypes } from '../src'

describe('resolveSchema', () => {
it('basic', () => {
const types = generateTypes(resolveSchema({
it('basic', async () => {
const types = generateTypes(await resolveSchema({
test: {
foo: {
$default: 'test value',
Expand All @@ -27,8 +27,8 @@ describe('resolveSchema', () => {
}"
`)
})
it('withOptions', () => {
const types = generateTypes(resolveSchema({
it('withOptions', async () => {
const types = generateTypes(await resolveSchema({
test: {
a: 123,
foo: { bar: 123, baz: { x: 123 } }
Expand All @@ -51,8 +51,8 @@ describe('resolveSchema', () => {
`)
})

it('array', () => {
const types = generateTypes(resolveSchema({
it('array', async () => {
const types = generateTypes(await resolveSchema({
empty: [],
numbers: [1, 2, 3],
mixed: [true, 123]
Expand All @@ -71,15 +71,15 @@ describe('resolveSchema', () => {
`)
})

it('escapeKey', () => {
const types = generateTypes(resolveSchema({
it('escapeKey', async () => {
const types = generateTypes(await resolveSchema({
'*key': '123'
}))
expect(types).toMatch('"*key": string')
})

it('functions', () => {
const types = generateTypes(resolveSchema({
it('functions', async () => {
const types = generateTypes(await resolveSchema({
add: {
$schema: {
type: 'function',
Expand All @@ -104,8 +104,8 @@ export interface Untyped {
`.trim())
})

it('extracts type imports to top-level', () => {
const types = generateTypes(resolveSchema({
it('extracts type imports to top-level', async () => {
const types = generateTypes(await resolveSchema({
test: {
foo: {
$schema: {
Expand Down
4 changes: 2 additions & 2 deletions web/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,12 @@ export default defineComponent({
const transpiledRef = safeComputed(() => loader.transform(state.ref))
const referenceObj = safeComputed(() => evaluateSource(transpiledRef.value))
const schema = safeComputed(() => resolveSchema(referenceObj.value))
const schema = safeComputed(async () => await resolveSchema(referenceObj.value))
const types = safeComputed(() => generateTypes(schema.value))
const markdown = safeComputed(() => generateMarkdown(schema.value))
const inputObj = safeComputed(() => evaluateSource(state.input))
const resolvedInput = safeComputed(() => applyDefaults(referenceObj.value, inputObj.value))
const resolvedInput = safeComputed(async () => await applyDefaults(referenceObj.value, inputObj.value))
return {
state,
Expand Down

0 comments on commit bf5fb1c

Please sign in to comment.