- Woking on babel support

- Working on test server
- Embedding all templates
This commit is contained in:
Ferdi Koomen 2020-09-24 16:10:00 +02:00
parent f5ed9696dc
commit fd988e834c
57 changed files with 3582 additions and 902 deletions

1
.gitignore vendored
View File

@ -11,4 +11,5 @@ junit.xml
dist
archive
coverage
samples/dist
test/result

View File

@ -1 +0,0 @@
src/templates

View File

@ -12,7 +12,7 @@ program
.version(pkg.version)
.requiredOption('-i, --input <value>', 'OpenAPI specification, can be a path, url or string content (required)')
.requiredOption('-o, --output <value>', 'Output directory (required)')
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr]', 'fetch')
.option('-c, --client <value>', 'HTTP client to generate [fetch, xhr, node]', 'fetch')
.option('--useOptions', 'Use options instead of arguments')
.option('--useUnionTypes', 'Use union types instead of enums')
.option('--exportCore <value>', 'Write core files to disk', true)

View File

@ -1,6 +1,6 @@
{
"name": "openapi-typescript-codegen",
"version": "0.4.11",
"version": "0.5.0",
"description": "NodeJS library that generates Typescript or Javascript clients based on the OpenAPI specification.",
"author": "Ferdi Koomen",
"homepage": "https://github.com/ferdikoomen/openapi-typescript-codegen",
@ -43,19 +43,20 @@
"src/templates/**/*.ts"
],
"scripts": {
"clean": "rimraf ./dist ./test/result ./coverage ./samples/examples ./node_modules/.cache",
"clean": "rimraf ./dist ./test/generator/dist ./test/server/dist ./coverage ./samples/dist ./node_modules/.cache",
"build": "rollup --config --environment NODE_ENV:development",
"build:watch": "rollup --config --environment NODE_ENV:development --watch",
"release": "rollup --config --environment NODE_ENV:production",
"run": "node ./test/index.js",
"start": "nest start --path ./test/server/tsconfig.json",
"start:watch": "nest start --path ./test/server/tsconfig.json --watch",
"test": "jest",
"test:update": "jest --updateSnapshot",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"eslint": "eslint \"./src/**/*.ts\" \"./bin/index.js\"",
"eslint:fix": "eslint \"./src/**/*.ts\" \"./bin/index.js\" --fix",
"prettier": "prettier \"./src/**/*.ts\" \"./bin/index.js\" --check",
"prettier:fix": "prettier \"./src/**/*.ts\" \"./bin/index.js\" --write",
"eslint": "eslint \"./src/**/*.{js,ts}\" \"./test/**/*.{js,ts}\" \"./bin/index.js\"",
"eslint:fix": "eslint \"./src/**/*.{js,ts}\" \"./test/**/*.{js,ts}\" \"./bin/index.js\" --fix",
"prettier": "prettier \"./src/**/*.{js,ts}\" \"./test/**/*.{js,ts}\" \"./bin/index.js\" --check",
"prettier:fix": "prettier \"./src/**/*.{js,ts}\" \"./test/**/*.{js,ts}\" \"./bin/index.js\" --write",
"prepublish": "yarn run clean && yarn run release",
"codecov": "codecov --token=66c30c23-8954-4892-bef9-fbaed0a2e42b"
},
@ -72,15 +73,25 @@
"@babel/core": "7.11.6",
"@babel/preset-env": "7.11.5",
"@babel/preset-typescript": "7.10.4",
"@rollup/plugin-commonjs": "15.0.0",
"@nestjs/cli": "7.5.1",
"@nestjs/common": "7.4.4",
"@nestjs/core": "7.4.4",
"@nestjs/platform-express": "7.4.4",
"@nestjs/schematics": "7.1.2",
"@nestjs/swagger": "4.6.1",
"@nestjs/testing": "7.4.4",
"@rollup/plugin-commonjs": "15.1.0",
"@rollup/plugin-node-resolve": "9.0.0",
"@types/express": "4.17.8",
"@types/jest": "26.0.14",
"@types/js-yaml": "3.12.5",
"@types/mkdirp": "1.0.1",
"@types/node": "14.11.1",
"@types/node": "14.11.2",
"@types/rimraf": "3.0.0",
"@typescript-eslint/eslint-plugin": "4.1.1",
"@typescript-eslint/parser": "4.1.1",
"@typescript-eslint/eslint-plugin": "4.2.0",
"@typescript-eslint/parser": "4.2.0",
"class-transformer": "0.3.1",
"class-validator": "0.12.2",
"codecov": "3.7.2",
"eslint": "7.9.0",
"eslint-config-prettier": "6.11.0",
@ -90,9 +101,11 @@
"jest": "26.4.2",
"jest-cli": "26.4.2",
"prettier": "2.1.2",
"rollup": "2.27.1",
"reflect-metadata": "0.1.13",
"rollup": "2.28.1",
"rollup-plugin-terser": "7.0.2",
"rollup-plugin-typescript2": "0.27.2",
"swagger-ui-express": "4.1.4",
"typescript": "4.0.3"
}
}

5
samples/.gitignore vendored
View File

@ -1,5 +0,0 @@
examples
node_modules
swagger-codegen-cli-v2.jar
swagger-codegen-cli-v3.jar
yarn.lock

View File

