skybase 0.1.84 → 0.1.87

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 (112) hide show
  1. package/.eslintignore +35 -35
  2. package/.eslintrc +41 -41
  3. package/CHANGELOG.md +30 -491
  4. package/README.md +214 -214
  5. package/demo/1-simple/README.md +1 -1
  6. package/demo/1-simple/index.js +7 -7
  7. package/demo/1-simple/model/api/demo.js +26 -26
  8. package/demo/1-simple/model/api/frontApiFiles//347/224/250/344/272/216/345/261/225/347/244/272/345/246/202/344/275/225/345/256/232/344/271/211/344/270/200/344/270/252/346/216/245/345/217/243.js +32 -32
  9. package/demo/1-simple/model//347/224/250/344/272/216/345/261/225/347/244/272/345/246/202/344/275/225/345/256/232/344/271/211/344/270/200/344/270/252/346/216/245/345/217/243.js +29 -29
  10. package/demo/1-simple/package.json +11 -11
  11. package/demo/1-simple/router/demo.js +8 -8
  12. package/demo/1-simple/ws_router/echo.js +9 -9
  13. package/demo/2-api-register/README.md +1 -1
  14. package/demo/2-api-register/config/config.default.js +25 -25
  15. package/demo/2-api-register/config/config.dev.js +15 -15
  16. package/demo/2-api-register/config/config.prod.js +15 -15
  17. package/demo/2-api-register/config/config.test.js +15 -15
  18. package/demo/2-api-register/config/index.js +32 -32
  19. package/demo/2-api-register/model/api/demo.js +26 -26
  20. package/demo/2-api-register/model/api/dir/demo.js +27 -27
  21. package/demo/2-api-register/model/api/redirect.js +30 -30
  22. package/demo/2-api-register/model/api/use-limit.js +45 -45
  23. package/demo/2-api-register/package.json +11 -11
  24. package/demo/2-api-register/router/demo.js +9 -9
  25. package/demo/2-api-register/router/dir/demo.js +9 -9
  26. package/demo/2-api-register/router/redirect.js +8 -8
  27. package/demo/2-api-register/router/use-limit.js +9 -9
  28. package/demo/3-full-module/README.md +1 -1
  29. package/demo/3-full-module/config/config.default.js +33 -33
  30. package/demo/3-full-module/config/config.dev.js +15 -15
  31. package/demo/3-full-module/config/config.prod.js +15 -15
  32. package/demo/3-full-module/config/config.test.js +15 -15
  33. package/demo/3-full-module/config/index.js +32 -32
  34. package/demo/3-full-module/index.js +36 -36
  35. package/demo/3-full-module/model/api/demo.js +26 -26
  36. package/demo/3-full-module/model/api/dir/demo.js +26 -26
  37. package/demo/3-full-module/model/api/use-rabbitmq.js +26 -26
  38. package/demo/3-full-module/model/api/use-redis.js +33 -33
  39. package/demo/3-full-module/package.json +17 -17
  40. package/demo/3-full-module/rabbit-consumer.js +45 -45
  41. package/demo/3-full-module/router/demo.js +9 -9
  42. package/demo/3-full-module/router/dir/demo.js +9 -9
  43. package/demo/3-full-module/router/use-redis.js +14 -14
  44. package/demo/4-api-to-file/README.md +8 -8
  45. package/demo/4-api-to-file/config/config.default.js +8 -8
  46. package/demo/4-api-to-file/config/index.js +32 -32
  47. package/demo/4-api-to-file/index.js +6 -6
  48. package/demo/4-api-to-file/model/api/api.js +142 -142
  49. package/demo/4-api-to-file/package.json +14 -14
  50. package/demo/4-api-to-file/router/api.js +37 -37
  51. package/demo/5-mock-api/README.md +2 -2
  52. package/demo/5-mock-api/config/config.default.js +8 -8
  53. package/demo/5-mock-api/config/index.js +32 -32
  54. package/demo/5-mock-api/index.js +24 -24
  55. package/demo/5-mock-api/model/api/mock.js +213 -213
  56. package/demo/5-mock-api/model/mock.js +27 -27
  57. package/demo/5-mock-api/package.json +15 -15
  58. package/demo/5-mock-api/router/mock.js +20 -20
  59. package/demo/6-sql-test/README.md +1 -1
  60. package/demo/6-sql-test/config/config.default.js +61 -61
  61. package/demo/6-sql-test/config/config.dev.js +15 -15
  62. package/demo/6-sql-test/config/config.prod.js +15 -15
  63. package/demo/6-sql-test/config/config.test.js +15 -15
  64. package/demo/6-sql-test/config/index.js +32 -32
  65. package/demo/6-sql-test/index.js +48 -48
  66. package/demo/6-sql-test/model/api/dir/dir/dir/four.js +18 -18
  67. package/demo/6-sql-test/model/api/dir/dir/three.js +26 -26
  68. package/demo/6-sql-test/model/api/dir/two.js +26 -26
  69. package/demo/6-sql-test/model/api/one.js +18 -18
  70. package/demo/6-sql-test/package.json +18 -18
  71. package/demo/6-sql-test/router/test.js +38 -38
  72. package/demo/6-sql-test/service/test.js +96 -96
  73. package/demo/7-token/README.md +1 -1
  74. package/demo/7-token/config/config.default.js +35 -35
  75. package/demo/7-token/config/config.dev.js +15 -15
  76. package/demo/7-token/config/config.prod.js +15 -15
  77. package/demo/7-token/config/config.test.js +15 -15
  78. package/demo/7-token/config/index.js +32 -32
  79. package/demo/7-token/model/api/demo.js +43 -43
  80. package/demo/7-token/package.json +17 -17
  81. package/demo/8-test/README.md +1 -1
  82. package/demo/8-test/config/config.default.js +35 -35
  83. package/demo/8-test/config/config.dev.js +15 -15
  84. package/demo/8-test/config/config.prod.js +15 -15
  85. package/demo/8-test/config/config.test.js +15 -15
  86. package/demo/8-test/config/index.js +32 -32
  87. package/demo/8-test/index.js +30 -30
  88. package/demo/8-test/model/api/demo.js +43 -43
  89. package/demo/8-test/model/api/dir/two.js +26 -26
  90. package/demo/8-test/model/api/mock.js +157 -157
  91. package/demo/8-test/model/api/one.js +150 -150
  92. package/demo/8-test/model/mock.js +35 -35
  93. package/demo/8-test/package.json +17 -17
  94. package/demo/8-test/router/demo.js +45 -45
  95. package/demo/8-test/router/mock.js +20 -20
  96. package/demo/8-test/router/test.js +43 -43
  97. package/demo/8-test/service/test.js +35 -35
  98. package/demo/9-mysql-chart/config/config.dev.js +15 -15
  99. package/demo/9-mysql-chart/config/config.prod.js +15 -15
  100. package/demo/9-mysql-chart/config/config.test.js +15 -15
  101. package/demo/9-mysql-chart/index.js +36 -36
  102. package/demo/9-mysql-chart/package.json +18 -18
  103. package/lib/middleware/sky-api-register.js +348 -348
  104. package/lib/middleware/sky-cors.js +8 -8
  105. package/lib/middleware/sky-output.js +83 -83
  106. package/lib/middleware/sky-static-server.js +16 -16
  107. package/outFiles.js +325 -325
  108. package/package.json +50 -67
  109. package/sky-module/create_amqplib.js +69 -69
  110. package/sky-module/create_ioredis.js +47 -47
  111. package/sky-module/create_kafka.js +24 -24
  112. package/tests/test.js +173 -173
