Skip to content

Commit

Permalink
feat: const keyword OpenAPI 3.0 draft
Browse files Browse the repository at this point in the history
  • Loading branch information
js2me committed Jul 19, 2023
1 parent f5960b9 commit d00e9c8
Show file tree
Hide file tree
Showing 8 changed files with 341 additions and 14 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# next release

feat: `const` keyword OpenAPI 3.0 draft
fix: problem with using `anyOf`
feat: `--extract-responses` (nodejs: `extractResponses`) option to extract all schemas from `/components/responses`

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"test:--extract-response-error": "node tests/spec/extractResponseError/test.js",
"test:--enum-names-as-values": "node tests/spec/enumNamesAsValues/test.js",
"test:--default-response": "node tests/spec/defaultResponse/test.js",
"test:const-keyword": "node tests/spec/const-keyword/test.js",
"test:--js": "node tests/spec/js/test.js",
"test:jsSingleHttpClientModular": "node tests/spec/jsSingleHttpClientModular/test.js",
"test:--js--axios": "node tests/spec/jsAxios/test.js",
Expand Down
2 changes: 1 addition & 1 deletion src/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ class CodeGenConfig {
/**
* $A
*/
NullValue: (content) => content,
NullValue: (content) => `null`,
/**
* $A1 | $A2
*/
Expand Down
59 changes: 46 additions & 13 deletions src/schema-parser/schema-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,24 +248,32 @@ class SchemaUtils {
);
}

const primitiveType = this.getSchemaPrimitiveType(schema);

if (primitiveType == null) return this.config.Ts.Keyword.Any;

let resultType;

const typeAlias =
_.get(this.config.primitiveTypes, [primitiveType, schema.format]) ||
_.get(this.config.primitiveTypes, [primitiveType, '$default']) ||
this.config.primitiveTypes[primitiveType];

if (_.isFunction(typeAlias)) {
resultType = typeAlias(schema, this);
if (this.isConstantSchema(schema)) {
resultType = this.formatJsValue(schema.const);
} else {
resultType = typeAlias || primitiveType;
const primitiveType = this.getSchemaPrimitiveType(schema);

if (primitiveType == null) {
return this.config.Ts.Keyword.Any;
}

const typeAlias =
_.get(this.config.primitiveTypes, [primitiveType, schema.format]) ||
_.get(this.config.primitiveTypes, [primitiveType, '$default']) ||
this.config.primitiveTypes[primitiveType];

if (_.isFunction(typeAlias)) {
resultType = typeAlias(schema, this);
} else {
resultType = typeAlias || primitiveType;
}
}

if (!resultType) return this.config.Ts.Keyword.Any;
if (!resultType) {
return this.config.Ts.Keyword.Any;
}

return this.checkAndAddRequiredKeys(
schema,
Expand All @@ -284,6 +292,31 @@ class SchemaUtils {
),
);
};

isConstantSchema(schema) {
return 'const' in schema;
}

formatJsValue = (value) => {
switch (typeof value) {
case 'string': {
return this.config.Ts.StringValue(value);
}
case 'boolean': {
return this.config.Ts.BooleanValue(value);
}
case 'number': {
return this.config.Ts.NumberValue(value);
}
default: {
if (value === null) {
return this.config.Ts.NullValue(value);
}

return this.config.Ts.Keyword.Any;
}
}
};
}