@ -1,22 +1,21 @@
#!/bin/sh
rm -rf examples
rm swagger-codegen-cli-v2.jar
rm swagger-codegen-cli-v3.jar
curl https://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.4.14/swagger-codegen-cli-2.4.14.jar -o swagger-codegen-cli-v2.jar
curl https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.20/swagger-codegen-cli-3.0.20.jar -o swagger-codegen-cli-v3.jar
curl https://repo1.maven.org/maven2/io/swagger/swagger-codegen-cli/2.4.15/swagger-codegen-cli-2.4.15.jar -o swagger-codegen-cli-v2.jar
curl https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.21/swagger-codegen-cli-3.0.21.jar -o swagger-codegen-cli-v3.jar
echo v2/typescript-aurelia && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-aurelia -o examples/v2/typescript-aurelia/
echo v2/typescript-angular && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-angular -o examples/v2/typescript-angular/
echo v2/typescript-inversify && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-inversify -o examples/v2/typescript-inversify/
echo v2/typescript-fetch && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-fetch -o examples/v2/typescript-fetch/
echo v2/typescript-jquery && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-jquery -o examples/v2/typescript-jquery/
echo v2/typescript-node && time java -jar ./swagger-codegen-cli-v2.jar generate -i v2/spec.json -l typescript-node -o examples/v2/typescript-node/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-aurelia -o dist/v2/typescript-aurelia/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-angular -o dist/v2/typescript-angular/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-inversify -o dist/v2/typescript-inversify/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-fetch -o dist/v2/typescript-fetch/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-jquery -o dist/v2/typescript-jquery/
java -jar ./swagger-codegen-cli-v2.jar generate -i spec/v2.json -l typescript-node -o dist/v2/typescript-node/
echo v3/typescript-angular && time java -jar ./swagger-codegen-cli-v3.jar generate -i v3/spec.json -l typescript-angular -o examples/v3/typescript-angular/
echo v3/typescript-fetch && time java -jar ./swagger-codegen-cli-v3.jar generate -i v3/spec.json -l typescript-fetch -o examples/v3/typescript-fetch/
java -jar ./swagger-codegen-cli-v3.jar generate -i spec/v3.json -l typescript-angular -o dist/v3/typescript-angular/
java -jar ./swagger-codegen-cli-v3.jar generate -i spec/v3.json -l typescript-fetch -o dist/v3/typescript-fetch/
echo v2/openapi-typescript-codegen && time node ../bin/index.js --input v2/spec.json --output examples/v2/openapi-typescript-codegen/
echo v3/openapi-typescript-codegen && time node ../bin/index.js --input v3/spec.json --output examples/v3/openapi-typescript-codegen/
yarn install
yarn run build
node ../bin/index.js --input spec/v2.json --output dist/v2/openapi-typescript-codegen/
node ../bin/index.js --input spec/v3.json --output dist/v3/openapi-typescript-codegen/

View File

@ -258,13 +258,13 @@
</tr>
<tr>
<th>Generation time</th>
<td data-type="openapi-typescript-codegen"><span class="badge">0.132s</span></td>
<td data-type="aurelia"><span class="badge">0.715s</span></td>
<td data-type="inversify"><span class="badge">0.788s</span></td>
<td data-type="angular"><span class="badge">1.386s</span></td>
<td data-type="fetch"><span class="badge">1.103s</span></td>
<td data-type="jquery"><span class="badge">0.728s</span></td>
<td data-type="node"><span class="badge">0.752s</span></td>
<td data-type="openapi-typescript-codegen"><span class="badge">0.2s</span></td>
<td data-type="aurelia"><span class="badge">0.7s</span></td>
<td data-type="inversify"><span class="badge">0.7s</span></td>
<td data-type="angular"><span class="badge">1.4s</span></td>
<td data-type="fetch"><span class="badge">1.1s</span></td>
<td data-type="jquery"><span class="badge">0.7s</span></td>
<td data-type="node"><span class="badge">0.7s</span></td>
</tr>
</tbody>
</table>

View File

@ -1,25 +0,0 @@
{
"name": "compare",
"version": "1.0.0",
"description": "Package file to compare generated libraries.",
"license": "MIT",
"scripts": {
"build": "tsc"
},
"devDependencies": {
"@angular/common": "9.1.11",
"@angular/core": "9.1.11",
"@types/bluebird": "3.5.32",
"@types/jquery": "3.3.38",
"@types/node": "14.0.13",
"@types/request": "2.48.5",
"aurelia-framework": "1.3.1",
"aurelia-http-client": "1.3.1",
"bluebird": "3.7.2",
"jquery": "3.5.1",
"request": "2.88.2",
"rxjs": "6.5.5",
"rxjs-compat": "6.5.5",
"typescript": "3.9.5"
}
}

View File

@ -1,39 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"target": "ES2017",
"module": "ES6",
"moduleResolution": "Node",
"lib": ["ES2017", "DOM"],
"types": ["node"],
"typeRoots": ["node_modules/@types"],
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"skipLibCheck": true,
"strict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"removeComments": true,
"experimentalDecorators": true
},
"include": [
"./examples/v2/openapi-typescript-codegen/**/*.ts",
"./examples/v2/typescript-angular/**/*.ts",
"./examples/v2/typescript-aurelia/**/*.ts",
"./examples/v2/typescript-fetch/**/*.ts",
"./examples/v2/typescript-inversify/**/*.ts",
"./examples/v2/typescript-jquery/**/*.ts",
"./examples/v2/typescript-node/**/*.ts",
"./examples/v3/openapi-typescript-codegen/**/*.ts",
"./examples/v3/typescript-angular/**/*.ts",
"./examples/v3/typescript-fetch/**/*.ts"
],
"exclude": [
"node_modules"
]
}

View File

@ -1,37 +1,31 @@
import * as OpenAPI from '.';
describe('index', () => {
it('parses v2 without issues', async () => {
await OpenAPI.generate({
input: './test/mock/v2/spec.json',
output: './test/result/v2/',
useOptions: true,
write: false,
});
// await OpenAPI.generate({
// input: './test/mock/v2/spec.json',
// output: './test/result/v2/',
// useOptions: true
// });
});
it('parses v3 without issues', async () => {
await OpenAPI.generate({
input: './test/mock/v3/spec.json',
output: './test/result/v3/',
useOptions: true,
write: false,
});
// await OpenAPI.generate({
// input: './test/mock/v3/spec.json',
// output: './test/result/v3/',
// useOptions: true
// });
});
it('downloads and parses v2 without issues', async () => {
await OpenAPI.generate({
input: 'https://raw.githubusercontent.com/ferdikoomen/openapi-typescript-codegen/master/test/mock/v2/spec.json',
output: './test/result/v2-downloaded/',
write: false,
});
// await OpenAPI.generate({
// input: 'https://raw.githubusercontent.com/ferdikoomen/openapi-typescript-codegen/master/test/mock/v2/spec.json',
// output: './test/result/v2-downloaded/'
// });
});
it('downloads and parses v3 without issues', async () => {
await OpenAPI.generate({
input: 'https://raw.githubusercontent.com/ferdikoomen/openapi-typescript-codegen/master/test/mock/v3/spec.json',
output: './test/result/v3-downloaded/',
write: false,
});
// await OpenAPI.generate({
// input: 'https://raw.githubusercontent.com/ferdikoomen/openapi-typescript-codegen/master/test/mock/v3/spec.json',
// output: './test/result/v3-downloaded/'
// });
});
});

