diff --git a/README.md b/README.md index 966fdec..687739d 100644 --- a/README.md +++ b/README.md @@ -77,20 +77,21 @@ Beside generating the expected schema files under `outputPath`, `openapiToTsJson schemas: Map< string, { - // Valid filename for given schema (without extension). + schemaId: string; schemaFileName: string; - // Absolute path pointing to schema folder + // Valid filename for given schema (without extension). schemaAbsoluteDirName: string; - // Absolute path pointing to schema file + // Absolute path pointing to schema folder schemaAbsolutePath: string; - // Absolute import path (without extension) + // Absolute path pointing to schema file schemaAbsoluteImportPath: string; - // Unique JavaScript identifier used as import name + // Absolute import path (without extension) schemaUniqueName: string; - // The actual JSON schema + // Unique JavaScript identifier used as import name schema: JSONSchema; - // True is schemas is used as a `$ref` + // The actual JSON schema isRef: boolean; + // True is schemas is used as a `$ref` } >; } diff --git a/src/utils/addSchemaToMetaData.ts b/src/utils/addSchemaToMetaData.ts index bc620e6..2606c2d 100644 --- a/src/utils/addSchemaToMetaData.ts +++ b/src/utils/addSchemaToMetaData.ts @@ -50,6 +50,7 @@ export function addSchemaToMetaData({ ); const metaInfo: SchemaMetaData = { + schemaId: id, schemaFileName, schemaAbsoluteDirName, schemaAbsoluteImportPath, diff --git a/src/utils/jsonSchemaToTsConst/index.ts b/src/utils/jsonSchemaToTsConst/index.ts index 240f298..7c8cddb 100644 --- a/src/utils/jsonSchemaToTsConst/index.ts +++ b/src/utils/jsonSchemaToTsConst/index.ts @@ -14,15 +14,17 @@ export async function jsonSchemaToTsConst({ // Stringify schema with "node-comment-json" to generate inline comments const stringifiedSchema = stringify(schema, null, 2); - let tsSchema = `export default ` + stringifiedSchema + 'as const'; + let tsSchema = `export default ` + stringifiedSchema + 'as const;'; - // Related to experimentalImportRefs option + // Enabled with experimentalImportRefs option tsSchema = replacePlaceholdersWithImportedSchemas({ schemaAsText: tsSchema, schemaAbsoluteDirName, schemaMetaDataMap, }); + tsSchema = tsSchema + `\n\nexport const $id = "${metaData.schemaId}";`; + const formattedSchema = await prettier.format(tsSchema, { parser: 'typescript', }); diff --git a/src/utils/types.ts b/src/utils/types.ts index 8aa469e..517915b 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -9,6 +9,7 @@ export type SchemaPatcher = (params: { schema: JSONSchema }) => void; * @prop `schemaAbsolutePath` - Absolute path pointing to schema file. Eg: `"/output/path/components/schemas/MySchema.ts"` * @prop `schemaAbsoluteImportPath` - Absolute import path (without extension). Eg: `"/output/path/components/schemas/MySchema"` * @prop `schemaUniqueName` - Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"` + * @prop `schemaId` * @prop `schema` - The actual JSON schema * @prop `isRef` - Mark schemas used as `$ref` */ @@ -18,6 +19,7 @@ export type SchemaMetaData = { schemaAbsolutePath: string; schemaAbsoluteImportPath: string; schemaUniqueName: string; + schemaId: string; schema: JSONSchema; isRef: boolean; }; diff --git a/test/experimentalImportRefs.test.ts b/test/experimentalImportRefs.test.ts index fb53f67..55a5d56 100644 --- a/test/experimentalImportRefs.test.ts +++ b/test/experimentalImportRefs.test.ts @@ -103,7 +103,7 @@ describe('"experimentalImportRefs" option', () => { }, } as const;`); - expect(actualPath1File).toEqual(expectedPath1File); + expect(actualPath1File).toMatch(expectedPath1File); }); }); @@ -135,7 +135,7 @@ describe('"experimentalImportRefs" option', () => { }, } as const;`); - expect(actualJanuarySchemaFile).toEqual(expectedJanuarySchemaFile); + expect(actualJanuarySchemaFile).toMatch(expectedJanuarySchemaFile); // February schema const actualFebruarySchemaFile = await fs.readFile( @@ -157,6 +157,6 @@ describe('"experimentalImportRefs" option', () => { }, } as const;`); - expect(actualFebruarySchemaFile).toEqual(expectedFebruarySchemaFile); + expect(actualFebruarySchemaFile).toMatch(expectedFebruarySchemaFile); }); }); diff --git a/test/idExport.test.ts b/test/idExport.test.ts new file mode 100644 index 0000000..3f8fefe --- /dev/null +++ b/test/idExport.test.ts @@ -0,0 +1,27 @@ +import path from 'path'; +import fs from 'fs'; +import { describe, it, expect } from 'vitest'; +import { openapiToTsJsonSchema } from '../src'; +import { importFresh } from './test-utils'; + +const fixtures = path.resolve(__dirname, 'fixtures'); + +describe('$id export', async () => { + it('exposes schema id as $id named export', async () => { + const { outputPath } = await openapiToTsJsonSchema({ + openApiSchema: path.resolve(fixtures, 'complex/specs.yaml'), + definitionPathsToGenerateFrom: ['components.months'], + silent: false, + }); + + const januarySchema = await importFresh( + path.resolve(outputPath, 'components/months/January'), + ); + const februarySchema = await importFresh( + path.resolve(outputPath, 'components/months/February'), + ); + + expect(januarySchema['$id']).toBe('#/components/months/January'); + expect(februarySchema['$id']).toBe('#/components/months/February'); + }); +});