w-web-api 1.0.52 → 1.0.53

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 (84) hide show
  1. package/_gh-pages-deploy/.nojekyll +0 -0
  2. package/_gh-pages-deploy/WWebApi.html +898 -0
  3. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  4. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  5. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  6. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  7. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  8. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  9. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  10. package/_gh-pages-deploy/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  11. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  12. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  13. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  14. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  15. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  16. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  17. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  18. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  19. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  20. package/_gh-pages-deploy/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  21. package/_gh-pages-deploy/index.html +84 -0
  22. package/_gh-pages-deploy/scripts/collapse.js +39 -0
  23. package/_gh-pages-deploy/scripts/commonNav.js +28 -0
  24. package/_gh-pages-deploy/scripts/linenumber.js +25 -0
  25. package/_gh-pages-deploy/scripts/nav.js +12 -0
  26. package/_gh-pages-deploy/scripts/polyfill.js +4 -0
  27. package/_gh-pages-deploy/scripts/prettify/Apache-License-2.0.txt +202 -0
  28. package/_gh-pages-deploy/scripts/prettify/lang-css.js +2 -0
  29. package/_gh-pages-deploy/scripts/prettify/prettify.js +28 -0
  30. package/_gh-pages-deploy/scripts/search.js +99 -0
  31. package/{docs/WWebApi.mjs.html → _gh-pages-deploy/server_WWebApi.mjs.html} +96 -39
  32. package/_gh-pages-deploy/src_components_Common_CheckYesNo.vue.html +187 -0
  33. package/_gh-pages-deploy/styles/jsdoc.css +776 -0
  34. package/_gh-pages-deploy/styles/prettify.css +80 -0
  35. package/dist/css/app.fe69497a.css +1 -0
  36. package/dist/index.tmp +4 -2
  37. package/dist/js/app-legacy.15819aa7.js +1 -0
  38. package/dist/js/app.15819aa7.js +1 -0
  39. package/dist/js/chunk-vendors-legacy.c1a32dd1.js +15 -0
  40. package/dist/js/chunk-vendors.c1a32dd1.js +15 -0
  41. package/dist/w-web-api.umd.js +2 -2
  42. package/dist/w-web-api.umd.js.map +1 -1
  43. package/docs/WWebApi.html +2 -2
  44. package/docs/index.html +1 -1
  45. package/docs/server_WWebApi.mjs.html +1012 -0
  46. package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
  47. package/g.getSettings.mjs +3 -0
  48. package/package.json +15 -11
  49. package/public/index.html +9 -2
  50. package/server/WWebApi.mjs +93 -36
  51. package/server/procApis.mjs +62 -0
  52. package/server/procLang.mjs +386 -0
  53. package/server/procProxy.mjs +120 -0
  54. package/server/srLog.mjs +30 -0
  55. package/server/staLogs/staEvent.mjs +129 -0
  56. package/server/staLogs/test_staEvent.mjs +132 -0
  57. package/settings.json +14 -0
  58. package/src/App.vue +11 -7
  59. package/src/assets/scalar-ui.css +113 -0
  60. package/src/components/Common/CheckYes.vue +102 -0
  61. package/src/components/Common/CheckYesNo.vue +115 -0
  62. package/src/components/Common/LoadingWinBar.vue +114 -0
  63. package/src/components/Layout.vue +8 -7
  64. package/src/components/LayoutContent.vue +308 -333
  65. package/src/components/LayoutContentEdit.vue +577 -0
  66. package/src/components/LayoutContentStats.vue +485 -0
  67. package/src/components/LayoutContentTest.vue +799 -0
  68. package/src/components/MdPanel.vue +80 -58
  69. package/src/main.js +8 -0
  70. package/src/plugins/mUI.mjs +19 -4
  71. package/src/schema/tables/apis.mjs +30 -0
  72. package/srv.mjs +47 -19
  73. package/tableTags.json +1 -1
  74. package/.github/workflows/ci-test.yml +0 -24
  75. package/.vscode/launch.json +0 -18
  76. package/db/wapis/apis/data.mdb +0 -0
  77. package/db/wapis/apis/lock.mdb +0 -0
  78. package/dist/css/app.b5cf2ef5.css +0 -1
  79. package/dist/js/app-legacy.927b5679.js +0 -1
  80. package/dist/js/app.927b5679.js +0 -1
  81. package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
  82. package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
  83. package/tableTags-web-api.json +0 -1
  84. package/test/all.test.mjs +0 -10
