Archived
1
0
Fork 0

implement required property of schema

client-only codegen
This commit is contained in:
sup39 2020-05-20 05:17:08 +09:00
parent 456cb9d119
commit 3d2fea95cb
11 changed files with 54 additions and 21 deletions

View file

@ -519,6 +519,9 @@ This tool only supports `application/json` type for request and response body. A
Other $ref like requestBody, responseBody are not supported currently. Other $ref like requestBody, responseBody are not supported currently.
## Versions ## Versions
#### 2.0.3
- implement `required` property of schema
- client-only codegen
#### 2.0.2 #### 2.0.2
- make number convertible to boolean - make number convertible to boolean
#### 2.0.1 #### 2.0.1

View file

@ -8,7 +8,8 @@ const badArgv = (x, code=1) => {
console.error([ console.error([
'Usage: api-codegen <apiDocPath> [flags]', 'Usage: api-codegen <apiDocPath> [flags]',
'Flags:', 'Flags:',
' -o --outputDir: outputDir', ' -o --outputDir <output-dir>: output directory(default: api/generated)',
' -c --client-only: client code only(default: client & server)',
].join('\n')); ].join('\n'));
process.exit(code); process.exit(code);
}; };
@ -20,8 +21,12 @@ const errExit = (x, err, code=1) => {
const argAttrs = ['apiDocPath']; const argAttrs = ['apiDocPath'];
const flag2attr = { const flag2attr = {
o: 'outputDir', 'o': 'outputDir',
outputDir: 'outputDir', 'outputDir': 'outputDir',
};
const flag2attr0 = { // nullary
'c': 'clientOnly',
'client-only': 'clientOnly',
}; };
const requiredAttrs = [ const requiredAttrs = [
...argAttrs, ...argAttrs,
@ -35,9 +40,17 @@ function parseArgv(argv) {
const setFlag = flag => { const setFlag = flag => {
flag0 = flag; flag0 = flag;
const attr0 = flag2attr[flag]; const attr0 = flag2attr[flag];
if (attr0 == null) {
const attr0 = flag2attr0[flag];
if (attr0 == null) return badArgv(`Unknown flag: ${flag}`); if (attr0 == null) return badArgv(`Unknown flag: ${flag}`);
// nullary attr
if (config[attr0] != null) return badArgv(`Duplicate flag: ${flag}`);
config[attr0] = true;
} else {
// attr
if (config[attr0] != null) return badArgv(`Duplicate flag: ${flag}`); if (config[attr0] != null) return badArgv(`Duplicate flag: ${flag}`);
attr = attr0; attr = attr0;
}
}; };
const setVal = val => { const setVal = val => {
if (attr == null) { if (attr == null) {

1
dist/Config.d.ts vendored
View file

@ -13,5 +13,6 @@ export interface ConfigOptional {
utilsTSPath: string; utilsTSPath: string;
outputDir: string; outputDir: string;
validateStatus: (status: string) => boolean; validateStatus: (status: string) => boolean;
clientOnly: boolean;
} }
export declare const configDefault: ConfigOptional; export declare const configDefault: ConfigOptional;

1
dist/Config.js vendored
View file

@ -15,4 +15,5 @@ exports.configDefault = {
// other // other
outputDir: 'api/generated', outputDir: 'api/generated',
validateStatus: function (status) { return /^2..$/.test(status); }, validateStatus: function (status) { return /^2..$/.test(status); },
clientOnly: false,
}; };

1
dist/OpenAPI.d.ts vendored
View file

@ -67,6 +67,7 @@ interface Schema {
nullable?: boolean; nullable?: boolean;
readOnly?: boolean; readOnly?: boolean;
maxSize?: number; maxSize?: number;
required?: string[];
} }
interface ArraySchema extends Schema { interface ArraySchema extends Schema {
items: Schema | Reference; items: Schema | Reference;

2
dist/OpenAPI.js vendored
View file

@ -164,7 +164,9 @@ var SchemaType = /** @class */ (function () {
if (format === 'int32') if (format === 'int32')
t = 'int32'; t = 'int32';
else { else {
if (format && format != 'int64') {
warn("Unsupport integer format " + format + ", use number instead"); warn("Unsupport integer format " + format + ", use number instead");
}
t = 'number'; // TODO int64 t = 'number'; // TODO int64
} }
} }

22
dist/codegen.js vendored
View file

@ -242,20 +242,22 @@ function codegenClientAPI(funcs, config, cp) {
return cp.end(); return cp.end();
} }
function codegenSchemas(schemas, config, cp) { function codegenSchemas(schemas, config, cp) {
var _a;
var utilsTSPath = config.utilsTSPath; var utilsTSPath = config.utilsTSPath;
// import // import
cp.writeln("import {FullDate, StrictTypeParser as STP} from '" + utilsTSPath + "'"); cp.writeln("import {FullDate, StrictTypeParser as STP} from '" + utilsTSPath + "'");
// schema // schema
for (var _i = 0, _a = Object.entries(schemas); _i < _a.length; _i++) { for (var _i = 0, _b = Object.entries(schemas); _i < _b.length; _i++) {
var _b = _a[_i], typeName = _b[0], schema = _b[1]; var _c = _b[_i], typeName = _c[0], schema = _c[1];
cp.writeln(); cp.writeln();
if (OpenAPI_1.isObjectSchema(schema)) { if (OpenAPI_1.isObjectSchema(schema)) {
// interface // interface
cp.writeln("export interface " + typeName + " {", 1); cp.writeln("export interface " + typeName + " {", 1);
var propTypes = []; var propTypes = [];
for (var _c = 0, _d = Object.entries(schema.properties); _c < _d.length; _c++) { var requireds = new Set((_a = schema.required) !== null && _a !== void 0 ? _a : []);
var _e = _d[_c], propName = _e[0], prop = _e[1]; for (var _d = 0, _e = Object.entries(schema.properties); _d < _e.length; _d++) {
var propType = new OpenAPI_1.SchemaType(prop, true); // TODO required var _f = _e[_d], propName = _f[0], prop = _f[1];
var propType = new OpenAPI_1.SchemaType(prop, requireds.has(propName));
propTypes.push([propName, propType]); propTypes.push([propName, propType]);
cp.writeln(propType.forProp(propName) + ';'); cp.writeln(propType.forProp(propName) + ';');
} }
@ -264,8 +266,8 @@ function codegenSchemas(schemas, config, cp) {
cp.writeln("export const " + typeName + " = {", 1); cp.writeln("export const " + typeName + " = {", 1);
// .from // .from
cp.writeln("from: (o: {[_: string]: any}): " + typeName + " => ({", 1); cp.writeln("from: (o: {[_: string]: any}): " + typeName + " => ({", 1);
for (var _f = 0, propTypes_1 = propTypes; _f < propTypes_1.length; _f++) { for (var _g = 0, propTypes_1 = propTypes; _g < propTypes_1.length; _g++) {
var _g = propTypes_1[_f], n = _g[0], t = _g[1]; var _h = propTypes_1[_g], n = _h[0], t = _h[1];
cp.writeln(n + ": " + t.stp("o." + n, typeName + '.' + n) + ","); cp.writeln(n + ": " + t.stp("o." + n, typeName + '.' + n) + ",");
} }
cp.writeln('}),', -1); cp.writeln('}),', -1);
@ -273,8 +275,8 @@ function codegenSchemas(schemas, config, cp) {
cp.writeln("Partial: (o: {[_: string]: any}): Partial<" + typeName + "> => {", 1); cp.writeln("Partial: (o: {[_: string]: any}): Partial<" + typeName + "> => {", 1);
cp.writeln("const r: Partial<" + typeName + "> = {};"); cp.writeln("const r: Partial<" + typeName + "> = {};");
var locPartial = "Partial<" + typeName + ">"; var locPartial = "Partial<" + typeName + ">";
for (var _h = 0, propTypes_2 = propTypes; _h < propTypes_2.length; _h++) { for (var _j = 0, propTypes_2 = propTypes; _j < propTypes_2.length; _j++) {
var _j = propTypes_2[_h], n = _j[0], t = _j[1]; var _k = propTypes_2[_j], n = _k[0], t = _k[1];
cp.writeln("if (o." + n + " !== void 0) r." + n + " = " + t.stp("o." + n, locPartial + '.' + n) + ";"); cp.writeln("if (o." + n + " !== void 0) r." + n + " = " + t.stp("o." + n, locPartial + '.' + n) + ";");
} }
cp.writeln('return r;'); cp.writeln('return r;');
@ -305,7 +307,9 @@ function codegen(openAPI, configUser) {
// handler // handler
ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName))); ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName)));
// server // server
if (!config.clientOnly) {
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName))); ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
}
// client // client
ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName))); ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName)));
// schema // schema

