@jayfong/x-server 2.32.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
+ };
@@ -40,58 +40,74 @@ function defineSliceTask(options) {
40
40
  }
41
41
  }
42
42
  });
43
- const redisKeyPrefix = `${_x.x.appId}_batch_task_${options.name}`;
44
- const res = {
45
- add: async (data, addOptions) => {
46
- const key = (addOptions == null ? void 0 : addOptions.key) || '';
47
- const duration = (addOptions == null ? void 0 : addOptions.duration) != null ? (0, _vtils.ms)(addOptions.duration) : typeof options.duration === 'function' ? (0, _vtils.ms)(options.duration(key)) : options.duration && (0, _vtils.ms)(options.duration);
48
- const threshold = (addOptions == null ? void 0 : addOptions.threshold) || typeof options.threshold && (typeof options.threshold === 'function' ? options.threshold(key) : options.threshold);
49
- const thresholdTimeout = (addOptions == null ? void 0 : addOptions.thresholdTimeout) != null ? (0, _vtils.ms)(addOptions.thresholdTimeout) : typeof options.thresholdTimeout === 'function' ? (0, _vtils.ms)(options.thresholdTimeout(key)) : options.thresholdTimeout && (0, _vtils.ms)(options.thresholdTimeout);
50
- (0, _assert.default)(duration != null || threshold != null, '参数 threshold 和 duration 必须至少设置 1 个');
51
- const redisKey = !key ? redisKeyPrefix : `${redisKeyPrefix}_${key}`;
52
- const res = await _x.x.redis.multi([['llen', redisKey], ['lpush', redisKey, JSON.stringify(data)]]).exec();
53
- const count = parseInt(res[0][1], 10) + 1;
43
+ const addAction = async (data, addOptions) => {
44
+ const redisKeyPrefix = `${_x.x.appId}_batch_task_${options.name}`;
45
+ const key = (addOptions == null ? void 0 : addOptions.key) || '';
46
+ const duration = (addOptions == null ? void 0 : addOptions.duration) != null ? (0, _vtils.ms)(addOptions.duration) : typeof options.duration === 'function' ? (0, _vtils.ms)(options.duration(key)) : options.duration && (0, _vtils.ms)(options.duration);
47
+ const threshold = (addOptions == null ? void 0 : addOptions.threshold) || typeof options.threshold && (typeof options.threshold === 'function' ? options.threshold(key) : options.threshold);
48
+ const thresholdTimeout = (addOptions == null ? void 0 : addOptions.thresholdTimeout) != null ? (0, _vtils.ms)(addOptions.thresholdTimeout) : typeof options.thresholdTimeout === 'function' ? (0, _vtils.ms)(options.thresholdTimeout(key)) : options.thresholdTimeout && (0, _vtils.ms)(options.thresholdTimeout);
49
+ (0, _assert.default)(duration != null || threshold != null, '参数 threshold duration 必须至少设置 1 个');
50
+ const redisKey = !key ? redisKeyPrefix : `${redisKeyPrefix}_${key}`;
51
+ const res = await _x.x.redis.multi([['llen', redisKey], ['lpush', redisKey, JSON.stringify(data)]]).exec();
52
+ const count = parseInt(res[0][1], 10) + 1;
54
53
 
55
- // 仅时段
56
- // 1分钟内的合并推送
57
- if (duration != null) {
58
- if (count === 1) {
59
- await task.add({
60
- key: key,
61
- redisKey: redisKey
62
- }, {
63
- delay: duration
64
- });
65
- }
54
+ // 仅时段
55
+ // 1分钟内的合并推送
56
+ if (duration != null) {
57
+ if (count === 1) {
58
+ await task.add({
59
+ key: key,
60
+ redisKey: redisKey
61
+ }, {
62
+ delay: duration
63
+ });
66
64
  }
67
- // 仅阈值
68
- // 满10条推送
69
- else if (threshold != null) {
70
- const delayTaskId = redisKey;
71
- const prevJob = await task.getJob(delayTaskId);
65
+ }
66
+ // 仅阈值
67
+ // 满10条推送
68
+ else if (threshold != null) {
69
+ const delayTaskId = redisKey;
70
+ const prevJob = await task.getJob(delayTaskId);
72
71
 
73
- // 到达阈值,立即发送
74
- if (count === threshold) {
75
- await (prevJob == null ? void 0 : prevJob.remove());
72
+ // 到达阈值,立即发送
73
+ if (count === threshold) {
74
+ await (prevJob == null ? void 0 : prevJob.remove());
75
+ await task.add({
76
+ key: key,
77
+ redisKey: redisKey
78
+ });
79
+ }
80
+ // 存在超时设置
81
+ else if (thresholdTimeout) {
82
+ if (!prevJob) {
76
83
  await task.add({
77
84
  key: key,
78
85
  redisKey: redisKey
86
+ }, {
87
+ jobId: delayTaskId,
88
+ delay: thresholdTimeout
79
89
  });
80
90
  }
81
- // 存在超时设置
82
- else if (thresholdTimeout) {
83
- if (!prevJob) {
84
- await task.add({
85
- key: key,
86
- redisKey: redisKey
87
- }, {
88
- jobId: delayTaskId,
89
- delay: thresholdTimeout
90
- });
91
- }
92
- }
93
91
  }
94
92
  }
95
93
  };
94
+ const addTask = defineTask({
95
+ name: `${options.name}_add`,
96
+ concurrency: 1,
97
+ handle: async payload => {
98
+ await addAction(payload.data, payload.options);
99
+ }
100
+ });
101
+ const res = {
102
+ add: async (data, addOptions) => {
103
+ const delay = addOptions.delay && (0, _vtils.ms)(addOptions.delay) || 0;
104
+ await addTask.add({
105
+ data: data,
106
+ options: addOptions
107
+ }, {
108
+ delay: delay
109
+ });
110
+ }
111
+ };
96
112
  return res;
97
113
  }
@@ -10,8 +10,7 @@ var vae = _interopRequireWildcard(require("vtils/vae"));
10
10
  var _validator = require("vtils/validator");
11
11
  var _http_error = require("../core/http_error");
12
12
  var _dispose = require("../services/dispose");
13
- // @ts-ignore
14
- // prettier-ignore
13
+ var _server = require("./server");
15
14
  _validator.yup.setLocale((0, _validator.getZhCN)({
16
15
  getLabel: params => params.label || params.path
17
16
  }));
@@ -79,9 +78,18 @@ class Handler {
79
78
  '_#': _lzString.default.compress(JSON.stringify(res))
80
79
  };
81
80
  }
81
+
82
+ // 加密返回数据
83
+ if (this.options.responseDataEncrypt && _server.Server.options.responseEncryptAlgorithm) {
84
+ if (_server.Server.options.responseEncryptAlgorithm === 'simple') {
85
+ res = {
86
+ _$: (0, _vtils.rot13)((0, _vtils.base64UrlEncode)(`${Date.now()}${JSON.stringify(res)}`))
87
+ };
88
+ }
89
+ }
82
90
  return res == null ? {} : res;
83
91
  };
84
- this.handleWs = async (data, ctx) => {
92
+ this.handleWs = async (_data, ctx) => {
85
93
  const dispose = new _dispose.DisposeService();
86
94
  ctx.ws.socket.on('message', async payload => {
87
95
  try {
@@ -6,9 +6,9 @@ exports.Server = void 0;
6
6
  var _interopRequireWildcard2 = _interopRequireDefault(require("@babel/runtime/helpers/interopRequireWildcard"));
7
7
  var _fastify = _interopRequireDefault(require("fastify"));
8
8
  var _vtils = require("vtils");
9
- var _http_method = require("./http_method");
10
- var _http_error = require("./http_error");
11
9
  var _x = require("../x");
10
+ var _http_error = require("./http_error");
11
+ var _http_method = require("./http_method");
12
12
  class Server {
13
13
  constructor(options) {
14
14
  this.options = options;
@@ -97,7 +97,6 @@ class Server {
97
97
  if (handlerMethod === 'FILE') {
98
98
  const part = await req.file();
99
99
  files = Object.keys(part.fields).reduce((res, name) => {
100
- ;
101
100
  res[name] = (0, _vtils.castArray)(part.fields[name]).map(item => item.file ? item : item.value)[0];
102
101
  return res;
103
102
  }, {});
@@ -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
+ };