Skip to content

Commit

Permalink
feat: add "openApiDefinition" to generated metaData (#257)
Browse files Browse the repository at this point in the history
* refactor: add openApiSchema refactor note

* feat: add "openApiDefinition" to generated metaData

* refactor: use openApi definition in addSchemaToMetaData

* chore: make openapi3-ts a dependency
  • Loading branch information
toomuchdesign authored May 20, 2024
1 parent d4b4031 commit fe4f838
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 87 deletions.
5 changes: 5 additions & 0 deletions .changeset/afraid-feet-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openapi-ts-json-schema': minor
---

Add `openApiDefinition` prop to generated metaData
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ Beside generating the expected schema files under `outputPath`, `openapiToTsJson
// JSON schema Compound Schema Document `$id`. Eg: `"/components/schemas/MySchema"`
uniqueName: string;
// Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
openApiDefinition: OpenApiObject;
// Original dereferenced openAPI definition
originalSchema: JSONSchema | string;
// Original dereferenced JSON schema
isRef: boolean;
Expand Down Expand Up @@ -162,6 +164,7 @@ Read [plugins documentation 📖](./docs/plugins.md).
- Find a way to merge multiple different OpenApi definitions consistently
- Consider implementing an option to inline circular $refs with a configurable nesting level
- Handle `$ref` parameters according to `refHandler` options
- Rename `openApiSchema` --> `OpenApiDocument`

[ci-badge]: https://github.com/toomuchdesign/openapi-ts-json-schema/actions/workflows/ci.yml/badge.svg
[ci]: https://github.com/toomuchdesign/openapi-ts-json-schema/actions/workflows/ci.yml
Expand Down
101 changes: 39 additions & 62 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"@types/lodash.get": "^4.4.7",
"@vitest/coverage-v8": "^1.1.0",
"fastify": "^4.23.2",
"openapi3-ts": "^4.3.1",
"rimraf": "^5.0.1",
"simple-git-hooks": "^2.9.0",
"tiny-glob": "^0.2.9",
Expand All @@ -67,6 +66,7 @@
"map-obj": "^4.3.0",
"namify": "^0.1.3",
"openapi-jsonschema-parameters": "^12.1.3",
"openapi3-ts": "^4.3.1",
"prettier": "^3.0.1"
}
}
26 changes: 19 additions & 7 deletions src/openapiToTsJsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from './utils';
import type {
SchemaMetaDataMap,
OpenApiObject,
JSONSchema,
ReturnPayload,
Options,
Expand Down Expand Up @@ -81,7 +82,11 @@ export async function openapiToTsJsonSchema(
// Convert oas definitions to JSON schema
const initialJsonSchema = convertOpenApiToJsonSchema(bundledOpenApiSchema);

const inlinedRefs: Map<string, JSONSchema> = new Map();
const inlinedRefs: Map<
string,
{ openApiDefinition: OpenApiObject; jsonSchema: JSONSchema }
> = new Map();

// Inline and collect internal $ref definitions
const dereferencedJsonSchema = await jsonSchemaParser.dereference(
initialJsonSchema,
Expand All @@ -96,7 +101,11 @@ export async function openapiToTsJsonSchema(
// Shallow copy the ref schema to avoid the mutations below
inlinedRefs.set(id, {
// @ts-expect-error Spread types may only be created from object types
...jsonSchemaParser.$refs.get(ref),
openApiDefinition: openApiParser.$refs.get(ref),
jsonSchema: {
// @ts-expect-error Spread types may only be created from object types
...jsonSchemaParser.$refs.get(ref),
},
});
}

Expand Down Expand Up @@ -133,12 +142,13 @@ export async function openapiToTsJsonSchema(
* $ref schemas to be generated no matter of
*/
if (refHandling === 'import' || refHandling === 'keep') {
for (const [id, schema] of inlinedRefs) {
for (const [id, { openApiDefinition, jsonSchema }] of inlinedRefs) {
addSchemaToMetaData({
id,
$id: $idMapper({ id }),
schemaMetaDataMap,
schema,
openApiDefinition,
jsonSchema,
outputPath,
isRef: true,
});
Expand All @@ -149,9 +159,10 @@ export async function openapiToTsJsonSchema(
* Create meta data for each output schema
*/
for (const definitionPath of definitionPathsToGenerateFrom) {
const definitionSchemas = get(jsonSchema, definitionPath);
const jsonSchemaDefinitions = get(jsonSchema, definitionPath);
const openApiDefinitions = get(bundledOpenApiSchema, definitionPath);

for (const schemaName in definitionSchemas) {
for (const schemaName in jsonSchemaDefinitions) {
// Create expected OpenAPI ref
const id = makeId({
schemaRelativeDirName: definitionPath,
Expand All @@ -162,7 +173,8 @@ export async function openapiToTsJsonSchema(
id,
$id: $idMapper({ id }),
schemaMetaDataMap,
schema: definitionSchemas[schemaName],
openApiDefinition: openApiDefinitions[schemaName],
jsonSchema: jsonSchemaDefinitions[schemaName],
outputPath,
isRef: inlinedRefs.has(id),
});
Expand Down
36 changes: 33 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,41 @@
import type { JSONSchema4, JSONSchema6, JSONSchema7 } from 'json-schema';
import type { ParameterObject, ReferenceObject } from 'openapi3-ts/oas31';
import type {
PathItemObject as PathItemObject_v3_0,
SchemaObject as SchemaObject_v3_0,
ParameterObject as ParameterObject_v3_0,
ReferenceObject as ReferenceObject_v3_0,
} from 'openapi3-ts/oas30';
import type {
PathItemObject as PathItemObject_v3_1,
SchemaObject as SchemaObject_v3_1,
ParameterObject as ParameterObject_v3_1,
ReferenceObject as ReferenceObject_v3_1,
} from 'openapi3-ts/oas31';

export type OpenApiDocument = Record<string, any>;
// This type should represent any generated OpenAPI
type OpenApiObject_v3_0 =
| PathItemObject_v3_0
| SchemaObject_v3_0
| ParameterObject_v3_0
| ReferenceObject_v3_0;
type OpenApiObject_v3_1 =
| PathItemObject_v3_1
| SchemaObject_v3_1
| ParameterObject_v3_1
| ReferenceObject_v3_1;
export type OpenApiObject = OpenApiObject_v3_0 | OpenApiObject_v3_1;

type OpenApiParameter_v3_0 = ParameterObject_v3_0 | ReferenceObject_v3_0;
type OpenApiParameter_v3_1 = ParameterObject_v3_1 | ReferenceObject_v3_1;
export type OpenApiParameter = OpenApiParameter_v3_0 | OpenApiParameter_v3_1;

export type JSONSchema = JSONSchema4 | JSONSchema6 | JSONSchema7;
export type JSONSchemaWithPlaceholders = JSONSchema | string;
export type OpenApiSchema = Record<string, any>;

export type SchemaPatcher = (params: { schema: JSONSchema }) => void;
export type RefHandling = 'import' | 'inline' | 'keep';
export type $idMapper = (input: { id: string }) => string;
export type OpenApiParameter = ParameterObject | ReferenceObject;

import type {
makeRelativeModulePath,
Expand All @@ -32,6 +60,7 @@ export type Options = {
* @property `$id` - JSON schema Compound Schema Document `$id`. Eg `"/components/schemas/MySchema"`
* @property `isRef` - True if schemas is used as `$ref`
* @property `uniqueName` - Unique JavaScript identifier used as import name. Eg: `"componentsSchemasMySchema"`
* @property `openApiDefinition` - Original dereferenced openAPI definition
* @property `originalSchema` - Original dereferenced JSON schema
*
* @property `absoluteDirName` - Absolute path pointing to schema folder (posix or win32). Eg: `"Users/username/output/path/components/schemas"`
Expand All @@ -43,6 +72,7 @@ export type SchemaMetaData = {
$id: string;
isRef: boolean;
uniqueName: string;
openApiDefinition?: OpenApiObject;
originalSchema: JSONSchema;

absoluteDirName: string;
Expand Down
Loading

0 comments on commit fe4f838

Please sign in to comment.