implement required
property of schema
client-only codegen
This commit is contained in:
parent
456cb9d119
commit
3d2fea95cb
11 changed files with 54 additions and 21 deletions
|
@ -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.
|
||||
|
||||
## Versions
|
||||
#### 2.0.3
|
||||
- implement `required` property of schema
|
||||
- client-only codegen
|
||||
#### 2.0.2
|
||||
- make number convertible to boolean
|
||||
#### 2.0.1
|
||||
|
|
|
@ -8,7 +8,8 @@ const badArgv = (x, code=1) => {
|
|||
console.error([
|
||||
'Usage: api-codegen <apiDocPath> [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'));
|
||||
process.exit(code);
|
||||
};
|
||||
|
@ -20,8 +21,12 @@ const errExit = (x, err, code=1) => {
|
|||
|
||||
const argAttrs = ['apiDocPath'];
|
||||
const flag2attr = {
|
||||
o: 'outputDir',
|
||||
outputDir: 'outputDir',
|
||||
'o': 'outputDir',
|
||||
'outputDir': 'outputDir',
|
||||
};
|
||||
const flag2attr0 = { // nullary
|
||||
'c': 'clientOnly',
|
||||
'client-only': 'clientOnly',
|
||||
};
|
||||
const requiredAttrs = [
|
||||
...argAttrs,
|
||||
|
@ -35,9 +40,17 @@ function parseArgv(argv) {
|
|||
const setFlag = flag => {
|
||||
flag0 = flag;
|
||||
const attr0 = flag2attr[flag];
|
||||
if (attr0 == null) return badArgv(`Unknown flag: ${flag}`);
|
||||
if (config[attr0] != null) return badArgv(`Duplicate flag: ${flag}`);
|
||||
attr = attr0;
|
||||
if (attr0 == null) {
|
||||
const attr0 = flag2attr0[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}`);
|
||||
attr = attr0;
|
||||
}
|
||||
};
|
||||
const setVal = val => {
|
||||
if (attr == null) {
|
||||
|
|
1
dist/Config.d.ts
vendored
1
dist/Config.d.ts
vendored
|
@ -13,5 +13,6 @@ export interface ConfigOptional {
|
|||
utilsTSPath: string;
|
||||
outputDir: string;
|
||||
validateStatus: (status: string) => boolean;
|
||||
clientOnly: boolean;
|
||||
}
|
||||
export declare const configDefault: ConfigOptional;
|
||||
|
|
1
dist/Config.js
vendored
1
dist/Config.js
vendored
|
@ -15,4 +15,5 @@ exports.configDefault = {
|
|||
// other
|
||||
outputDir: 'api/generated',
|
||||
validateStatus: function (status) { return /^2..$/.test(status); },
|
||||
clientOnly: false,
|
||||
};
|
||||
|
|
1
dist/OpenAPI.d.ts
vendored
1
dist/OpenAPI.d.ts
vendored
|
@ -67,6 +67,7 @@ interface Schema {
|
|||
nullable?: boolean;
|
||||
readOnly?: boolean;
|
||||
maxSize?: number;
|
||||
required?: string[];
|
||||
}
|
||||
interface ArraySchema extends Schema {
|
||||
items: Schema | Reference;
|
||||
|
|
4
dist/OpenAPI.js
vendored
4
dist/OpenAPI.js
vendored
|
@ -164,7 +164,9 @@ var SchemaType = /** @class */ (function () {
|
|||
if (format === 'int32')
|
||||
t = 'int32';
|
||||
else {
|
||||
warn("Unsupport integer format " + format + ", use number instead");
|
||||
if (format && format != 'int64') {
|
||||
warn("Unsupport integer format " + format + ", use number instead");
|
||||
}
|
||||
t = 'number'; // TODO int64
|
||||
}
|
||||
}
|
||||
|
|
24
dist/codegen.js
vendored
24
dist/codegen.js
vendored
|
@ -242,20 +242,22 @@ function codegenClientAPI(funcs, config, cp) {
|
|||
return cp.end();
|
||||
}
|
||||
function codegenSchemas(schemas, config, cp) {
|
||||
var _a;
|
||||
var utilsTSPath = config.utilsTSPath;
|
||||
// import
|
||||
cp.writeln("import {FullDate, StrictTypeParser as STP} from '" + utilsTSPath + "'");
|
||||
// schema
|
||||
for (var _i = 0, _a = Object.entries(schemas); _i < _a.length; _i++) {
|
||||
var _b = _a[_i], typeName = _b[0], schema = _b[1];
|
||||
for (var _i = 0, _b = Object.entries(schemas); _i < _b.length; _i++) {
|
||||
var _c = _b[_i], typeName = _c[0], schema = _c[1];
|
||||
cp.writeln();
|
||||
if (OpenAPI_1.isObjectSchema(schema)) {
|
||||
// interface
|
||||
cp.writeln("export interface " + typeName + " {", 1);
|
||||
var propTypes = [];
|
||||
for (var _c = 0, _d = Object.entries(schema.properties); _c < _d.length; _c++) {
|
||||
var _e = _d[_c], propName = _e[0], prop = _e[1];
|
||||
var propType = new OpenAPI_1.SchemaType(prop, true); // TODO required
|
||||
var requireds = new Set((_a = schema.required) !== null && _a !== void 0 ? _a : []);
|
||||
for (var _d = 0, _e = Object.entries(schema.properties); _d < _e.length; _d++) {
|
||||
var _f = _e[_d], propName = _f[0], prop = _f[1];
|
||||
var propType = new OpenAPI_1.SchemaType(prop, requireds.has(propName));
|
||||
propTypes.push([propName, propType]);
|
||||
cp.writeln(propType.forProp(propName) + ';');
|
||||
}
|
||||
|
@ -264,8 +266,8 @@ function codegenSchemas(schemas, config, cp) {
|
|||
cp.writeln("export const " + typeName + " = {", 1);
|
||||
// .from
|
||||
cp.writeln("from: (o: {[_: string]: any}): " + typeName + " => ({", 1);
|
||||
for (var _f = 0, propTypes_1 = propTypes; _f < propTypes_1.length; _f++) {
|
||||
var _g = propTypes_1[_f], n = _g[0], t = _g[1];
|
||||
for (var _g = 0, propTypes_1 = propTypes; _g < propTypes_1.length; _g++) {
|
||||
var _h = propTypes_1[_g], n = _h[0], t = _h[1];
|
||||
cp.writeln(n + ": " + t.stp("o." + n, typeName + '.' + n) + ",");
|
||||
}
|
||||
cp.writeln('}),', -1);
|
||||
|
@ -273,8 +275,8 @@ function codegenSchemas(schemas, config, cp) {
|
|||
cp.writeln("Partial: (o: {[_: string]: any}): Partial<" + typeName + "> => {", 1);
|
||||
cp.writeln("const r: Partial<" + typeName + "> = {};");
|
||||
var locPartial = "Partial<" + typeName + ">";
|
||||
for (var _h = 0, propTypes_2 = propTypes; _h < propTypes_2.length; _h++) {
|
||||
var _j = propTypes_2[_h], n = _j[0], t = _j[1];
|
||||
for (var _j = 0, propTypes_2 = propTypes; _j < propTypes_2.length; _j++) {
|
||||
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('return r;');
|
||||
|
@ -305,7 +307,9 @@ function codegen(openAPI, configUser) {
|
|||
// handler
|
||||
ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName)));
|
||||
// server
|
||||
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
|
||||
if (!config.clientOnly) {
|
||||
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
|
||||
}
|
||||
// client
|
||||
ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName)));
|
||||
// schema
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface ConfigOptional {
|
|||
// other
|
||||
outputDir: string;
|
||||
validateStatus: (status: string) => boolean;
|
||||
clientOnly: boolean;
|
||||
}
|
||||
export const configDefault: ConfigOptional = {
|
||||
// format
|
||||
|
@ -33,4 +34,5 @@ export const configDefault: ConfigOptional = {
|
|||
// other
|
||||
outputDir: 'api/generated',
|
||||
validateStatus: (status: string) => /^2..$/.test(status),
|
||||
clientOnly: false,
|
||||
};
|
||||
|
|
|
@ -77,6 +77,7 @@ interface Schema {
|
|||
nullable?: boolean;
|
||||
readOnly?: boolean;
|
||||
maxSize?: number;
|
||||
required?: string[];
|
||||
}
|
||||
interface ArraySchema extends Schema {
|
||||
items: Schema | Reference;
|
||||
|
@ -227,7 +228,9 @@ export class SchemaType {
|
|||
} else if (type === 'integer') {
|
||||
if (format === 'int32') t = 'int32';
|
||||
else {
|
||||
warn(`Unsupport integer format ${format}, use number instead`);
|
||||
if (format && format != 'int64') {
|
||||
warn(`Unsupport integer format ${format}, use number instead`);
|
||||
}
|
||||
t = 'number'; // TODO int64
|
||||
}
|
||||
} else t = type;
|
||||
|
|
|
@ -245,8 +245,9 @@ function codegenSchemas(schemas: Schemas, config: Config, cp: CodePrinter) {
|
|||
// interface
|
||||
cp.writeln(`export interface ${typeName} {`, 1);
|
||||
const propTypes: [string, SchemaType][] = [];
|
||||
const requireds = new Set(schema.required ?? []);
|
||||
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]);
|
||||
cp.writeln(propType.forProp(propName)+';');
|
||||
}
|
||||
|
@ -298,7 +299,9 @@ export default function codegen(openAPI: OpenAPI, configUser: ConfigUser) {
|
|||
// handler
|
||||
ps.push(codegenIHandler(apiFuncs, config, gCP(config.IHandlerName)));
|
||||
// server
|
||||
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
|
||||
if (!config.clientOnly) {
|
||||
ps.push(codegenRouter(apiFuncs, config, gCP(config.routerName)));
|
||||
}
|
||||
// client
|
||||
ps.push(codegenClientAPI(apiFuncs, config, gCP(config.ClientAPIName)));
|
||||
// schema
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@sup39/api-ts-gen",
|
||||
"version": "2.0.2-b",
|
||||
"version": "2.0.3",
|
||||
"description": "OpenAPI code generator for TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
Reference in a new issue