@jayfong/x-server 2.34.0 → 2.35.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -136,7 +136,9 @@ class ApiGenerator {
136
136
  this.debug('写入文件...');
137
137
  await Promise.all([_fsExtra.default.outputJSON(_path.default.join(this.cwd, 'temp/api.json'), apiData, {
138
138
  spaces: 2
139
- }), _fsExtra.default.outputJSON(_path.default.join(this.cwd, 'temp/yapi.json'), this.genYApiData(apiData), {
139
+ }), _fsExtra.default.outputJSON(_path.default.join(this.cwd, 'temp/yapi.json'), this.apiDataToYApiData(apiData), {
140
+ spaces: 2
141
+ }), _fsExtra.default.outputJSON(_path.default.join(this.cwd, 'temp/openapi31.json'), this.apiDataToOpenAPI31Data(apiData), {
140
142
  spaces: 2
141
143
  })]);
142
144
  }
@@ -281,7 +283,7 @@ class ApiGenerator {
281
283
  }
282
284
  return jsonSchema;
283
285
  }
284
- genYApiData(handles) {
286
+ apiDataToYApiData(handles) {
285
287
  const data = {};
286
288
  for (const handle of handles) {
287
289
  for (const path of handle.path) {
@@ -344,5 +346,50 @@ class ApiGenerator {
344
346
  list: data[cat]
345
347
  }));
346
348
  }
349
+ apiDataToOpenAPI31Data(handles) {
350
+ const data = {
351
+ openapi: '3.1.0',
352
+ info: {
353
+ title: `${process.env.APP_NAME}`,
354
+ version: '1.0.0'
355
+ },
356
+ paths: {},
357
+ servers: [{
358
+ url: `${process.env.APP_URL}`,
359
+ description: '生产'
360
+ }, {
361
+ url: `http://127.0.0.1:${process.env.APP_PORT}/`,
362
+ description: '本地'
363
+ }]
364
+ };
365
+ for (const handle of handles) {
366
+ for (const path of handle.path) {
367
+ data.paths[path] = {
368
+ [handle.method.toLowerCase()]: {
369
+ tags: [handle.category],
370
+ summary: handle.name,
371
+ requestBody: {
372
+ content: {
373
+ 'application/json': {
374
+ schema: handle.requestDataJsonSchema
375
+ }
376
+ }
377
+ },
378
+ responses: {
379
+ '200': {
380
+ description: 'success',
381
+ content: {
382
+ 'application/json': {
383
+ schema: handle.responseDataJsonSchema
384
+ }
385
+ }
386
+ }
387
+ }
388
+ }
389
+ };
390
+ }
391
+ }
392
+ return data;
393
+ }
347
394
  }
348
395
  exports.ApiGenerator = ApiGenerator;
@@ -8,7 +8,6 @@ var _vscodeGenerateIndexStandalone = require("vscode-generate-index-standalone")
8
8
  var _vtils = require("vtils");
9
9
  var _yargs = _interopRequireDefault(require("yargs"));
10
10
  var _api_generator = require("./api_generator");
11
- var _api_generator2 = require("./api_generator1");
12
11
  var _build_util = require("./build_util");
13
12
  var _deploy_util = require("./deploy_util");
14
13
  var _dev_util = require("./dev_util");
@@ -124,8 +123,6 @@ _yargs.default.command('dev', '开始开发', _ => _.positional('index', {
124
123
  console.log('构建成功');
125
124
  }).command('api', '生成 API', async () => {
126
125
  await new _api_generator.ApiGenerator().start();
127
- }).command('api1', '(old) 生成 API', async () => {
128
- await new _api_generator2.ApiGenerator1().generate();
129
126
  }).command('prisma', 'prisma 代理,主要为了注入环境变量', _ => _.positional('production', {
130
127
  alias: 'p',
131
128
  describe: '是否生产模式',
@@ -1,31 +1,29 @@
1
- import { x, HttpError } from '@jayfong/x-server'
2
- import { PrismaClient, Prisma } from '@prisma/client'
1
+ import { x } from '@jayfong/x-server';
2
+ import { Prisma, PrismaClient } from '@prisma/client';
3
3
 
4
- export const prismaClient = new PrismaClient({
5
- rejectOnNotFound: err => new HttpError.NotFound(err.message),
6
- })
4
+ export const prismaClient = new PrismaClient();
7
5
 
8
- x.dispose.add(() => prismaClient.$disconnect())
6
+ x.dispose.add(() => prismaClient.$disconnect());
9
7
 
10
8
  type ModelName =
11
9
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
12
- ''
10
+ '';
13
11
  // @endindex
14
12
 
15
13
  function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
16
14
  return class BaseModel {
17
- public query = prismaClient[name]
15
+ public query = prismaClient[name];
18
16
 
19
- public transactionClient: Prisma.TransactionClient | null = null
17
+ public transactionClient: Prisma.TransactionClient | null = null;
20
18
 
21
19
  public transactionify = (tx: Prisma.TransactionClient) => {
22
20
  // @ts-ignore
23
21
  return new (class extends this.constructor {
24
- public query = tx[name]
22
+ public query = tx[name];
25
23
 
26
- public transactionClient = tx
27
- })() as typeof this
28
- }
24
+ public transactionClient = tx;
25
+ })() as typeof this;
26
+ };
29
27
 
30
28
  public getModel = <T extends ModelName>(
31
29
  name: T,
@@ -34,27 +32,29 @@ function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
34
32
  ? require('../../src/models')[`${name}Model`].transactionify(
35
33
  this.transactionClient,
36
34
  )
37
- : require('../../src/models')[`${name}Model`]
38
- }
39
- }
35
+ : require('../../src/models')[`${name}Model`];
36
+ };
37
+ };
40
38
  }
41
39
 