@@ -0,0 +1,187 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <title>src/components/Common/CheckYesNo.vue - Documentation</title>
7
+
8
+
9
+ <script src="scripts/prettify/prettify.js"></script>
10
+ <script src="scripts/prettify/lang-css.js"></script>
11
+ <!--[if lt IE 9]>
12
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
13
+ <![endif]-->
14
+ <link type="text/css" rel="stylesheet" href="styles/prettify.css">
15
+ <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
16
+ <script src="scripts/nav.js" defer></script>
17
+
18
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
19
+ </head>
20
+ <body>
21
+
22
+ <input type="checkbox" id="nav-trigger" class="nav-trigger" />
23
+ <label for="nav-trigger" class="navicon-button x">
24
+ <div class="navicon"></div>
25
+ </label>
26
+
27
+ <label for="nav-trigger" class="overlay"></label>
28
+
29
+ <nav >
30
+
31
+
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebApi.html">WWebApi</a></li></ul>
33
+
34
+ </nav>
35
+
36
+ <div id="main">
37
+
38
+ <h1 class="page-title">src/components/Common/CheckYesNo.vue</h1>
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ <section>
47
+ <article>
48
+ <pre class="prettyprint source linenums"><code>&lt;template>
49
+ &lt;WConfirm
50
+ :show.sync="bShow"
51
+ :title="$t('systemMessage')"
52
+ :content="content"
53
+ :_contentColor="'white'"
54
+ :_contentIconColor="'white'"
55
+ :_contentBackgroundColor="'orange lighten-5'"
56
+ :_titleColor="'white'"
57
+ :headerBackgroundColor="'grey lighten-3'"
58
+ :noBtnText="$t('no')"
59
+ :yesBtnText="$t('yes')"
60
+ @click-no="clickBtn(false)"
61
+ @click-yes="clickBtn(true)"
62
+ >&lt;/WConfirm>
63
+ &lt;/template>
64
+
65
+ &lt;script>
66
+ import Vue from 'vue'
67
+ import genPm from 'wsemi/src/genPm.mjs'
68
+ import WConfirm from 'w-component-vue/src/components/WConfirm.vue'
69
+
70
+ export default {
71
+ components: {
72
+ WConfirm,
73
+ },
74
+ props: {
75
+ },
76
+ data: function() {
77
+ return {
78
+
79
+ bShow: false,
80
+ pm: null,
81
+
82
+ content: '',
83
+
84
+ }
85
+ },
86
+ mounted: function() {
87
+ //console.log('mounted')
88
+
89
+ let vo = this
90
+
91
+ //set
92
+ Vue.prototype.$dg.showCheckYesNo = vo.show
93
+
94
+ },
95
+ computed: {
96
+ },
97
+ methods: {
98
+
99
+ /**
100
+ * 顯示 Yes/No 確認對話框並回傳 Promise。
101
+ *
102
+ * **Contract** (caller 須遵守):
103
+ * - 使用者點 **Yes** → Promise `resolve()` (無值, 進 `.then()`)
104
+ * - 使用者點 **No** → Promise `reject('close')` (進 `.catch(err => err === 'close')`)
105
+ *
106
+ * 正確 caller pattern:
107
+ *
108
+ * vo.$dg.showCheckYesNo('確定要 X?')
109
+ * .then(() => {
110
+ * //使用者點 Yes
111
+ * doX()
112
+ * })
113
+ * .catch((err) => {
114
+ * //使用者點 No (err === 'close') 為正常路徑, 靜默處理
115
+ * if (err === 'close') return
116
+ * //非預期錯誤 (CheckYesNo 本身故障等)
117
+ * console.log('showCheckYesNo unexpected error', err)
118
+ * })
119
+ *
120
+ * @param {string} content - 顯示在 modal 中的訊息文字
121
+ * @returns {Promise&lt;void>} Yes → resolve(); No → reject('close')
122
+ */
123
+ show: function(content) {
124
+ //console.log('methods show', content)
125
+
126
+ let vo = this
127
+
128
+ //pm
129
+ vo.pm = genPm()
130
+
131
+ //save
132
+ vo.content = content
133
+
134
+ //show
135
+ vo.bShow = true
136
+
137
+ return vo.pm
138
+ },
139
+
140
+ clickBtn: function(mode) {
141
+ //console.log('methods clickBtn', mode)
142
+
143
+ let vo = this
144
+
145
+ if (mode) {
146
+ vo.pm.resolve()
147
+ }
148
+ else {
149
+ vo.pm.reject('close')
150
+ }
151
+
152
+ //hide
153
+ vo.bShow = false
154
+
155
+ },
156
+
157
+ }
158
+ }
159
+ &lt;/script>
160
+
161
+ &lt;style scoped>
162
+ &lt;/style>
163
+ </code></pre>
164
+ </article>
165
+ </section>
166
+
167
+
168
+
169
+
170
+
171
+
172
+ </div>
173
+
174
+ <br class="clear">
175
+
176
+ <footer>
177
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Jun 22 2026 15:42:09 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
178
+ </footer>
179
+
180
+ <script>prettyPrint();</script>
181
+ <script src="scripts/polyfill.js"></script>
182
+ <script src="scripts/linenumber.js"></script>
183
+
184
+
185
+
186
+ </body>
187
+ </html>
package/g.getSettings.mjs CHANGED
@@ -12,6 +12,9 @@ function getSettings() {
12
12
  // 'dbPort': 27017,
13
13
  'dbUrl': './db',
14
14
  'dbName': 'wapis',
15
+ 'ssoBaseUrl': 'http://localhost:11007',
16
+ 'ssoAppToken': '', //部署時填入SSO tokens表中isApp=y的app token
17
+ 'ssoLoginUrl': 'http://localhost:11007/', //未登入時導向之SSO登入頁
15
18
  }
