evaengine 1.0.14 → 2.0.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.
Files changed (199) hide show
  1. package/README.md +15 -1
  2. package/bin/engine +2 -31
  3. package/dist/bin.d.ts +1 -0
  4. package/dist/bin.js +40 -0
  5. package/dist/bin.js.map +1 -0
  6. package/{src/commands/index.js → dist/commands/index.d.ts} +1 -8
  7. package/dist/commands/index.js +6 -0
  8. package/dist/commands/index.js.map +1 -0
  9. package/dist/commands/interface.d.ts +18 -0
  10. package/dist/commands/interface.js +40 -0
  11. package/dist/commands/interface.js.map +1 -0
  12. package/dist/commands/make_entity.d.ts +47 -0
  13. package/dist/commands/make_entity.js +410 -0
  14. package/dist/commands/make_entity.js.map +1 -0
  15. package/dist/commands/tramp.d.ts +7 -0
  16. package/dist/commands/tramp.js +29 -0
  17. package/dist/commands/tramp.js.map +1 -0
  18. package/dist/config/index.d.ts +92 -0
  19. package/dist/config/index.js +96 -0
  20. package/dist/config/index.js.map +1 -0
  21. package/dist/di.d.ts +73 -0
  22. package/dist/di.js +76 -0
  23. package/dist/di.js.map +1 -0
  24. package/dist/engine.d.ts +85 -0
  25. package/dist/engine.js +404 -0
  26. package/dist/engine.js.map +1 -0
  27. package/dist/entities/index.d.ts +54 -0
  28. package/dist/entities/index.js +228 -0
  29. package/dist/entities/index.js.map +1 -0
  30. package/dist/exceptions/index.d.ts +153 -0
  31. package/dist/exceptions/index.js +439 -0
  32. package/dist/exceptions/index.js.map +1 -0
  33. package/dist/index.d.ts +45 -0
  34. package/dist/index.js +45 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/middlewares/auth.d.ts +5 -0
  37. package/dist/middlewares/auth.js +63 -0
  38. package/dist/middlewares/auth.js.map +1 -0
  39. package/dist/middlewares/auth_kong.d.ts +2 -0
  40. package/dist/middlewares/auth_kong.js +24 -0
  41. package/dist/middlewares/auth_kong.js.map +1 -0
  42. package/dist/middlewares/debug.d.ts +3 -0
  43. package/dist/middlewares/debug.js +50 -0
  44. package/dist/middlewares/debug.js.map +1 -0
  45. package/{src/middlewares/index.js → dist/middlewares/index.d.ts} +1 -11
  46. package/dist/middlewares/index.js +9 -0
  47. package/dist/middlewares/index.js.map +1 -0
  48. package/dist/middlewares/providers.d.ts +25 -0
  49. package/dist/middlewares/providers.js +63 -0
  50. package/dist/middlewares/providers.js.map +1 -0
  51. package/dist/middlewares/session.d.ts +6 -0
  52. package/dist/middlewares/session.js +51 -0
  53. package/dist/middlewares/session.js.map +1 -0
  54. package/dist/middlewares/trace.d.ts +52 -0
  55. package/dist/middlewares/trace.js +225 -0
  56. package/dist/middlewares/trace.js.map +1 -0
  57. package/dist/middlewares/validator.d.ts +10 -0
  58. package/dist/middlewares/validator.js +43 -0
  59. package/dist/middlewares/validator.js.map +1 -0
  60. package/dist/middlewares/view_cache.d.ts +14 -0
  61. package/dist/middlewares/view_cache.js +102 -0
  62. package/dist/middlewares/view_cache.js.map +1 -0
  63. package/dist/services/cache.d.ts +66 -0
  64. package/dist/services/cache.js +207 -0
  65. package/dist/services/cache.js.map +1 -0
  66. package/dist/services/config.d.ts +25 -0
  67. package/dist/services/config.js +88 -0
  68. package/dist/services/config.js.map +1 -0
  69. package/dist/services/env.d.ts +12 -0
  70. package/dist/services/env.js +24 -0
  71. package/dist/services/env.js.map +1 -0
  72. package/dist/services/event_manager.d.ts +29 -0
  73. package/dist/services/event_manager.js +75 -0
  74. package/dist/services/event_manager.js.map +1 -0
  75. package/dist/services/http_client.d.ts +66 -0
  76. package/dist/services/http_client.js +62 -0
  77. package/dist/services/http_client.js.map +1 -0
  78. package/{src/services/index.js → dist/services/index.d.ts} +1 -15
  79. package/dist/services/index.js +14 -0
  80. package/dist/services/index.js.map +1 -0
  81. package/{src/services/interface.js → dist/services/interface.d.ts} +1 -3
  82. package/dist/services/interface.js +6 -0
  83. package/dist/services/interface.js.map +1 -0
  84. package/{src/services/joi.js → dist/services/joi.d.ts} +2 -9
  85. package/dist/services/joi.js +11 -0
  86. package/dist/services/joi.js.map +1 -0
  87. package/dist/services/jwt_token.d.ts +24 -0
  88. package/dist/services/jwt_token.js +77 -0
  89. package/dist/services/jwt_token.js.map +1 -0
  90. package/dist/services/jwt_token_kong.d.ts +25 -0
  91. package/dist/services/jwt_token_kong.js +65 -0
  92. package/dist/services/jwt_token_kong.js.map +1 -0
  93. package/dist/services/logger.d.ts +30 -0
  94. package/dist/services/logger.js +126 -0
  95. package/dist/services/logger.js.map +1 -0
  96. package/dist/services/namespace.d.ts +55 -0
  97. package/dist/services/namespace.js +157 -0
  98. package/dist/services/namespace.js.map +1 -0
  99. package/dist/services/now.d.ts +14 -0
  100. package/dist/services/now.js +43 -0
  101. package/dist/services/now.js.map +1 -0
  102. package/dist/services/providers.d.ts +55 -0
  103. package/dist/services/providers.js +134 -0
  104. package/dist/services/providers.js.map +1 -0
  105. package/dist/services/redis.d.ts +18 -0
  106. package/dist/services/redis.js +53 -0
  107. package/dist/services/redis.js.map +1 -0
  108. package/dist/services/rest_client.d.ts +48 -0
  109. package/dist/services/rest_client.js +96 -0
  110. package/dist/services/rest_client.js.map +1 -0
  111. package/dist/swagger/index.d.ts +223 -0
  112. package/dist/swagger/index.js +564 -0
  113. package/dist/swagger/index.js.map +1 -0
  114. package/dist/types/express.d.ts +14 -0
  115. package/dist/types/vendor.d.ts +102 -0
  116. package/dist/utils/api_scaffold.d.ts +74 -0
  117. package/dist/utils/api_scaffold.js +220 -0
  118. package/dist/utils/api_scaffold.js.map +1 -0
  119. package/dist/utils/case_converter.d.ts +7 -0
  120. package/dist/utils/case_converter.js +29 -0
  121. package/dist/utils/case_converter.js.map +1 -0
  122. package/dist/utils/crc32.d.ts +2 -0
  123. package/dist/utils/crc32.js +43 -0
  124. package/dist/utils/crc32.js.map +1 -0
  125. package/dist/utils/cron.d.ts +27 -0
  126. package/dist/utils/cron.js +186 -0
  127. package/dist/utils/cron.js.map +1 -0
  128. package/dist/utils/datetime.d.ts +4 -0
  129. package/dist/utils/datetime.js +6 -0
  130. package/dist/utils/datetime.js.map +1 -0
  131. package/dist/utils/host.d.ts +18 -0
  132. package/dist/utils/host.js +33 -0
  133. package/dist/utils/host.js.map +1 -0
  134. package/{src/utils/index.js → dist/utils/index.d.ts} +2 -26
  135. package/dist/utils/index.js +12 -0
  136. package/dist/utils/index.js.map +1 -0
  137. package/dist/utils/pagination.d.ts +150 -0
  138. package/dist/utils/pagination.js +242 -0
  139. package/dist/utils/pagination.js.map +1 -0
  140. package/dist/utils/random.d.ts +3 -0
  141. package/dist/utils/random.js +18 -0
  142. package/dist/utils/random.js.map +1 -0
  143. package/dist/utils/request_client.d.ts +33 -0
  144. package/dist/utils/request_client.js +153 -0
  145. package/dist/utils/request_client.js.map +1 -0
  146. package/dist/utils/smart_query.d.ts +144 -0
  147. package/dist/utils/smart_query.js +310 -0
  148. package/dist/utils/smart_query.js.map +1 -0
  149. package/dist/utils/test.d.ts +14 -0
  150. package/dist/utils/test.js +37 -0
  151. package/dist/utils/test.js.map +1 -0
  152. package/dist/utils/wrapper.d.ts +3 -0
  153. package/dist/utils/wrapper.js +5 -0
  154. package/dist/utils/wrapper.js.map +1 -0
  155. package/package.json +24 -10
  156. package/index.js +0 -2
  157. package/src/commands/interface.js +0 -45
  158. package/src/commands/make_entity.js +0 -490
  159. package/src/commands/tramp.js +0 -34
  160. package/src/config/index.js +0 -95
  161. package/src/di.js +0 -96
  162. package/src/engine.js +0 -556
  163. package/src/entities/index.js +0 -272
  164. package/src/exceptions/index.js +0 -501
  165. package/src/index.js +0 -55
  166. package/src/middlewares/auth.js +0 -67
  167. package/src/middlewares/auth_kong.js +0 -28
  168. package/src/middlewares/debug.js +0 -88
  169. package/src/middlewares/providers.js +0 -73
  170. package/src/middlewares/session.js +0 -63
  171. package/src/middlewares/trace.js +0 -254
  172. package/src/middlewares/validator.js +0 -50
  173. package/src/middlewares/view_cache.js +0 -127
  174. package/src/services/cache.js +0 -223
  175. package/src/services/config.js +0 -115
  176. package/src/services/env.js +0 -28
  177. package/src/services/event_manager.js +0 -84
  178. package/src/services/http_client.js +0 -69
  179. package/src/services/jwt_token.js +0 -89
  180. package/src/services/jwt_token_kong.js +0 -75
  181. package/src/services/logger.js +0 -150
  182. package/src/services/namespace.js +0 -176
  183. package/src/services/now.js +0 -49
  184. package/src/services/providers.js +0 -158
  185. package/src/services/redis.js +0 -63
  186. package/src/services/rest_client.js +0 -112
  187. package/src/swagger/index.js +0 -665
  188. package/src/utils/api_scaffold.js +0 -240
  189. package/src/utils/case_converter.js +0 -33
  190. package/src/utils/crc32.js +0 -44
  191. package/src/utils/cron.js +0 -208
  192. package/src/utils/datetime.js +0 -13
  193. package/src/utils/host.js +0 -39
  194. package/src/utils/pagination.js +0 -260
  195. package/src/utils/random.js +0 -23
  196. package/src/utils/request_client.js +0 -179
  197. package/src/utils/smart_query.js +0 -352
  198. package/src/utils/test.js +0 -48
  199. package/src/utils/wrapper.js +0 -8
