w-web-api 1.0.51 → 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 (86) 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} +118 -41
  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 +115 -38
  51. package/server/procApis.mjs +62 -0
  52. package/server/procLang.mjs +724 -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 +33 -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 +58 -71
  71. package/src/schema/tables/apis.mjs +30 -0
  72. package/src/store/mutations.mjs +1 -1
  73. package/srv.mjs +47 -19
  74. package/tableTags.json +1 -1
  75. package/.github/workflows/ci-test.yml +0 -24
  76. package/.vscode/launch.json +0 -18
  77. package/db/wapis/apis/data.mdb +0 -0
  78. package/db/wapis/apis/lock.mdb +0 -0
  79. package/dist/css/app.b5cf2ef5.css +0 -1
  80. package/dist/js/app-legacy.fbfba810.js +0 -1
  81. package/dist/js/app.fbfba810.js +0 -1
  82. package/dist/js/chunk-vendors-legacy.735ec7d6.js +0 -13
  83. package/dist/js/chunk-vendors.735ec7d6.js +0 -13
  84. package/src/plugins/mLang.mjs +0 -250
  85. package/tableTags-web-api.json +0 -1
  86. 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.51",
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.9.0",
8
- "lodash-es": "^4.17.21",
7
+ "axios": "^1.18.0",
8
+ "lodash-es": "^4.18.1",
9
9
  "showdown": "^2.1.0",
10
- "w-component-vue": "^2.4.39",
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.38"
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.2"
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>
@@ -25,6 +25,11 @@ import fsIsFile from 'wsemi/src/fsIsFile.mjs'
25
25
  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
+ 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'
28
33
  import ds from '../src/schema/index.mjs'
29
34
 
30
35
 
@@ -222,6 +227,20 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
222
227
  let urlRedirect = get(opt, 'urlRedirect', '')
223
228
 
224
229
 
230
+ //params
231
+ let showLanguage = get(opt, 'showLanguage', 'y')
232
+ let language = get(opt, 'language', 'eng')
233
+ let logFd = get(opt, 'logFd', './_logs') //srLog 寫入 + staEvent 統計共用之 log 資料夾
234
+
235
+
236
+ //kpLangExt
237
+ let kpLangExt = get(opt, 'kpLangExt', {})
238
+
239
+
240
+ //kpLang
241
+ let kpLang = procLang({ kpLangExt, webName, webDescription })
242
+
243
+
225
244
  //WServOrm
226
245
  let optWServOrm = {
227
246
  useCheckUser,
@@ -238,12 +257,47 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
238
257
  let { woItems, procOrm } = wp
239
258
 
240
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
+
241
289
  //getWebInfor
242
290
  let getWebInfor = (userId) => {
243
291
  return {
244
- webName,
245
- webDescription,
292
+
293
+ // webName, //已併入kpLang
294
+ // webDescription, //已併入kpLang
246
295
  webLogo,
296
+
297
+ showLanguage,
298
+ language,
299
+ kpLang,
300
+
247
301
  }
248
302
  }
249
303
 
@@ -254,26 +308,26 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
254
308
  if (!isestr(id)) {
255
309
  console.log('user', user)
256
310
  console.log('can not get the userId')
257
- return Promise.reject(`can not get the userId`)
311
+ return Promise.reject('errUserIdMissing')
258
312
  }
259
313
  let email = get(user, 'email', '')
260
314
  if (!isestr(email)) {
261
315
  console.log('user', user)
262
316
  console.log('can not get the email of user')
263
- return Promise.reject(`can not get the email of user`)
317
+ return Promise.reject('errUserEmailMissing')
264
318
  }
265
319
  let name = get(user, 'name', '')
266
320
  if (!isestr(name)) {
267
321
  console.log('user', user)
268
322
  console.log('can not get userName')
269
- return Promise.reject(`can not get userName`)
323
+ return Promise.reject('errUserNameMissing')
270
324
  }
271
325
  let isAdmin = get(user, 'isAdmin', '')
272
326
  if (isAdmin !== 'y' && isAdmin !== 'n') {
273
327
  console.log('user', user)
274
328
  console.log('user.isAdmin is not y or n', user.isAdmin)
275
329
  console.log('can not get the role of user')
276
- return Promise.reject(`can not get the role of user`)
330
+ return Promise.reject('errUserRoleMissing')
277
331
  }
278
332
  return true
279
333
  }
@@ -293,7 +347,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
293
347
  // if (!iseobj(userSelf)) {
294
348
  // console.log(`token`, token)
295
349
  // console.log(`can not find the user from token`)
296
- // return Promise.reject(`can not find the user from token`)
350
+ // return Promise.reject('errUserNotFound')
297
351
  // }
298
352
  await checkUser(userSelf)