16
19
  }
17
20
 
package/package.json CHANGED
@@ -1,40 +1,44 @@
1
1
  {
2
2
  "name": "w-web-api",
3
- "version": "1.0.52",
3
+ "version": "1.0.53",
4
4
  "main": "dist/w-web-api.umd.js",
5
5
  "dependencies": {
6
6
  "@mdi/js": "^7.4.47",
7
- "axios": "^1.13.6",
8
- "lodash-es": "^4.17.23",
7
+ "axios": "^1.18.0",
8
+ "lodash-es": "^4.18.1",
9
9
  "showdown": "^2.1.0",
10
- "w-component-vue": "^2.4.44",
10
+ "w-component-vue": "^2.4.66",
11
11
  "w-data-collector": "^1.0.22",
12
12
  "w-serv-hapi": "^1.0.72",
13
13
  "w-serv-orm": "^1.0.38",
14
14
  "w-ui-loginout": "^1.0.10",
15
- "wsemi": "^1.8.43"
15
+ "w-syslog": "^1.0.8",
16
+ "wsemi": "^1.8.61"
16
17
  },
17
18
  "devDependencies": {
18
19
  "@vue/cli-plugin-babel": "^5.0.8",
19
20
  "@vue/cli-plugin-eslint": "^5.0.8",
20
21
  "@vue/cli-service": "^5.0.8",
21
22
  "eslint": "^8.37.0",
22
- "eslint-config-standard": "^17.0.0",
23
+ "eslint-config-standard": "^17.1.0",
23
24
  "eslint-friendly-formatter": "^4.0.1",
24
25
  "eslint-plugin-import": "^2.27.5",
25
- "eslint-plugin-node": "^11.1.0",
26
+ "eslint-plugin-n": "^16.6.2",
26
27
  "eslint-plugin-promise": "^6.1.1",
27
- "eslint-plugin-standard": "^4.1.0",
28
28
  "eslint-plugin-vue": "^9.10.0",
29
+ "pixelmatch": "^7.2.0",
30
+ "playwright": "^1.61.0",
31
+ "pngjs": "^7.0.0",
29
32
  "vue": "^2.6.14",
30
33
  "vuex": "^3.6.2",
31
- "w-orm-lmdb": "^1.0.3",
32
- "w-package-tools": "^1.1.3"
34
+ "w-orm-lmdb": "^1.0.6",
35
+ "w-screenctl": "^1.0.3",
36
+ "w-package-tools": "^1.1.9"
33
37
  },
34
38
  "scripts": {
35
39
  "serve": "vue-cli-service serve",
36
40
  "build": "vue-cli-service build",
37
- "test": "mocha --parallel --timeout 60000",
41
+ "test": "mocha --timeout 300000",
38
42
  "lint": "vue-cli-service lint",
39
43
  "deploy": "gh-pages -d docs"
40
44
  },
package/public/index.html CHANGED
@@ -7,10 +7,10 @@
7
7
  <title></title>
8
8
 
9
9
  <!-- mdi font -->
10
- <link href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet">
10
+ <link _href="https://cdn.jsdelivr.net/npm/@mdi/font@7.4.47/css/materialdesignicons.min.css" rel="stylesheet">
11
11
 
12
12
  <!-- fontawesome -->
13
- <link href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css" rel="stylesheet">
13
+ <link _href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.2/css/all.min.css" rel="stylesheet">
14
14
 
15
15
  <!-- ___pmwapi___ -->
16
16
  <script>
@@ -19,6 +19,13 @@
19
19
  }
