Skip to content

Commit

Permalink
refactor: generate metaData for all schemas for all refHandling modes
Browse files Browse the repository at this point in the history
  • Loading branch information
toomuchdesign committed May 22, 2024
1 parent 353420e commit 027e02f
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 64 deletions.
48 changes: 28 additions & 20 deletions src/openapiToTsJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,26 +136,6 @@ export async function openapiToTsJsonSchema(
const jsonSchema = convertOpenApiPathsParameters(dereferencedJsonSchema);
const schemaMetaDataMap: SchemaMetaDataMap = new Map();

/**
* Create meta data for $ref schemas which have been previously dereferenced.
* It happens only with "import" and "keep" refHandling since they expect
* $ref schemas to be generated no matter of
*/
if (refHandling === 'import' || refHandling === 'keep') {
for (const [id, { openApiDefinition, jsonSchema }] of inlinedRefs) {
addSchemaToMetaData({
id,
$id: $idMapper({ id }),
schemaMetaDataMap,
openApiDefinition,
jsonSchema,
outputPath,
isRef: true,
shouldBeGenerated: true,
});
}
}

/**
* Create meta data for each output schema
*/
Expand Down Expand Up @@ -183,6 +163,34 @@ export async function openapiToTsJsonSchema(
}
}

/**
* Create meta data for each $ref schemas which have been previously dereferenced.
*/
for (const [id, { openApiDefinition, jsonSchema }] of inlinedRefs) {
let shouldBeGenerated = true;

/**
* In "inline" mode $ref schemas not explicitly marked for generation
* should not be generated
*
* All the other "refHandling" modes generate all $ref schemas
*/
if (refHandling === 'inline' && !schemaMetaDataMap.has(id)) {
shouldBeGenerated = false;
}

addSchemaToMetaData({
id,
$id: $idMapper({ id }),
schemaMetaDataMap,
openApiDefinition,
jsonSchema,
outputPath,
isRef: true,
shouldBeGenerated,
});
}