299
353
  }
@@ -335,9 +389,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
335
389
  if (!b) {
336
390
  console.log('user', user)
337
391
  console.log(`user does not have permission`)
338
- return Promise.reject(`user does not have permission`)
392
+ return Promise.reject('errUserNoPermission')
339
393
  }
340
394
 
395
+ srLog.info({ event: 'verifyClientUser', from, userId: get(user, 'id', '') }) //瀏覽使用者驗證通過
341
396
  return user
342
397
  }
343
398
 
@@ -360,7 +415,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
360
415
  if (!iseobj(user)) {
361
416
  console.log(`token`, token)
362
417
  console.log(`can not find the user from token`)
363
- return Promise.reject(`can not find the user from token`)
418
+ return Promise.reject('errUserNotFound')
364
419
  }
365
420
 
366
421
  //verifyAppUser
@@ -373,9 +428,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
373
428
  if (!b) {
374
429
  console.log('user', user)
375
430
  console.log(`user does not have permission`)
376
- return Promise.reject(`user does not have permission`)
431
+ return Promise.reject('errUserNoPermission')
377
432
  }
378
433
 
434
+ srLog.info({ event: 'verifyAppUser', from, userId: get(user, 'id', '') }) //應用程式使用者驗證通過
379
435
  return user
380
436
  }
381
437
 
@@ -402,7 +458,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
402
458
  if (!iseobj(payload)) {
403
459
  console.log('payload', payload)
404
460
  console.log(`invalid payload in req`)
405
- return Promise.reject(`invalid payload in req`)
461
+ return Promise.reject('errPayloadInvalid')
406
462
  }
407
463
 
408
464
  //group
@@ -412,7 +468,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
412
468
  if (!isestr(group)) {
413
469
  console.log('payload', payload)
414
470
  console.log(`invalid group in payload`)
415
- return Promise.reject(`invalid group in payload`)
471
+ return Promise.reject('errGroupInvalid')
416
472
  }
417
473
 
418
474
  //rows
@@ -422,7 +478,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
422
478
  if (!isearr(rows)) {
423
479
  console.log('payload', payload)
424
480
  console.log(`invalid rows in payload`)
425
- return Promise.reject(`invalid rows in payload`)
481
+ return Promise.reject('errRowsInvalid')
426
482
  }
427
483
 
428
484
  //r
@@ -462,7 +518,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
462
518
  console.log('inp', inp)
463
519
  console.log('group', group)
464
520
  console.log(`invalid group`)
465
- return Promise.reject(`invalid group`)
521
+ return Promise.reject('errGroupInvalid')
466
522
  }
467
523
 
468
524
  //rows
@@ -473,7 +529,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
473
529
  if (!isearr(rows)) {
474
530
  console.log('inp', inp)
475
531
  console.log('keyTable', keyTable)
476
- return Promise.reject(`invalid rows`)
532
+ return Promise.reject('errRowsInvalid')
477
533
  }
478
534
 
479
535
  //save from
@@ -544,6 +600,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
544
600
  c = replace(c, '/mapi/', '{sfd}/') //方法同genEntry
545
601
  c = replace(c, '{sfd}', subfolder)
546
602
  c = replace(c, '{urlRedirect}', urlRedirect)
603
+ c = replace(c, '{language}', language) //注入初始語系 → window.___pmwperm___.language(前端 getLang 之來源之一)
547
604
  fs.writeFileSync(fpEntryOut, c, 'utf8')
548
605
  }
549
606
  catch (err) {
@@ -572,7 +629,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
572
629
  console.log('token', token)
573
630
  console.log('[API]getUserByToken/check token: invalid token')
574
631
  console.log(`token does not have permission`)
575
- return Promise.reject(`token does not have permission`)
632
+ return Promise.reject('errTokenNoPermission')
576
633
  }
577
634
 
578
635
  //getAndVerifyClientUser
@@ -583,9 +640,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
583
640
  console.log('token', token)
584
641
  console.log('[API]getUserByToken/check user: invalid user')
585
642
  console.log(`token does not have permission`)
586
- return Promise.reject(`token does not have permission`)
643
+ return Promise.reject('errTokenNoPermission')
587
644
  }
588
645
 
646
+ srLog.info({ event: 'api/getUserByToken', userId: get(user, 'id', '') })
589
647
  return user
590
648
  }
591
649
 
@@ -617,7 +675,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
617
675
  // console.log('token', token)
618
676
  // console.log('[API]getAPIsList/check token: invalid token')
619
677
  // console.log(`token does not have permission`)
620
- // return Promise.reject(`token does not have permission`)
678
+ // return Promise.reject('errTokenNoPermission')
621
679
  // }
622
680
 