20
20
  </script>
21
21
 
22
+ <!-- ___pmwperm___ -->
23
+ <script>
24
+ window.___pmwperm___={
25
+ language: '{language}',
26
+ }
27
+ </script>
28
+
22
29
  </head>
23
30
  <body style="font-family:'Microsoft JhengHei','Avenir','Helvetica', 'Arial', 'sans-serif'; padding:0px; margin:0px;">
24
31
  <noscript>
@@ -26,6 +26,10 @@ import replace from 'wsemi/src/replace.mjs'
26
26
  import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
27
27
  import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
28
28
  import procLang from './procLang.mjs'
29
+ import procProxy from './procProxy.mjs'
30
+ import procApis from './procApis.mjs'
31
+ import staEvent from './staLogs/staEvent.mjs'
32
+ import srLogInit from './srLog.mjs'
29
33
  import ds from '../src/schema/index.mjs'
30
34
 
31
35
 
@@ -226,6 +230,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
226
230
  //params
227
231
  let showLanguage = get(opt, 'showLanguage', 'y')
228
232
  let language = get(opt, 'language', 'eng')
233
+ let logFd = get(opt, 'logFd', './_logs') //srLog 寫入 + staEvent 統計共用之 log 資料夾
229
234
 
230
235
 
231
236
  //kpLangExt
@@ -252,6 +257,35 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
252
257
  let { woItems, procOrm } = wp
253
258
 
254
259
 
260
+ //srLog(後端 log;錯誤一律 log err-key 供識別,對齊 w-web-sso)
261
+ let srLog = srLogInit(opt)
262
+
263
+ //kpFunExt 邊界統一處理:成功記 info(供 staEvent 統計呼叫頻率);catch 後端錯誤 → srLog 該 err-key →
264
+ //原樣 re-reject(前端依 key 查自己 lang 顯示)。event 統一加 'kpfun-' 前綴 → 專用事件、與 api/verifyConn 區分。
265
+ let wrapErrLog = (event, fn) => {
266
+ let ev = 'kpfun-' + event
267
+ return async (...args) => {
268
+ try {
269
+ let result = await fn(...args)
270
+ srLog.info({ event: ev }) //成功也記 info
271
+ return result
272
+ }
273
+ catch (err) {
274
+ srLog.error({ event: ev, err })
275
+ return Promise.reject(err)
276
+ }
277
+ }
278
+ }
279
+
280
+
281
+ //procProxy
282
+ let { proxyRequest } = procProxy({ srLog })
283
+
284
+
285
+ //procApis
286
+ let { getApisList, saveApi, deleteApi } = procApis({ woItems, procOrm, ds })
287
+
288
+
255
289
  //getWebInfor