42
40
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = makeBaseModel('${_.camel(m[1])}')`)
43
41
  // @endindex
44
42
 
45
- export * from '@prisma/client'
43
+ export * from '@prisma/client';
46
44
 
47
45
  export const startTransaction = <T>(
48
- cb: (models: {
49
- [K in ModelName]: typeof import('../../src/models')[`${K}Model`]
50
- }) => Promise<T>,
46
+ cb: (
47
+ models: {
48
+ [K in ModelName]: typeof import('../../src/models')[`${K}Model`];
49
+ },
50
+ ) => Promise<T>,
51
51
  ): Promise<T> => {
52
52
  return prismaClient.$transaction(async tx => {
53
- const _models = require('../../src/models')
54
- const cache = Object.create(null)
53
+ const _models = require('../../src/models');
54
+ const cache = Object.create(null);
55
55
  return cb({
56
56
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return cache.${_.camel(m[1])} || (cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(tx)) }, `)
57
57
  // @endindex
58
- })
59
- })
60
- }
58
+ });
59
+ });
60
+ };
@@ -1,5 +1,6 @@
1
1
  import createDebug from 'debug';
2
2
  import { type JSONSchema4 } from 'json-schema';
3
+ import { type OpenAPIV3_1 } from 'openapi-types';
3
4
  import { ts } from 'ts-morph';
4
5
  import { LiteralUnion } from 'vtils/types';
5
6
  import { type XHandler } from '../core/types';
@@ -43,10 +44,23 @@ export declare class ApiGenerator {
43
44
  keySymbol?: ts.Symbol;
44
45
  }): ApiDto;
45
46
  apiDataToJsonSchema(apiData: ApiDto, jsonSchema?: JSONSchema4): JSONSchema4;
46
- genYApiData(handles: ApiData[]): {
47
+ apiDataToYApiData(handles: ApiData[]): {
47
48
  name: string;
48
49
  desc: string;
49
50
  list: any;
50
51
  }[];
52
+ apiDataToOpenAPI31Data(handles: ApiData[]): Omit<Omit<import("openapi-types").OpenAPIV3.Document<{}>, "paths" | "components">, "info" | "paths" | "components" | "servers" | "webhooks" | "jsonSchemaDialect"> & {
53
+ info: OpenAPIV3_1.InfoObject;
54
+ jsonSchemaDialect?: string;
55
+ servers?: OpenAPIV3_1.ServerObject[];
56
+ } & Pick<{
57
+ paths: OpenAPIV3_1.PathsObject<{}, {}>;
58
+ webhooks: Record<string, OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.PathItemObject<{}>>;
59
+ components: OpenAPIV3_1.ComponentsObject;
60
+ }, "paths"> & Omit<Partial<{
61
+ paths: OpenAPIV3_1.PathsObject<{}, {}>;
62
+ webhooks: Record<string, OpenAPIV3_1.ReferenceObject | OpenAPIV3_1.PathItemObject<{}>>;
63
+ components: OpenAPIV3_1.ComponentsObject;
64
+ }>, "paths">;
51
65
  }
52
66
  export {};
@@ -131,7 +131,9 @@ export class ApiGenerator {
131
131
  this.debug('写入文件...');
132
132
  await Promise.all([fs.outputJSON(path.join(this.cwd, 'temp/api.json'), apiData, {
133
133
  spaces: 2
134
- }), fs.outputJSON(path.join(this.cwd, 'temp/yapi.json'), this.genYApiData(apiData), {
134
+ }), fs.outputJSON(path.join(this.cwd, 'temp/yapi.json'), this.apiDataToYApiData(apiData), {
135
+ spaces: 2
136
+ }), fs.outputJSON(path.join(this.cwd, 'temp/openapi31.json'), this.apiDataToOpenAPI31Data(apiData), {
135
137
  spaces: 2
136
138
  })]);
137
139
  }
@@ -276,7 +278,7 @@ export class ApiGenerator {
276
278
  }
277
279
  return jsonSchema;
278
280
  }
279
- genYApiData(handles) {
281
+ apiDataToYApiData(handles) {
280
282
  const data = {};
281
283
  for (const handle of handles) {
282
284
  for (const path of handle.path) {
@@ -339,4 +341,49 @@ export class ApiGenerator {
339
341
  list: data[cat]
340
342
  }));
341
343
  }
344
+ apiDataToOpenAPI31Data(handles) {
345
+ const data = {
346
+ openapi: '3.1.0',
347
+ info: {
348
+ title: `${process.env.APP_NAME}`,
349
+ version: '1.0.0'
350
+ },
351
+ paths: {},
352
+ servers: [{
353
+ url: `${process.env.APP_URL}`,
354
+ description: '生产'
355
+ }, {
356
+ url: `http://127.0.0.1:${process.env.APP_PORT}/`,
357
+ description: '本地'
358
+ }]
359
+ };
360
+ for (const handle of handles) {
361
+ for (const path of handle.path) {
362
+ data.paths[path] = {
363
+ [handle.method.toLowerCase()]: {
364
+ tags: [handle.category],
365
+ summary: handle.name,
366
+ requestBody: {
367
+ content: {
368
+ 'application/json': {
369
+ schema: handle.requestDataJsonSchema
370
+ }
371
+ }
372
+ },
373
+ responses: {
374
+ '200': {
375
+ description: 'success',
376
+ content: {
377
+ 'application/json': {
378
+ schema: handle.responseDataJsonSchema
379
+ }
380
+ }
381
+ }
382
+ }
383
+ }
384
+ };
385
+ }
386
+ }
387
+ return data;
388
+ }
342
389
  }
package/lib/cli/cli.js CHANGED
@@ -5,7 +5,6 @@ import { generateManyIndex } from 'vscode-generate-index-standalone';
5
5
  import { castArray, debounce } from 'vtils';
6
6
  import yargs from 'yargs';
7
7
  import { ApiGenerator } from "./api_generator";
8
- import { ApiGenerator1 } from "./api_generator1";
9
8
  import { BuildUtil } from "./build_util";
10
9
  import { DeployUtil } from "./deploy_util";
11
10
  import { DevUtil } from "./dev_util";