623
681
  // //getAndVerifyClientUser
@@ -628,7 +686,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
628
686
  // console.log('token', token)
629
687
  // console.log('[API]getAPIsList/check user: invalid user')
630
688
  // console.log(`token does not have permission`)
631
- // return Promise.reject(`token does not have permission`)
689
+ // return Promise.reject('errTokenNoPermission')
632
690
  // }
633
691
 
634
692
  // //getAPIsList
@@ -666,7 +724,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
666
724
  // console.log('token', token)
667
725
  // console.log('[API]updateAPIs/check token: invalid token')
668
726
  // console.log(`token does not have permission`)
669
- // return Promise.reject(`token does not have permission`)
727
+ // return Promise.reject('errTokenNoPermission')
670
728
  // }
671
729
 
672
730
  // //getAndVerifyClientUser
@@ -677,7 +735,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
677
735
  // console.log('token', token)
678
736
  // console.log('[API]updateAPIs/check user: invalid user')
679
737
  // console.log(`token does not have permission`)
680
- // return Promise.reject(`token does not have permission`)
738
+ // return Promise.reject('errTokenNoPermission')
681
739
  // }
682
740
 
683
741
  // //parsePayload
@@ -718,7 +776,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
718
776
  console.log('token', token)
719
777
  console.log('[API]syncAndReplaceTabs/check token: invalid token')
720
778
  console.log(`token does not have permission`)
721
- return Promise.reject(`token does not have permission`)
779
+ return Promise.reject('errTokenNoPermission')
722
780
  }
723
781
 
724
782
  //keyTable
@@ -730,14 +788,14 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
730
788
  console.log('keyTable', keyTable)
731
789
  console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
732
790
  console.log(`token does not have permission`)
733
- return Promise.reject(`token does not have permission`)
791
+ return Promise.reject('errTokenNoPermission')
734
792
  }
735
793
 
736
794
  //check keyTable
737
795
  let allowedTables = ['apis']
738
796
  if (!allowedTables.includes(keyTable)) {
739
797
  console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
740
- return Promise.reject(`invalid keyTable: ${keyTable}`)
798
+ return Promise.reject('errKeyTableInvalid')
741
799
  }
742
800
 
743
801
  //getAndVerifyAppUser
@@ -748,7 +806,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
748
806
  console.log('token', token)
749
807
  console.log('[API]syncAndReplaceTabs/check user: invalid user')
750
808
  console.log(`token does not have permission`)
751
- return Promise.reject(`token does not have permission`)
809
+ return Promise.reject('errTokenNoPermission')
752
810
  }
753
811
 
754
812
  //userId
@@ -760,7 +818,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
760
818
  console.log('user', user)
761
819
  console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
762
820
  console.log(`token does not have permission`)
763
- return Promise.reject(`token does not have permission`)
821
+ return Promise.reject('errTokenNoPermission')
764
822
  }
765
823
 
766
824
  //parsePayload
@@ -769,6 +827,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
769
827
  //syncAndReplaceTabs
770
828
  let r = await syncAndReplaceTabs(userId, inp, keyTable)
771
829
 
830
+ srLog.info({ event: 'api/syncAndReplaceTabs', userId, keyTable })
772
831
  return r
773
832
  }
774
833
 
@@ -820,19 +879,17 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
820
879
  let b = await p.checkToken(token)
821
880
  // console.log('b', b)
822
881
 
882
+ srLog.info({ event: 'verifyConn', apiType }) //連線驗證通過(checkToken 失敗時會 throw 不到此)
823
883
  return b
824
884
  },
825
885
  getUserIdByToken: async (token) => { //可使用async或sync函數
826
886
  // console.log('getUserIdByToken', token)
827
- return ''
828
- // let user = await getUserByToken(token) //api儲存時須使用
829
- // let userId = get(user, 'id', '')
830
- // if (!isestr(userId)) {
831
- // console.log('token', token)
832
- // console.log('userId', userId)
833
- // return Promise.reject(`can not find user.id`)
834
- // }
835
- // return userId
887
+ if (!isestr(token)) {
888
+ return ''
889
+ }
890
+ let user = await getUserByToken(token)
891
+ let userId = get(user, 'id', '')
892
+ return userId
836
893
  },
837
894
  useDbOrm: true,
838
895
  kpOrm: woItems,
@@ -840,9 +897,29 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
840
897
  tableNamesExec,
841
898
  methodsExec: ['select', 'insert', 'save', 'del'], //mix需於procOrm內註冊以提供
842
899
  tableNamesSync,
843
- kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數
844
-
845
- 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
+ }),
846
923
 
847
924
  // getAPIsList: (userId, query = {}) => { //待提供api管理系統界面使用
848
925
  // return getAPIsList(query)