@@ -5,8 +5,9 @@ import type {
55 JSONSchema7Definition ,
66} from 'json-schema' ;
77import type { Options , SchemaType , SchemaTypeKeys } from './types' ;
8- import { oas3schema } from './lib/openApiSchema' ;
98import { Walker } from 'json-schema-walker' ;
9+ import { allowedKeywords } from './const' ;
10+ import type { OpenAPI3 } from 'openapi-typescript' ;
1011
1112class InvalidTypeError extends Error {
1213 constructor ( message : string ) {
@@ -18,23 +19,63 @@ class InvalidTypeError extends Error {
1819
1920const oasExtensionPrefix = 'x-' ;
2021
21- // TODO: having definitions inside an oas3 schema isn't exactly valid,
22- // maybe it is an idea to extract and split them into multiple oas3 schemas and reference to them.
23- // For now leaving as is.
24- const allowedKeywords = [
25- '$ref' ,
26- 'definitions' ,
27- ...Object . keys ( oas3schema . definitions . Schema . properties ) ,
28- ] ;
22+ const handleDefinition = async < T > (
23+ def : JSONSchema7Definition | JSONSchema6Definition | JSONSchema4 ,
24+ schema : T
25+ ) => {
26+ if ( typeof def !== 'object' ) {
27+ return def ;
28+ }
29+
30+ const type = def . type ;
31+ if ( type ) {
32+ // Walk just the definitions types
33+ const walker = new Walker < T > ( ) ;
34+ await walker . loadSchema ( { ...def , $schema : schema [ '$schema' ] } as any , {
35+ dereference : true ,
36+ cloneSchema : true ,
37+ dereferenceOptions : {
38+ dereference : {
39+ circular : 'ignore' ,
40+ } ,
41+ } ,
42+ } ) ;
43+ await walker . walk ( convertSchema , walker . vocabularies . DRAFT_07 ) ;
44+ return walker . rootSchema ;
45+ } else if ( Array . isArray ( def ) ) {
46+ // if it's an array, we might want to reconstruct the type;
47+ const typeArr = def ;
48+ const hasNull = typeArr . includes ( 'null' ) ;
49+ if ( hasNull ) {
50+ const actualTypes = typeArr . filter ( ( l ) => l !== 'null' ) ;
51+ return {
52+ type : actualTypes . length === 1 ? actualTypes [ 0 ] : actualTypes ,
53+ nullable : true ,
54+ // this is incorrect but thats ok, we are in the inbetween phase here
55+ } as JSONSchema7Definition | JSONSchema6Definition | JSONSchema4 ;
56+ }
57+ }
58+
59+ return def ;
60+ } ;
2961
3062const convert = async < T = JSONSchema > (
3163 schema : T ,
3264 options ?: Options
33- ) : Promise < SchemaType > => {
65+ ) : Promise < OpenAPI3 > => {
3466 const walker = new Walker < T > ( ) ;
67+ const convertDefs = options ?. convertUnreferencedDefinitions ?? true ;
3568 await walker . loadSchema ( schema , options ) ;
3669 await walker . walk ( convertSchema , walker . vocabularies . DRAFT_07 ) ;
37- return walker . rootSchema ;
70+ // if we want to convert unreferenced definitions, we need to do it iteratively here
71+ const rootSchema = walker . rootSchema as unknown as JSONSchema ;
72+ if ( convertDefs && rootSchema ?. definitions ) {
73+ for ( const defName in rootSchema . definitions ) {
74+ const def = rootSchema . definitions [ defName ] ;
75+ rootSchema . definitions [ defName ] = await handleDefinition ( def , schema ) ;
76+ }
77+ }
78+ return rootSchema as OpenAPI3 ;
3879} ;
3980
4081function stripIllegalKeywords ( schema : SchemaType ) {
0 commit comments