const returnPayload: ReturnPayload = {
outputPath,
metaData: { schemas: schemaMetaDataMap },
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/fastifyIntegrationPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ const fastifyIntegrationPlugin: Plugin<PluginOptions | void> = ({
onBeforeGeneration: async ({ outputPath, metaData, options, utils }) => {
// Derive the schema data necessary to generate the declarations
const allSchemas = [...metaData.schemas]
.map(([id, schema]) => schema)
.map(([_id, schema]) => schema)
.filter((schema) => schema.shouldBeGenerated)
.map(({ absoluteImportPath, uniqueName, id, isRef }) => {
return {
importPath: utils.makeRelativeModulePath({
Expand Down
45 changes: 21 additions & 24 deletions src/utils/addSchemaToMetaData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,29 @@ export function addSchemaToMetaData({
shouldBeGenerated: boolean;
outputPath: string;
}): void {
// Do not override existing meta info of inlined schemas
if (!schemaMetaDataMap.has(id)) {
const { schemaRelativeDirName, schemaName } = parseId(id);
const absoluteDirName = path.join(outputPath, schemaRelativeDirName);
const schemaFileName = filenamify(schemaName);
const absoluteImportPath = path.join(absoluteDirName, schemaFileName);
const { schemaRelativeDirName, schemaName } = parseId(id);
const absoluteDirName = path.join(outputPath, schemaRelativeDirName);
const schemaFileName = filenamify(schemaName);
const absoluteImportPath = path.join(absoluteDirName, schemaFileName);

// Convert components.parameters after convertOpenApiPathsParameters is called
if (isOpenApiParameterObject(openApiDefinition)) {
jsonSchema = convertOpenApiParameterToJsonSchema(openApiDefinition);
}
// Convert components.parameters after convertOpenApiPathsParameters is called
if (isOpenApiParameterObject(openApiDefinition)) {
jsonSchema = convertOpenApiParameterToJsonSchema(openApiDefinition);
}

const metaInfo: SchemaMetaData = {
id,
$id,
uniqueName: namify(id),
isRef,
shouldBeGenerated,
openApiDefinition,
originalSchema: jsonSchema,
const metaInfo: SchemaMetaData = {
id,
$id,
uniqueName: namify(id),
isRef,
shouldBeGenerated,
openApiDefinition,
originalSchema: jsonSchema,

absoluteDirName,
absoluteImportPath,
absolutePath: absoluteImportPath + '.ts',
};
absoluteDirName,
absoluteImportPath,
absolutePath: absoluteImportPath + '.ts',
};

schemaMetaDataMap.set(id, metaInfo);
}
schemaMetaDataMap.set(id, metaInfo);
}
20 changes: 11 additions & 9 deletions src/utils/makeTsJsonSchemaFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,17 @@ export async function makeTsJsonSchemaFiles({
$idMapper: $idMapper;
}) {
for (const [_, metaData] of schemaMetaDataMap) {
const tsSchema = await makeTsJsonSchema({
metaData,
schemaMetaDataMap,
refHandling,
schemaPatcher,
$idMapper,
});
if (metaData.shouldBeGenerated) {
const tsSchema = await makeTsJsonSchema({
metaData,
schemaMetaDataMap,
refHandling,
schemaPatcher,
$idMapper,
});

const { absolutePath } = metaData;
await saveFile({ path: [absolutePath], data: tsSchema });
const { absolutePath } = metaData;
await saveFile({ path: [absolutePath], data: tsSchema });
}
}
}
39 changes: 33 additions & 6 deletions test/circularReference.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,33 @@ describe('Circular reference', () => {
description: 'February description',
type: 'object',
properties: {
previousMonth: {},
previousMonth: {
description: 'January description',
properties: {},
type: 'object',
},
},
},
nextMonthTwo: {
description: 'February description',
type: 'object',
properties: {
previousMonth: {},
previousMonth: {
description: 'January description',
properties: {},
type: 'object',
},
},
},
nextMonthThree: {
description: 'February description',
type: 'object',
properties: {
previousMonth: {},
previousMonth: {
description: 'January description',
properties: {},
type: 'object',
},
},
},
},
Expand All @@ -66,9 +78,24 @@ describe('Circular reference', () => {
description: "January description",
type: "object",
properties: {
nextMonth: {},
nextMonthTwo: {},
nextMonthThree: {},
nextMonth: {
// $ref: "#/components/schemas/February"
description: "February description",
type: "object",
properties: {},
},
nextMonthTwo: {
// $ref: "#/components/schemas/February"
description: "February description",
type: "object",
properties: {},
},
nextMonthThree: {
// $ref: "#/components/schemas/February"
description: "February description",
type: "object",
properties: {},
},
},
},`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,25 @@ describe('fastifyIntegration plugin', () => {
// @TODO find a better way to assert against generated types
const expectedAsText = await formatTypeScript(`
// File autogenerated by "openapi-ts-json-schema". Do not edit :)
import { with$id as componentsSchemasAnswer } from "./components/schemas/Answer";
import { with$id as componentsSchemasJanuary } from "./components/schemas/January";
import { with$id as componentsSchemasFebruary } from "./components/schemas/February";
import { with$id as componentsSchemasMarch } from "./components/schemas/March";
import { with$id as componentsSchemasAnswer } from "./components/schemas/Answer";
// RefSchemas type: tuple of $ref schema types to enable json-schema-to-ts hydrate $refs via "references" option
export type RefSchemas = [
typeof componentsSchemasAnswer,
typeof componentsSchemasJanuary,
typeof componentsSchemasFebruary,
typeof componentsSchemasMarch,
typeof componentsSchemasAnswer,
];
// schemas: array of JSON schemas to be registered with "fastify.addSchema"
export const schemas = [
componentsSchemasAnswer,
componentsSchemasJanuary,
componentsSchemasFebruary,
componentsSchemasMarch,
componentsSchemasAnswer,
]`);

expect(actualAsText).toBe(expectedAsText);
Expand All @@ -68,10 +68,10 @@ describe('fastifyIntegration plugin', () => {
);

expect(actual.schemas).toEqual([
answerSchema.with$id,
januarySchema.with$id,
februarySchema.with$id,
marchSchema.with$id,
answerSchema.with$id,
]);
});

Expand Down

0 comments on commit 027e02f

Please sign in to comment.