Skip to content

Commit 2d5c756

Browse files
authored
feat: 抽离generate命令&支持返回值schema (#21)
Co-authored-by: cmtlyt <cmtlyt@163.com>
1 parent 8e7b42a commit 2d5c756

File tree

3 files changed

+57
-35
lines changed

3 files changed

+57
-35
lines changed

src/cli.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,31 @@ const run = defineCommand({
3737
},
3838
});
3939

40-
const generateRequestScript = defineCommand({
40+
const requestScript = defineCommand({
4141
meta: {
42-
name: 'generateRequestScript',
43-
description: 'Generate request script',
42+
name: 'requestScript',
43+
description: 'Generate request script with router schema',
4444
},
4545
async run() {
4646
await generateRequestScriptCli();
4747
},
4848
});
4949

50+
const generate = defineCommand({
51+
meta: {
52+
name: 'generate',
53+
description: 'Generate other file',
54+
},
55+
subCommands: { requestScript },
56+
});
57+
5058
const main = defineCommand({
5159
meta: {
5260
name: 'tee',
5361
version,
5462
description: '@cmtlyt/tee cli',
5563
},
56-
subCommands: { dev, build, run, grs: generateRequestScript },
64+
subCommands: { dev, build, run, generate, g: generate },
5765
});
5866

5967
runMain(main);

src/cli/generate-request-script/index.ts

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type TeeKoa from '../..';
2-
import type { DataKey, RequestMethod, RouterInfo } from '../../types';
2+
import type { DataKey, RequestMethod, RouterDataSchema, RouterInfo, RouterSchema } from '../../types';
33
import fs from 'node:fs';
44
import path from 'node:path';
55
import { noop } from '@cmtlyt/base';
@@ -23,7 +23,7 @@ function filterValidRouter(routerInfoMap: Record<string, RouterInfo>) {
2323
return validRouterInfoMap;
2424
}
2525

26-
type TypeInfo = Partial<Record<DataKey, string>>;
26+
type TypeInfo = Partial<Record<DataKey | 'response', string>>;
2727

2828
export type MethodTypeInfo = {
2929
path: string | RegExp;
@@ -41,7 +41,7 @@ function getDataKeyName(key: string): DataKey {
4141
case 'body':
4242
return 'body';
4343
default:
44-
return 'body';
44+
return key as DataKey;
4545
}
4646
}
4747

@@ -56,26 +56,42 @@ function getRouterParams(path: string) {
5656
return params;
5757
}
5858

59-
function genereateTypeInfo(routerInfoMap: Record<string, RouterInfo>) {
59+
function getRouterDataSchema(dataKey: string, schema: RouterDataSchema) {
60+
if (dataKey === 'response') {
61+
return schema.response?.['200'] || schema.response?.default || {};
62+
}
63+
return schema[dataKey];
64+
}
65+
66+
function parseRouterDataSchema(methodSchema: RouterDataSchema) {
67+
const typeInfo: TypeInfo = {};
68+
for (const dataKey in methodSchema) {
69+
const schema = getRouterDataSchema(dataKey, methodSchema)!;
70+
const declaration = generateTypes(schema, { addDefaults: false, addExport: false, allowExtraKeys: true });
71+
typeInfo[getDataKeyName(dataKey)] = declaration.slice(declaration.indexOf('{')).replace(/\n\s*/g, ' ');
72+
}
73+
return typeInfo;
74+
}
75+
76+
function parseMethodSchema(schemaMap: RouterSchema) {
77+
const methodTypeInfo: Partial<Record<RequestMethod, TypeInfo>> = {};
78+
for (const method in schemaMap) {
79+
const methodSchema = schemaMap[method as RequestMethod];
80+
methodTypeInfo[method as RequestMethod] = parseRouterDataSchema(methodSchema!);
81+
}
82+
return methodTypeInfo;
83+
}
84+
85+
function parseTypeInfo(routerInfoMap: Record<string, RouterInfo>) {
6086
const typeInfoList: MethodTypeInfo[] = [];
6187
for (const stringPath in routerInfoMap) {
6288
const routerSchema = routerInfoMap[stringPath];
6389
const { schema: schemaMap, path } = routerSchema;
64-
const methodTypeInfo: MethodTypeInfo = { path, schemaPath: stringPath, params: getRouterParams(stringPath) };
65-
if (!schemaMap) {
90+
const baseMethodTypeInfo: MethodTypeInfo = { path, schemaPath: stringPath, params: getRouterParams(stringPath) };
91+
if (!schemaMap)
6692
continue;
67-
}
68-
for (const method in schemaMap) {
69-
const methodSchema = schemaMap[method as RequestMethod];
70-
const typeInfo: TypeInfo = {};
71-
for (const dataKey in methodSchema) {
72-
const schema = methodSchema[dataKey as DataKey];
73-
const declaration = generateTypes(schema, { addDefaults: false, addExport: false, allowExtraKeys: true });
74-
typeInfo[getDataKeyName(dataKey)] = declaration.slice(declaration.indexOf('{')).replace(/\n\s*/g, ' ');
75-
}
76-
methodTypeInfo[method as RequestMethod] = typeInfo;
77-
}
78-
typeInfoList.push(methodTypeInfo);
93+
const methodTypeInfo = parseMethodSchema(schemaMap);
94+
typeInfoList.push(Object.assign(baseMethodTypeInfo, methodTypeInfo));
7995
}
8096
return typeInfoList;
8197
}
@@ -104,10 +120,10 @@ function parseAPIInfo(typeInfoList: MethodTypeInfo[]) {
104120
typeInfoList.forEach((item) => {
105121
const { path: _, schemaPath, params, ...methodType } = item;
106122
for (const method in methodType) {
107-
const typeInfo = methodType[method as RequestMethod]!;
123+
const { response, ...typeInfo } = methodType[method as RequestMethod]!;
108124
const methodName = getMethodName(method, schemaPath);
109125
const apiInfo = {
110-
type: `${methodName}: <T>(option: ${getMethodOptionsType(typeInfo)}) => Promise<T>`,
126+
type: `${methodName}: <T = ${response || 'unknown'}>(option: ${getMethodOptionsType(typeInfo)}) => Promise<T>`,
111127
request: `${methodName}: request(${JSON.stringify(Object.assign({ method: method.toLowerCase() }, pick_(['path', 'schemaPath', 'params'], item)))})`,
112128
};
113129
apiInfoList.push(apiInfo);
@@ -116,7 +132,7 @@ function parseAPIInfo(typeInfoList: MethodTypeInfo[]) {
116132
return apiInfoList;
117133
}
118134

119-
function generateAPIContentInfo(apiInfo: APIInfo[]) {
135+
function parseAPIContentInfo(apiInfo: APIInfo[]) {
120136
const { type, method } = apiInfo.reduce<{ type: string[]; method: string[] }>((prev, cur) => {
121137
prev.type.push(cur.type);
122138
prev.method.push(cur.request);
@@ -152,9 +168,9 @@ export async function generateRequestScriptCli() {
152168
const routerInfoMap = getStorage('routerInfoMap');
153169
const validRouterInfoMap = filterValidRouter(routerInfoMap);
154170

155-
const typeInfoList = genereateTypeInfo(validRouterInfoMap);
171+
const typeInfoList = parseTypeInfo(validRouterInfoMap);
156172
const apiInfoList = parseAPIInfo(typeInfoList);
157-
const contentInfo = generateAPIContentInfo(apiInfoList);
173+
const contentInfo = parseAPIContentInfo(apiInfoList);
158174

159175
const outputContent = generateAPIFile(contentInfo);
160176

@@ -166,10 +182,3 @@ export async function generateRequestScriptCli() {
166182

167183
fs.writeFileSync(outputFile, outputContent);
168184
}
169-
170-
// console.dir(generateTypes({
171-
// type: 'object',
172-
// properties: { id: { type: 'string' } },
173-
// }, {
174-
// interfaceName: pascalCase('get/user/info/:id'),
175-
// }));

src/types/index.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,12 @@ export interface ConfigFile {
224224
generateTypeConfig?: GenerateTypeConfig;
225225
}
226226

227-
export type BaseRouterSchema = Record<RequestMethod | string & {}, Partial<Record<DataKey | string & {}, JsonSchema>>>;
227+
export type RouterDataSchema = Partial<{
228+
response: Record<string, JsonSchema>;
229+
[key: string]: JsonSchema | Record<string, JsonSchema>;
230+
} & Record<DataKey, JsonSchema>>;
231+
232+
export type BaseRouterSchema = Record<RequestMethod | string & {}, RouterDataSchema>;
228233

229234
export type RouterSchema = Partial<BaseRouterSchema>;
230235

0 commit comments

Comments
 (0)