Skip to content

Commit

Permalink
fix: make nullable work in components/schema (#92)
Browse files Browse the repository at this point in the history
  • Loading branch information
Himenon committed Nov 15, 2022
1 parent 43b4068 commit 33ded2b
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 19 deletions.
72 changes: 64 additions & 8 deletions src/internal/OpenApiTools/components/Schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import ts, { skipPartiallyEmittedExpressions } from "typescript";
import ts from "typescript";

import type { OpenApi } from "../../../types";
import { FeatureDevelopmentError } from "../../Exception";
Expand All @@ -10,6 +10,20 @@ import type { AnySchema, ArraySchema, ObjectSchema, PrimitiveSchema } from "../t
import type * as Walker from "../Walker";
import * as ExternalDocumentation from "./ExternalDocumentation";

const nullable = (factory: Factory.Type, typeNode: ts.TypeNode, nullable: boolean): ts.TypeNode => {
if (nullable) {
return factory.UnionTypeNode.create({
typeNodes: [
typeNode,
factory.TypeNode.create({
type: "null",
}),
],
});
}
return typeNode;
};

export const generatePropertySignatures = (
entryPoint: string,
currentPoint: string,
Expand Down Expand Up @@ -42,6 +56,41 @@ export const generatePropertySignatures = (
});
};

export const generateTypeAliasDeclarationForObject = (
entryPoint: string,
currentPoint: string,
factory: Factory.Type,
name: string,
schema: ObjectSchema,
context: ToTypeNode.Context,
convertContext: ConvertContext.Types,
): ts.TypeAliasDeclaration => {
if (schema.type !== "object") {
throw new FeatureDevelopmentError("Please use generateTypeAlias");
}
let members: ts.TypeElement[] = [];
const propertySignatures = generatePropertySignatures(entryPoint, currentPoint, factory, schema, context, convertContext);
if (Guard.isObjectSchemaWithAdditionalProperties(schema)) {
const additionalProperties = ToTypeNode.convertAdditionalProperties(entryPoint, currentPoint, factory, schema, context, convertContext);
if (schema.additionalProperties === true) {
members = members.concat(additionalProperties);
} else {
members = [...propertySignatures, additionalProperties];
}
} else {
members = propertySignatures;
}
const typeNode = factory.TypeLiteralNode.create({
members,
});
return factory.TypeAliasDeclaration.create({
export: true,
name: convertContext.escapeDeclarationText(name),
comment: [schema.title, schema.description].filter(v => !!v).join("\n\n"),
type: nullable(factory, typeNode, schema.nullable === true),
});
};

export const generateInterface = (
entryPoint: string,
currentPoint: string,
Expand Down Expand Up @@ -164,11 +213,10 @@ export const generateTypeAlias = (
type: schema.type,
});
}