256
290
  let getWebInfor = (userId) => {
257
291
  return {
@@ -274,26 +308,26 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
274
308
  if (!isestr(id)) {
275
309
  console.log('user', user)
276
310
  console.log('can not get the userId')
277
- return Promise.reject(`can not get the userId`)
311
+ return Promise.reject('errUserIdMissing')
278
312
  }
279
313
  let email = get(user, 'email', '')
280
314
  if (!isestr(email)) {
281
315
  console.log('user', user)
282
316
  console.log('can not get the email of user')
283
- return Promise.reject(`can not get the email of user`)
317
+ return Promise.reject('errUserEmailMissing')
284
318
  }
285
319
  let name = get(user, 'name', '')
286
320
  if (!isestr(name)) {
287
321
  console.log('user', user)
288
322
  console.log('can not get userName')
289
- return Promise.reject(`can not get userName`)
323
+ return Promise.reject('errUserNameMissing')
290
324
  }
291
325
  let isAdmin = get(user, 'isAdmin', '')
292
326
  if (isAdmin !== 'y' && isAdmin !== 'n') {
293
327
  console.log('user', user)
294
328
  console.log('user.isAdmin is not y or n', user.isAdmin)
295
329
  console.log('can not get the role of user')
296
- return Promise.reject(`can not get the role of user`)
330
+ return Promise.reject('errUserRoleMissing')
297
331
  }
298
332
  return true
299
333
  }
@@ -313,7 +347,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
313
347
  // if (!iseobj(userSelf)) {
314
348
  // console.log(`token`, token)
315
349
  // console.log(`can not find the user from token`)
316
- // return Promise.reject(`can not find the user from token`)
350
+ // return Promise.reject('errUserNotFound')
317
351
  // }
318
352
  await checkUser(userSelf)
319
353
  }
@@ -355,9 +389,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
355
389
  if (!b) {
356
390
  console.log('user', user)
357
391
  console.log(`user does not have permission`)
358
- return Promise.reject(`user does not have permission`)
392
+ return Promise.reject('errUserNoPermission')
359
393
  }
360
394
 
395
+ srLog.info({ event: 'verifyClientUser', from, userId: get(user, 'id', '') }) //瀏覽使用者驗證通過
361
396
  return user
362
397
  }
363
398
 
@@ -380,7 +415,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
380
415
  if (!iseobj(user)) {
381
416
  console.log(`token`, token)
382
417
  console.log(`can not find the user from token`)
383
- return Promise.reject(`can not find the user from token`)
418
+ return Promise.reject('errUserNotFound')
384
419
  }
385
420
 
386
421
  //verifyAppUser
@@ -393,9 +428,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
393
428
  if (!b) {
394
429
  console.log('user', user)
395
430
  console.log(`user does not have permission`)
396
- return Promise.reject(`user does not have permission`)
431
+ return Promise.reject('errUserNoPermission')
397
432
  }
398
433
 
434
+ srLog.info({ event: 'verifyAppUser', from, userId: get(user, 'id', '') }) //應用程式使用者驗證通過
399
435
  return user
400
436
  }
401
437
 
@@ -422,7 +458,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
422
458
  if (!iseobj(payload)) {
423
459
  console.log('payload', payload)
424
460
  console.log(`invalid payload in req`)
425
- return Promise.reject(`invalid payload in req`)
461
+ return Promise.reject('errPayloadInvalid')
426
462
  }
427
463
 
428
464
  //group
@@ -432,7 +468,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
432
468
  if (!isestr(group)) {
433
469
  console.log('payload', payload)
434
470
  console.log(`invalid group in payload`)
435
- return Promise.reject(`invalid group in payload`)
471
+ return Promise.reject('errGroupInvalid')
436
472
  }
437
473
 
438
474
  //rows
@@ -442,7 +478,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
442
478
  if (!isearr(rows)) {
443
479
  console.log('payload', payload)
444
480
  console.log(`invalid rows in payload`)
445
- return Promise.reject(`invalid rows in payload`)
481
+ return Promise.reject('errRowsInvalid')
446
482
  }
447
483
 
448
484
  //r
@@ -482,7 +518,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
482
518
  console.log('inp', inp)
483
519
  console.log('group', group)
