From 499e9f503d459ee42d0d69acdd8a00f7c26b0183 Mon Sep 17 00:00:00 2001 From: JonLuca De Caro Date: Mon, 8 Aug 2022 11:49:07 -0400 Subject: [PATCH] fix: add suffix to esm import (#35) * fix(esm): add suffix to import * fix(modules): Change module resolution to node16 to prevent esm import errors, change types library * fix(nested-definitions): add definitions availability for nested definitions --- package.json | 4 +- src/index.ts | 34 +++++++----- .../dereference_schema.test.ts.snap | 52 +++++++++++++++++++ test/dereference_schema.test.ts | 47 +++++++++++++++++ tsconfig.json | 2 +- 5 files changed, 124 insertions(+), 15 deletions(-) create mode 100644 test/__snapshots__/dereference_schema.test.ts.snap diff --git a/package.json b/package.json index c1dc747..108e66b 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "dependencies": { "@apidevtools/json-schema-ref-parser": "^9.0.9", "json-schema-walker": "^0.0.4", + "openapi-types": "^12.0.0", "yargs": "^17.5.1" }, "devDependencies": { @@ -48,10 +49,9 @@ "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-unused-imports": "^2.0.0", "nock": "^13.2.9", - "openapi-typescript": "^5.4.1", "prettier": "^2.7.1", "typescript": "^4.7.4", - "vitest": "^0.20.3" + "vitest": "^0.21.0" }, "prettier": { "singleQuote": true, diff --git a/src/index.ts b/src/index.ts index fb5a483..965aa0a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,8 +6,8 @@ import type { } from 'json-schema'; import type { Options, SchemaType, SchemaTypeKeys } from './types'; import { Walker } from 'json-schema-walker'; -import { allowedKeywords } from './const'; -import type { OpenAPI3 } from 'openapi-typescript'; +import { allowedKeywords } from './const.js'; +import type { OpenAPIV3 } from 'openapi-types'; class InvalidTypeError extends Error { constructor(message: string) { @@ -31,16 +31,26 @@ const handleDefinition = async ( if (type) { // Walk just the definitions types const walker = new Walker(); - await walker.loadSchema({ ...def, $schema: schema['$schema'] } as any, { - dereference: true, - cloneSchema: true, - dereferenceOptions: { - dereference: { - circular: 'ignore', + await walker.loadSchema( + { + definitions: schema['definitions'] || [], + ...def, + $schema: schema['$schema'], + } as any, + { + dereference: true, + cloneSchema: true, + dereferenceOptions: { + dereference: { + circular: 'ignore', + }, }, - }, - }); + } + ); await walker.walk(convertSchema, walker.vocabularies.DRAFT_07); + if ('definitions' in walker.rootSchema) { + delete (walker.rootSchema).definitions; + } return walker.rootSchema; } else if (Array.isArray(def)) { // if it's an array, we might want to reconstruct the type; @@ -62,7 +72,7 @@ const handleDefinition = async ( const convert = async ( schema: T, options?: Options -): Promise => { +): Promise => { const walker = new Walker(); const convertDefs = options?.convertUnreferencedDefinitions ?? true; await walker.loadSchema(schema, options); @@ -75,7 +85,7 @@ const convert = async ( rootSchema.definitions[defName] = await handleDefinition(def, schema); } } - return rootSchema as OpenAPI3; + return rootSchema as OpenAPIV3.Document; }; function stripIllegalKeywords(schema: SchemaType) { diff --git a/test/__snapshots__/dereference_schema.test.ts.snap b/test/__snapshots__/dereference_schema.test.ts.snap new file mode 100644 index 0000000..9f1beff --- /dev/null +++ b/test/__snapshots__/dereference_schema.test.ts.snap @@ -0,0 +1,52 @@ +// Vitest Snapshot v1 + +exports[`throws an error when dereferecing fails 1`] = ` +{ + "additionalProperties": false, + "definitions": { + "configvariable": { + "additionalProperties": false, + "properties": { + "default": { + "type": "string", + }, + "name": { + "pattern": "^[A-Z_]+[A-Z0-9_]*$", + "type": "string", + }, + "required": { + "default": true, + "type": "boolean", + }, + }, + "required": [ + "name", + ], + "type": "object", + }, + "envVarName": { + "pattern": "^[A-Z_]+[A-Z0-9_]*$", + "type": "string", + }, + }, + "properties": { + "componentId": { + "pattern": "^(.*)$", + "title": "The component id Schema", + "type": "string", + }, + "configurationTemplate": { + "items": { + "$ref": "#/definitions/configvariable", + }, + "title": "The Configurationtemplate Schema", + "type": "array", + }, + }, + "required": [ + "componentId", + ], + "title": "Component Manifest Schema", + "type": "object", +} +`; diff --git a/test/dereference_schema.test.ts b/test/dereference_schema.test.ts index 73967da..9467b89 100644 --- a/test/dereference_schema.test.ts +++ b/test/dereference_schema.test.ts @@ -264,3 +264,50 @@ it('throws an error when dereferecing fails', async ({ expect }) => { expect(error).have.property('ioErrorCode', 'ENOENT'); }); + +it('throws an error when dereferecing fails', async ({ expect }) => { + const schema = { + definitions: { + envVarName: { + type: 'string', + pattern: '^[A-Z_]+[A-Z0-9_]*$', + }, + configvariable: { + type: 'object', + properties: { + name: { $ref: '#/definitions/envVarName' }, + default: { type: 'string' }, + required: { type: 'boolean', default: true }, + }, + required: ['name'], + additionalProperties: false, + }, + }, + $schema: 'http://json-schema.org/draft-07/schema#', + $id: 'http://example.com/root.json', + type: 'object', + title: 'Component Manifest Schema', + required: ['componentId'], + additionalProperties: false, + properties: { + componentId: { + $id: '#/properties/componentId', + type: 'string', + title: 'The component id Schema', + pattern: '^(.*)$', + }, + configurationTemplate: { + $id: '#/properties/configurationTemplate', + type: 'array', + title: 'The Configurationtemplate Schema', + items: { + $ref: '#/definitions/configvariable', + }, + }, + }, + }; + + const result = await convert(schema); + + expect(result).toMatchSnapshot(); +}); diff --git a/tsconfig.json b/tsconfig.json index 5e3eaa4..4feb4d3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ "lib": ["esnext"], "listEmittedFiles": false, "listFiles": false, - "moduleResolution": "node", + "moduleResolution": "node16", "noFallthroughCasesInSwitch": true, "pretty": true, "resolveJsonModule": true,