diff --git a/README.md b/README.md index f757a833..021428cc 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Options: --id Set schema id. [string] [default: ""] --defaultNumberType Default number type. [choices: "number", "integer"] [default: "number"] --tsNodeRegister Use ts-node/register (needed for require typescript files). [boolean] [default: false] + --constAsEnum Use enums with a single value when declaring constants. [boolean] [default: false] ``` ### Programmatic use diff --git a/test/programs/const-as-enum/main.ts b/test/programs/const-as-enum/main.ts new file mode 100644 index 00000000..fd13ce55 --- /dev/null +++ b/test/programs/const-as-enum/main.ts @@ -0,0 +1,3 @@ +export interface MyObject { + reference: true; +} diff --git a/test/programs/const-as-enum/schema.json b/test/programs/const-as-enum/schema.json new file mode 100644 index 00000000..061c10c0 --- /dev/null +++ b/test/programs/const-as-enum/schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "reference": { + "enum": [ + true + ], + "type": "boolean" + } + }, + "required": [ + "reference" + ], + "type": "object" +} diff --git a/test/schema.test.ts b/test/schema.test.ts index 14069c50..247eef78 100644 --- a/test/schema.test.ts +++ b/test/schema.test.ts @@ -543,3 +543,7 @@ describe("satisfies keyword - ignore from a \"satisfies\" and build by rally typ describe("const keyword", () => { assertSchema("const-keyword", "Object"); }); + +describe("constAsEnum option", () => { + assertSchema("const-as-enum", "MyObject", { constAsEnum: true }); +}); diff --git a/typescript-json-schema-cli.ts b/typescript-json-schema-cli.ts index 11eb182b..97418620 100644 --- a/typescript-json-schema-cli.ts +++ b/typescript-json-schema-cli.ts @@ -53,6 +53,8 @@ export function run() { .describe("defaultNumberType", "Default number type.") .boolean("tsNodeRegister").default("tsNodeRegister", defaultArgs.tsNodeRegister) .describe("tsNodeRegister", "Use ts-node/register (needed for requiring typescript files).") + .boolean("constAsEnum").default("constAsEnum", defaultArgs.constAsEnum) + .describe("constAsEnum", "Use enums with a single value when declaring constants. Needed for OpenAPI compatibility") .argv; exec(args._[0], args._[1], { @@ -78,6 +80,7 @@ export function run() { id: args.id, defaultNumberType: args.defaultNumberType, tsNodeRegister: args.tsNodeRegister, + constAsEnum: args.constAsEnum, }); } diff --git a/typescript-json-schema.ts b/typescript-json-schema.ts index 2337b64c..45876994 100644 --- a/typescript-json-schema.ts +++ b/typescript-json-schema.ts @@ -59,6 +59,7 @@ export function getDefaultArgs(): Args { id: "", defaultNumberType: "number", tsNodeRegister: false, + constAsEnum: false, }; } @@ -89,6 +90,7 @@ export type Args = { id: string; defaultNumberType: "number" | "integer"; tsNodeRegister: boolean; + constAsEnum: boolean; }; export type PartialArgs = Partial; @@ -486,6 +488,12 @@ export class JsonSchemaGenerator { */ private userValidationKeywords: ValidationKeywords; + /** + * If true, this makes constants be defined as enums with a single value. This is useful + * for cases where constant values are not supported, such as OpenAPI. + */ + private constAsEnum: boolean; + /** * Types are assigned names which are looked up by their IDs. This is the * map from type IDs to type names. @@ -511,6 +519,7 @@ export class JsonSchemaGenerator { this.inheritingTypes = inheritingTypes; this.tc = tc; this.userValidationKeywords = args.validationKeywords.reduce((acc, word) => ({ ...acc, [word]: true }), {}); + this.constAsEnum = args.constAsEnum; } public get ReffedDefinitions(): { [key: string]: Definition } { @@ -709,7 +718,11 @@ export class JsonSchemaGenerator { default: throw new Error(`Not supported: ${value} as a enum value`); } - definition.const = value; + if (this.constAsEnum) { + definition.enum = [value]; + } else { + definition.const = value; + } } else if (arrayType !== undefined) { if ( propertyType.flags & ts.TypeFlags.Object &&