484
520
  console.log(`invalid group`)
485
- return Promise.reject(`invalid group`)
521
+ return Promise.reject('errGroupInvalid')
486
522
  }
487
523
 
488
524
  //rows
@@ -493,7 +529,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
493
529
  if (!isearr(rows)) {
494
530
  console.log('inp', inp)
495
531
  console.log('keyTable', keyTable)
496
- return Promise.reject(`invalid rows`)
532
+ return Promise.reject('errRowsInvalid')
497
533
  }
498
534
 
499
535
  //save from
@@ -564,6 +600,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
564
600
  c = replace(c, '/mapi/', '{sfd}/') //方法同genEntry
565
601
  c = replace(c, '{sfd}', subfolder)
566
602
  c = replace(c, '{urlRedirect}', urlRedirect)
603
+ c = replace(c, '{language}', language) //注入初始語系 → window.___pmwperm___.language(前端 getLang 之來源之一)
567
604
  fs.writeFileSync(fpEntryOut, c, 'utf8')
568
605
  }
569
606
  catch (err) {
@@ -592,7 +629,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
592
629
  console.log('token', token)
593
630
  console.log('[API]getUserByToken/check token: invalid token')
594
631
  console.log(`token does not have permission`)
595
- return Promise.reject(`token does not have permission`)
632
+ return Promise.reject('errTokenNoPermission')
596
633
  }
597
634
 
598
635
  //getAndVerifyClientUser
@@ -603,9 +640,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
603
640
  console.log('token', token)
604
641
  console.log('[API]getUserByToken/check user: invalid user')
605
642
  console.log(`token does not have permission`)
606
- return Promise.reject(`token does not have permission`)
643
+ return Promise.reject('errTokenNoPermission')
607
644
  }
608
645
 
646
+ srLog.info({ event: 'api/getUserByToken', userId: get(user, 'id', '') })
609
647
  return user
610
648
  }
611
649
 
@@ -637,7 +675,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
637
675
  // console.log('token', token)
638
676
  // console.log('[API]getAPIsList/check token: invalid token')
639
677
  // console.log(`token does not have permission`)
640
- // return Promise.reject(`token does not have permission`)
678
+ // return Promise.reject('errTokenNoPermission')
641
679
  // }
642
680
 
643
681
  // //getAndVerifyClientUser
@@ -648,7 +686,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
648
686
  // console.log('token', token)
649
687
  // console.log('[API]getAPIsList/check user: invalid user')
650
688
  // console.log(`token does not have permission`)
651
- // return Promise.reject(`token does not have permission`)
689
+ // return Promise.reject('errTokenNoPermission')
652
690
  // }
653
691
 
654
692
  // //getAPIsList
@@ -686,7 +724,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
686
724
  // console.log('token', token)
687
725
  // console.log('[API]updateAPIs/check token: invalid token')
688
726
  // console.log(`token does not have permission`)
689
- // return Promise.reject(`token does not have permission`)
727
+ // return Promise.reject('errTokenNoPermission')
690
728
  // }
691
729
 
692
730
  // //getAndVerifyClientUser
@@ -697,7 +735,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
697
735
  // console.log('token', token)
698
736
  // console.log('[API]updateAPIs/check user: invalid user')
699
737
  // console.log(`token does not have permission`)
700
- // return Promise.reject(`token does not have permission`)
738
+ // return Promise.reject('errTokenNoPermission')
701
739
  // }
702
740
 
703
741
  // //parsePayload
@@ -738,7 +776,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
738
776
  console.log('token', token)
739
777
  console.log('[API]syncAndReplaceTabs/check token: invalid token')
740
778
  console.log(`token does not have permission`)
741
- return Promise.reject(`token does not have permission`)
779
+ return Promise.reject('errTokenNoPermission')
742
780
  }
743
781
 
744
782
  //keyTable
@@ -750,14 +788,14 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
750
788
  console.log('keyTable', keyTable)
751
789
  console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
752
790
  console.log(`token does not have permission`)
753
- return Promise.reject(`token does not have permission`)
791
+ return Promise.reject('errTokenNoPermission')
754
792
  }
755
793
 
756
794
  //check keyTable