@@ -1,348 +1,348 @@
1
- /**
2
- * 注册api
3
- * */
4
-
5
- const $G = (global.$G = global.$G || {})
6
- const fs = require('fs')
7
- const path = require('path')
8
- const $ = require('meeko')
9
- const Mock = require('mockjs')
10
- const SkyConfig = require('../../skyconfig')
11
- Mock.Random.extend($.Mock)
12
- const mockFn = {
13
- noMock () {
14
- return function (ctx) {
15
- ctx.ok('controller未定义 & mock未定义')
16
- }
17
- },
18
- mockRouter (mockModels) {
19
- return function (ctx) {
20
- mockModels.isMock = 1
21
- ctx.ok(Mock.mock(mockModels))
22
- }
23
- }
24
- }
25
-
26
- const skyExt = require('../sky_extend')
27
- const router = require('koa-router')()
28
- const {
29
- routerDir,
30
- rootDir,
31
- apiDir,
32
- logger,
33
- serviceDir
34
- } = require('../../skyconfig')
35
-
36
- const apiStat = ($G.apiStat = {}) // 接口各种状态
37
-
38
- const frontApi = ($G.frontApi = {}) // 推送给前端的接口定义
39
-
40
- skyExt.artStage('API Checking')
41
-
42
- const controllerDir = path.join(rootDir, routerDir || 'router')
43
-
44
- const apiRootDir = path.resolve(rootDir, apiDir)
45
- const api = ($G.api = $G.api || {})
46
- const $S = ($G.$S = $G.$S || {})
47
-
48
- const routerLog = (result, name, apiPath, ms) => {
49
- if (logger) {
50
- let resultValue = JSON.stringify(result || {}).replace(
51
- /: *"([^"]+)"/g,
52
- function (...item) {
53
- return item[1].length > 25
54
- ? `:"${item[1].slice(0, 25)}${$.c.m('...')}"`
55
- : `:"${item[1]}"`
56
- }
57
- )
58
- let resultKey = resultValue.replace(/"([a-zA-Z0-9_\$\.]+)" *:/g, function (
59
- ...item
60
- ) {
61
- return `"${$.c.dimy(item[1])}":`
62
- })
63
- resultKey = resultKey.slice(0, 1000)
64
- $.log(
65
- '[router处理]=>',
66
- resultKey,
67
- `\n${$.c.dimc(name + apiPath)} => ${$.c.dimc(ms || '0')} ms\n`
68
- )
69
- }
70
- }
71
-
72
- const warn = (...args) => {
73
- if (logger) {
74
- console.warn(...args)
75
- }
76
- }
77
-
78
- // 检查接口定义是否规范,不规范也不会出错,只会打印提示
79
- const checkapiStandard = (apiPath, opt) => {
80
- const apiDesc = opt.name || opt.desc
81
- if (!apiDesc) {
82
- $.log($.c.y('?'), apiPath.fillStr(' ', 30), $.c.y('接口未写名称或描述'))
83
- } else if (apiPath.includes('_')) {
84
- $.log($.c.y('?'), apiPath.fillStr(' ', 30), $.c.y('接口命名不规范'))
85
- }
86
- }
87
-
88
- // 获取api需要执行的函数,判断是否使用mock也在这里面
89
- const getApiFn = (apiPath, opt) => {
90
- let mockModel = 0
91
- if (!opt.controller) {
92
- if (opt.mock) {
93
- $.log(
94
- $.c.g('✔'),
95
- apiPath.fillStr(' ', 30),
96
- $.c.r('controller未定义'),
97
- $.c.g('& mock已定义')
98
- )
99
- mockModel = 1
100
- } else {
101
- $.log(
102
- $.c.r('✘'),
103
- apiPath.fillStr(' ', 30),
104
- $.c.r('controller未定义 & mock未定义')
105
- )
106
- mockModel = 2
107
- }
108
- }
109
-
110
- let func
111
- if (mockModel) {
112
- const fn = mockModel === 1 ? 'mockRouter' : 'noMock'
113
- func = mockFn[fn] && mockFn[fn](opt.mock)
114
- } else {
115
- const [file, fn] = opt.controller.split('.')
116
- try {
117
- const fileDir = path.resolve(rootDir, controllerDir, file)
118
- const contr = require(fileDir) || {}
119
- func = contr[fn]
120
- if (!func) {
121
- $.log(
122
- $.c.r('✘'),
123
- apiPath.fillStr(' ', 30),
124
- $.c.r(`文件“${fileDir}”中不存在“${fn}”方法`)
125
- )
126
- }
127
- } catch (e) {
128
- $.log($.c.r('✘'), apiPath.fillStr(' ', 30), $.c.r(`router不存在 ${file}`))
129
- $.log(e.stack)
130
- }
131
- }
132
- return func
133
- }
134
-
135
- const limitReqAction = (action, apiPath) => {
136
- return async function (ctx, next) {
137
- const start = Date.now()
138
-
139
- const { feqLimit, name, desc } = api[apiPath] || {}
140
-
141
- // 接口频率控制
142
- if (+feqLimit > 0) {
143
- const it = (apiStat[apiPath] = apiStat[apiPath] || { n: 1, t: 0 })
144
- it.n++
145
- const diff = start - it.t
146
- if ((1 / feqLimit) * 1000 > diff) {
147
- ctx.body = {
148
- code: 402,
149
- data: diff,
150
- msg: '访问过快请稍后再试!'
151
- }
152
-
153
- routerLog(ctx.body, name || desc, apiPath, Date.now() - start)
154
- return ctx.body
155
- }
156
- it.t = start
157
- }
158
-
159
- // 执行controller的方法
160
- if (action) {
161
- try {
162
- await action(ctx, next)
163
- } catch (e) {
164
- console.error('[controller error]', e)
165
-
166
- ctx.body = {
167
- code: 406,
168
- data: {},
169
- msg: `[controller error]`
170
- }
171
- let errStack = e.stack
172
- .split('\n')
173
- .filter(x => !x.includes('node_modules'))
174
- $G.errorList.push({ time: new Date().date2Str(), desc: errStack })
175
- if ($G.errorList.length > 20) $G.errorList.shift() //保持20条
176
- }
177
- } else {
178
- ctx.body = {
179
- code: 406,
180
- data: {},
181
- msg: `${apiPath}的Control不存在,请在api定义中定义mock对象`
182
- }
183
- }
184
-
185
- routerLog(ctx.body, name || desc, apiPath, Date.now() - start)
186
- if (global.rtsMQ) {
187
- try {
188
- if (rtsMQ.ch.connection.expectSocketClose) {
189
- // mq断开了
190
- return ctx.body
191
- }
192
- } catch (e) {
193
- return ctx.body
194
- }
195
-
196
- process.nextTick(function () {
197
- const mqObj = {
198
- type: 'rts_api',
199
- key: `api:${apiPath.replace(/\//g, '_')}`,
200
- number: Date.now() - start,
201
- method: ['count', 'max', 'min', 'avg'],
202
- time: +$.now()
203
- }
204
- global.rtsMQ.send({
205
- queueName: SkyConfig.rtsQueueName,
206
- text: JSON.stringify(mqObj)
207
- })
208
- })
209
- } else if (global.rts) {
210
- // add stack
211
- process.nextTick(function () {
212
- global.rts.record(
213
- `api:${apiPath.replace(/\//g, '_')}`,
214
- Date.now() - start,
215
- ['count', 'max', 'min', 'avg']
216
- )
217
- })
218
- }
219
- return ctx.body
220
- }
221
- }
222
-
223
- const registerApi = (apiPath, opt) => {
224
- if (!opt.method) {
225
- return
226
- }
227
-
228
- if (api[apiPath]) {
229
- $.err('出现重复的api定义:', apiPath, api[apiPath])
230
- }
231
-
232
- opt.method = opt.method.toLowerCase()
233
- api[apiPath] = opt
234
-
235
- const action = limitReqAction(getApiFn(apiPath, opt), apiPath)
236
-
237
- if (opt.method === 'all') {
238
- router.get(apiPath, action)
239
- router.post(apiPath, action)
240
- } else {
241
- router[opt.method](apiPath, action)
242
- }
243
-
244
- checkapiStandard(apiPath, opt)
245
- }
246
-
247
- const checkApi = (apiDir, apiPath = '') => {
248
- try {
249
- const files = fs.readdirSync(apiDir)
250
- for (let i = 0; i < files.length; i++) {
251
- const dir = path.join(apiDir, files[i])
252
- const stat = fs.statSync(dir)
253
- if (stat.isDirectory()) {
254
- // 是文件夹
255
- checkApi(dir, `${apiPath}/${files[i]}`)
256
- } else {
257
- const ap = require(dir)
258
- for (const [p, opt] of Object.entries(ap)) {
259
- const path = (p.indexOf('/') === 0
260
- ? p
261
- : `${apiPath}/${files[i].split('.')[0]}/${p}`
262
- )
263
- .split('/')
264
- .filter(v => !!v)
265
- .join('/')
266
- registerApi(`/${path}`, opt)
267
- }
268
- }
269
- }
270
- } catch (e) {
271
- $.err($.c.r(`✘ ${e.stack}`))
272
- }
273
-
274
- // process.exit(0)
275
- //
276
- // for (const ap of Object.values(api)) {
277
- // for (const [apiPath, opt] of Object.entries(ap)) {
278
- // registerApi(apiPath, opt)
279
- // }
280
- // }
281
- }
282
-
283
- const loadRunDict = () => {
284
- // 加载处理程序需要的数据
285
- if (serviceDir) {
286
- try {
287
- const S = $.requireAll(path.join(rootDir, 'service')) || {}
288
- Object.assign($S, S)
289
- } catch (e) {
290
- warn('引用service报错', e.stack)
291
- }
292
- }
293
-
294
- let [n, m, k] = [0, 0, 0]
295
- try {
296
- $S._controlCode = {}
297
- $S._srvCode = {}
298
- Object.keys($S).forEach(i => {
299
- $S._srvCode[i] = (++k).toString(16).padStart(2, '0')
300
- })
301
-
302
- // let file = yield fs.readFile(path.join(__dirname+'/../', '/models/dict_db.js'))
303
- // const dict = JSON.parse(file)
304
- // global.dictObj = dict
305
- Object.entries(api).forEach(([k, item]) => {
306
- m++
307
- const [aK] = k.split('/').filter(function (item) {
308
- return item !== '' && item !== '__swagger__'
309
- })
310
- if (aK) {
311
- $S._controlCode[k] = m.toString(36).padStart(2, '0')
312
- }
313
- if (item.front) {
314
- n++
315
- Object.values(item.param).forEach(v => {
316
- if (v.req === 0) {
317
- delete v.req
318
- }
319
- if (v.def === null) {
320
- delete v.def
321
- }
322
- if (v.type === 'string') {
323
- delete v.type
324
- }
325
- })
326
-
327
- frontApi[k] = { method: item.method, param: item.param }
328
- }
329
- })
330
- } catch (e) {
331
- $.err(e.stack)
332
- }
333
-
334
- // $.dir($S)
335
-
336
- $.log(
337
- n === 0 ? $.c.r('✘') : $.c.g('✔'),
338
- `[${$.c.y('frontApi/totlaApi')}] = [${$.c.y(
339
- `${n}/${m}`
340
- )}] Routers at [${$.c.y(controllerDir)}]`
341
- )
342
- }
343
-
344
- checkApi(apiRootDir)
345
-
346
- loadRunDict()
347
-
348
- module.exports = [router.routes(), router.allowedMethods()]
1
+ /**
2
+ * 注册api
3
+ * */
4
+
5
+ const $G = (global.$G = global.$G || {})
6
+ const fs = require('fs')
7
+ const path = require('path')
8
+ const $ = require('meeko')
9
+ const Mock = require('mockjs')
10
+ const SkyConfig = require('../../skyconfig')
11
+ Mock.Random.extend($.Mock)
12
+ const mockFn = {
13
+ noMock () {
14
+ return function (ctx) {
15
+ ctx.ok('controller未定义 & mock未定义')
16
+ }
17
+ },
18
+ mockRouter (mockModels) {
19
+ return function (ctx) {
20
+ mockModels.isMock = 1
21
+ ctx.ok(Mock.mock(mockModels))
22
+ }
23
+ }
24
+ }
25
+
26
+ const skyExt = require('../sky_extend')
27
+ const router = require('koa-router')()
28
+ const {
29
+ routerDir,
30
+ rootDir,
31
+ apiDir,
32
+ logger,
33
+ serviceDir
34
+ } = require('../../skyconfig')
35
+
36
+ const apiStat = ($G.apiStat = {}) // 接口各种状态
37
+
38
+ const frontApi = ($G.frontApi = {}) // 推送给前端的接口定义
39
+
40
+ skyExt.artStage('API Checking')
41
+
42
+ const controllerDir = path.join(rootDir, routerDir || 'router')
43
+
44
+ const apiRootDir = path.resolve(rootDir, apiDir)
45
+ const api = ($G.api = $G.api || {})
46
+ const $S = ($G.$S = $G.$S || {})
47
+
48
+ const routerLog = (result, name, apiPath, ms) => {
49
+ if (logger) {
50
+ let resultValue = JSON.stringify(result || {}).replace(
51
+ /: *"([^"]+)"/g,
52
+ function (...item) {
53
+ return item[1].length > 25
54
+ ? `:"${item[1].slice(0, 25)}${$.c.m('...')}"`
55
+ : `:"${item[1]}"`
56
+ }
57
+ )
58
+ let resultKey = resultValue.replace(/"([a-zA-Z0-9_\$\.]+)" *:/g, function (
59
+ ...item
60
+ ) {
61
+ return `"${$.c.dimy(item[1])}":`
62
+ })
63
+ resultKey = resultKey.slice(0, 1000)
64
+ $.log(
65
+ '[router处理]=>',
66
+ resultKey,
67
+ `\n${$.c.dimc(name + apiPath)} => ${$.c.dimc(ms || '0')} ms\n`
68
+ )
69
+ }
70
+ }
71
+
72
+ const warn = (...args) => {
73
+ if (logger) {
74
+ console.warn(...args)
75
+ }
76
+ }
77
+
78
+ // 检查接口定义是否规范,不规范也不会出错,只会打印提示
79
+ const checkapiStandard = (apiPath, opt) => {
80
+ const apiDesc = opt.name || opt.desc
81
+ if (!apiDesc) {
82
+ $.log($.c.y('?'), apiPath.fillStr(' ', 30), $.c.y('接口未写名称或描述'))
83
+ } else if (apiPath.includes('_')) {
84
+ $.log($.c.y('?'), apiPath.fillStr(' ', 30), $.c.y('接口命名不规范'))
85
+ }
86
+ }
87
+
88
+ // 获取api需要执行的函数,判断是否使用mock也在这里面
89
+ const getApiFn = (apiPath, opt) => {
90
+ let mockModel = 0
91
+ if (!opt.controller) {
92
+ if (opt.mock) {
93
+ $.log(
94
+ $.c.g('✔'),
95
+ apiPath.fillStr(' ', 30),
96
+ $.c.r('controller未定义'),
97
+ $.c.g('& mock已定义')
98
+ )
99
+ mockModel = 1
100
+ } else {
101
+ $.log(
102
+ $.c.r('✘'),
103
+ apiPath.fillStr(' ', 30),
104
+ $.c.r('controller未定义 & mock未定义')
105
+ )
106
+ mockModel = 2
107
+ }
108
+ }
109
+
110
+ let func
111
+ if (mockModel) {
112
+ const fn = mockModel === 1 ? 'mockRouter' : 'noMock'
113
+ func = mockFn[fn] && mockFn[fn](opt.mock)
114
+ } else {
115
+ const [file, fn] = opt.controller.split('.')
116
+ try {
117
+ const fileDir = path.resolve(rootDir, controllerDir, file)
118
+ const contr = require(fileDir) || {}
119
+ func = contr[fn]
120
+ if (!func) {
121
+ $.log(
122
+ $.c.r('✘'),
123
+ apiPath.fillStr(' ', 30),
124
+ $.c.r(`文件“${fileDir}”中不存在“${fn}”方法`)
125
+ )
126
+ }
127
+ } catch (e) {
128
+ $.log($.c.r('✘'), apiPath.fillStr(' ', 30), $.c.r(`router不存在 ${file}`))
129
+ $.log(e.stack)
130
+ }
131
+ }
132
+ return func
133
+ }
134
+
135
+ const limitReqAction = (action, apiPath) => {
136
+ return async function (ctx, next) {
137
+ const start = Date.now()
138
+
139
+ const { feqLimit, name, desc } = api[apiPath] || {}
140
+
141
+ // 接口频率控制
142
+ if (+feqLimit > 0) {
143
+ const it = (apiStat[apiPath] = apiStat[apiPath] || { n: 1, t: 0 })
144
+ it.n++
145
+ const diff = start - it.t
146
+ if ((1 / feqLimit) * 1000 > diff) {
147
+ ctx.body = {
148
+ code: 402,
149
+ data: diff,
150
+ msg: '访问过快请稍后再试!'
151
+ }
152
+
153
+ routerLog(ctx.body, name || desc, apiPath, Date.now() - start)
154
+ return ctx.body
155
+ }
156
+ it.t = start
157
+ }
158
+
159
+ // 执行controller的方法
160
+ if (action) {
161
+ try {
162
+ await action(ctx, next)
163
+ } catch (e) {
164
+ console.error('[controller error]', e)
165
+
166
+ ctx.body = {
167
+ code: 406,
168
+ data: {},
169
+ msg: `[controller error]`
170
+ }
171
+ let errStack = e.stack
172
+ .split('\n')
173
+ .filter(x => !x.includes('node_modules'))
174
+ $G.errorList.push({ time: new Date().date2Str(), desc: errStack })
175
+ if ($G.errorList.length > 20) $G.errorList.shift() //保持20条
176
+ }
177
+ } else {
178
+ ctx.body = {
179
+ code: 406,
180
+ data: {},
181
+ msg: `${apiPath}的Control不存在,请在api定义中定义mock对象`
182
+ }
183
+ }
184
+
185
+ routerLog(ctx.body, name || desc, apiPath, Date.now() - start)
186
+ if (global.rtsMQ) {
187
+ try {
188
+ if (rtsMQ.ch.connection.expectSocketClose) {
189
+ // mq断开了
190
+ return ctx.body
191
+ }
192
+ } catch (e) {
193
+ return ctx.body
194
+ }
195
+
196
+ process.nextTick(function () {
197
+ const mqObj = {
198
+ type: 'rts_api',
199
+ key: `api:${apiPath.replace(/\//g, '_')}`,
200
+ number: Date.now() - start,
201
+ method: ['count', 'max', 'min', 'avg'],
202
+ time: +$.now()
203
+ }
204
+ global.rtsMQ.send({
205
+ queueName: SkyConfig.rtsQueueName,
206
+ text: JSON.stringify(mqObj)
207
+ })
208
+ })
209
+ } else if (global.rts) {
210
+ // add stack
211
+ process.nextTick(function () {
212
+ global.rts.record(
213
+ `api:${apiPath.replace(/\//g, '_')}`,
214
+ Date.now() - start,
215
+ ['count', 'max', 'min', 'avg']
216
+ )
217
+ })
218
+ }
219
+ return ctx.body
220
+ }
221
+ }
222
+
223
+ const registerApi = (apiPath, opt) => {
224
+ if (!opt.method) {
225
+ return
226
+ }
227
+
228
+ if (api[apiPath]) {
229
+ $.err('出现重复的api定义:', apiPath, api[apiPath])
230
+ }
231
+
232
+ opt.method = opt.method.toLowerCase()
233
+ api[apiPath] = opt
234
+
235
+ const action = limitReqAction(getApiFn(apiPath, opt), apiPath)
236
+
237
+ if (opt.method === 'all') {
238
+ router.get(apiPath, action)
239
+ router.post(apiPath, action)
240
+ } else {
241
+ router[opt.method](apiPath, action)
242
+ }
243
+
244
+ checkapiStandard(apiPath, opt)
245
+ }
246
+
247
+ const checkApi = (apiDir, apiPath = '') => {
248
+ try {
249
+ const files = fs.readdirSync(apiDir)
250
+ for (let i = 0; i < files.length; i++) {
251
+ const dir = path.join(apiDir, files[i])
252
+ const stat = fs.statSync(dir)
253
+ if (stat.isDirectory()) {
254
+ // 是文件夹
255
+ checkApi(dir, `${apiPath}/${files[i]}`)
256
+ } else {
257
+ const ap = require(dir)
258
+ for (const [p, opt] of Object.entries(ap)) {
259
+ const path = (p.indexOf('/') === 0
260
+ ? p
261
+ : `${apiPath}/${files[i].split('.')[0]}/${p}`
262
+ )
263
+ .split('/')
264
+ .filter(v => !!v)
265
+ .join('/')
266
+ registerApi(`/${path}`, opt)
267
+ }
268
+ }
269
+ }
270
+ } catch (e) {
271
+ $.err($.c.r(`✘ ${e.stack}`))
272
+ }
273
+
274
+ // process.exit(0)
275
+ //
276
+ // for (const ap of Object.values(api)) {
277
+ // for (const [apiPath, opt] of Object.entries(ap)) {
278
+ // registerApi(apiPath, opt)
279
+ // }
280
+ // }
281
+ }
282
+
283
+ const loadRunDict = () => {
284
+ // 加载处理程序需要的数据
285
+ if (serviceDir) {
286
+ try {
287
+ const S = $.requireAll(path.join(rootDir, 'service')) || {}
288
+ Object.assign($S, S)
289
+ } catch (e) {
290
+ warn('引用service报错', e.stack)
291
+ }
292
+ }
293
+
294
+ let [n, m, k] = [0, 0, 0]
295
+ try {
296
+ $S._controlCode = {}
297
+ $S._srvCode = {}
298
+ Object.keys($S).forEach(i => {
299
+ $S._srvCode[i] = (++k).toString(16).padStart(2, '0')
300
+ })
301
+
302
+ // let file = yield fs.readFile(path.join(__dirname+'/../', '/models/dict_db.js'))
303
+ // const dict = JSON.parse(file)
304
+ // global.dictObj = dict
305
+ Object.entries(api).forEach(([k, item]) => {
306
+ m++
307
+ const [aK] = k.split('/').filter(function (item) {
308
+ return item !== '' && item !== '__swagger__'
309
+ })
310
+ if (aK) {
311
+ $S._controlCode[k] = m.toString(36).padStart(2, '0')
312
+ }
313
+ if (item.front) {
314
+ n++
315
+ Object.values(item.param).forEach(v => {
316
+ if (v.req === 0) {
317
+ delete v.req
318
+ }
319
+ if (v.def === null) {
320
+ delete v.def
321
+ }
322
+ if (v.type === 'string') {
323
+ delete v.type
324
+ }
325
+ })
326
+
327
+ frontApi[k] = { method: item.method, param: item.param }
328
+ }
329
+ })
330
+ } catch (e) {
331
+ $.err(e.stack)
332
+ }
333
+
334
+ // $.dir($S)
335
+
336
+ $.log(
337
+ n === 0 ? $.c.r('✘') : $.c.g('✔'),
338
+ `[${$.c.y('frontApi/totlaApi')}] = [${$.c.y(
339
+ `${n}/${m}`
340
+ )}] Routers at [${$.c.y(controllerDir)}]`
341
+ )
342
+ }
343
+
344
+ checkApi(apiRootDir)
345
+
346
+ loadRunDict()
347
+
348
+ module.exports = [router.routes(), router.allowedMethods()]