@@ -1,665 +0,0 @@
1
- /*eslint new-cap: [1]*/
2
- import fs from 'fs';
3
- import { createRequire } from 'module';
4
- import { format } from 'util';
5
- import assert from 'assert';
6
- import merge from 'lodash/merge.js';
7
- import * as doctrine from 'doctrine';
8
- import * as acorn from 'acorn';
9
- import * as yaml from 'js-yaml';
10
- import Entitles from '../entities/index.js';
11
- import { RuntimeException, StandardException } from '../exceptions/index.js';
12
-
13
- const require = createRequire(import.meta.url);
14
-
15
- export class AcornParsingException extends StandardException {
16
- }
17
-
18
- export class YamlParsingException extends StandardException {
19
- /**
20
- * @param {Annotation} annotation
21
- * @returns {YamlParsingException}
22
- */
23
- setAnnotation(annotation) {
24
- this.annotation = annotation || {};
25
- return this;
26
- }
27
-
28
- /**
29
- * @returns {Annotation}
30
- */
31
- getAnnotation() {
32
- return this.annotation || {};
33
- }
34
-
35
- toString() {
36
- const {
37
- file, start, end, value
38
- } = this.getAnnotation();
39
- return format(
40
- 'Yaml parsing error happened in %s Line[%s - %s]\n Yaml error: %s \nOriginal Yaml Text:',
41
- file, start, end,
42
- this.getPrevError() ? this.getPrevError().message : '',
43
- value ? value.split('\n').map((v, i) => `${(i - 1).toString().padStart(5)} ${v}`) : []
44
- );
45
- }
46
-
47
- constructor(...args) {
48
- super(...args);
49
- this.annotation = {};
50
- }
51
- }
52
-
53
-
54
- //Mapping sequelize data types to swagger data types
55
- //Sequelize types: http://docs.sequelizejs.com/en/latest/api/datatypes/
56
- //Swagger Data Types: http://swagger.io/specification/
57
- export const MODEL_TO_FRAGMENT_TYPES_MAPPING = {
58
- BIGINT: 'integer',
59
- ENUM: 'string',
60
- INTEGER: 'integer',
61
- FLOAT: 'number',
62
- DOUBLE: 'number',
63
- DECIMAL: 'number',
64
- BOOLEAN: 'boolean',
65
- CHAR: 'string',
66
- STRING: 'string',
67
- TEXT: 'string',
68
- REAL: 'string',
69
- TIME: 'string',
70
- DATE: 'string',
71
- DATEONLY: 'string',
72
- HSTORE: 'string',
73
- JSON: 'string',
74
- JSONB: 'string',
75
- NOW: 'string',
76
- BLOB: 'string',
77
- UUID: 'string',
78
- UUIDV1: 'string',
79
- UUIDV4: 'string',
80
- VIRTUAL: 'string'
81
- };
82
-
83
- const modelDefaultValueHandlers = {
84
- integer: v => parseInt(v, 10),
85
- boolean: v => Boolean(parseInt(v, 10)),
86
- number: v => parseFloat(v),
87
- default: v => v
88
- };
89
-
90
- const FRAGMENT_TYPE_PATH = 'path';
91
- const FRAGMENT_TYPE_DEFINITION = 'definition';
92
- const FRAGMENT_TYPE_EXCEPTION = 'exception';
93
- const FRAGMENT_TYPE_UNKNOWN = 'unknown';
94
-
95
- export class Fragment {
96
- /**
97
- * @returns {[*,*,*,*]}
98
- */
99
- getTypes() {
100
- return [FRAGMENT_TYPE_PATH, FRAGMENT_TYPE_DEFINITION,
101
- FRAGMENT_TYPE_EXCEPTION, FRAGMENT_TYPE_UNKNOWN];
102
- }
103
-
104
- isPath() {
105
- return this.type === FRAGMENT_TYPE_PATH;
106
- }
107
-
108
- isDefinition() {
109
- return this.type === FRAGMENT_TYPE_DEFINITION;
110
- }
111
-
112
- isUnknown() {
113
- return this.type === FRAGMENT_TYPE_UNKNOWN;
114
- }
115
-
116
- isException() {
117
- return this.type === FRAGMENT_TYPE_EXCEPTION;
118
- }
119
-
120
- /**
121
- * @param {Fragment} fragment
122
- * @returns {Fragment}
123
- */
124
- setParentFragment(fragment) {
125
- assert(fragment && fragment instanceof Fragment, 'Parent fragment must be instance of Fragment');
126
- this.parent = fragment;
127
- return this;
128
- }
129
-
130
- /**
131
- * @returns {null|Fragment}
132
- */
133
- getParentFragment() {
134
- return this.parent;
135
- }
136
-
137
- correctSwaggerPath(swaggerDoc = {}) {
138
- return swaggerDoc;
139
- }
140
-
141
- toSwaggerDoc(exceptions = {}) {
142
- if (this.isPath()) {
143
- const path = Object.keys(this.value)[0];
144
- const method = Object.keys(this.value[path])[0];
145
- return {
146
- paths: {
147
- [path]: {
148
- [method]: this.correctSwaggerPath(this.value[path][method])
149
- }
150
- }
151
- };
152
- }
153
-
154
- if (this.isDefinition()) {
155
- const key = Object.keys(this.value)[0];
156
- return {
157
- definitions: {
158
- [key]: this.value[key]
159
- }
160
- };
161
- }
162
-
163
- if (this.isException()) {
164
- if (!this.getParentFragment()) {
165
- return {};
166
- }
167
- const key = this.value;
168
- const exception = exceptions[key];
169
- if (!exception) {
170
- return {};
171
- }
172
-
173
- const path = Object.keys(this.getParentFragment().value)[0];
174
- const method = Object.keys(this.getParentFragment().value[path])[0];
175
- return {
176
- definitions: {
177
- [key]: Fragment.exceptionMapping(exception)
178
- },
179
- paths: {
180
- [path]: {
181
- [method]: {
182
- responses: {
183
- [exception.getStatusCode()]: {
184
- description: this.description,
185
- schema: {
186
- $ref: `#/definitions/${key}`
187
- }
188
- }
189
- }
190
- }
191
- }
192
- }
193
- };
194
- }
195
-
196
- return {};
197
- }
198
-
199
- static exceptionMapping(exception) {
200
- return {
201
- properties: {
202
- code: {
203
- type: 'integer',
204
- format: 'int64'
205
- },
206
- message: {
207
- type: 'string'
208
- }
209
- },
210
- required: [
211
- 'code',
212
- 'message'
213
- ],
214
- example: {
215
- code: exception.getCode(),
216
- message: exception.message
217
- }
218
- };
219
- }
220
-
221
- /**
222
- * @param jsdoc
223
- * @param {Annotation} annotation
224
- * @returns {Fragment}
225
- */
226
- static factory(jsdoc, annotation) {
227
- const { title, description, type } = jsdoc;
228
- if (title === 'throws') {
229
- return new Fragment({
230
- type: FRAGMENT_TYPE_EXCEPTION,
231
- description,
232
- value: type ? type.name : FRAGMENT_TYPE_UNKNOWN,
233
- file: annotation.file,
234
- start: annotation.start,
235
- end: annotation.end
236
- });
237
- }
238
-
239
- let elementType = FRAGMENT_TYPE_UNKNOWN;
240
- const value = yaml.load(description);
241
- const key = Object.keys(value)[0];
242
- if (title === 'swagger') {
243
- elementType = key.startsWith('/') ? FRAGMENT_TYPE_PATH : FRAGMENT_TYPE_DEFINITION;
244
- }
245
- return new Fragment({
246
- type: elementType,
247
- description,
248
- value,
249
- file: annotation.file,
250
- start: annotation.start,
251
- end: annotation.end
252
- });
253
- }
254
-
255
- constructor({
256
- type, description, value, file, start, end
257
- }) {
258
- assert(type && description && value && file && start && end, 'Fragment require type && description && value && file && start && end');
259
- assert(this.getTypes().includes(type), 'Fragment types not match input');
260
- this.type = type;
261
- this.description = description;
262
- this.value = value;
263
- this.file = file;
264
- this.start = start;
265
- this.end = end;
266
- this.parent = null;
267
- }
268
- }
269
-
270
- export class Annotation {
271
- /**
272
- * @returns {Array<Fragment>}
273
- */
274
- getFragments() {
275
- if (this.fragments) {
276
- return this.fragments;
277
- }
278
- //支持两种注解:
279
- //1. 所有行首必定为 space*
280
- //2. 所有行首必定不为 space*
281
- const unwrap = this.value.startsWith('*\n *');
282
- const { tags: jsDocs = [] } = doctrine.parse(this.value, { unwrap });
283
- if (jsDocs.length < 1) {
284
- return [];
285
- }
286
-
287
- /**
288
- * @type {Array<Fragment>}
289
- */
290
- const fragments = [];
291
- jsDocs.filter(jsDoc =>
292
- jsDoc.title
293
- && (jsDoc.title === 'swagger' || jsDoc.title === 'throws')
294
- && jsDoc.description)
295
- .forEach((jsDoc) => {
296
- try {
297
- fragments.push(Fragment.factory(jsDoc, this));
298
- } catch (e) {
299
- this.yamlErrors.push((new YamlParsingException(e)).setAnnotation(this));
300
- }
301
- });
302
-
303
- fragments.forEach((fragment) => {
304
- if (fragment.isException()) {
305
- fragment.setParentFragment(fragments.filter(f => f.isPath())[0]);
306
- }
307
- });
308
-
309
- this.fragments = fragments;
310
- return fragments;
311
- }
312
-
313
- toString() {
314
- return format('Annotation %s [%s - %s]: %s', this.file, this.start, this.end, this.value);
315
- }
316
-
317
- getYamlErrors() {
318
- return this.yamlErrors;
319
- }
320
-
321
- constructor({
322
- type, //Block
323
- value, //Long string
324
- file, //String
325
- start,
326
- end
327
- }) {
328
- assert(type && type === 'Block', 'Annotation type must be Block');
329
- assert(value && typeof value === 'string', 'Annotation value must be Block');
330
- assert(file, 'Annotation must have file');
331
- this.value = value;
332
- this.file = file;
333
- this.start = start;
334
- this.end = end;
335
- this.yamlErrors = [];
336
- this.fragments = null;
337
- }
338
- }
339
-
340
- export class AnnotationsContainer {
341
- /**
342
- * @returns {string}
343
- */
344
- getFile() {
345
- return this.file;
346
- }
347
-
348
- /**
349
- * @returns {boolean}
350
- */
351
- hasAnnotations() {
352
- return this.annotations.length > 0;
353
- }
354
-
355
- /**
356
- * @returns {Array<Annotation>}
357
- */
358
- getAnnotations() {
359
- return this.annotations;
360
- }
361
-
362
- /**
363
- * @returns {Array.<Fragment>}
364
- */
365
- collectFragments() {
366
- if (this.fragments.length > 0) {
367
- return this.fragments;
368
- }
369
-
370
- for (const annotation of this.getAnnotations()) {
371
- this.fragments = this.fragments.concat(annotation.getFragments());
372
- }
373
-
374
- return this.fragments;
375
- }
376
-
377
- /**
378
- * @returns {Array}
379
- */
380
- collectYamlErrors() {
381
- let errors = [];
382
- for (const annotation of this.getAnnotations()) {
383
- errors = errors.concat(annotation.getYamlErrors());
384
- }
385
- return errors;
386
- }
387
-
388
- constructor(file, acornComments) {
389
- assert(file && typeof file === 'string', 'Annotations require a file input');
390
- assert(acornComments && Array.isArray(acornComments), `Annotations for ${file} require an array of Acorn comments input`);
391
- this.file = file;
392
- //Annotations MUST start with double stars
393
- this.annotations = acornComments
394
- .filter(v => v.type === 'Block' && v.value.startsWith('*\n'))
395
- .map(c => new Annotation(Object.assign(c, { file })));
396
- this.fragments = [];
397
- }
398
- }
399
-
400
- /**
401
- * A Swagger Json document generator
402
- * Generate document from
403
- * - JS source code annotations (Parser is Doctrine)
404
- * - ORM entities (Based on Sequelize)
405
- * - EvaEngine Exceptions
406
- */
407
- export class ExSwagger {
408
- /**
409
- * Get file path array by glob
410
- * @param path
411
- * @param options
412
- * @returns {Promise|Array.<string>}
413
- */
414
- static async scanFiles(path, options = {}) {
415
- return fs.globSync(path, options);
416
- }
417
-
418
- /**
419
- * Get annotations from comments
420
- * An annotation MUST start with double stars
421
- * @param files {Array.<string>}
422
- * @returns {Array.<AnnotationsContainer>}
423
- */
424
- static async filesToAnnotationsContainers(files) {
425
- const results = [];
426
- for (const file of files) {
427
- const comments = [];
428
- const source = await fs.readFileSync(file);
429
- try {
430
- acorn.parse(source, {
431
- ecmaVersion: 'latest',
432
- sourceType: 'module',
433
- allowImportExportEverywhere: true,
434
- onComment: comments
435
- });
436
- } catch (e) {
437
- throw (new AcornParsingException(`Acorn parsing file ${file} failed`)).setPrevError(e);
438
- }
439
-
440
- results.push(new AnnotationsContainer(file, comments));
441
- }
442
- return results;
443
- }
444
-
445
- static modelToSwaggerDefinition(model) {
446
- const definition = {
447
- type: 'object',
448
- properties: {}
449
- };
450
- const requires = [];
451
- Object.keys(model).forEach((columnName) => {
452
- const column = model[columnName];
453
- const swaggerType = MODEL_TO_FRAGMENT_TYPES_MAPPING[column.type.key];
454
- const property = {
455
- type: swaggerType,
456
- description: column.comment
457
- };
458
- if (column.defaultValue) {
459
- const defaultValueHandler = modelDefaultValueHandlers[swaggerType] ?
460
- modelDefaultValueHandlers[swaggerType] : modelDefaultValueHandlers.default;
461
- property.default = defaultValueHandler(column.defaultValue);
462
- }
463
- if (column.allowNull === false) {
464
- requires.push(columnName);
465
- }
466
- definition.properties[columnName] = property;
467
- });
468
- definition.required = requires;
469
- return definition;
470
- }
471
-
472
- static modelsToSwaggerDefinitions(models, blacklist = []) {
473
- const definitions = new Map();
474
- Object.keys(models).forEach((modelName) => {
475
- if (blacklist.includes(modelName)) {
476
- return true;
477
- }
478
- const model = models[modelName];
479
- const attributes = model.attributes || model.rawAttributes;
480
- const definition = ExSwagger.modelToSwaggerDefinition(attributes);
481
- definitions.set(modelName, definition);
482
- return true;
483
- });
484
- return definitions;
485
- }
486
-
487
- static async scanExceptions(path, exceptionInterface = Error) {
488
- const exceptions = {};
489
- const files = await ExSwagger.scanFiles(path);
490
- if (files.length < 1) {
491
- return exceptions;
492
- }
493
- for (const file of files) {
494
- const exceptionsInFile = require(file);
495
- Object.keys(exceptionsInFile).forEach((exceptionName) => {
496
- const exceptionClass = exceptionsInFile[exceptionName];
497
- const exception = new exceptionClass(exceptionName); //eslint-disable-line new-cap
498
- if (exception instanceof exceptionInterface) {
499
- exceptions[exceptionName] = exception;
500
- }
501
- });
502
- }
503
- return exceptions;
504
- }
505
-
506
-
507
- async exportJson(dist = this.swaggerDocsPath) {
508
- this.logger.debug('Start export swagger docs by meta %j', this.getStates());
509
- const fileGroups = await Promise
510
- .all(this.sourceFilesPath.map(path => ExSwagger.scanFiles(path)));
511
- let files = [];
512
- fileGroups.forEach((fileGroup) => {
513
- files = files.concat(fileGroup);
514
- });
515
- if (!files || files.length < 1) {
516
- throw new RuntimeException('No swagger source files found');
517
- }
518
- this.logger.debug('Scanner will scan %s files under %j:', files.length, this.sourceFilesPath);
519
-
520
- const annotationsContainers = await ExSwagger.filesToAnnotationsContainers(files);
521
- let fragments = [];
522
- annotationsContainers.forEach((annotationsContainer) => {
523
- if (!annotationsContainer.hasAnnotations()) {
524
- return false;
525
- }
526
- const annotationFragments = annotationsContainer.collectFragments();
527
- fragments = fragments.concat(annotationFragments);
528
- this.logger.debug(
529
- 'Scanner found %s annotations and collected %s fragments in file %s',
530
- annotationsContainer.getAnnotations().length.toString().padStart(3),
531
- annotationFragments.length.toString().padStart(3),
532
- annotationsContainer.getFile()
533
- );
534
-
535
- const yamlErrors = annotationsContainer.collectYamlErrors();
536
- yamlErrors.forEach(yamlError => this.logger.error(yamlError));
537
- return true;
538
- });
539
-
540
- this.logger.debug('Scanner collected %s fragments in total', fragments.length);
541
-
542
- const template = this.swaggerDocsTemplate;
543
- const exceptions = {};
544
- for (const exceptionPath of this.exceptionPaths) {
545
- this.logger.debug('Search exception in %s', exceptionPath);
546
- const exceptionsInFile = await ExSwagger.scanExceptions(
547
- exceptionPath,
548
- this.exceptionInterface
549
- );
550
- Object.assign(exceptions, exceptionsInFile);
551
- this.logger.debug(
552
- 'Scanner found %s exceptions: %j',
553
- Object.keys(exceptions).length,
554
- Object.keys(exceptions)
555
- );
556
- }
557
- const modelDefinitions = this.models ?
558
- ExSwagger.modelsToSwaggerDefinitions(this.models, this.modelBlacklist) : new Map();
559
- const swaggerDocs = ExSwagger.mergeAll(template, fragments, exceptions, modelDefinitions);
560
- this.logger.debug('Export to %s', dist);
561
- await fs.writeFileSync(dist, JSON.stringify(swaggerDocs));
562
- return swaggerDocs;
563
- }
564
-
565
- /**
566
- * @param _template
567
- * @param {Array<Fragment>} fragments
568
- * @param exceptions
569
- * @param modelDefinitions
570
- * @returns {*}
571
- */
572
- static mergeAll(_template, fragments, exceptions, modelDefinitions) {
573
- const template = _template;
574
- fragments.forEach(fragment => merge(template, fragment.toSwaggerDoc(exceptions)));
575
- if (modelDefinitions) {
576
- modelDefinitions.forEach((definition, modelName) => {
577
- template.definitions[modelName] = definition;
578
- });
579
- }
580
- return template;
581
- }
582
-
583
- getStates() {
584
- return {
585
- swaggerTemplate: this.swaggerDocsTemplate,
586
- modelBlacklist: this.modelBlacklist,
587
- sourceFilesPath: this.sourceFilesPath,
588
- exceptionPaths: this.exceptionPaths,
589
- compileDistPath: this.compileDistPath,
590
- swaggerUIPath: this.swaggerUIPath,
591
- swaggerDocsPath: this.swaggerDocsPath
592
- };
593
- }
594
-
595
- getSwaggerUIPath() {
596
- return this.swaggerUIPath;
597
- }
598
-
599
- async getSwaggerIndexHtml() {
600
- const uiPath = this.getSwaggerUIPath();
601
- const content = await fs.readFileSync(`${uiPath}/index.html`);
602
- return content.toString().replace(
603
- 'https://petstore.swagger.io/v2/swagger/index.json',
604
- this.swaggerDocsPath.replace(this.compileDistPath, '')
605
- );
606
- }
607
-
608
- getCompileDistPath() {
609
- return this.compileDistPath;
610
- }
611
-
612
- constructor({
613
- sourceRootPath,
614
- compileDistPath,
615
- models,
616
- modelBlacklist = [],
617
- swaggerDocsTemplate,
618
- logger,
619
- swaggerUIPath,
620
- swaggerDocsPath = `${compileDistPath}/docs.json`,
621
- sourceFilesPath = `${sourceRootPath}/**/*.js`,
622
- exceptionInterface = StandardException,
623
- extraSourcePaths = [`${import.meta.dirname}/../utils/**/*.js`],
624
- exceptionPaths
625
- }) {
626
- this.logger = logger ||
627
- {
628
- debug: () => {
629
- },
630
- warn: () => {
631
- },
632
- error: () => {
633
- }
634
- };
635
-
636
- if (!swaggerDocsTemplate) {
637
- throw new RuntimeException('No swagger docs template input');
638
- }
639
- this.swaggerDocsTemplate = swaggerDocsTemplate;
640
- if (models && !(models instanceof Entitles)) {
641
- throw new RuntimeException('Input models must instance of engine.Entities');
642
- }
643
- this.models = models ? models.getAll() : null;
644
- this.modelBlacklist = modelBlacklist;
645
-
646
- this.sourceFilesPath = Array.isArray(sourceFilesPath)
647
- ? extraSourcePaths.concat(sourceFilesPath) :
648
- extraSourcePaths.concat([sourceFilesPath]);
649
- this.exceptionPaths = exceptionPaths ?
650
- [`${import.meta.dirname}/../exceptions`].concat(exceptionPaths) : [`${import.meta.dirname}/../exceptions`];
651
- this.exceptionInterface = exceptionInterface;
652
- this.compileDistPath = compileDistPath;
653
- if (swaggerUIPath) {
654
- this.swaggerUIPath = swaggerUIPath;
655
- } else {
656
- this.swaggerUIPath = `${import.meta.dirname}/../../node_modules/swagger-ui-dist`;
657
- try {
658
- fs.accessSync(this.swaggerUIPath, fs.F_OK);
659
- } catch {
660
- this.swaggerUIPath = `${import.meta.dirname}/../../../swagger-ui-dist`; //For NPM v3.x
661
- }
662
- }
663
- this.swaggerDocsPath = swaggerDocsPath;
664
- }
665
- }