View file

@ -17,6 +17,7 @@ export interface ConfigOptional {
// other // other
outputDir: string; outputDir: string;
validateStatus: (status: string) => boolean; validateStatus: (status: string) => boolean;
clientOnly: boolean;
} }
export const configDefault: ConfigOptional = { export const configDefault: ConfigOptional = {
// format // format
@ -33,4 +34,5 @@ export const configDefault: ConfigOptional = {
// other // other
outputDir: 'api/generated', outputDir: 'api/generated',
validateStatus: (status: string) => /^2..$/.test(status), validateStatus: (status: string) => /^2..$/.test(status),
clientOnly: false,
}; };

View file

@ -77,6 +77,7 @@ interface Schema {
nullable?: boolean; nullable?: boolean;
readOnly?: boolean; readOnly?: boolean;
maxSize?: number; maxSize?: number;
required?: string[];
} }
interface ArraySchema extends Schema { interface ArraySchema extends Schema {
items: Schema | Reference; items: Schema | Reference;
@ -227,7 +228,9 @@ export class SchemaType {
} else if (type === 'integer') { } else if (type === 'integer') {
if (format === 'int32') t = 'int32'; if (format === 'int32') t = 'int32';
else { else {
if (format && format != 'int64') {
warn(`Unsupport integer format ${format}, use number instead`); warn(`Unsupport integer format ${format}, use number instead`);
}
t = 'number'; // TODO int64 t = 'number'; // TODO int64
} }
} else t = type; } else t = type;

View file

@ -245,8 +245,9 @@ function codegenSchemas(schemas: Schemas, config: Config, cp: CodePrinter) {
// interface // interface
cp.writeln(`export interface ${typeName} {`, 1); cp.writeln(`export interface ${typeName} {`, 1);
const propTypes: [string, SchemaType][] = []; const propTypes: [string, SchemaType][] = [];
const requireds = new Set(schema.required ?? []);
for (const [propName, prop] of Object.entries(schema.properties)) { for (const [propName, prop] of Object.entries(schema.properties)) {
const propType = new SchemaType(prop, true); // TODO required const propType = new SchemaType(prop, requireds.has(propName));
propTypes.push([propName, propType]); propTypes.push([propName, propType]);
cp.writeln(propType.forProp(propName)+';'); cp.writeln(propType.forProp(propName)+';');
} }
@ -298,7 +299,9 @@ export default function codegen(openAPI: OpenAPI, configUser: ConfigUser) {
// handler // handler
ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName))); ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName)));
// server // server
if (!config.clientOnly) {
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName))); ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
}
// client // client
ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName))); ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName)));
// schema // schema

View file

@ -1,6 +1,6 @@
{ {
"name": "@sup39/api-ts-gen", "name": "@sup39/api-ts-gen",
"version": "2.0.2-b", "version": "2.0.3",
"description": "OpenAPI code generator for TypeScript", "description": "OpenAPI code generator for TypeScript",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",