@@ -121,8 +120,6 @@ yargs.command('dev', '开始开发', _ => _.positional('index', {
121
120
  console.log('构建成功');
122
121
  }).command('api', '生成 API', async () => {
123
122
  await new ApiGenerator().start();
124
- }).command('api1', '(old) 生成 API', async () => {
125
- await new ApiGenerator1().generate();
126
123
  }).command('prisma', 'prisma 代理,主要为了注入环境变量', _ => _.positional('production', {
127
124
  alias: 'p',
128
125
  describe: '是否生产模式',
@@ -1,31 +1,29 @@
1
- import { x, HttpError } from '@jayfong/x-server'
2
- import { PrismaClient, Prisma } from '@prisma/client'
1
+ import { x } from '@jayfong/x-server';
2
+ import { Prisma, PrismaClient } from '@prisma/client';
3
3
 
4
- export const prismaClient = new PrismaClient({
5
- rejectOnNotFound: err => new HttpError.NotFound(err.message),
6
- })
4
+ export const prismaClient = new PrismaClient();
7
5
 
8
- x.dispose.add(() => prismaClient.$disconnect())
6
+ x.dispose.add(() => prismaClient.$disconnect());
9
7
 
10
8
  type ModelName =
11
9
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `| '${_.camel(m[1])}'`)
12
- ''
10
+ '';
13
11
  // @endindex
14
12
 
15
13
  function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
16
14
  return class BaseModel {
17
- public query = prismaClient[name]
15
+ public query = prismaClient[name];
18
16
 
19
- public transactionClient: Prisma.TransactionClient | null = null
17
+ public transactionClient: Prisma.TransactionClient | null = null;
20
18
 
21
19
  public transactionify = (tx: Prisma.TransactionClient) => {
22
20
  // @ts-ignore
23
21
  return new (class extends this.constructor {
24
- public query = tx[name]
22
+ public query = tx[name];
25
23
 
26
- public transactionClient = tx
27
- })() as typeof this
28
- }
24
+ public transactionClient = tx;
25
+ })() as typeof this;
26
+ };
29
27
 
30
28
  public getModel = <T extends ModelName>(
31
29
  name: T,
@@ -34,27 +32,29 @@ function makeBaseModel<TModelName extends ModelName>(name: TModelName) {
34
32
  ? require('../../src/models')[`${name}Model`].transactionify(
35
33
  this.transactionClient,
36
34
  )
37
- : require('../../src/models')[`${name}Model`]
38
- }
39
- }
35
+ : require('../../src/models')[`${name}Model`];
36
+ };
37
+ };
40
38
  }
41
39
 
42
40
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `export const ${m[1]}BaseModel = makeBaseModel('${_.camel(m[1])}')`)
43
41
  // @endindex
44
42
 
45
- export * from '@prisma/client'
43
+ export * from '@prisma/client';
46
44
 
47
45
  export const startTransaction = <T>(
48
- cb: (models: {
49
- [K in ModelName]: typeof import('../../src/models')[`${K}Model`]
50
- }) => Promise<T>,
46
+ cb: (
47
+ models: {
48
+ [K in ModelName]: typeof import('../../src/models')[`${K}Model`];
49
+ },
50
+ ) => Promise<T>,
51
51
  ): Promise<T> => {
52
52
  return prismaClient.$transaction(async tx => {
53
- const _models = require('../../src/models')
54
- const cache = Object.create(null)
53
+ const _models = require('../../src/models');
54
+ const cache = Object.create(null);
55
55
  return cb({
56
56
  // @index('../.prisma/client/index.d.ts', /(?<=const ModelName:).+?(?=\})/s, /(\S+?):/g, (m, _) => `get ${_.camel(m[1])}() { return cache.${_.camel(m[1])} || (cache.${_.camel(m[1])} = _models.${_.camel(m[1])}Model.transactionify(tx)) }, `)
57
57
  // @endindex
58
- })
59
- })
60
- }
58
+ });
59
+ });
60
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jayfong/x-server",
3
- "version": "2.34.0",
3
+ "version": "2.35.0",
4
4
  "license": "ISC",
5
5
  "sideEffects": false,
6
6
  "main": "lib/_cjs/index.js",
@@ -9,9 +9,7 @@
9
9
  "bin": {
10
10
  "xs": "lib/_cjs/cli/cli.js"
11
11
  },
12
- "files": [
13
- "lib"
14
- ],
12
+ "files": ["lib"],
15
13
  "scripts": {
16
14
  "build": "haoma compile",
17
15
  "build_test_pkg": "tyn build && rm -rf ./lib_test && mkdir -p ./lib_test && cp -r ./lib ./lib_test/lib && cp ./package.json ./lib_test/package.json && cd ./tests/app && tyn add file:../../lib_test",
@@ -19,16 +17,14 @@
19
17
  "test": "tsc --noEmit -p ./tsconfig.build.json && jest \"$(pwd)/src/\"",
20
18
  "test_all": "tsc --noEmit -p ./tsconfig.build.json && jest",
21
19
  "test_api_bot": "cd /Users/admin/Documents/jfWorks/qiqi-bot && DEBUG=api tsx /Users/admin/Documents/jfWorks/x/packages/x-server/src/cli/cli.ts api",
22
- "test_api_qiqi": "cd /Users/admin/Documents/jfWorks/qiqi-server && DEBUG=api tsx /Users/admin/Documents/jfWorks/x/packages/x-server/src/cli/cli.ts api",
23
- "test_api1_bot": "cd /Users/admin/Documents/jfWorks/qiqi-bot && DEBUG=api1 tsx /Users/admin/Documents/jfWorks/x/packages/x-server/src/cli/cli.ts api1",
24
- "test_api1_qiqi": "cd /Users/admin/Documents/jfWorks/qiqi-server && DEBUG=api1 tsx /Users/admin/Documents/jfWorks/x/packages/x-server/src/cli/cli.ts api1"
20
+ "test_api_qiqi": "cd /Users/admin/Documents/jfWorks/qiqi-server && DEBUG=api tsx /Users/admin/Documents/jfWorks/x/packages/x-server/src/cli/cli.ts api"
25
21
  },
