diff --git a/src/generator.ts b/src/generator.ts index b4ef1931..9059538f 100644 --- a/src/generator.ts +++ b/src/generator.ts @@ -107,22 +107,19 @@ function declareNamedTypes(ast: AST, options: Options, rootASTName: string, proc } processed.add(ast) - let type = '' switch (ast.type) { case 'ARRAY': - type = [ + return [ declareNamedTypes(ast.params, options, rootASTName, processed), hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined ] .filter(Boolean) .join('\n') - break case 'ENUM': - type = '' - break + return '' case 'INTERFACE': - type = getSuperTypesAndParams(ast) + return getSuperTypesAndParams(ast) .map( ast => (ast.standaloneName === rootASTName || options.declareExternallyReferenced) && @@ -130,11 +127,10 @@ function declareNamedTypes(ast: AST, options: Options, rootASTName: string, proc ) .filter(Boolean) .join('\n') - break case 'INTERSECTION': case 'TUPLE': case 'UNION': - type = [ + return [ hasStandaloneName(ast) ? generateStandaloneType(ast, options) : undefined, ast.params .map(ast => declareNamedTypes(ast, options, rootASTName, processed)) @@ -146,14 +142,12 @@ function declareNamedTypes(ast: AST, options: Options, rootASTName: string, proc ] .filter(Boolean) .join('\n') - break default: if (hasStandaloneName(ast)) { - type = generateStandaloneType(ast, options) + return generateStandaloneType(ast, options) } + return '' } - - return type } function generateTypeUnmemoized(ast: AST, options: Options): string { diff --git a/src/index.ts b/src/index.ts index d8f68611..cc4cfbc7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -165,25 +165,13 @@ export async function compile(schema: JSONSchema4, name: string, options: Partia } const normalized = normalize(linked, name, _options) - if (process.env.VERBOSE) { - if (isDeepStrictEqual(linked, normalized)) { - log('yellow', 'normalizer', time(), '✅ No change') - } else { - log('yellow', 'normalizer', time(), '✅ Result:', normalized) - } - } + log('yellow', 'normalizer', time(), '✅ Result:', normalized) const parsed = parse(normalized, _options) log('blue', 'parser', time(), '✅ Result:', parsed) const optimized = optimize(parsed, _options) - if (process.env.VERBOSE) { - if (isDeepStrictEqual(parsed, optimized)) { - log('cyan', 'optimizer', time(), '✅ No change') - } else { - log('cyan', 'optimizer', time(), '✅ Result:', optimized) - } - } + log('cyan', 'optimizer', time(), '✅ Result:', optimized) const generated = generate(optimized, _options) log('magenta', 'generator', time(), '✅ Result:', generated) diff --git a/src/normalizer.ts b/src/normalizer.ts index 57b496e2..e74bef4b 100644 --- a/src/normalizer.ts +++ b/src/normalizer.ts @@ -1,5 +1,5 @@ import {JSONSchemaTypeName, LinkedJSONSchema, NormalizedJSONSchema, Parent} from './types/JSONSchema' -import {appendToDescription, escapeBlockComment, justName, toSafeString, traverse} from './utils' +import {appendToDescription, escapeBlockComment, isSchemaLike, justName, toSafeString, traverse} from './utils' import {Options} from './' type Rule = (schema: LinkedJSONSchema, fileName: string, options: Options) => void @@ -50,10 +50,25 @@ rules.set('Default additionalProperties', (schema, _, options) => { } }) -rules.set('Default top level `id`', (schema, fileName) => { +rules.set('Transform id to $id', (schema, fileName) => { + if (!isSchemaLike(schema)) { + return + } + if (schema.id && schema.$id && schema.id !== schema.$id) { + throw ReferenceError( + `Schema must define either id or $id, not both. Given id=${schema.id}, $id=${schema.$id} in ${fileName}` + ) + } + if (schema.id) { + schema.$id = schema.id + delete schema.id + } +}) + +rules.set('Default top level $id', (schema, fileName) => { const isRoot = schema[Parent] === null - if (isRoot && !schema.id) { - schema.id = toSafeString(justName(fileName)) + if (isRoot && !schema.$id) { + schema.$id = toSafeString(justName(fileName)) } }) diff --git a/src/parser.ts b/src/parser.ts index 6cb6cef3..55ffa037 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -51,9 +51,9 @@ export function parse( // so that it gets first pick for standalone name. const ast = parseAsTypeWithCache( { + $id: schema.$id, allOf: [], description: schema.description, - id: schema.id, title: schema.title }, 'ALL_OF', @@ -247,7 +247,7 @@ function parseNonLiteral( keyName, standaloneName: standaloneName(schema, keyNameFromDefinition, usedNames), params: (schema.type as JSONSchema4TypeName[]).map(type => { - const member: LinkedJSONSchema = {...omit(schema, 'description', 'id', 'title'), type} + const member: LinkedJSONSchema = {...omit(schema, '$id', 'description', 'title'), type} return parse(maybeStripDefault(member as any), options, undefined, processed, usedNames) }), type: 'UNION' @@ -300,7 +300,7 @@ function standaloneName( keyNameFromDefinition: string | undefined, usedNames: UsedNames ): string | undefined { - const name = schema.title || schema.id || keyNameFromDefinition + const name = schema.title || schema.$id || keyNameFromDefinition if (name) { return generateName(name, usedNames) } diff --git a/src/types/JSONSchema.ts b/src/types/JSONSchema.ts index d11d099f..da5f56d5 100644 --- a/src/types/JSONSchema.ts +++ b/src/types/JSONSchema.ts @@ -87,6 +87,9 @@ export interface NormalizedJSONSchema extends LinkedJSONSchema { oneOf?: NormalizedJSONSchema[] not?: NormalizedJSONSchema required: string[] + + // Removed by normalizer + id: never } export interface EnumJSONSchema extends NormalizedJSONSchema { @@ -114,15 +117,13 @@ export interface CustomTypeJSONSchema extends NormalizedJSONSchema { tsType: string } -export const getRootSchema = memoize( - (schema: LinkedJSONSchema): LinkedJSONSchema => { - const parent = schema[Parent] - if (!parent) { - return schema - } - return getRootSchema(parent) +export const getRootSchema = memoize((schema: LinkedJSONSchema): LinkedJSONSchema => { + const parent = schema[Parent] + if (!parent) { + return schema } -) + return getRootSchema(parent) +}) export function isPrimitive(schema: LinkedJSONSchema | JSONSchemaType): schema is JSONSchemaType { return !isPlainObject(schema) diff --git a/src/typesOfSchema.ts b/src/typesOfSchema.ts index 130c5665..19d56bb9 100644 --- a/src/typesOfSchema.ts +++ b/src/typesOfSchema.ts @@ -65,7 +65,7 @@ const matchers: Record boolean> = { return 'enum' in schema && 'tsEnumNames' in schema }, NAMED_SCHEMA(schema) { - return 'id' in schema && ('patternProperties' in schema || 'properties' in schema) + return '$id' in schema && ('patternProperties' in schema || 'properties' in schema) }, NULL(schema) { return schema.type === 'null' diff --git a/src/utils.ts b/src/utils.ts index 184d3166..2fe7fa86 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,6 @@ import {deburr, isPlainObject, trim, upperFirst} from 'lodash' import {basename, dirname, extname, join, normalize, sep} from 'path' -import {JSONSchema, LinkedJSONSchema} from './types/JSONSchema' +import {JSONSchema, LinkedJSONSchema, Parent} from './types/JSONSchema' // TODO: pull out into a separate package export function Try(fn: () => T, err: (e: Error) => any): T { @@ -79,8 +79,6 @@ export function traverse( return } - // console.log('key', key + '\n') - processed.add(schema) callback(schema, key ?? null) @@ -328,19 +326,19 @@ export function maybeStripDefault(schema: LinkedJSONSchema): LinkedJSONSchema { } /** - * Removes the schema's `id`, `name`, and `description` properties + * Removes the schema's `$id`, `name`, and `description` properties * if they exist. * Useful when parsing intersections. * * Mutates `schema`. */ export function maybeStripNameHints(schema: JSONSchema): JSONSchema { + if ('$id' in schema) { + delete schema.$id + } if ('description' in schema) { delete schema.description } - if ('id' in schema) { - delete schema.id - } if ('name' in schema) { delete schema.name } @@ -353,3 +351,31 @@ export function appendToDescription(existingDescription: string | undefined, ... } return values.join('\n') } + +export function isSchemaLike(schema: LinkedJSONSchema) { + if (!isPlainObject(schema)) { + return false + } + const parent = schema[Parent] + if (parent === null) { + return true + } + + const JSON_SCHEMA_KEYWORDS = [ + 'allOf', + 'anyOf', + 'dependencies', + 'enum', + 'oneOf', + 'definitions', + 'not', + 'patternProperties', + 'properties', + 'required' + ] + if (JSON_SCHEMA_KEYWORDS.some(_ => parent[_] === schema)) { + return false + } + + return true +} diff --git a/test/__snapshots__/test/test.ts.md b/test/__snapshots__/test/test.ts.md index c48a3d3d..f27f9d47 100644 --- a/test/__snapshots__/test/test.ts.md +++ b/test/__snapshots__/test/test.ts.md @@ -697,6 +697,7 @@ Generated by [AVA](https://avajs.dev). */␊ ␊ export type LastName = string;␊ + export type Height = number;␊ ␊ export interface ExampleSchema {␊ firstName: string;␊ @@ -705,7 +706,7 @@ Generated by [AVA](https://avajs.dev). * Age in years␊ */␊ age?: number;␊ - height?: number;␊ + height?: Height;␊ favoriteFoods?: unknown[];␊ likesDogs?: boolean;␊ [k: string]: unknown;␊ diff --git a/test/__snapshots__/test/test.ts.snap b/test/__snapshots__/test/test.ts.snap index 5bfe27d0..d318cdfc 100644 Binary files a/test/__snapshots__/test/test.ts.snap and b/test/__snapshots__/test/test.ts.snap differ diff --git a/test/e2e/basics.ts b/test/e2e/basics.ts index 1c3dade3..25bf3e0e 100644 --- a/test/e2e/basics.ts +++ b/test/e2e/basics.ts @@ -15,6 +15,7 @@ export const input = { minimum: 0 }, height: { + $id: 'height', type: 'number' }, favoriteFoods: { diff --git a/test/normalizer/addEmptyRequiredProperty.json b/test/normalizer/addEmptyRequiredProperty.json index 6a4fa123..1495f2f3 100644 --- a/test/normalizer/addEmptyRequiredProperty.json +++ b/test/normalizer/addEmptyRequiredProperty.json @@ -1,23 +1,25 @@ { "name": "Add empty `required` property if none is defined", "in": { - "id": "foo", - "type": ["object"], + "$id": "foo", + "type": [ + "object" + ], "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" } }, "additionalProperties": true }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" } }, "additionalProperties": true, diff --git a/test/normalizer/constToEnum.json b/test/normalizer/constToEnum.json index 9e3567c6..8251b5dd 100644 --- a/test/normalizer/constToEnum.json +++ b/test/normalizer/constToEnum.json @@ -1,11 +1,13 @@ { "name": "Normalize const to singleton enum", "in": { - "id": "foo", + "$id": "foo", "const": "foobar" }, "out": { - "id": "foo", - "enum": ["foobar"] + "$id": "foo", + "enum": [ + "foobar" + ] } } diff --git a/test/normalizer/defaultAdditionalProperties.2.json b/test/normalizer/defaultAdditionalProperties.2.json index 460b610c..a6a98f14 100644 --- a/test/normalizer/defaultAdditionalProperties.2.json +++ b/test/normalizer/defaultAdditionalProperties.2.json @@ -1,14 +1,14 @@ { "name": "Default additionalProperties to false", "in": { - "id": "foo", + "$id": "foo", "type": [ "object" ], "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" }, "b": { "type": "object" @@ -20,12 +20,12 @@ "additionalProperties": false }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" }, "b": { "additionalProperties": false, diff --git a/test/normalizer/defaultAdditionalProperties.json b/test/normalizer/defaultAdditionalProperties.json index 854004f6..a4963c8e 100644 --- a/test/normalizer/defaultAdditionalProperties.json +++ b/test/normalizer/defaultAdditionalProperties.json @@ -1,23 +1,25 @@ { "name": "Default additionalProperties to true", "in": { - "id": "foo", - "type": ["object"], + "$id": "foo", + "type": [ + "object" + ], "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" } }, "required": [] }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "a": { "type": "integer", - "id": "a" + "$id": "a" } }, "required": [], diff --git a/test/normalizer/defaultID.json b/test/normalizer/defaultID.1.json similarity index 59% rename from test/normalizer/defaultID.json rename to test/normalizer/defaultID.1.json index 214e81cd..0f29537c 100644 --- a/test/normalizer/defaultID.json +++ b/test/normalizer/defaultID.1.json @@ -1,15 +1,19 @@ { - "name": "Default top level `id`", + "name": "Default top level `id` (1)", "in": { "friend": { "properties": { "knowsFrom": { - "enum": ["work", "school", "other"] + "enum": [ + "work", + "school", + "other" + ] } }, "additionalProperties": true, "required": [], - "id": "friend" + "$id": "friend" }, "properties": { "firstName": { @@ -17,18 +21,25 @@ } }, "additionalProperties": true, - "required": ["firstName"] + "required": [ + "firstName" + ] }, "out": { + "$id": "DefaultID1", "friend": { "properties": { "knowsFrom": { - "enum": ["work", "school", "other"] + "enum": [ + "work", + "school", + "other" + ] } }, "additionalProperties": true, "required": [], - "id": "friend" + "$id": "friend" }, "properties": { "firstName": { @@ -36,7 +47,8 @@ } }, "additionalProperties": true, - "required": ["firstName"], - "id": "DefaultID" + "required": [ + "firstName" + ] } } diff --git a/test/normalizer/defaultID.2.json b/test/normalizer/defaultID.2.json new file mode 100644 index 00000000..c2b749a4 --- /dev/null +++ b/test/normalizer/defaultID.2.json @@ -0,0 +1,55 @@ +{ + "name": "Default top level `id` (2)", + "in": { + "$id": "DefaultID", + "friend": { + "properties": { + "knowsFrom": { + "enum": [ + "work", + "school", + "other" + ] + } + }, + "additionalProperties": true, + "required": [], + "$id": "friend" + }, + "properties": { + "firstName": { + "type": "string" + } + }, + "additionalProperties": true, + "required": [ + "firstName" + ] + }, + "out": { + "$id": "DefaultID", + "friend": { + "properties": { + "knowsFrom": { + "enum": [ + "work", + "school", + "other" + ] + } + }, + "additionalProperties": true, + "required": [], + "$id": "friend" + }, + "properties": { + "firstName": { + "type": "string" + } + }, + "additionalProperties": true, + "required": [ + "firstName" + ] + } +} diff --git a/test/normalizer/destructureUnaryTypes.json b/test/normalizer/destructureUnaryTypes.json index f9c05628..2f7df972 100644 --- a/test/normalizer/destructureUnaryTypes.json +++ b/test/normalizer/destructureUnaryTypes.json @@ -1,36 +1,42 @@ { "name": "Destructure unary types", "in": { - "id": "foo", - "type": ["object"], + "$id": "foo", + "type": [ + "object" + ], "definitions": { "a": { - "type": ["integer"], - "id": "a" + "type": [ + "integer" + ], + "$id": "a" } }, "properties": { "b": { - "type": ["string"], - "id": "b" + "type": [ + "string" + ], + "$id": "b" } }, "additionalProperties": true, "required": [] }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "definitions": { "a": { "type": "integer", - "id": "a" + "$id": "a" } }, "properties": { "b": { "type": "string", - "id": "b" + "$id": "b" } }, "additionalProperties": true, diff --git a/test/normalizer/emptyStringConstToEnum.json b/test/normalizer/emptyStringConstToEnum.json index 87293397..a7ecee21 100644 --- a/test/normalizer/emptyStringConstToEnum.json +++ b/test/normalizer/emptyStringConstToEnum.json @@ -1,11 +1,13 @@ { "name": "Normalize empty const to singleton enum", "in": { - "id": "foo", + "$id": "foo", "const": "" }, "out": { - "id": "foo", - "enum": [""] + "$id": "foo", + "enum": [ + "" + ] } } diff --git a/test/normalizer/nonObjectItems.json b/test/normalizer/nonObjectItems.json index 12cdbdfa..f86e0ecf 100644 --- a/test/normalizer/nonObjectItems.json +++ b/test/normalizer/nonObjectItems.json @@ -1,7 +1,7 @@ { "name": "Non object items.items", "in": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "myProperty": { @@ -12,7 +12,7 @@ "additionalProperties": false }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "myProperty": { diff --git a/test/normalizer/defsToDefinitions.json b/test/normalizer/normalizeDefs.json similarity index 64% rename from test/normalizer/defsToDefinitions.json rename to test/normalizer/normalizeDefs.json index 050ca47f..c8eb3895 100644 --- a/test/normalizer/defsToDefinitions.json +++ b/test/normalizer/normalizeDefs.json @@ -1,14 +1,14 @@ { "name": "Normalize $defs to definitions", "in": { - "id": "foo", - "$defs" : { + "$id": "foo", + "$defs": { "bar": "baz" } }, "out": { - "id": "foo", - "definitions" : { + "$id": "foo", + "definitions": { "bar": "baz" } } diff --git a/test/normalizer/normalizeExtends.json b/test/normalizer/normalizeExtends.json index d0fc19d6..b6e6f940 100644 --- a/test/normalizer/normalizeExtends.json +++ b/test/normalizer/normalizeExtends.json @@ -1,14 +1,14 @@ { "name": "Normalize extends to an array", "in": { - "id": "foo", + "$id": "foo", "extends": "foo", "type": "object", "required": [], "additionalProperties": true }, "out": { - "id": "foo", + "$id": "foo", "extends": [ "foo" ], diff --git a/test/normalizer/normalizeID.json b/test/normalizer/normalizeID.json new file mode 100644 index 00000000..95d3e19f --- /dev/null +++ b/test/normalizer/normalizeID.json @@ -0,0 +1,29 @@ +{ + "name": "Transform id to $id", + "in": { + "properties": { + "b": { + "id": "b", + "type": "object", + "additionalProperties": false, + "required": [] + } + }, + "additionalProperties": false, + "required": [], + "id": "a" + }, + "out": { + "properties": { + "b": { + "$id": "b", + "type": "object", + "additionalProperties": false, + "required": [] + } + }, + "additionalProperties": false, + "required": [], + "$id": "a" + } +} diff --git a/test/normalizer/redundantNull.json b/test/normalizer/redundantNull.json index 8ff6060b..bfad6e30 100644 --- a/test/normalizer/redundantNull.json +++ b/test/normalizer/redundantNull.json @@ -4,40 +4,71 @@ "type": "object", "properties": { "noopMissingType": { - "enum": ["foo", "bar"] + "enum": [ + "foo", + "bar" + ] }, "noopMissingEnum": { - "type": ["null", "string"] + "type": [ + "null", + "string" + ] }, "noopNonNullableEnum": { "type": "string", - "enum": ["foo", "bar", null] + "enum": [ + "foo", + "bar", + null + ] }, "dedupeNulls": { - "type": ["null", "string"], - "enum": ["foo", "bar", null] + "type": [ + "null", + "string" + ], + "enum": [ + "foo", + "bar", + null + ] } } }, "out": { "additionalProperties": true, - "id": "RedundantNull", + "$id": "RedundantNull", "required": [], "type": "object", "properties": { "noopMissingType": { - "enum": ["foo", "bar"] + "enum": [ + "foo", + "bar" + ] }, "noopMissingEnum": { - "type": ["null", "string"] + "type": [ + "null", + "string" + ] }, "noopNonNullableEnum": { "type": "string", - "enum": ["foo", "bar", null] + "enum": [ + "foo", + "bar", + null + ] }, "dedupeNulls": { "type": "string", - "enum": ["foo", "bar", null] + "enum": [ + "foo", + "bar", + null + ] } } } diff --git a/test/normalizer/removeEmptyExtends.1.json b/test/normalizer/removeEmptyExtends.1.json index 17382b5e..ae1aa3e5 100644 --- a/test/normalizer/removeEmptyExtends.1.json +++ b/test/normalizer/removeEmptyExtends.1.json @@ -1,14 +1,14 @@ { "name": "Remove empty extends (1)", "in": { - "id": "foo", + "$id": "foo", "extends": [], "type": "object", "required": [], "additionalProperties": true }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "required": [], "additionalProperties": true diff --git a/test/normalizer/removeEmptyExtends.2.json b/test/normalizer/removeEmptyExtends.2.json index 77c72e19..bc668866 100644 --- a/test/normalizer/removeEmptyExtends.2.json +++ b/test/normalizer/removeEmptyExtends.2.json @@ -1,14 +1,14 @@ { "name": "Remove empty extends (2)", "in": { - "id": "foo", + "$id": "foo", "extends": null, "type": "object", "required": [], "additionalProperties": true }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "required": [], "additionalProperties": true diff --git a/test/normalizer/removeMaxItems.1.json b/test/normalizer/removeMaxItems.1.json index b01fe130..01fa7e1d 100644 --- a/test/normalizer/removeMaxItems.1.json +++ b/test/normalizer/removeMaxItems.1.json @@ -2,7 +2,7 @@ "name": "Remove maxItems if it is big enough to likely cause OOMs (1)", "in": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "minItems": 5, @@ -31,7 +31,7 @@ }, "out": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "description": "@minItems 5", diff --git a/test/normalizer/removeMaxItems.2.json b/test/normalizer/removeMaxItems.2.json index fe6d93da..7625d859 100644 --- a/test/normalizer/removeMaxItems.2.json +++ b/test/normalizer/removeMaxItems.2.json @@ -2,7 +2,7 @@ "name": "Remove maxItems if it is big enough to likely cause OOMs (2)", "in": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "minItems": 5, @@ -31,7 +31,7 @@ }, "out": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "description": "@minItems 5", diff --git a/test/normalizer/removeMaxItems.3.json b/test/normalizer/removeMaxItems.3.json index 6f137477..ad73854b 100644 --- a/test/normalizer/removeMaxItems.3.json +++ b/test/normalizer/removeMaxItems.3.json @@ -2,7 +2,7 @@ "name": "Remove maxItems if it is big enough to likely cause OOMs (3)", "in": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "description": "Test", @@ -33,7 +33,7 @@ }, "out": { "additionalProperties": false, - "id": "RemoveMaxItems", + "$id": "RemoveMaxItems", "properties": { "a": { "description": "Test\n\n@minItems 5", diff --git a/test/normalizer/schemaIgnoreMaxMinItems.json b/test/normalizer/schemaIgnoreMaxMinItems.json index 3cfe53c4..a9efb778 100644 --- a/test/normalizer/schemaIgnoreMaxMinItems.json +++ b/test/normalizer/schemaIgnoreMaxMinItems.json @@ -4,7 +4,7 @@ "ignoreMinAndMaxItems": true }, "in": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untyped": { @@ -162,7 +162,7 @@ "required": [] }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untyped": { diff --git a/test/normalizer/schemaItems.json b/test/normalizer/schemaItems.json index c4ec54ad..e7ced8ae 100644 --- a/test/normalizer/schemaItems.json +++ b/test/normalizer/schemaItems.json @@ -1,7 +1,7 @@ { "name": "Normalize schema.items", "in": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untypedUnbounded": { @@ -79,7 +79,7 @@ "additionalProperties": false }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untypedUnbounded": { diff --git a/test/normalizer/schemaMinItems.json b/test/normalizer/schemaMinItems.json index c64cb8c8..dbdfba87 100644 --- a/test/normalizer/schemaMinItems.json +++ b/test/normalizer/schemaMinItems.json @@ -1,7 +1,7 @@ { "name": "Normalise schema.minItems", "in": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untyped": { @@ -159,7 +159,7 @@ "required": [] }, "out": { - "id": "foo", + "$id": "foo", "type": "object", "properties": { "untyped": { diff --git a/test/testUtils.ts b/test/testUtils.ts index e7442280..8876a267 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -1,5 +1,7 @@ import test from 'ava' -import {pathTransform, generateName} from '../src/utils' +import {link} from '../src/linker' +import {LinkedJSONSchema} from '../src/types/JSONSchema' +import {pathTransform, generateName, isSchemaLike} from '../src/utils' export function run() { test('pathTransform', t => { @@ -20,4 +22,27 @@ export function run() { t.is(generateName('a', usedNames), 'A2') t.is(generateName('a', usedNames), 'A3') }) + test('isSchemaLike', t => { + const schema = link({ + title: 'Example Schema', + type: 'object', + properties: { + firstName: { + type: 'string' + }, + lastName: { + id: 'lastName', + type: 'string' + } + }, + required: ['firstName', 'lastName'] + }) + t.is(isSchemaLike(schema), true) + t.is(isSchemaLike([] as any as LinkedJSONSchema), false) + t.is(isSchemaLike(schema.properties as LinkedJSONSchema), false) + t.is(isSchemaLike(schema.required as any as LinkedJSONSchema), false) + t.is(isSchemaLike(schema.title as any as LinkedJSONSchema), false) + t.is(isSchemaLike(schema.properties!.firstName), true) + t.is(isSchemaLike(schema.properties!.lastName), true) + }) }