module.exports = {
Expand Down
91 changes: 91 additions & 0 deletions tests/spec/const-keyword/expected.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable */
/* tslint:disable */
/*
* ---------------------------------------------------------------
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
* ## ##
* ## AUTHOR: acacode ##
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
* ---------------------------------------------------------------
*/

export interface ObjTest {
/**
* title
* description
* @default "main"
*/
page_type?: "main";
/**
* title
* description
*/
page_type_nullable?: "main" | null;
}

/**
* title
* description
* @default "string"
*/
export type TestString = "string";

/**
* title
* description
*/
export type TestStringNullable = "string" | null;

/**
* title
* description
*/
export type TestBooleanNullable = false | null;

/**
* title
* description
* @default false
*/
export type TestBooleanFalse = false;

/**
* title
* description
* @default true
*/
export type TestBooleanTrue = true;

/**
* title
* description
* @default 5
*/
export type TestNumber5 = 5;

/**
* title
* description
*/
export type TestNumberNullable = 666 | null;

/**
* title
* description
* @default 0
*/
export type TestNumber0 = 0;

/**
* title
* description
* @default 10
*/
export type TestNumber10 = 10;

/**
* title
* description
* @default null
*/
export type TestNull = null;
88 changes: 88 additions & 0 deletions tests/spec/const-keyword/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"openapi": "3.0.1",
"info": {
"title": "Nullable Refs Example",
"version": "1.0.0"
},
"components": {
"schemas": {
"obj-test": {
"type": "object",
"properties": {
"page_type": {
"const": "main",
"default": "main",
"description": "description",
"title": "title"
},
"page_type_nullable": {
"const": "main",
"description": "description",
"title": "title",
"nullable": true
}
}
},
"test-string": {
"const": "string",
"default": "string",
"description": "description",
"title": "title"
},
"test-string-nullable": {
"const": "string",
"description": "description",
"title": "title",
"nullable": true
},
"test-boolean-nullable": {
"const": false,
"description": "description",
"title": "title",
"nullable": true
},
"test-boolean-false": {
"const": false,
"default": false,
"description": "description",
"title": "title"
},
"test-boolean-true": {
"const": true,
"default": true,
"description": "description",
"title": "title"
},
"test-number-5": {
"const": 5,
"default": 5,
"description": "description",
"title": "title"
},
"test-number-nullable": {
"const": 666,
"description": "description",
"title": "title",
"nullable": true,
},
"test-number-0": {
"const": 0,
"default": 0,
"description": "description",
"title": "title"
},
"test-number-10": {
"const": 10,
"default": 10,
"description": "description",
"title": "title"
},
"test-null": {
"const": null,
"default": null,
"description": "description",
"title": "title"
}
}
}
}
91 changes: 91 additions & 0 deletions tests/spec/const-keyword/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* eslint-disable */
/* tslint:disable */
/*
* ---------------------------------------------------------------
* ## THIS FILE WAS GENERATED VIA SWAGGER-TYPESCRIPT-API ##
* ## ##
* ## AUTHOR: acacode ##
* ## SOURCE: https://github.com/acacode/swagger-typescript-api ##
* ---------------------------------------------------------------
*/

export interface ObjTest {
/**
* title
* description
* @default "main"
*/
page_type?: "main";
/**
* title
* description
*/
page_type_nullable?: "main" | null;
}

/**
* title
* description
* @default "string"
*/
export type TestString = "string";

/**
* title
* description
*/
export type TestStringNullable = "string" | null;

/**
* title
* description
*/
export type TestBooleanNullable = false | null;

/**
* title
* description
* @default false
*/
export type TestBooleanFalse = false;

/**
* title
* description
* @default true
*/
export type TestBooleanTrue = true;

/**
* title
* description
* @default 5
*/
export type TestNumber5 = 5;

/**
* title
* description
*/
export type TestNumberNullable = 666 | null;

/**
* title
* description
* @default 0
*/
export type TestNumber0 = 0;

/**
* title
* description
* @default 10
*/
export type TestNumber10 = 10;

/**
* title
* description
* @default null
*/
export type TestNull = null;
22 changes: 22 additions & 0 deletions tests/spec/const-keyword/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { generateApiForTest } = require("../../helpers/generateApiForTest");
const { resolve } = require("path");
const validateGeneratedModule = require("../../helpers/validateGeneratedModule");
const assertGeneratedModule = require("../../helpers/assertGeneratedModule");
const createSchemaInfos = require("../../helpers/createSchemaInfos");

const schemas = createSchemaInfos({ absolutePathToSchemas: resolve(__dirname, "./") });

schemas.forEach(({ absolutePath, apiFileName }) => {
generateApiForTest({
testName: "const-keyword test",
silent: true,
name: apiFileName,
input: absolutePath,
output: resolve(__dirname, "./"),
addReadonly: true,
generateClient: false,
}).then(() => {
validateGeneratedModule(resolve(__dirname, `./${apiFileName}`));
assertGeneratedModule(resolve(__dirname, `./${apiFileName}`), resolve(__dirname, `./expected.ts`));
});
});

0 comments on commit d00e9c8

Please sign in to comment.