26
22
  "dependencies": {
27
23
  "@fastify/cors": "^8.3.0",
28
24
  "@fastify/formbody": "^7.4.0",
29
25
  "@fastify/multipart": "^7.7.0",
30
26
  "@fastify/websocket": "^8.1.0",
31
- "@prisma/client": "^4.8.0",
27
+ "@prisma/client": "^5.8.0",
32
28
  "@types/busboy": "^0.3.2",
33
29
  "@types/http-errors": "^1.8.2",
34
30
  "@types/jsonwebtoken": "^8.5.8",
@@ -62,7 +58,7 @@
62
58
  "nodemailer": "^6.7.3",
63
59
  "pino-pretty": "^10.0.1",
64
60
  "pirates": "^4.0.6",
65
- "prisma": "^4.8.0",
61
+ "prisma": "^5.8.0",
66
62
  "select-run": "^1.1.2",
67
63
  "supports-color": "^8",
68
64
  "svg-captcha": "^1.4.0",
@@ -85,7 +81,8 @@
85
81
  "ioredis-mock": "^8.7.0",
86
82
  "json-xml-parse": "^1.2.4",
87
83
  "node-fetch": "^3.3.1",
88
- "npm-check-updates": "^12.5.9"
84
+ "npm-check-updates": "^12.5.9",
85
+ "openapi-types": "^12.1.3"
89
86
  },
