use IState as a generic type and remove it from api-codegen
This commit is contained in:
parent
6ab69e4141
commit
d51c345867
8 changed files with 42 additions and 30 deletions
27
README.md
27
README.md
|
@ -72,6 +72,7 @@ import {IServerAPI} from '#api/IServerAPI';
|
|||
export default {
|
||||
operationId: async (req, state, ctx) => {
|
||||
// ...
|
||||
return [status, body];
|
||||
},
|
||||
// ...
|
||||
} as IServerAPI;
|
||||
|
@ -84,14 +85,34 @@ Any parameter will be put in `req.{in}.{name}`, where `{in}` is one of `path`, `
|
|||
`requestBody` will be put in `req.body`.
|
||||
#### state
|
||||
Alias to `ctx.state`
|
||||
|
||||
You can specify the type of `ctx.state` by setting the export default type to `IServerAPI<YourStateType>`.
|
||||
```
|
||||
// example
|
||||
import {IServerAPI} from '#api/IHandler';
|
||||
|
||||
interface IState {
|
||||
user: {
|
||||
id: number;
|
||||
}
|
||||
}
|
||||
export default {
|
||||
// ...
|
||||
operationId: async (req, state, ctx) => {
|
||||
// state has IState type here
|
||||
state.user.id // number
|
||||
// ...
|
||||
},
|
||||
} as IServerAPI<IState> // specify ctx.state type to IState
|
||||
```
|
||||
#### ctx
|
||||
The `ctx` object from koa router. **Avoid to use it** unless required.
|
||||
```
|
||||
// Don't do this unless required
|
||||
// Don't do this
|
||||
ctx.body = responseBody;
|
||||
ctx.status = statusCode;
|
||||
// Do this
|
||||
res[statusCode](responseBody);
|
||||
return [statusCode, responseBody];
|
||||
```
|
||||
#### return value
|
||||
`[status, body]`
|
||||
|
@ -497,6 +518,8 @@ 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.1
|
||||
- use IState as a generic type and remove it from api-codegen.
|
||||
#### 2.0.0
|
||||
- simplify generated code
|
||||
- merge all APIPromise class
|
||||
|
|
|
@ -9,7 +9,6 @@ const badArgv = (x, code=1) => {
|
|||
'Usage: api-codegen <apiDocPath> [flags]',
|
||||
'Flags:',
|
||||
' -o --outputDir: outputDir',
|
||||
' -s --stateTSPath: ctx.state type definition file path',
|
||||
].join('\n'));
|
||||
process.exit(code);
|
||||
};
|
||||
|
@ -23,8 +22,6 @@ const argAttrs = ['apiDocPath'];
|
|||
const flag2attr = {
|
||||
o: 'outputDir',
|
||||
outputDir: 'outputDir',
|
||||
s: 'stateTSPath',
|
||||
stateTSPath: 'stateTSPath',
|
||||
};
|
||||
const requiredAttrs = [
|
||||
...argAttrs,
|
||||
|
|
1
dist/Config.d.ts
vendored
1
dist/Config.d.ts
vendored
|
@ -11,7 +11,6 @@ export interface ConfigOptional {
|
|||
routerName: string;
|
||||
ServerAPITSPath: string;
|
||||
utilsTSPath: string;
|
||||
stateTSPath: string | null;
|
||||
outputDir: string;
|
||||
validateStatus: (status: string) => boolean;
|
||||
}
|
||||
|
|
1
dist/Config.js
vendored
1
dist/Config.js
vendored
|
@ -12,7 +12,6 @@ exports.configDefault = {
|
|||
// TS path
|
||||
ServerAPITSPath: '#ServerAPI',
|
||||
utilsTSPath: '@supmiku39/api-ts-gen/utils',
|
||||
stateTSPath: null,
|
||||
// other
|
||||
outputDir: 'api/generated',
|
||||
validateStatus: function (status) { return /^2..$/.test(status); },
|
||||
|
|
18
dist/codegen.js
vendored
18
dist/codegen.js
vendored
|
@ -6,15 +6,13 @@ var Config_1 = require("./Config");
|
|||
var OpenAPI_1 = require("./OpenAPI");
|
||||
var CodePrinter_1 = require("./CodePrinter");
|
||||
function codegenIHandler(funcs, config, cp) {
|
||||
var schemasName = config.schemasName, utilsTSPath = config.utilsTSPath, stateTSPath = config.stateTSPath;
|
||||
var schemasName = config.schemasName, utilsTSPath = config.utilsTSPath;
|
||||
// import
|
||||
cp.writeln("import * as Schemas from './" + schemasName + "'");
|
||||
cp.writeln('import {FullDate, StrictTypeParser as STP, APIPromise} ' +
|
||||
("from '" + utilsTSPath + "'"));
|
||||
cp.writeln('import {RouterContext as CTX} from \'@koa/router\'');
|
||||
cp.writeln('import {AxiosResponse} from \'axios\'');
|
||||
cp.writeln(stateTSPath ?
|
||||
"import IState from '" + stateTSPath + "'" : 'type IState = any');
|
||||
// api req, res types
|
||||
cp.writeln("export type TAPI = {", 1);
|
||||
for (var _i = 0, _a = Object.entries(funcs); _i < _a.length; _i++) {
|
||||
|
@ -62,26 +60,27 @@ function codegenIHandler(funcs, config, cp) {
|
|||
// export IServerAPI
|
||||
cp.writeln('');
|
||||
cp.writeln('type ValueOf<T> = T[keyof T];');
|
||||
cp.writeln('type Dict<T> = {[_: string]: T};');
|
||||
cp.writeln('type RServerAPI<T> = ValueOf<', 1);
|
||||
cp.writeln('{[K in keyof T]: T[K] extends void ? [K, any?] : [K, T[K]]}>;', -1, false);
|
||||
cp.writeln('export type IServerAPI = {[K in keyof TAPI]:', 1);
|
||||
cp.writeln('export type IServerAPI<IState=any> = {[K in keyof TAPI]:', 1);
|
||||
cp.writeln("(req: TAPI[K]['req'], state: IState, ctx: CTX) =>", 1);
|
||||
cp.writeln("Promise<RServerAPI<TAPI[K]['res']>>}", -2, false);
|
||||
// return
|
||||
return cp.end();
|
||||
}
|
||||
function codegenRouter(funcs, config, cp) {
|
||||
var schemasName = config.schemasName, ServerAPITSPath = config.ServerAPITSPath, utilsTSPath = config.utilsTSPath, stateTSPath = config.stateTSPath;
|
||||
var schemasName = config.schemasName, IHandlerName = config.IHandlerName, ServerAPITSPath = config.ServerAPITSPath, utilsTSPath = config.utilsTSPath;
|
||||
// import
|
||||
cp.writeln("import * as Schemas from './" + schemasName + "'");
|
||||
cp.writeln("import {IServerAPI} from './" + IHandlerName + "'");
|
||||
cp.writeln("import * as Router from '@koa/router'");
|
||||
cp.writeln("import {FullDate, StrictTypeParser as STP} from '" + utilsTSPath + "'");
|
||||
cp.writeln("import * as bodyParser from 'koa-body'");
|
||||
cp.writeln(stateTSPath ?
|
||||
"import IState from '" + stateTSPath + "'" : 'type IState = any');
|
||||
cp.writeln("type CTX = Router.RouterContext<IState>;");
|
||||
// api
|
||||
cp.writeln("\nimport api from '" + ServerAPITSPath + "'");
|
||||
cp.writeln("type IState = typeof api extends IServerAPI<infer T> ? T : any;");
|
||||
// router
|
||||
cp.writeln("type CTX = Router.RouterContext<IState>;");
|
||||
cp.writeln("\nconst router = new Router<IState>();");
|
||||
// function
|
||||
var gcGetParams = {
|
||||
|
@ -91,7 +90,6 @@ function codegenRouter(funcs, config, cp) {
|
|||
cookie: function (attr) { return "ctx.cookies.get('" + attr + "')"; },
|
||||
};
|
||||
// route
|
||||
cp.writeln("\nimport api from '" + ServerAPITSPath + "'");
|
||||
for (var _i = 0, _a = Object.entries(funcs); _i < _a.length; _i++) {
|
||||
var _b = _a[_i], funcName = _b[0], func = _b[1];
|
||||
var method = func.method, url = func.url, reqTypes = func.reqTypes;
|
||||
|
|
|
@ -14,7 +14,6 @@ export interface ConfigOptional {
|
|||
// TS path
|
||||
ServerAPITSPath: string;
|
||||
utilsTSPath: string;
|
||||
stateTSPath: string | null;
|
||||
// other
|
||||
outputDir: string;
|
||||
validateStatus: (status: string) => boolean;
|
||||
|
@ -31,7 +30,6 @@ export const configDefault: ConfigOptional = {
|
|||
// TS path
|
||||
ServerAPITSPath: '#ServerAPI',
|
||||
utilsTSPath: '@supmiku39/api-ts-gen/utils',
|
||||
stateTSPath: null,
|
||||
// other
|
||||
outputDir: 'api/generated',
|
||||
validateStatus: (status: string) => /^2..$/.test(status),
|
||||
|
|
|
@ -9,7 +9,7 @@ import {CodePrinter} from './CodePrinter';
|
|||
|
||||
function codegenIHandler(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
||||
const {
|
||||
schemasName, utilsTSPath, stateTSPath,
|
||||
schemasName, utilsTSPath,
|
||||
} = config;
|
||||
// import
|
||||
cp.writeln(`import * as Schemas from './${schemasName}'`);
|
||||
|
@ -17,8 +17,6 @@ function codegenIHandler(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
|||
`from '${utilsTSPath}'`);
|
||||
cp.writeln('import {RouterContext as CTX} from \'@koa/router\'');
|
||||
cp.writeln('import {AxiosResponse} from \'axios\'');
|
||||
cp.writeln(stateTSPath ?
|
||||
`import IState from '${stateTSPath}'` : 'type IState = any');
|
||||
// api req, res types
|
||||
cp.writeln(`export type TAPI = {`, 1);
|
||||
for (const [funcName, func] of Object.entries(funcs)) {
|
||||
|
@ -60,11 +58,10 @@ function codegenIHandler(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
|||
// export IServerAPI
|
||||
cp.writeln('');
|
||||
cp.writeln('type ValueOf<T> = T[keyof T];');
|
||||
cp.writeln('type Dict<T> = {[_: string]: T};');
|
||||
cp.writeln('type RServerAPI<T> = ValueOf<', 1);
|
||||
cp.writeln('{[K in keyof T]: T[K] extends void ? [K, any?] : [K, T[K]]}>;',
|
||||
-1, false);
|
||||
cp.writeln('export type IServerAPI = {[K in keyof TAPI]:', 1);
|
||||
cp.writeln('export type IServerAPI<IState=any> = {[K in keyof TAPI]:', 1);
|
||||
cp.writeln(`(req: TAPI[K]['req'], state: IState, ctx: CTX) =>`, 1);
|
||||
cp.writeln(`Promise<RServerAPI<TAPI[K]['res']>>}`, -2, false);
|
||||
// return
|
||||
|
@ -72,18 +69,20 @@ function codegenIHandler(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
|||
}
|
||||
function codegenRouter(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
||||
const {
|
||||
schemasName, ServerAPITSPath, utilsTSPath, stateTSPath,
|
||||
schemasName, IHandlerName, ServerAPITSPath, utilsTSPath,
|
||||
} = config;
|
||||
// import
|
||||
cp.writeln(`import * as Schemas from './${schemasName}'`);
|
||||
cp.writeln(`import {IServerAPI} from './${IHandlerName}'`);
|
||||
cp.writeln(`import * as Router from '@koa/router'`);
|
||||
cp.writeln(
|
||||
`import {FullDate, StrictTypeParser as STP} from '${utilsTSPath}'`);
|
||||
cp.writeln(`import * as bodyParser from 'koa-body'`);
|
||||
cp.writeln(stateTSPath ?
|
||||
`import IState from '${stateTSPath}'` : 'type IState = any');
|
||||
cp.writeln(`type CTX = Router.RouterContext<IState>;`);
|
||||
// api
|
||||
cp.writeln(`\nimport api from '${ServerAPITSPath}'`);
|
||||
cp.writeln(`type IState = typeof api extends IServerAPI<infer T> ? T : any;`);
|
||||
// router
|
||||
cp.writeln(`type CTX = Router.RouterContext<IState>;`);
|
||||
cp.writeln(`\nconst router = new Router<IState>();`);
|
||||
// function
|
||||
const gcGetParams = {
|
||||
|
@ -93,7 +92,6 @@ function codegenRouter(funcs: APIFuncs, config: Config, cp: CodePrinter) {
|
|||
cookie: (attr: string) => `ctx.cookies.get('${attr}')`,
|
||||
};
|
||||
// route
|
||||
cp.writeln(`\nimport api from '${ServerAPITSPath}'`);
|
||||
for (const [funcName, func] of Object.entries(funcs)) {
|
||||
const {
|
||||
method, url, reqTypes,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@supmiku39/api-ts-gen",
|
||||
"version": "2.0.0-fix01",
|
||||
"version": "2.0.1",
|
||||
"description": "OpenAPI code generator for TypeScript",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
|
Reference in a new issue