Skip to content

Commit a9bb215

Browse files
authored
add constAsEnum flag to convert constant values to single value enum (YousefED#571)
* add constAsEnum flag to convert constant values in properties to single value enum * fix lint
1 parent 3268f3b commit a9bb215

File tree

6 files changed

+41
-1
lines changed

6 files changed

+41
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ Options:
5151
--id Set schema id. [string] [default: ""]
5252
--defaultNumberType Default number type. [choices: "number", "integer"] [default: "number"]
5353
--tsNodeRegister Use ts-node/register (needed for require typescript files). [boolean] [default: false]
54+
--constAsEnum Use enums with a single value when declaring constants. [boolean] [default: false]
5455
```
5556

5657
### Programmatic use

test/programs/const-as-enum/main.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface MyObject {
2+
reference: true;
3+
}
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema#",
3+
"additionalProperties": false,
4+
"properties": {
5+
"reference": {
6+
"enum": [
7+
true
8+
],
9+
"type": "boolean"
10+
}
11+
},
12+
"required": [
13+
"reference"
14+
],
15+
"type": "object"
16+
}

test/schema.test.ts

+4
Original file line numberDiff line numberDiff line change
@@ -543,3 +543,7 @@ describe("satisfies keyword - ignore from a \"satisfies\" and build by rally typ
543543
describe("const keyword", () => {
544544
assertSchema("const-keyword", "Object");
545545
});
546+
547+
describe("constAsEnum option", () => {
548+
assertSchema("const-as-enum", "MyObject", { constAsEnum: true });
549+
});

typescript-json-schema-cli.ts

+3
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export function run() {
5353
.describe("defaultNumberType", "Default number type.")
5454
.boolean("tsNodeRegister").default("tsNodeRegister", defaultArgs.tsNodeRegister)
5555
.describe("tsNodeRegister", "Use ts-node/register (needed for requiring typescript files).")
56+
.boolean("constAsEnum").default("constAsEnum", defaultArgs.constAsEnum)
57+
.describe("constAsEnum", "Use enums with a single value when declaring constants. Needed for OpenAPI compatibility")
5658
.argv;
5759

5860
exec(args._[0], args._[1], {
@@ -78,6 +80,7 @@ export function run() {
7880
id: args.id,
7981
defaultNumberType: args.defaultNumberType,
8082
tsNodeRegister: args.tsNodeRegister,
83+
constAsEnum: args.constAsEnum,
8184
});
8285
}
8386

typescript-json-schema.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export function getDefaultArgs(): Args {
5959
id: "",
6060
defaultNumberType: "number",
6161
tsNodeRegister: false,
62+
constAsEnum: false,
6263
};
6364
}
6465

@@ -89,6 +90,7 @@ export type Args = {
8990
id: string;
9091
defaultNumberType: "number" | "integer";
9192
tsNodeRegister: boolean;
93+
constAsEnum: boolean;
9294
};
9395

9496
export type PartialArgs = Partial<Args>;
@@ -486,6 +488,12 @@ export class JsonSchemaGenerator {
486488
*/
487489
private userValidationKeywords: ValidationKeywords;
488490

491+
/**
492+
* If true, this makes constants be defined as enums with a single value. This is useful
493+
* for cases where constant values are not supported, such as OpenAPI.
494+
*/
495+
private constAsEnum: boolean;
496+
489497
/**
490498
* Types are assigned names which are looked up by their IDs. This is the
491499
* map from type IDs to type names.
@@ -511,6 +519,7 @@ export class JsonSchemaGenerator {
511519
this.inheritingTypes = inheritingTypes;
512520
this.tc = tc;
513521
this.userValidationKeywords = args.validationKeywords.reduce((acc, word) => ({ ...acc, [word]: true }), {});
522+
this.constAsEnum = args.constAsEnum;
514523
}
515524

516525
public get ReffedDefinitions(): { [key: string]: Definition } {
@@ -709,7 +718,11 @@ export class JsonSchemaGenerator {
709718
default:
710719
throw new Error(`Not supported: ${value} as a enum value`);
711720
}
712-
definition.const = value;
721+
if (this.constAsEnum) {
722+
definition.enum = [value];
723+
} else {
724+
definition.const = value;
725+
}
713726
} else if (arrayType !== undefined) {
714727
if (
715728
propertyType.flags & ts.TypeFlags.Object &&

0 commit comments

Comments
 (0)