90
87
  "publishConfig": {
91
88
  "access": "public"
@@ -1,286 +0,0 @@
1
- "use strict";
2
-
3
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
5
- exports.__esModule = true;
6
- exports.ApiGenerator1 = void 0;
7
- var _nodePath = _interopRequireDefault(require("node:path"));
8
- var parseComment = _interopRequireWildcard(require("comment-parser"));
9
- var _debug = _interopRequireDefault(require("debug"));
10
- var _fsExtra = _interopRequireDefault(require("fs-extra"));
11
- var ts = _interopRequireWildcard(require("ts-morph"));
12
- var _vtils = require("vtils");
13
- var _http_method = require("../core/http_method");
14
- class ApiGenerator1 {
15
- constructor() {
16
- this.debug = (0, _debug.default)('api1');
17
- this.cwd = process.cwd();
18
- // cwd = '/Users/admin/Documents/jfWorks/x-server-test'
19
- this.project = void 0;
20
- }
21
- getTypeBySymbol(symbol) {
22
- return symbol.getTypeAtLocation(symbol.getDeclarations()[0] || symbol.getValueDeclarationOrThrow());
23
- }
24
- getComment(declaration) {
25
- var _declaration$getLeadi;
26
- const text = ((declaration == null || (_declaration$getLeadi = declaration.getLeadingCommentRanges()[0]) == null ? void 0 : _declaration$getLeadi.getText()) || '').trim();
27
- const comment = parseComment.parse(text)[0];
28
- const description = (comment == null ? void 0 : comment.description) || '';
29
- const tags = new Map();
30
- comment == null ? void 0 : comment.tags.forEach(tag => {
31
- tags.set(tag.tag, tag.description);
32
- });
33
- return {
34
- existing: !!comment,
35
- description: description,
36
- tags: tags
37
- };
38
- }
39
- getCommentBySymbol(symbol) {
40
- var _this$getComment;
41
- return ((_this$getComment = this.getComment(symbol.getDeclarations()[0])) == null ? void 0 : _this$getComment.description) || '';
42
- }
43
- typeToApiData(type, _symbol) {
44
- var _type$getSymbol, _type$getSymbol2, _type$getSymbol3;
45
- // ws
46
- if (((_type$getSymbol = type.getSymbol()) == null ? void 0 : _type$getSymbol.getName()) === 'SocketStream') {
47
- return {
48
- name: 'ws',
49
- desc: 'ws',
50
- required: false,
51
- type: 'object',
52
- children: [],
53
- enum: []
54
- };
55
- }
56
-
57
- // XFile
58
- if (((_type$getSymbol2 = type.getSymbol()) == null ? void 0 : _type$getSymbol2.getName()) === 'MultipartFile') {
59
- const symbol = _symbol || type.getSymbol();
60
- return {
61
- name: 'file',
62
- desc: symbol && this.getCommentBySymbol(symbol) || '',
63
- required: !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional),
64
- type: 'file',
65
- children: [],
66
- enum: []
67
- };
68
- }
69
- let isRequired = true;
70
- let isUnion = type.isUnion();
71
- const unionTypes = isUnion ? type.getUnionTypes().filter(item => !item.isBooleanLiteral() && !item.isNull() && !item.isUndefined()) : [];
72
- isUnion = !!unionTypes.length;
73
- if (isUnion) {
74
- if (unionTypes.length === 1 && !unionTypes[0].isLiteral()) {
75
- isUnion = false;
76
- }
77
- // 兼容 prisma 生成的类型用 null 表示可选
78
- isRequired = unionTypes.length === type.getUnionTypes().length;
79
- // 必须用 getBaseTypeOfLiteralType 获取枚举字面量的原始类型
80
- type = unionTypes[0].getBaseTypeOfLiteralType();
81
- }
82
- const isEnum = type.isEnum();
83
- const enumData = isEnum ?
84
- // @ts-ignore
85
- type.compilerType.types.reduce((res, item) => {
86
- res[item.getSymbol().getName()] = item.value;
87
- return res;
88
- }, {}) : {};
89
- const enumKeys = Object.keys(enumData);
90
- const enumValues = Object.values(enumData);
91
- const isIntersection = type.isIntersection();
92
- const intersectionTypes = isIntersection && type.getIntersectionTypes();
93
- const isArray = type.isArray();
94
- const isString = isEnum ? typeof enumValues[0] === 'string' : type.isString() || ['Date'].includes(((_type$getSymbol3 = type.getSymbol()) == null ? void 0 : _type$getSymbol3.getName()) || '');
95
- const isNumber = isEnum ? typeof enumValues[0] === 'number' : type.isNumber();
96
- const isBoolean = type.isBoolean() || type.isUnion() && type.getUnionTypes().some(item => item.isBooleanLiteral()) && type.getUnionTypes().every(item => item.isBooleanLiteral() || item.isNull() || item.isUndefined());
97
- const isObject = !isArray && !isString && !isNumber && !isBoolean && type.isObject() ||
98
- // 将交集类型视为对象
99
- isIntersection;
100
- const symbol = _symbol || type.getSymbol();
101
- const parentSymbol = symbol;
102
- const apiName = (symbol == null ? void 0 : symbol.getName()) || '__type';
103
- const apiDesc = [symbol && this.getCommentBySymbol(symbol), isEnum && `枚举:${enumKeys.map((key, index) => `${key}->${enumValues[index]}`).join('; ')}`].filter(Boolean).join('\n');
104
- const apiEnum = isUnion ? unionTypes.map(t => t.getLiteralValue()) : isEnum ? enumValues : [];
105
- const apiType = isArray ? 'array' : isString ? 'string' : isNumber ? 'number' : isBoolean ? 'boolean' : 'object';
106
- const apiRequired = isRequired === false ? false : !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional);
107
- const apiChildren = isArray ? [this.typeToApiData(type.getArrayElementTypeOrThrow())] : isObject ? (0, _vtils.ii)(() => {
108
- const context = type._context;
109
- const compilerFactory = context.compilerFactory;
110
- const rawChecker = type.compilerType.checker;
111
- let symbols = [];
112
- if (intersectionTypes) {
113
- // https://github.com/microsoft/TypeScript/issues/38184
114
- symbols = rawChecker.getAllPossiblePropertiesOfTypes(intersectionTypes.map(item => item.compilerType))
115
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
116
- .map(symbol => compilerFactory.getSymbol(symbol));
117
- } else {
118
- // symbols = type.getApparentProperties()
119
- // https://github.com/microsoft/TypeScript/issues/38184
120
- symbols = rawChecker.getAllPossiblePropertiesOfTypes([type.compilerType])
121
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
122
- .map(symbol => compilerFactory.getSymbol(symbol));
123
- }
124
- return symbols.map(symbol => {
125
- return this.typeToApiData(!symbol.compilerSymbol.declarations ?
126
- // 对于复杂对象,没有定义的,通过 type 直接获取(在前面通过 getText 预处理得到)
127
- symbol.compilerSymbol.type ? compilerFactory.getType(symbol.compilerSymbol.type) :
128
- // fix: symbol.compilerSymbol.type 为 undefined
129
- // https://github.com/styleguidist/react-docgen-typescript/blob/master/src/parser.ts#L696
130
- compilerFactory.getType(rawChecker.getTypeOfSymbolAtLocation(
131
- // @ts-ignore
132
- symbol.compilerSymbol,
133
- // @ts-ignore
134
- parentSymbol.compilerSymbol.declarations[0])) : this.getTypeBySymbol(symbol), symbol);
135
- });
136
- }) : [];
137
- return {
138
- name: apiName,
139
- desc: apiDesc,
140
- enum: apiEnum,
141
- type: apiType,
142
- required: apiRequired,
143
- children: apiChildren
144
- };
145
- }
146
- apiDataToJsonSchema(apiData, jsonSchema = {}) {
147
- jsonSchema.description = apiData.desc;
148
- if (apiData.type === 'object') {
149
- jsonSchema.type = 'object';
150
- jsonSchema.properties = apiData.children.reduce((res, item) => {
151
- res[item.name] = this.apiDataToJsonSchema(item);
152
- return res;
153
- }, {});
154
- jsonSchema.required = apiData.children.filter(item => item.required).map(item => item.name);
155
- } else if (apiData.type === 'array') {
156
- jsonSchema.type = 'array';
157
- jsonSchema.items = apiData.children.map(item => this.apiDataToJsonSchema(item))[0];
158
- } else {
159
- jsonSchema.type = apiData.type;
160
- if (apiData.enum.length) {
161
- jsonSchema.enum = apiData.enum;
162
- }
163
- }
164
- return jsonSchema;
165
- }
166
- genYApiData(handles) {
167
- const data = {};
168
- for (const handle of handles) {
169
- data[handle.category] = data[handle.category] || [];
170
- data[handle.category].push(handle.handlerMethod === 'GET' ? {
171
- method: handle.method.toUpperCase(),
172
- title: handle.name,
173
- path: handle.path,
174
- res_body_type: 'json',
175
- req_body_is_json_schema: false,
176
- res_body_is_json_schema: true,
177
- req_params: [],
178
- req_query: handle.requestData.children.map(item => ({
179
- required: item.required ? 1 : 0,
180
- name: item.name,
181
- desc: item.desc,
182
- type: 'string'
183
- })),
184
- req_headers: [],
185
- req_body_form: [],
186
- res_body: JSON.stringify(handle.responseDataJsonSchema)
187
- } : handle.handlerMethod === 'FILE' ? {
188
- method: handle.method.toUpperCase(),
189
- title: handle.name,
190
- path: handle.path,
191
- req_body_type: 'form',
192
- res_body_type: 'json',
193
- req_body_is_json_schema: false,
194
- res_body_is_json_schema: true,
195
- req_params: [],
196
- req_query: [],
197
- req_headers: [],
198
- req_body_form: handle.requestData.children.map(item => ({
199
- required: item.required ? 1 : 0,
200
- name: item.name,
201
- desc: item.desc,
202
- type: item.type === 'file' ? 'file' : 'text'
203
- })),
204
- res_body: JSON.stringify(handle.responseDataJsonSchema)
205
- } : {
206
- method: handle.method.toUpperCase(),
207
- title: handle.name,
208
- path: handle.path,
209
- req_body_type: 'json',
210
- res_body_type: 'json',
211
- req_body_is_json_schema: true,
212
- res_body_is_json_schema: true,
213
- req_params: [],
214
- req_query: [],
215
- req_headers: [],
216
- req_body_form: [],
217
- req_body_other: JSON.stringify(handle.requestDataJsonSchema),
218
- res_body: JSON.stringify(handle.responseDataJsonSchema)
219
- });
220
- }
221
- return Object.keys(data).map(cat => ({
222
- name: cat,
223
- desc: cat,
224
- list: data[cat]
225
- }));
226
- }
227
- async generate() {
228
- this.debug('启动项目...');
229
- this.project = new ts.Project({
230
- tsConfigFilePath: _nodePath.default.join(this.cwd, 'tsconfig.json')
231
- });
232
- this.debug('加载文件...');
233
- const sourceFile = this.project.createSourceFile(_nodePath.default.join(this.cwd, 'src/generated/handlers.ts'), await _fsExtra.default.readFile(_nodePath.default.join(this.cwd, 'node_modules/.x/handlers.ts'), 'utf-8'));
234
- this.debug('导出处理器...');
235
- const handlerGroup = sourceFile.getExportSymbols();
236
- const handles = [];
237
- this.debug('生成API文档...');
238
- for (const handlerList of handlerGroup) {
239
- const handlerListSourceFile = this.getTypeBySymbol(handlerList).getProperties()[0].getDeclarations()[0].getSourceFile();
240
- const basePath = `/${handlerListSourceFile.getFilePath().replace('.ts', '').split('/src/handlers/')[1].replace(/(^|\/)index$/, '/').split('/').map(v => (0, _vtils.snakeCase)(v)).join('/')}/`.replace(/\/{2,}/g, '/');
241
- for (const handler of handlerListSourceFile.getVariableStatements().filter(item => item.isExported())) {
242
- // 重要:这一步必须,先调一遍 getText 获取看到的对象,后续对于复杂定义才不会报错
243
- handler.getDeclarations().forEach(exp => {
244
- exp.getType().getText();
245
- });
246
- const handlerExp = handler.getDeclarations()[0];
247
- const handlerPath = `${basePath}${handlerExp.getName()}`;
248
- this.debug('生成接口: %s ...', handlerPath);
249
- const [requestType, responseType, methodType] = handlerExp.getType().getTypeArguments();
250
- const handlerComment = this.getComment(handlerExp.getParent().getParent());
251
- if (handlerComment.tags.has('private')) {
252
- this.debug('跳过生成接口: %s', `${handlerPath}`);
253
- continue;
254
- }
255
- const handlerCategory = (0, _vtils.pascalCase)(basePath) || 'Index';
256
- const handlerName = handlerComment.description || handlerPath;
257
- const handlerMethod = methodType.getLiteralValueOrThrow();
258
- const serverMethod = _http_method.HandlerMethodToHttpMethod[handlerMethod];
259
- const requestData = this.typeToApiData(requestType);
260
- const responseData = this.typeToApiData(responseType);
261
- const requestDataJsonSchema = this.apiDataToJsonSchema(requestData);
262
- const responseDataJsonSchema = this.apiDataToJsonSchema(responseData);
263
- handles.push({
264
- category: handlerCategory,
265
- name: handlerName,
266
- path: handlerPath,
267
- handlerMethod: handlerMethod,
268
- method: serverMethod,
269
- requestData: requestData,
270
- responseData: responseData,
271
- requestDataJsonSchema: requestDataJsonSchema,
272
- responseDataJsonSchema: responseDataJsonSchema
273
- });
274
- }
275
- }
276
- this.debug('写入文件...');
277
- await Promise.all([_fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, 'temp/api1.json'), handles, {
278
- spaces: 2
279
- }), _fsExtra.default.outputJSON(_nodePath.default.join(this.cwd, 'temp/yapi1.json'), this.genYApiData(handles), {
280
- spaces: 2
281
- })]);
282
- }
283
- }
284
-
285
- // new ApiGenerator().generate()
286
- exports.ApiGenerator1 = ApiGenerator1;
@@ -1,44 +0,0 @@
1
- import createDebug from 'debug';
2
- import type { JSONSchema4 } from 'json-schema';
3
- import * as ts from 'ts-morph';
4
- import type { XHandler } from '../core/types';
5
- interface ApiData {
6
- name: string;
7
- desc: string;
8
- type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'file';
9
- enum: any[];
10
- required: boolean;
11
- children: ApiData[];
12
- }
13
- type ApiHandles = Array<{
14
- category: string;
15
- name: string;
16
- path: string;
17
- handlerMethod: XHandler.Method;
18
- method: string;
19
- requestData: ApiData;
20
- responseData: ApiData;
21
- requestDataJsonSchema: JSONSchema4;
22
- responseDataJsonSchema: JSONSchema4;
23
- }>;
24
- export declare class ApiGenerator1 {
25
- debug: createDebug.Debugger;
26
- cwd: string;
27
- project: ts.Project;
28
- getTypeBySymbol(symbol: ts.Symbol): ts.Type;
29
- getComment(declaration?: ts.Node): {
30
- existing: boolean;
31
- description: string;
32
- tags: Map<string, string>;
33
- };
34
- getCommentBySymbol(symbol: ts.Symbol): string;
35
- typeToApiData(type: ts.Type, _symbol?: ts.Symbol): ApiData;
36
- apiDataToJsonSchema(apiData: ApiData, jsonSchema?: JSONSchema4): JSONSchema4;
37
- genYApiData(handles: ApiHandles): {
38
- name: string;
39
- desc: string;
40
- list: any;
41
- }[];
42
- generate(): Promise<void>;
43
- }
44
- export {};
@@ -1,279 +0,0 @@
1
- import path from 'node:path';
2
- import * as parseComment from 'comment-parser';
3
- import createDebug from 'debug';
4
- import fs from 'fs-extra';
5
- import * as ts from 'ts-morph';
6
- import { ii, pascalCase, snakeCase } from 'vtils';
7
- import { HandlerMethodToHttpMethod } from "../core/http_method";
8
- export class ApiGenerator1 {
9
- constructor() {
10
- this.debug = createDebug('api1');
11
- this.cwd = process.cwd();
12
- // cwd = '/Users/admin/Documents/jfWorks/x-server-test'
13
- this.project = void 0;
14
- }
15
- getTypeBySymbol(symbol) {
16
- return symbol.getTypeAtLocation(symbol.getDeclarations()[0] || symbol.getValueDeclarationOrThrow());
17
- }
18
- getComment(declaration) {
19
- var _declaration$getLeadi;
20
- const text = ((declaration == null || (_declaration$getLeadi = declaration.getLeadingCommentRanges()[0]) == null ? void 0 : _declaration$getLeadi.getText()) || '').trim();
21
- const comment = parseComment.parse(text)[0];
22
- const description = (comment == null ? void 0 : comment.description) || '';
23
- const tags = new Map();
24
- comment == null ? void 0 : comment.tags.forEach(tag => {
25
- tags.set(tag.tag, tag.description);
26
- });
27
- return {
28
- existing: !!comment,
29
- description: description,
30
- tags: tags
31
- };
32
- }
33
- getCommentBySymbol(symbol) {
34
- var _this$getComment;
35
- return ((_this$getComment = this.getComment(symbol.getDeclarations()[0])) == null ? void 0 : _this$getComment.description) || '';
36
- }
37
- typeToApiData(type, _symbol) {
38
- var _type$getSymbol, _type$getSymbol2, _type$getSymbol3;
39
- // ws
40
- if (((_type$getSymbol = type.getSymbol()) == null ? void 0 : _type$getSymbol.getName()) === 'SocketStream') {
41
- return {
42
- name: 'ws',
43
- desc: 'ws',
44
- required: false,
45
- type: 'object',
46
- children: [],
47
- enum: []
48
- };
49
- }
50
-
51
- // XFile
52
- if (((_type$getSymbol2 = type.getSymbol()) == null ? void 0 : _type$getSymbol2.getName()) === 'MultipartFile') {
53
- const symbol = _symbol || type.getSymbol();
54
- return {
55
- name: 'file',
56
- desc: symbol && this.getCommentBySymbol(symbol) || '',
57
- required: !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional),
58
- type: 'file',
59
- children: [],
60
- enum: []
61
- };
62
- }
63
- let isRequired = true;
64
- let isUnion = type.isUnion();
65
- const unionTypes = isUnion ? type.getUnionTypes().filter(item => !item.isBooleanLiteral() && !item.isNull() && !item.isUndefined()) : [];
66
- isUnion = !!unionTypes.length;
67
- if (isUnion) {
68
- if (unionTypes.length === 1 && !unionTypes[0].isLiteral()) {
69
- isUnion = false;
70
- }
71
- // 兼容 prisma 生成的类型用 null 表示可选
72
- isRequired = unionTypes.length === type.getUnionTypes().length;
73
- // 必须用 getBaseTypeOfLiteralType 获取枚举字面量的原始类型
74
- type = unionTypes[0].getBaseTypeOfLiteralType();
75
- }
76
- const isEnum = type.isEnum();
77
- const enumData = isEnum ?
78
- // @ts-ignore
79
- type.compilerType.types.reduce((res, item) => {
80
- res[item.getSymbol().getName()] = item.value;
81
- return res;
82
- }, {}) : {};
83
- const enumKeys = Object.keys(enumData);
84
- const enumValues = Object.values(enumData);
85
- const isIntersection = type.isIntersection();
86
- const intersectionTypes = isIntersection && type.getIntersectionTypes();
87
- const isArray = type.isArray();
88
- const isString = isEnum ? typeof enumValues[0] === 'string' : type.isString() || ['Date'].includes(((_type$getSymbol3 = type.getSymbol()) == null ? void 0 : _type$getSymbol3.getName()) || '');
89
- const isNumber = isEnum ? typeof enumValues[0] === 'number' : type.isNumber();
90
- const isBoolean = type.isBoolean() || type.isUnion() && type.getUnionTypes().some(item => item.isBooleanLiteral()) && type.getUnionTypes().every(item => item.isBooleanLiteral() || item.isNull() || item.isUndefined());
91
- const isObject = !isArray && !isString && !isNumber && !isBoolean && type.isObject() ||
92
- // 将交集类型视为对象
93
- isIntersection;
94
- const symbol = _symbol || type.getSymbol();
95
- const parentSymbol = symbol;
96
- const apiName = (symbol == null ? void 0 : symbol.getName()) || '__type';
97
- const apiDesc = [symbol && this.getCommentBySymbol(symbol), isEnum && `枚举:${enumKeys.map((key, index) => `${key}->${enumValues[index]}`).join('; ')}`].filter(Boolean).join('\n');
98
- const apiEnum = isUnion ? unionTypes.map(t => t.getLiteralValue()) : isEnum ? enumValues : [];
99
- const apiType = isArray ? 'array' : isString ? 'string' : isNumber ? 'number' : isBoolean ? 'boolean' : 'object';
100
- const apiRequired = isRequired === false ? false : !!symbol && !(symbol.getFlags() & ts.SymbolFlags.Optional);
101
- const apiChildren = isArray ? [this.typeToApiData(type.getArrayElementTypeOrThrow())] : isObject ? ii(() => {
102
- const context = type._context;
103
- const compilerFactory = context.compilerFactory;
104
- const rawChecker = type.compilerType.checker;
105
- let symbols = [];
106
- if (intersectionTypes) {
107
- // https://github.com/microsoft/TypeScript/issues/38184
108
- symbols = rawChecker.getAllPossiblePropertiesOfTypes(intersectionTypes.map(item => item.compilerType))
109
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
110
- .map(symbol => compilerFactory.getSymbol(symbol));
111
- } else {
112
- // symbols = type.getApparentProperties()
113
- // https://github.com/microsoft/TypeScript/issues/38184
114
- symbols = rawChecker.getAllPossiblePropertiesOfTypes([type.compilerType])
115
- // https://github.com/dsherret/ts-morph/blob/a7072fcf6f9babb784b40f0326c80dea4563a4aa/packages/ts-morph/src/compiler/types/Type.ts#L296
116
- .map(symbol => compilerFactory.getSymbol(symbol));
117
- }
118
- return symbols.map(symbol => {
119
- return this.typeToApiData(!symbol.compilerSymbol.declarations ?
120
- // 对于复杂对象,没有定义的,通过 type 直接获取(在前面通过 getText 预处理得到)
121
- symbol.compilerSymbol.type ? compilerFactory.getType(symbol.compilerSymbol.type) :
122
- // fix: symbol.compilerSymbol.type 为 undefined
123
- // https://github.com/styleguidist/react-docgen-typescript/blob/master/src/parser.ts#L696
124
- compilerFactory.getType(rawChecker.getTypeOfSymbolAtLocation(
125
- // @ts-ignore
126
- symbol.compilerSymbol,
127
- // @ts-ignore
128
- parentSymbol.compilerSymbol.declarations[0])) : this.getTypeBySymbol(symbol), symbol);
129
- });
130
- }) : [];
131
- return {
132
- name: apiName,
133
- desc: apiDesc,
134
- enum: apiEnum,
135
- type: apiType,
136
- required: apiRequired,
137
- children: apiChildren
138
- };
139
- }
140
- apiDataToJsonSchema(apiData, jsonSchema = {}) {
141
- jsonSchema.description = apiData.desc;
142
- if (apiData.type === 'object') {
143
- jsonSchema.type = 'object';
144
- jsonSchema.properties = apiData.children.reduce((res, item) => {
145
- res[item.name] = this.apiDataToJsonSchema(item);
146
- return res;
147
- }, {});
148
- jsonSchema.required = apiData.children.filter(item => item.required).map(item => item.name);
149
- } else if (apiData.type === 'array') {
150
- jsonSchema.type = 'array';
151
- jsonSchema.items = apiData.children.map(item => this.apiDataToJsonSchema(item))[0];
152
- } else {
153
- jsonSchema.type = apiData.type;
154
- if (apiData.enum.length) {
155
- jsonSchema.enum = apiData.enum;
156
- }
157
- }
158
- return jsonSchema;
159
- }
160
- genYApiData(handles) {
161
- const data = {};
162
- for (const handle of handles) {
163
- data[handle.category] = data[handle.category] || [];
164
- data[handle.category].push(handle.handlerMethod === 'GET' ? {
165
- method: handle.method.toUpperCase(),
166
- title: handle.name,
167
- path: handle.path,
168
- res_body_type: 'json',
169
- req_body_is_json_schema: false,
170
- res_body_is_json_schema: true,
171
- req_params: [],
172
- req_query: handle.requestData.children.map(item => ({
173
- required: item.required ? 1 : 0,
174
- name: item.name,
175
- desc: item.desc,
176
- type: 'string'
177
- })),
178
- req_headers: [],
179
- req_body_form: [],
180
- res_body: JSON.stringify(handle.responseDataJsonSchema)
181
- } : handle.handlerMethod === 'FILE' ? {
182
- method: handle.method.toUpperCase(),
183
- title: handle.name,
184
- path: handle.path,
185
- req_body_type: 'form',
186
- res_body_type: 'json',
187
- req_body_is_json_schema: false,
188
- res_body_is_json_schema: true,
189
- req_params: [],
190
- req_query: [],
191
- req_headers: [],
192
- req_body_form: handle.requestData.children.map(item => ({
193
- required: item.required ? 1 : 0,
194
- name: item.name,
195
- desc: item.desc,
196
- type: item.type === 'file' ? 'file' : 'text'
197
- })),
198
- res_body: JSON.stringify(handle.responseDataJsonSchema)
199
- } : {
200
- method: handle.method.toUpperCase(),
201
- title: handle.name,
202
- path: handle.path,
203
- req_body_type: 'json',
204
- res_body_type: 'json',
205
- req_body_is_json_schema: true,
206
- res_body_is_json_schema: true,
207
- req_params: [],
208
- req_query: [],
209
- req_headers: [],
210
- req_body_form: [],
211
- req_body_other: JSON.stringify(handle.requestDataJsonSchema),
212
- res_body: JSON.stringify(handle.responseDataJsonSchema)
213
- });
214
- }
215
- return Object.keys(data).map(cat => ({
216
- name: cat,
217
- desc: cat,
218
- list: data[cat]
219
- }));
220
- }
221
- async generate() {
222
- this.debug('启动项目...');
223
- this.project = new ts.Project({
224
- tsConfigFilePath: path.join(this.cwd, 'tsconfig.json')
225
- });
226
- this.debug('加载文件...');
227
- const sourceFile = this.project.createSourceFile(path.join(this.cwd, 'src/generated/handlers.ts'), await fs.readFile(path.join(this.cwd, 'node_modules/.x/handlers.ts'), 'utf-8'));
228
- this.debug('导出处理器...');
229
- const handlerGroup = sourceFile.getExportSymbols();
230
- const handles = [];
231
- this.debug('生成API文档...');
232
- for (const handlerList of handlerGroup) {
233
- const handlerListSourceFile = this.getTypeBySymbol(handlerList).getProperties()[0].getDeclarations()[0].getSourceFile();
234
- const basePath = `/${handlerListSourceFile.getFilePath().replace('.ts', '').split('/src/handlers/')[1].replace(/(^|\/)index$/, '/').split('/').map(v => snakeCase(v)).join('/')}/`.replace(/\/{2,}/g, '/');
235
- for (const handler of handlerListSourceFile.getVariableStatements().filter(item => item.isExported())) {
236
- // 重要:这一步必须,先调一遍 getText 获取看到的对象,后续对于复杂定义才不会报错
237
- handler.getDeclarations().forEach(exp => {
238
- exp.getType().getText();
239
- });
240
- const handlerExp = handler.getDeclarations()[0];
241
- const handlerPath = `${basePath}${handlerExp.getName()}`;
242
- this.debug('生成接口: %s ...', handlerPath);
243
- const [requestType, responseType, methodType] = handlerExp.getType().getTypeArguments();
244
- const handlerComment = this.getComment(handlerExp.getParent().getParent());
245
- if (handlerComment.tags.has('private')) {
246
- this.debug('跳过生成接口: %s', `${handlerPath}`);
247
- continue;
248
- }
249
- const handlerCategory = pascalCase(basePath) || 'Index';
250
- const handlerName = handlerComment.description || handlerPath;
251
- const handlerMethod = methodType.getLiteralValueOrThrow();
252
- const serverMethod = HandlerMethodToHttpMethod[handlerMethod];
253
- const requestData = this.typeToApiData(requestType);
254
- const responseData = this.typeToApiData(responseType);
255
- const requestDataJsonSchema = this.apiDataToJsonSchema(requestData);
256
- const responseDataJsonSchema = this.apiDataToJsonSchema(responseData);
257
- handles.push({
258
- category: handlerCategory,
259
- name: handlerName,
260
- path: handlerPath,
261
- handlerMethod: handlerMethod,
262
- method: serverMethod,
263
- requestData: requestData,
264
- responseData: responseData,
265
- requestDataJsonSchema: requestDataJsonSchema,
266
- responseDataJsonSchema: responseDataJsonSchema
267
- });
268
- }
269
- }
270
- this.debug('写入文件...');
271
- await Promise.all([fs.outputJSON(path.join(this.cwd, 'temp/api1.json'), handles, {
272
- spaces: 2
273
- }), fs.outputJSON(path.join(this.cwd, 'temp/yapi1.json'), this.genYApiData(handles), {
274
- spaces: 2
275
- })]);
276
- }
277
- }
278
-
279
- // new ApiGenerator().generate()