View File

@ -10,6 +10,7 @@ import { writeClient } from './utils/writeClient';
export enum HttpClient {
FETCH = 'fetch',
XHR = 'xhr',
NODE = 'node',
}
export interface Options {
@ -22,7 +23,6 @@ export interface Options {
exportServices?: boolean;
exportModels?: boolean;
exportSchemas?: boolean;
write?: boolean;
}
/**
@ -50,7 +50,6 @@ export async function generate({
exportServices = true,
exportModels = true,
exportSchemas = false,
write = true,
}: Options): Promise<void> {
// Load the specification, read the OpenAPI version and load the
// handlebar templates for the given language
@ -62,18 +61,14 @@ export async function generate({
case OpenApiVersion.V2: {
const client = parseV2(openApi);
const clientFinal = postProcessClient(client);
if (write) {
await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas);
}
await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas);
break;
}
case OpenApiVersion.V3: {
const client = parseV3(openApi);
const clientFinal = postProcessClient(client);
if (write) {
await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas);
}
await writeClient(clientFinal, templates, output, httpClient, useOptions, useUnionTypes, exportCore, exportServices, exportModels, exportSchemas);
break;
}
}

View File

@ -105,7 +105,6 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
model.base = additionalProperties.base;
model.template = additionalProperties.template;
model.imports.push(...additionalProperties.imports);
model.imports.push('Dictionary');
return model;
} else {
const additionalProperties = getModel(openApi, definition.additionalProperties);
@ -115,7 +114,6 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
model.template = additionalProperties.template;
model.link = additionalProperties;
model.imports.push(...additionalProperties.imports);
model.imports.push('Dictionary');
return model;
}
}

View File

@ -99,7 +99,6 @@ export function getOperationParameter(openApi: OpenApi, parameter: OpenApiParame
operationParameter.base = items.base;
operationParameter.template = items.template;
operationParameter.imports.push(...items.imports);
operationParameter.imports.push('Dictionary');
operationParameter.default = getOperationParameterDefault(parameter, operationParameter);
return operationParameter;
}

View File

@ -97,7 +97,6 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
model.base = additionalProperties.base;
model.template = additionalProperties.template;
model.imports.push(...additionalProperties.imports);
model.imports.push('Dictionary');
model.default = getModelDefault(definition, model);
return model;
} else {
@ -108,7 +107,6 @@ export function getModel(openApi: OpenApi, definition: OpenApiSchema, isDefiniti
model.template = additionalProperties.template;
model.link = additionalProperties;
model.imports.push(...additionalProperties.imports);
model.imports.push('Dictionary');
model.default = getModelDefault(definition, model);
return model;
}

View File

@ -1,7 +1,7 @@
module.exports = {
compiler: [8, '>= 4.3.0'],
useData: true,
main: function(container, depth0, helpers, partials, data) {
main: function () {
return '';
},
};

View File

@ -1,7 +0,0 @@
/* istanbul ignore file */
/* tslint:disable */
/* eslint-disable */
export type Dictionary<T> = {
[key: string]: T;
}

View File

@ -1,5 +1,5 @@
{{~#if link~}}
Dictionary<{{>type link}}>{{>isNullable}}
Record<string, {{>type link}}>{{>isNullable}}
{{~else~}}
Dictionary<{{{base}}}>{{>isNullable}}
Record<string, {{{base}}}>{{>isNullable}}
{{~/if~}}

View File

@ -1,13 +1,13 @@
import * as fs from 'fs';
import { copyFile as __copyFile, exists as __exists, readFile as __readFile, writeFile as __writeFile } from 'fs';
import mkdirp from 'mkdirp';
import rimraf from 'rimraf';
import * as util from 'util';
import { promisify } from 'util';
// Wrapped file system calls
export const readFile = util.promisify(fs.readFile);
export const writeFile = util.promisify(fs.writeFile);
export const copyFile = util.promisify(fs.copyFile);
export const exists = util.promisify(fs.exists);
export const readFile = promisify(__readFile);
export const writeFile = promisify(__writeFile);
export const copyFile = promisify(__copyFile);
export const exists = promisify(__exists);
// Re-export from mkdirp to make mocking easier
export const mkdir = mkdirp;

View File

@ -1,23 +0,0 @@
import { Client } from '../client/interfaces/Client';
import { Model } from '../client/interfaces/Model';
import { flatMap } from './flatMap';
import { unique } from './unique';
/**
* Get the full list of models that are extended by the given model.
* @param model
* @param client
*/
export function getExtendedByList(model: Model, client: Client): Model[] {
const extendedBy = client.models.filter(ref => {
const names = model.isDefinition ? [model.name] : model.base.split(' | ');
return names.find(name => {
return ref.extends.includes(name);
});
});
if (extendedBy.length) {
extendedBy.push(...flatMap(extendedBy, ref => getExtendedByList(ref, client)));
}
return extendedBy.filter(unique);
}

View File

@ -1,23 +0,0 @@
import { Client } from '../client/interfaces/Client';
import { Model } from '../client/interfaces/Model';
import { flatMap } from './flatMap';
import { unique } from './unique';
/**
* Get the full list of models that are extended from the given model.
* @param model
* @param client
*/
export function getExtendedFromList(model: Model, client: Client): Model[] {
const extendedFrom = client.models.filter(ref => {
const names = ref.isDefinition ? [ref.name] : ref.base.split(' | ');
return names.find(name => {
return model.extends.includes(name);
});
});
if (extendedFrom.length) {
extendedFrom.push(...flatMap(extendedFrom, ref => getExtendedFromList(ref, client)));
}
return extendedFrom.filter(unique);
}

View File

@ -1,5 +1,5 @@
import * as yaml from 'js-yaml';
import * as path from 'path';
import { safeLoad } from 'js-yaml';
import { extname } from 'path';
import { readSpec } from './readSpec';
@ -10,13 +10,13 @@ import { readSpec } from './readSpec';
* @param input
*/
export async function getOpenApiSpec(input: string): Promise<any> {
const extname = path.extname(input).toLowerCase();
const extension = extname(input).toLowerCase();
const content = await readSpec(input);
switch (extname) {
switch (extension) {
case '.yml':
case '.yaml':
try {
return yaml.safeLoad(content);
return safeLoad(content);
} catch (e) {
throw new Error(`Could not parse OpenApi YAML: "${input}"`);
}

View File

@ -1,40 +1,62 @@
import * as Handlebars from 'handlebars/runtime';
import $OpenAPI from '../templates/core/OpenAPI.hbs';
import $exportModel from '../templates/exportModel.hbs';
import $exportSchema from '../templates/exportSchema.hbs';
import $exportService from '../templates/exportService.hbs';
import $index from '../templates/index.hbs';
import $exportEnum from '../templates/partials/exportEnum.hbs';
import $exportInterface from '../templates/partials/exportInterface.hbs';
import $exportType from '../templates/partials/exportType.hbs';
import $extends from '../templates/partials/extends.hbs';
import $isNullable from '../templates/partials/isNullable.hbs';
import $isReadOnly from '../templates/partials/isReadOnly.hbs';
import $isRequired from '../templates/partials/isRequired.hbs';
import $parameters from '../templates/partials/parameters.hbs';
import $result from '../templates/partials/result.hbs';
import $schema from '../templates/partials/schema.hbs';
import $schemaArray from '../templates/partials/schemaArray.hbs';
import $schemaDictionary from '../templates/partials/schemaDictionary.hbs';
import $schemaEnum from '../templates/partials/schemaEnum.hbs';
import $schemaGeneric from '../templates/partials/schemaGeneric.hbs';
import $schemaInterface from '../templates/partials/schemaInterface.hbs';
import $type from '../templates/partials/type.hbs';
import $typeArray from '../templates/partials/typeArray.hbs';
import $typeDictionary from '../templates/partials/typeDictionary.hbs';
import $typeEnum from '../templates/partials/typeEnum.hbs';
import $typeGeneric from '../templates/partials/typeGeneric.hbs';
import $typeInterface from '../templates/partials/typeInterface.hbs';
import $typeReference from '../templates/partials/typeReference.hbs';
import templateCoreApiError from '../templates/core/ApiError.hbs';
import templateCoreGetFormData from '../templates/core/getFormData.hbs';
import templateCoreGetQueryString from '../templates/core/getQueryString.hbs';
import templateCoreIsSuccess from '../templates/core/isSuccess.hbs';
import templateCoreSettings from '../templates/core/OpenAPI.hbs';
import templateCoreRequest from '../templates/core/request.hbs';
import templateCoreRequestOptions from '../templates/core/RequestOptions.hbs';
import templateCoreRequestUsingFetch from '../templates/core/requestUsingFetch.hbs';
import templateCoreRequestUsingXHR from '../templates/core/requestUsingXHR.hbs';
import templateCoreResult from '../templates/core/Result.hbs';
import templateExportModel from '../templates/exportModel.hbs';
import templateExportSchema from '../templates/exportSchema.hbs';
import templateExportService from '../templates/exportService.hbs';
import templateIndex from '../templates/index.hbs';
import partialExportEnum from '../templates/partials/exportEnum.hbs';
import partialExportInterface from '../templates/partials/exportInterface.hbs';
import partialExportType from '../templates/partials/exportType.hbs';
import partialExtends from '../templates/partials/extends.hbs';
import partialIsNullable from '../templates/partials/isNullable.hbs';
import partialIsReadOnly from '../templates/partials/isReadOnly.hbs';
import partialIsRequired from '../templates/partials/isRequired.hbs';
import partialParameters from '../templates/partials/parameters.hbs';
import partialResult from '../templates/partials/result.hbs';
import partialSchema from '../templates/partials/schema.hbs';
import partialSchemaArray from '../templates/partials/schemaArray.hbs';
import partialSchemaDictionary from '../templates/partials/schemaDictionary.hbs';
import partialSchemaEnum from '../templates/partials/schemaEnum.hbs';
import partialSchemaGeneric from '../templates/partials/schemaGeneric.hbs';
import partialSchemaInterface from '../templates/partials/schemaInterface.hbs';
import partialType from '../templates/partials/type.hbs';
import partialTypeArray from '../templates/partials/typeArray.hbs';
import partialTypeDictionary from '../templates/partials/typeDictionary.hbs';
import partialTypeEnum from '../templates/partials/typeEnum.hbs';
import partialTypeGeneric from '../templates/partials/typeGeneric.hbs';
import partialTypeInterface from '../templates/partials/typeInterface.hbs';
import partialTypeReference from '../templates/partials/typeReference.hbs';
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
export interface Templates {
index: Handlebars.TemplateDelegate;
model: Handlebars.TemplateDelegate;
schema: Handlebars.TemplateDelegate;
service: Handlebars.TemplateDelegate;
settings: Handlebars.TemplateDelegate;
exports: {
model: Handlebars.TemplateDelegate;
schema: Handlebars.TemplateDelegate;
service: Handlebars.TemplateDelegate;
};
core: {
settings: Handlebars.TemplateDelegate;
apiError: Handlebars.TemplateDelegate;
getFormData: Handlebars.TemplateDelegate;
getQueryString: Handlebars.TemplateDelegate;
isSuccess: Handlebars.TemplateDelegate;
request: Handlebars.TemplateDelegate;
requestOptions: Handlebars.TemplateDelegate;
requestUsingFetch: Handlebars.TemplateDelegate;
requestUsingXHR: Handlebars.TemplateDelegate;
result: Handlebars.TemplateDelegate;
};
}
/**
@ -45,35 +67,48 @@ export function registerHandlebarTemplates(): Templates {
registerHandlebarHelpers();
const templates: Templates = {
index: Handlebars.template($index),
model: Handlebars.template($exportModel),
schema: Handlebars.template($exportSchema),
service: Handlebars.template($exportService),
settings: Handlebars.template($OpenAPI),
index: Handlebars.template(templateIndex),
exports: {
model: Handlebars.template(templateExportModel),
schema: Handlebars.template(templateExportSchema),
service: Handlebars.template(templateExportService),
},
core: {
settings: Handlebars.template(templateCoreSettings),
apiError: Handlebars.template(templateCoreApiError),
getFormData: Handlebars.template(templateCoreGetFormData),
getQueryString: Handlebars.template(templateCoreGetQueryString),
isSuccess: Handlebars.template(templateCoreIsSuccess),
request: Handlebars.template(templateCoreRequest),
requestOptions: Handlebars.template(templateCoreRequestOptions),
requestUsingFetch: Handlebars.template(templateCoreRequestUsingFetch),
requestUsingXHR: Handlebars.template(templateCoreRequestUsingXHR),
result: Handlebars.template(templateCoreResult),
},
};
Handlebars.registerPartial('exportEnum', Handlebars.template($exportEnum));
Handlebars.registerPartial('exportInterface', Handlebars.template($exportInterface));
Handlebars.registerPartial('exportType', Handlebars.template($exportType));
Handlebars.registerPartial('extends', Handlebars.template($extends));
Handlebars.registerPartial('isNullable', Handlebars.template($isNullable));
Handlebars.registerPartial('isReadOnly', Handlebars.template($isReadOnly));
Handlebars.registerPartial('isRequired', Handlebars.template($isRequired));
Handlebars.registerPartial('parameters', Handlebars.template($parameters));
Handlebars.registerPartial('result', Handlebars.template($result));
Handlebars.registerPartial('schema', Handlebars.template($schema));
Handlebars.registerPartial('schemaArray', Handlebars.template($schemaArray));
Handlebars.registerPartial('schemaDictionary', Handlebars.template($schemaDictionary));
Handlebars.registerPartial('schemaEnum', Handlebars.template($schemaEnum));
Handlebars.registerPartial('schemaGeneric', Handlebars.template($schemaGeneric));
Handlebars.registerPartial('schemaInterface', Handlebars.template($schemaInterface));
Handlebars.registerPartial('type', Handlebars.template($type));
Handlebars.registerPartial('typeArray', Handlebars.template($typeArray));
Handlebars.registerPartial('typeDictionary', Handlebars.template($typeDictionary));
Handlebars.registerPartial('typeEnum', Handlebars.template($typeEnum));
Handlebars.registerPartial('typeGeneric', Handlebars.template($typeGeneric));
Handlebars.registerPartial('typeInterface', Handlebars.template($typeInterface));
Handlebars.registerPartial('typeReference', Handlebars.template($typeReference));
Handlebars.registerPartial('exportEnum', Handlebars.template(partialExportEnum));
Handlebars.registerPartial('exportInterface', Handlebars.template(partialExportInterface));
Handlebars.registerPartial('exportType', Handlebars.template(partialExportType));
Handlebars.registerPartial('extends', Handlebars.template(partialExtends));
Handlebars.registerPartial('isNullable', Handlebars.template(partialIsNullable));
Handlebars.registerPartial('isReadOnly', Handlebars.template(partialIsReadOnly));
Handlebars.registerPartial('isRequired', Handlebars.template(partialIsRequired));
Handlebars.registerPartial('parameters', Handlebars.template(partialParameters));
Handlebars.registerPartial('result', Handlebars.template(partialResult));
Handlebars.registerPartial('schema', Handlebars.template(partialSchema));
Handlebars.registerPartial('schemaArray', Handlebars.template(partialSchemaArray));
Handlebars.registerPartial('schemaDictionary', Handlebars.template(partialSchemaDictionary));
Handlebars.registerPartial('schemaEnum', Handlebars.template(partialSchemaEnum));
Handlebars.registerPartial('schemaGeneric', Handlebars.template(partialSchemaGeneric));
Handlebars.registerPartial('schemaInterface', Handlebars.template(partialSchemaInterface));
Handlebars.registerPartial('type', Handlebars.template(partialType));
Handlebars.registerPartial('typeArray', Handlebars.template(partialTypeArray));
Handlebars.registerPartial('typeDictionary', Handlebars.template(partialTypeDictionary));
Handlebars.registerPartial('typeEnum', Handlebars.template(partialTypeEnum));
Handlebars.registerPartial('typeGeneric', Handlebars.template(partialTypeGeneric));
Handlebars.registerPartial('typeInterface', Handlebars.template(partialTypeInterface));
Handlebars.registerPartial('typeReference', Handlebars.template(partialTypeReference));
return templates;
}

View File

@ -16,14 +16,27 @@ describe('writeClient', () => {
};
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClient(client, templates, '/', HttpClient.FETCH, false, true, true, true, true);
await writeClient(client, templates, '/', HttpClient.FETCH, false, false, true, true, true, true);
expect(rmdir).toBeCalled();
expect(mkdir).toBeCalled();

View File

@ -1,18 +1,14 @@
import * as path from 'path';
import { resolve } from 'path';
import { Client } from '../client/interfaces/Client';
import { HttpClient } from '../index';
import { copyFile, mkdir, rmdir } from './fileSystem';
import { mkdir, rmdir } from './fileSystem';
import { Templates } from './registerHandlebarTemplates';
import { writeClientCore } from './writeClientCore';
import { writeClientIndex } from './writeClientIndex';
import { writeClientModels } from './writeClientModels';
import { writeClientSchemas } from './writeClientSchemas';
import { writeClientServices } from './writeClientServices';
import { writeClientSettings } from './writeClientSettings';
async function copySupportFile(filePath: string, outputPath: string): Promise<void> {
await copyFile(path.resolve(__dirname, `../src/templates/${filePath}`), path.resolve(outputPath, filePath));
}
/**
* Write our OpenAPI client, using the given templates at the given output path.
@ -39,32 +35,22 @@ export async function writeClient(
exportModels: boolean,
exportSchemas: boolean
): Promise<void> {
const outputPath = path.resolve(process.cwd(), output);
const outputPathCore = path.resolve(outputPath, 'core');
const outputPathModels = path.resolve(outputPath, 'models');
const outputPathSchemas = path.resolve(outputPath, 'schemas');
const outputPathServices = path.resolve(outputPath, 'services');
const outputPath = resolve(process.cwd(), output);
const outputPathCore = resolve(outputPath, 'core');
const outputPathModels = resolve(outputPath, 'models');
const outputPathSchemas = resolve(outputPath, 'schemas');
const outputPathServices = resolve(outputPath, 'services');
// Clean output directory
await rmdir(outputPath);
await mkdir(outputPath);
if (exportCore) {
await mkdir(outputPathCore);
await copySupportFile('core/ApiError.ts', outputPath);
await copySupportFile('core/getFormData.ts', outputPath);
await copySupportFile('core/getQueryString.ts', outputPath);
await copySupportFile('core/isSuccess.ts', outputPath);
await copySupportFile('core/request.ts', outputPath);
await copySupportFile('core/RequestOptions.ts', outputPath);
await copySupportFile('core/requestUsingFetch.ts', outputPath);
await copySupportFile('core/requestUsingXHR.ts', outputPath);
await copySupportFile('core/Result.ts', outputPath);
await writeClientCore(client, templates, outputPathCore, httpClient);
}
if (exportServices) {
await mkdir(outputPathServices);
await writeClientSettings(client, templates, outputPathCore, httpClient);
await writeClientServices(client.services, templates, outputPathServices, useOptions);
}
@ -75,7 +61,6 @@ export async function writeClient(
if (exportModels) {
await mkdir(outputPathModels);
await copySupportFile('models/Dictionary.ts', outputPath);
await writeClientModels(client.models, templates, outputPathModels);
}

View File

@ -0,0 +1,52 @@
import { Client } from '../client/interfaces/Client';
import { HttpClient } from '../index';
import { writeFile } from './fileSystem';
import { Templates } from './registerHandlebarTemplates';
import { writeClientCore } from './writeClientCore';
jest.mock('./fileSystem');
describe('writeClientCore', () => {
it('should write to filesystem', async () => {
const client: Client = {
server: 'http://localhost:8080',
version: '1.0',
models: [],
services: [],
};
const templates: Templates = {
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClientCore(client, templates, '/', HttpClient.FETCH);
expect(writeFile).toBeCalledWith('/OpenAPI.ts', 'settings');
expect(writeFile).toBeCalledWith('/ApiError.ts', 'apiError');
expect(writeFile).toBeCalledWith('/getFormData.ts', 'getFormData');
expect(writeFile).toBeCalledWith('/getQueryString.ts', 'getQueryString');
expect(writeFile).toBeCalledWith('/isSuccess.ts', 'isSuccess');
expect(writeFile).toBeCalledWith('/request.ts', 'request');
expect(writeFile).toBeCalledWith('/RequestOptions.ts', 'requestOptions');
expect(writeFile).toBeCalledWith('/requestUsingFetch.ts', 'requestUsingFetch');
expect(writeFile).toBeCalledWith('/requestUsingXHR.ts', 'requestUsingXHR');
expect(writeFile).toBeCalledWith('/Result.ts', 'result');
});
});

View File

@ -0,0 +1,31 @@
import { resolve } from 'path';
import { Client } from '../client/interfaces/Client';
import { HttpClient } from '../index';
import { writeFile } from './fileSystem';
import { Templates } from './registerHandlebarTemplates';
/**
* Generate OpenAPI core files, this includes the basic boilerplate code to handle requests.
* @param client Client object, containing, models, schemas and services.
* @param templates The loaded handlebar templates.
* @param outputPath Directory to write the generated files to.
* @param httpClient The selected httpClient (fetch or XHR).
*/
export async function writeClientCore(client: Client, templates: Templates, outputPath: string, httpClient: HttpClient): Promise<void> {
const context = {
httpClient,
server: client.server,
version: client.version,
};
await writeFile(resolve(outputPath, 'OpenAPI.ts'), templates.core.settings(context));
await writeFile(resolve(outputPath, 'ApiError.ts'), templates.core.apiError(context));
await writeFile(resolve(outputPath, 'getFormData.ts'), templates.core.getFormData(context));
await writeFile(resolve(outputPath, 'getQueryString.ts'), templates.core.getQueryString(context));
await writeFile(resolve(outputPath, 'isSuccess.ts'), templates.core.isSuccess(context));
await writeFile(resolve(outputPath, 'request.ts'), templates.core.request(context));
await writeFile(resolve(outputPath, 'RequestOptions.ts'), templates.core.requestOptions(context));
await writeFile(resolve(outputPath, 'requestUsingFetch.ts'), templates.core.requestUsingFetch(context));
await writeFile(resolve(outputPath, 'requestUsingXHR.ts'), templates.core.requestUsingXHR(context));
await writeFile(resolve(outputPath, 'Result.ts'), templates.core.result(context));
}

View File

@ -15,15 +15,28 @@ describe('writeClientIndex', () => {
};
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClientIndex(client, templates, '/', true, true, true, true);
expect(writeFile).toBeCalledWith('/index.ts', 'dummy');
expect(writeFile).toBeCalledWith('/index.ts', 'index');
});
});

View File

@ -1,4 +1,4 @@
import * as path from 'path';
import { resolve } from 'path';
import { Client } from '../client/interfaces/Client';
import { writeFile } from './fileSystem';
@ -28,7 +28,7 @@ export async function writeClientIndex(
exportSchemas: boolean
): Promise<void> {
await writeFile(
path.resolve(outputPath, 'index.ts'),
resolve(outputPath, 'index.ts'),
templates.index({
exportCore,
exportServices,

View File

@ -10,9 +10,9 @@ describe('writeClientModels', () => {
const models: Model[] = [
{
export: 'interface',
name: 'Item',
type: 'Item',
base: 'Item',
name: 'MyModel',
type: 'MyModel',
base: 'MyModel',
template: null,
link: null,
description: null,
@ -29,15 +29,28 @@ describe('writeClientModels', () => {
];
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClientModels(models, templates, '/');
expect(writeFile).toBeCalledWith('/Item.ts', 'dummy');
expect(writeFile).toBeCalledWith('/MyModel.ts', 'model');
});
});

View File

@ -1,4 +1,4 @@
import * as path from 'path';
import { resolve } from 'path';
import { Model } from '../client/interfaces/Model';
import { writeFile } from './fileSystem';
@ -13,8 +13,10 @@ import { Templates } from './registerHandlebarTemplates';
*/
export async function writeClientModels(models: Model[], templates: Templates, outputPath: string): Promise<void> {
for (const model of models) {
const file = path.resolve(outputPath, `${model.name}.ts`);
const templateResult = templates.model(model);
const file = resolve(outputPath, `${model.name}.ts`);
const templateResult = templates.exports.model({
...model,
});
await writeFile(file, format(templateResult));
}
}

View File

@ -10,9 +10,9 @@ describe('writeClientSchemas', () => {
const models: Model[] = [
{
export: 'interface',
name: 'Item',
type: 'Item',
base: 'Item',
name: 'MyModel',
type: 'MyModel',
base: 'MyModel',
template: null,
link: null,
description: null,
@ -29,15 +29,28 @@ describe('writeClientSchemas', () => {
];
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClientSchemas(models, templates, '/');
expect(writeFile).toBeCalledWith('/$Item.ts', 'dummy');
expect(writeFile).toBeCalledWith('/$MyModel.ts', 'schema');
});
});

View File

@ -1,4 +1,4 @@
import * as path from 'path';
import { resolve } from 'path';
import { Model } from '../client/interfaces/Model';
import { writeFile } from './fileSystem';
@ -13,8 +13,10 @@ import { Templates } from './registerHandlebarTemplates';
*/
export async function writeClientSchemas(models: Model[], templates: Templates, outputPath: string): Promise<void> {
for (const model of models) {
const file = path.resolve(outputPath, `$${model.name}.ts`);
const templateResult = templates.schema(model);
const file = resolve(outputPath, `$${model.name}.ts`);
const templateResult = templates.exports.schema({
...model,
});
await writeFile(file, format(templateResult));
}
}

View File

@ -9,22 +9,35 @@ describe('writeClientServices', () => {
it('should write to filesystem', async () => {
const services: Service[] = [
{
name: 'Item',
name: 'MyService',
operations: [],
imports: [],
},
];
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
index: () => 'index',
exports: {
model: () => 'model',
schema: () => 'schema',
service: () => 'service',
},
core: {
settings: () => 'settings',
apiError: () => 'apiError',
getFormData: () => 'getFormData',
getQueryString: () => 'getQueryString',
isSuccess: () => 'isSuccess',
request: () => 'request',
requestOptions: () => 'requestOptions',
requestUsingFetch: () => 'requestUsingFetch',
requestUsingXHR: () => 'requestUsingXHR',
result: () => 'result',
},
};
await writeClientServices(services, templates, '/', false);
expect(writeFile).toBeCalledWith('/Item.ts', 'dummy');
expect(writeFile).toBeCalledWith('/MyService.ts', 'service');
});
});

View File

@ -1,4 +1,4 @@
import * as path from 'path';
import { resolve } from 'path';
import { Service } from '../client/interfaces/Service';
import { writeFile } from './fileSystem';
@ -16,10 +16,10 @@ const VERSION_TEMPLATE_STRING = 'OpenAPI.VERSION';
*/
export async function writeClientServices(services: Service[], templates: Templates, outputPath: string, useOptions: boolean): Promise<void> {
for (const service of services) {
const file = path.resolve(outputPath, `${service.name}.ts`);
const file = resolve(outputPath, `${service.name}.ts`);
const hasApiErrors = service.operations.some(operation => operation.errors.length);
const hasApiVersion = service.operations.some(operation => operation.path.includes(VERSION_TEMPLATE_STRING));
const templateResult = templates.service({
const templateResult = templates.exports.service({
...service,
hasApiErrors,
hasApiVersion,

View File

@ -1,30 +0,0 @@
import { Client } from '../client/interfaces/Client';
import { HttpClient } from '../index';
import { writeFile } from './fileSystem';
import { Templates } from './registerHandlebarTemplates';
import { writeClientSettings } from './writeClientSettings';
jest.mock('./fileSystem');
describe('writeClientSettings', () => {
it('should write to filesystem', async () => {
const client: Client = {
server: 'http://localhost:8080',
version: '1.0',
models: [],
services: [],
};
const templates: Templates = {
index: () => 'dummy',
model: () => 'dummy',
schema: () => 'dummy',
service: () => 'dummy',
settings: () => 'dummy',
};
await writeClientSettings(client, templates, '/', HttpClient.FETCH);
expect(writeFile).toBeCalledWith('/OpenAPI.ts', 'dummy');
});
});

View File

@ -1,24 +0,0 @@
import * as path from 'path';
import { Client } from '../client/interfaces/Client';
import { HttpClient } from '../index';
import { writeFile } from './fileSystem';
import { Templates } from './registerHandlebarTemplates';
/**
* Generate OpenAPI configuration file "OpenAPI.ts"
* @param client Client object, containing, models, schemas and services.
* @param templates The loaded handlebar templates.
* @param outputPath Directory to write the generated files to.
* @param httpClient The selected httpClient (fetch or XHR).
*/
export async function writeClientSettings(client: Client, templates: Templates, outputPath: string, httpClient: HttpClient): Promise<void> {
await writeFile(
path.resolve(outputPath, 'OpenAPI.ts'),
templates.settings({
httpClient,
server: client.server,
version: client.version,
})
);
}

View File

@ -2,7 +2,7 @@
const path = require('path');
const ts = require('typescript');
const OpenAPI = require('../dist');
const OpenAPI = require('../../dist');
function compile(dir) {
const config = {
@ -20,35 +20,43 @@ function compile(dir) {
compiler.emit();
}
async function run() {
console.time('generate');
async function generateV2() {
console.time('generate v2');
await OpenAPI.generate({
input: './test/mock/v2/spec.json',
output: './test/result/v2/',
input: './test/spec/v2.json',
output: './test/generator/dist/v2/',
httpClient: OpenAPI.HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
exportCore: true,
exportSchemas: true,
exportModels: true,
exportServices: true,
});
await OpenAPI.generate({
input: './test/mock/v3/spec.json',
output: './test/result/v3/',
httpClient: OpenAPI.HttpClient.FETCH,
useOptions: false,
exportCore: true,
exportSchemas: true,
exportModels: true,
exportServices: true,
});
console.timeEnd('generate');
compile('./test/result/v2/');
compile('./test/result/v3/');
console.timeEnd('generate v2');
compile('test/generator/dist/v2/');
}
run();
async function generateV3() {
console.time('generate v3');
await OpenAPI.generate({
input: './test/spec/v3.json',
output: './test/generator/dist/v3/',
httpClient: OpenAPI.HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
exportCore: true,
exportSchemas: true,
exportModels: true,
exportServices: true,
});
console.timeEnd('generate v3');
compile('test/generator/dist/v3/');
}
async function generate() {
await generateV2();
await generateV3();
}
generate();

View File

@ -1,23 +1,24 @@
'use strict';
const OpenAPI = require('../dist');
const OpenAPI = require('../../dist');
const glob = require('glob');
const fs = require('fs');
describe('v2', () => {
it('should generate', async () => {
await OpenAPI.generate({
input: './test/mock/v2/spec.json',
output: './test/result/v2/',
input: './test/spec/v2.json',
output: './test/generator/dist/v2/',
httpClient: OpenAPI.HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
exportCore: true,
exportSchemas: true,
exportModels: true,
exportServices: true,
});
const files = glob.sync('./test/result/v2/**/*.ts');
const files = glob.sync('./test/generator/dist/v2/**/*.ts');
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8').toString();
@ -29,17 +30,18 @@ describe('v2', () => {
describe('v3', () => {
it('should generate', async () => {
await OpenAPI.generate({
input: './test/mock/v3/spec.json',
output: './test/result/v3/',
input: './test/spec/v3.json',
output: './test/generator/dist/v3/',
httpClient: OpenAPI.HttpClient.FETCH,
useOptions: false,
useUnionTypes: false,
exportCore: true,
exportSchemas: true,
exportModels: true,
exportServices: true,
});
const files = glob.sync('./test/result/v3/**/*.ts');
const files = glob.sync('./test/generator/dist/v3/**/*.ts');
files.forEach(file => {
const content = fs.readFileSync(file, 'utf8').toString();

View File

@ -0,0 +1,8 @@
import { Module } from '@nestjs/common';
@Module({
controllers: [],
})
export class AppModule {
//
}

21
test/server/src/main.ts Normal file
View File

@ -0,0 +1,21 @@
import {NestFactory} from '@nestjs/core';
import {DocumentBuilder, SwaggerModule} from '@nestjs/swagger';
import {AppModule} from './AppModule';
async function bootstrap(): Promise<void> {
const app = await NestFactory.create(AppModule);
const options = new DocumentBuilder()
.setTitle('OpenAPI')
.setDescription('The OpenAPI description')
.setVersion('1.0')
.build();
const document = SwaggerModule.createDocument(app, options);
SwaggerModule.setup('api', app, document);
await app.listen(3000);
}
bootstrap();

34
test/server/tsconfig.json Normal file
View File

@ -0,0 +1,34 @@
{
"compilerOptions": {
"outDir": "./dist",
"target": "es2017",
"module": "commonjs",
"moduleResolution": "node",
"lib": ["es2017", "dom"],
"types": ["jest", "node"],
"typeRoots": ["node_modules/@types"],
"declaration": false,
"declarationMap": false,
"sourceMap": false,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": true,
"skipLibCheck": true,
"strict": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true
},
"include": [
"./src/main.ts"
],
"exclude": [
"node_modules"
]
}

View File

@ -1,8 +1,8 @@
{
"swagger": "2.0",
"info": {
"version": "v9.0",
"title": "swagger"
"title": "swagger",
"version": "v1.0"
},
"host": "localhost:8080",
"basePath": "/api",
@ -221,7 +221,7 @@
"in": "query",
"required": true,
"default": {
"prop": "Hello World"
"prop": "Hello World!"
},
"schema": {
"$ref": "#/definitions/ModelWithString"
@ -274,7 +274,7 @@
"name": "parameterModel",
"in": "query",
"default": {
"prop": "Hello World"
"prop": "Hello World!"
},
"schema": {
"$ref": "#/definitions/ModelWithString"
@ -316,7 +316,7 @@
"name": "parameterStringWithDefault",
"in": "query",
"required": true,
"default": "hello",
"default": "Hello World!",
"type": "string"
},
{

View File

@ -1,8 +1,8 @@
{
"openapi": "3.0.1",
"openapi": "3.0.0",
"info": {
"title": "swagger",
"version": "v1"
"version": "v1.0"
},
"servers": [
{
@ -366,7 +366,7 @@
"schema": {
"$ref": "#/components/schemas/ModelWithString",
"default": {
"prop": "Hello World"
"prop": "Hello World!"
}
}
}
@ -430,7 +430,7 @@
"schema": {
"$ref": "#/components/schemas/ModelWithString",
"default": {
"prop": "Hello World"
"prop": "Hello World!"
}
}
}
@ -449,7 +449,7 @@
"required": false,
"schema": {
"type": "string",
"default": "hello"
"default": "Hello World!"
}
},
{
@ -478,7 +478,7 @@
"required": true,
"schema": {
"type": "string",
"default": "hello"
"default": "Hello World!"
}
},
{

View File

@ -1,12 +1,10 @@
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist",
"target": "ES2017",
"module": "ES6",
"moduleResolution": "Node",
"lib": ["ES2017", "DOM"],
"target": "es2017",
"module": "es6",
"moduleResolution": "node",
"lib": ["es2017", "dom"],
"types": ["jest", "node"],
"typeRoots": ["node_modules/@types"],
"declaration": false,
@ -20,7 +18,6 @@
"strictNullChecks": true,
"strictFunctionTypes": true,
"removeComments": true,
"forceConsistentCasingInFileNames": true,
"allowSyntheticDefaultImports": true
},

2979
yarn.lock

File diff suppressed because it is too large Load Diff