757
795
  let allowedTables = ['apis']
758
796
  if (!allowedTables.includes(keyTable)) {
759
797
  console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
760
- return Promise.reject(`invalid keyTable: ${keyTable}`)
798
+ return Promise.reject('errKeyTableInvalid')
761
799
  }
762
800
 
763
801
  //getAndVerifyAppUser
@@ -768,7 +806,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
768
806
  console.log('token', token)
769
807
  console.log('[API]syncAndReplaceTabs/check user: invalid user')
770
808
  console.log(`token does not have permission`)
771
- return Promise.reject(`token does not have permission`)
809
+ return Promise.reject('errTokenNoPermission')
772
810
  }
773
811
 
774
812
  //userId
@@ -780,7 +818,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
780
818
  console.log('user', user)
781
819
  console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
782
820
  console.log(`token does not have permission`)
783
- return Promise.reject(`token does not have permission`)
821
+ return Promise.reject('errTokenNoPermission')
784
822
  }
785
823
 
786
824
  //parsePayload
@@ -789,6 +827,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
789
827
  //syncAndReplaceTabs
790
828
  let r = await syncAndReplaceTabs(userId, inp, keyTable)
791
829
 
830
+ srLog.info({ event: 'api/syncAndReplaceTabs', userId, keyTable })
792
831
  return r
793
832
  }
794
833
 
@@ -840,19 +879,17 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
840
879
  let b = await p.checkToken(token)
841
880
  // console.log('b', b)
842
881
 
882
+ srLog.info({ event: 'verifyConn', apiType }) //連線驗證通過(checkToken 失敗時會 throw 不到此)
843
883
  return b
844
884
  },
845
885
  getUserIdByToken: async (token) => { //可使用async或sync函數
846
886
  // console.log('getUserIdByToken', token)
847
- return ''
848
- // let user = await getUserByToken(token) //api儲存時須使用
849
- // let userId = get(user, 'id', '')
850
- // if (!isestr(userId)) {
851
- // console.log('token', token)
852
- // console.log('userId', userId)
853
- // return Promise.reject(`can not find user.id`)
854
- // }
855
- // return userId
887
+ if (!isestr(token)) {
888
+ return ''
889
+ }
890
+ let user = await getUserByToken(token)
891
+ let userId = get(user, 'id', '')
892
+ return userId
856
893
  },
857
894
  useDbOrm: true,
858
895
  kpOrm: woItems,
@@ -860,9 +897,29 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
860
897
  tableNamesExec,
861
898
  methodsExec: ['select', 'insert', 'save', 'del'], //mix需於procOrm內註冊以提供
862
899
  tableNamesSync,
863
- kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數
864
-
865
- getWebInfor,
900
+ kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數(皆經 wrapErrLog:錯誤 srLog err-key 後 re-reject)
901
+
902
+ getWebInfor: wrapErrLog('getWebInfor', getWebInfor),
903
+
904
+ proxyRequest: wrapErrLog('proxyRequest', (userId, reqSpec) => {
905
+ return proxyRequest(reqSpec)
906
+ }),
907
+
908
+ getApisList: wrapErrLog('getApisList', (userId) => {
909
+ return getApisList(userId)
910
+ }),
911
+ saveApi: wrapErrLog('saveApi', (userId, row) => {
912
+ return saveApi(userId, row)
913
+ }),
914
+ deleteApi: wrapErrLog('deleteApi', (userId, id) => {
915
+ return deleteApi(userId, id)
916
+ }),
917
+
918
+ //統計資訊頁:回傳各 event 之時段發生頻率(讀 logFd 之 log)。連線已由 verifyClientUser 限管理員,
919
+ //故此處不另檢查(同 getApisList)。timeLength 天數 / timeInterval 'hr'|'day'。
920
+ getStaEvent: wrapErrLog('getStaEvent', (userId, timeLength = 7, timeInterval = 'hr') => {
921
+ return staEvent(timeLength, timeInterval, { fdLog: logFd })
922
+ }),
866
923
 
867
924
  // getAPIsList: (userId, query = {}) => { //待提供api管理系統界面使用
868
925
  // return getAPIsList(query)