return factory.TypeAliasDeclaration.create({
export: true,
name: convertContext.escapeDeclarationText(name),
type,
type: nullable(factory, type, schema.nullable === true),
comment: [schema.title, schema.description].filter(v => !!v).join("\n\n"),
});
};
Expand Down Expand Up @@ -239,11 +287,19 @@ export const addSchema = (
value: generateArrayTypeAlias(entryPoint, currentPoint, factory, declarationName, schema, context, convertContext),
});
} else if (Guard.isObjectSchema(schema)) {
store.addStatement(targetPoint, {
kind: "interface",
name: convertContext.escapeDeclarationText(declarationName),
value: generateInterface(entryPoint, currentPoint, factory, declarationName, schema, context, convertContext),
});
if (schema.nullable) {
store.addStatement(targetPoint, {
kind: "typeAlias",
name: convertContext.escapeDeclarationText(declarationName),
value: generateTypeAliasDeclarationForObject(entryPoint, currentPoint, factory, declarationName, schema, context, convertContext),
});
} else {
store.addStatement(targetPoint, {
kind: "interface",
name: convertContext.escapeDeclarationText(declarationName),
value: generateInterface(entryPoint, currentPoint, factory, declarationName, schema, context, convertContext),
});
}
} else if (Guard.isPrimitiveSchema(schema)) {
store.addStatement(targetPoint, {
kind: "typeAlias",
Expand Down
22 changes: 11 additions & 11 deletions src/internal/OpenApiTools/components/Schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,17 @@ export const generateNamespace = (
);
}
if (Guard.isObjectSchema(schema)) {
return store.addStatement(
path,
{
kind: "interface",
name: convertContext.escapeDeclarationText(name),
value: Schema.generateInterface(entryPoint, currentPoint, factory, name, schema, context, convertContext),
},
{ override: true },
);
}
if (Guard.isObjectSchema(schema)) {
if (schema.nullable) {
return store.addStatement(
path,
{
kind: "typeAlias",
name: convertContext.escapeDeclarationText(name),
value: Schema.generateTypeAliasDeclarationForObject(entryPoint, currentPoint, factory, name, schema, context, convertContext),
},
{ override: true },
);
}
return store.addStatement(
path,
{
Expand Down
7 changes: 7 additions & 0 deletions test/__tests__/__snapshots__/spit-code-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,13 @@ export namespace Schemas {
export type RemoteRefArray = Schemas.Level1.Level2.Level3.RemoteArray;
/** Level 4 */
export type RemoteRefObject = Schemas.Level1.Level2.Level3.Level4.RemoteObject;
export type NullableString = string | null;
export type NullableBoolean = boolean | null;
export type NullableNumber = number | null;
export type NullableArray = string[] | null;
export type NullableObject = {
gt?: string;
} | null;
export namespace DirectRef {
export type ForHeader = string;
export interface ForResponse {
Expand Down
7 changes: 7 additions & 0 deletions test/__tests__/__snapshots__/typedef-only-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ export namespace Schemas {
export type RemoteRefArray = Schemas.Level1.Level2.Level3.RemoteArray;
/** Level 4 */
export type RemoteRefObject = Schemas.Level1.Level2.Level3.Level4.RemoteObject;
export type NullableString = string | null;
export type NullableBoolean = boolean | null;
export type NullableNumber = number | null;
export type NullableArray = string[] | null;
export type NullableObject = {
gt?: string;
} | null;
export namespace DirectRef {
export type ForHeader = string;
export interface ForResponse {
Expand Down
14 changes: 14 additions & 0 deletions test/__tests__/__snapshots__/typedef-with-template-test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@ export namespace Schemas {
export type RemoteRefArray = Schemas.Level1.Level2.Level3.RemoteArray;
/** Level 4 */
export type RemoteRefObject = Schemas.Level1.Level2.Level3.Level4.RemoteObject;
export type NullableString = string | null;
export type NullableBoolean = boolean | null;
export type NullableNumber = number | null;
export type NullableArray = string[] | null;
export type NullableObject = {
gt?: string;
} | null;
export namespace DirectRef {
export type ForHeader = string;
export interface ForResponse {
Expand Down Expand Up @@ -650,6 +657,13 @@ export namespace Schemas {
export type RemoteRefArray = Schemas.Level1.Level2.Level3.RemoteArray;
/** Level 4 */
export type RemoteRefObject = Schemas.Level1.Level2.Level3.Level4.RemoteObject;
export type NullableString = string | null;
export type NullableBoolean = boolean | null;
export type NullableNumber = number | null;
export type NullableArray = string[] | null;
export type NullableObject = {
gt?: string;
} | null;
export namespace DirectRef {
export type ForHeader = string;
export interface ForResponse {
Expand Down
20 changes: 20 additions & 0 deletions test/api.test.domain/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,26 @@ components:
$ref: "./components/schemas/Level1/Level2/Level3/RemoteArray.yml"
RemoteRefObject:
$ref: "./components/schemas/Level1/Level2/Level3/Level4/RemoteObject.yml"
NullableString:
type: string
nullable: true
NullableBoolean:
type: boolean
nullable: true
NullableNumber:
type: number
nullable: true
NullableArray:
type: array
items:
type: string
nullable: true
NullableObject:
type: object
nullable: true
properties:
gt:
type: string
headers:
StringHeader:
schema:
Expand Down

0 comments on commit 33ded2b

Please sign in to comment.