w-web-api 1.0.52 → 1.0.55

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 (78) hide show
  1. package/README.md +1 -1
  2. package/dist/css/app.cad4a1ca.css +1 -0
  3. package/dist/index.tmp +4 -2
  4. package/dist/js/app-legacy.7687b23b.js +1 -0
  5. package/dist/js/app.7687b23b.js +1 -0
  6. package/dist/js/chunk-vendors-legacy.4c27cf51.js +15 -0
  7. package/dist/js/chunk-vendors.4c27cf51.js +15 -0
  8. package/dist/w-web-api.umd.js +2 -2
  9. package/dist/w-web-api.umd.js.map +1 -1
  10. package/docs/WWebApi.html +2 -2
  11. package/docs/index.html +1 -1
  12. package/docs/{WWebApi.mjs.html → server_WWebApi.mjs.html} +113 -66
  13. package/docs/src_components_Common_CheckYesNo.vue.html +187 -0
  14. package/g.getSettings.mjs +3 -0
  15. package/logs/2026-06-19T16.log +6 -0
  16. package/logs/2026-06-20T11.log +4 -0
  17. package/logs/2026-06-20T14.log +2 -0
  18. package/logs/2026-06-21T20.log +1 -0
  19. package/logs/2026-06-21T21.log +4 -0
  20. package/logs/2026-06-22T07.log +12 -0
  21. package/logs/2026-06-22T08.log +808 -0
  22. package/logs/2026-06-22T09.log +104 -0
  23. package/logs/2026-06-22T10.log +26 -0
  24. package/logs/2026-06-22T11.log +860 -0
  25. package/logs/2026-06-22T12.log +430 -0
  26. package/logs/2026-06-22T23.log +1547 -0
  27. package/logs/2026-06-23T00.log +473 -0
  28. package/logs/2026-06-23T08.log +231 -0
  29. package/logs/2026-06-23T09.log +179 -0
  30. package/logs/2026-07-01T11.log +488 -0
  31. package/logs/2026-07-09T22.log +370 -0
  32. package/logs/2026-07-09T23.log +370 -0
  33. package/logs/2026-07-10T12.log +284 -0
  34. package/logs/2026-07-10T13.log +777 -0
  35. package/logs/2026-07-11T17.log +2 -0
  36. package/package.json +20 -15
  37. package/public/index.html +9 -2
  38. package/server/WWebApi.mjs +110 -63
  39. package/server/procApis.mjs +62 -0
  40. package/server/procLang.mjs +372 -66
  41. package/server/procProxy.mjs +120 -0
  42. package/server/srLog.mjs +30 -0
  43. package/server/staLogs/filterVpfsByWindow.mjs +27 -0
  44. package/server/staLogs/staEvent.mjs +131 -0
  45. package/server/staLogs/test_staEvent.mjs +198 -0
  46. package/settings.json +18 -0
  47. package/src/App.vue +11 -7
  48. package/src/assets/scalar-ui.css +113 -0
  49. package/src/components/Common/CheckYes.vue +102 -0
  50. package/src/components/Common/CheckYesNo.vue +115 -0
  51. package/src/components/Common/LoadingWinBar.vue +114 -0
  52. package/src/components/Layout.vue +8 -26
  53. package/src/components/LayoutContent.vue +299 -350
  54. package/src/components/LayoutContentEdit.vue +577 -0
  55. package/src/components/LayoutContentStats.vue +485 -0
  56. package/src/components/LayoutContentTest.vue +781 -0
  57. package/src/components/MdPanel.vue +80 -58
  58. package/src/main.js +11 -8
  59. package/src/plugins/mUI.mjs +19 -39
  60. package/src/schema/tables/apis.mjs +30 -0
  61. package/src/store/mutations.mjs +0 -14
  62. package/src/store/types.mjs +0 -3
  63. package/srv.mjs +50 -20
  64. package/tableTags.json +1 -1
  65. package/z/344/277/256/346/255/243/350/246/217/345/212/203/346/233/270.md +246 -0
  66. package/.github/workflows/ci-test.yml +0 -24
  67. package/.vscode/launch.json +0 -18
  68. package/db/wapis/apis/data.mdb +0 -0
  69. package/db/wapis/apis/lock.mdb +0 -0
  70. package/dist/css/app.b5cf2ef5.css +0 -1
  71. package/dist/js/app-legacy.927b5679.js +0 -1
  72. package/dist/js/app.927b5679.js +0 -1
  73. package/dist/js/chunk-vendors-legacy.ffb0c6c5.js +0 -13
  74. package/dist/js/chunk-vendors.ffb0c6c5.js +0 -13
  75. package/src/plugins/mDataSelectorSchema.mjs +0 -30
  76. package/src/plugins/mShare.mjs +0 -44
  77. package/tableTags-web-api.json +0 -1
  78. package/test/all.test.mjs +0 -10
package/docs/WWebApi.html CHANGED
@@ -80,7 +80,7 @@
80
80
 
81
81
  <dt class="tag-source">Source:</dt>
82
82
  <dd class="tag-source"><ul class="dummy"><li>
83
- <a href="WWebApi.mjs.html">WWebApi.mjs</a>, <a href="WWebApi.mjs.html#line132">line 132</a>
83
+ <a href="server_WWebApi.mjs.html">server/WWebApi.mjs</a>, <a href="server_WWebApi.mjs.html#line136">line 136</a>
84
84
  </li></ul></dd>
85
85
 
86
86
 
@@ -885,7 +885,7 @@
885
885
  <br class="clear">
886
886
 
887
887
  <footer>
888
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Sat Mar 28 2026 23:43:26 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
888
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
889
889
  </footer>
890
890
 
891
891
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Sat Mar 28 2026 23:43:26 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
 
5
5
  <meta charset="utf-8">
6
- <title>WWebApi.mjs - Documentation</title>
6
+ <title>server/WWebApi.mjs - Documentation</title>
7
7
 
8
8
 
9
9
  <script src="scripts/prettify/prettify.js"></script>
@@ -35,7 +35,7 @@
35
35
 
36
36
  <div id="main">
37
37
 
38
- <h1 class="page-title">WWebApi.mjs</h1>
38
+ <h1 class="page-title">server/WWebApi.mjs</h1>
39
39
 
40
40
 
41
41
 
@@ -73,6 +73,10 @@ import replace from 'wsemi/src/replace.mjs'
73
73
  import WServHapiServer from 'w-serv-hapi/src/WServHapiServer.mjs'
74
74
  import WServOrm from 'w-serv-orm/src/WServOrm.mjs'
75
75
  import procLang from './procLang.mjs'
76
+ import procProxy from './procProxy.mjs'
77
+ import procApis from './procApis.mjs'
78
+ import staEvent from './staLogs/staEvent.mjs'
79
+ import srLogInit from './srLog.mjs'
76
80
  import ds from '../src/schema/index.mjs'
77
81
 
78
82
 
@@ -273,6 +277,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
273
277
  //params
274
278
  let showLanguage = get(opt, 'showLanguage', 'y')
275
279
  let language = get(opt, 'language', 'eng')
280
+ let logFd = get(opt, 'logFd', './logs') //srLog 寫入 + staEvent 統計共用之 log 資料夾
276
281
 
277
282
 
278
283
  //kpLangExt
@@ -294,11 +299,45 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
294
299
  wp = WServOrm(ds, WOrm, url, db, optWServOrm)
295
300
  }
296
301
  catch (err) {
297
- console.log(err)
302
+ //ORM 為必要依賴:初始化失敗即 fail-fast,不以 wp={} 帶 undefined woItems/procOrm 殘缺啟動(與建構子其餘必要依賴一致)
303
+ console.log('WServOrm init failed', err)
304
+ throw err
298
305
  }
299
306
  let { woItems, procOrm } = wp
300
307
 
301
308
 
309
+ //srLog(後端 log;錯誤一律 log err-key 供識別,對齊 w-web-sso)
310
+ let srLog = srLogInit(opt)
311
+
312
+ //maskTok:debug console.log 不印完整 token/authorization(憑證),僅前 4 碼 + ***,避免憑證落入 stdout
313
+ let maskTok = (t) => isestr(t) ? (strleft(t, 4) + '***') : t
314
+
315
+ //kpFunExt 邊界統一處理:成功記 info(供 staEvent 統計呼叫頻率);catch 後端錯誤 → srLog 該 err-key →
316
+ //原樣 re-reject(前端依 key 查自己 lang 顯示)。event 統一加 'kpfun-' 前綴 → 專用事件、與 api/verifyConn 區分。
317
+ let wrapErrLog = (event, fn) => {
318
+ let ev = 'kpfun-' + event
319
+ return async (...args) => {
320
+ try {
321
+ let result = await fn(...args)
322
+ srLog.info({ event: ev }) //成功也記 info
323
+ return result
324
+ }
325
+ catch (err) {
326
+ srLog.error({ event: ev, err })
327
+ return Promise.reject(err)
328
+ }
329
+ }
330
+ }
331
+
332
+
333
+ //procProxy
334
+ let { proxyRequest } = procProxy({ srLog })
335
+
336
+
337
+ //procApis
338
+ let { getApisList, saveApi, deleteApi } = procApis({ woItems, procOrm, ds })
339
+
340
+
302
341
  //getWebInfor
303
342
  let getWebInfor = (userId) => {
304
343
  return {
@@ -321,26 +360,26 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
321
360
  if (!isestr(id)) {
322
361
  console.log('user', user)
323
362
  console.log('can not get the userId')
324
- return Promise.reject(`can not get the userId`)
363
+ return Promise.reject('errUserIdMissing')
325
364
  }
326
365
  let email = get(user, 'email', '')
327
366
  if (!isestr(email)) {
328
367
  console.log('user', user)
329
368
  console.log('can not get the email of user')
330
- return Promise.reject(`can not get the email of user`)
369
+ return Promise.reject('errUserEmailMissing')
331
370
  }
332
371
  let name = get(user, 'name', '')
333
372
  if (!isestr(name)) {
334
373
  console.log('user', user)
335
374
  console.log('can not get userName')
336
- return Promise.reject(`can not get userName`)
375
+ return Promise.reject('errUserNameMissing')
337
376
  }
338
377
  let isAdmin = get(user, 'isAdmin', '')
339
378
  if (isAdmin !== 'y' &amp;&amp; isAdmin !== 'n') {
340
379
  console.log('user', user)
341
380
  console.log('user.isAdmin is not y or n', user.isAdmin)
342
381
  console.log('can not get the role of user')
343
- return Promise.reject(`can not get the role of user`)
382
+ return Promise.reject('errUserRoleMissing')
344
383
  }
345
384
  return true
346
385
  }
@@ -356,14 +395,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
356
395
  }
357
396
 
358
397
  //check
359
- if (true) {
360
- // if (!iseobj(userSelf)) {
361
- // console.log(`token`, token)
362
- // console.log(`can not find the user from token`)
363
- // return Promise.reject(`can not find the user from token`)
364
- // }
365
- await checkUser(userSelf)
366
- }
398
+ await checkUser(userSelf)
367
399
 
368
400
  return userSelf
369
401
  }
@@ -402,9 +434,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
402
434
  if (!b) {
403
435
  console.log('user', user)
404
436
  console.log(`user does not have permission`)
405
- return Promise.reject(`user does not have permission`)
437
+ return Promise.reject('errUserNoPermission')
406
438
  }
407
439
 
440
+ srLog.info({ event: 'verifyClientUser', from, userId: get(user, 'id', '') }) //瀏覽使用者驗證通過
408
441
  return user
409
442
  }
410
443
 
@@ -427,7 +460,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
427
460
  if (!iseobj(user)) {
428
461
  console.log(`token`, token)
429
462
  console.log(`can not find the user from token`)
430
- return Promise.reject(`can not find the user from token`)
463
+ return Promise.reject('errUserNotFound')
431
464
  }
432
465
 
433
466
  //verifyAppUser
@@ -440,9 +473,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
440
473
  if (!b) {
441
474
  console.log('user', user)
442
475
  console.log(`user does not have permission`)
443
- return Promise.reject(`user does not have permission`)
476
+ return Promise.reject('errUserNoPermission')
444
477
  }
445
478
 
479
+ srLog.info({ event: 'verifyAppUser', from, userId: get(user, 'id', '') }) //應用程式使用者驗證通過
446
480
  return user
447
481
  }
448
482
 
@@ -469,7 +503,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
469
503
  if (!iseobj(payload)) {
470
504
  console.log('payload', payload)
471
505
  console.log(`invalid payload in req`)
472
- return Promise.reject(`invalid payload in req`)
506
+ return Promise.reject('errPayloadInvalid')
473
507
  }
474
508
 
475
509
  //group
@@ -479,7 +513,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
479
513
  if (!isestr(group)) {
480
514
  console.log('payload', payload)
481
515
  console.log(`invalid group in payload`)
482
- return Promise.reject(`invalid group in payload`)
516
+ return Promise.reject('errGroupInvalid')
483
517
  }
484
518
 
485
519
  //rows
@@ -489,7 +523,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
489
523
  if (!isearr(rows)) {
490
524
  console.log('payload', payload)
491
525
  console.log(`invalid rows in payload`)
492
- return Promise.reject(`invalid rows in payload`)
526
+ return Promise.reject('errRowsInvalid')
493
527
  }
494
528
 
495
529
  //r
@@ -529,7 +563,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
529
563
  console.log('inp', inp)
530
564
  console.log('group', group)
531
565
  console.log(`invalid group`)
532
- return Promise.reject(`invalid group`)
566
+ return Promise.reject('errGroupInvalid')
533
567
  }
534
568
 
535
569
  //rows
@@ -540,7 +574,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
540
574
  if (!isearr(rows)) {
541
575
  console.log('inp', inp)
542
576
  console.log('keyTable', keyTable)
543
- return Promise.reject(`invalid rows`)
577
+ return Promise.reject('errRowsInvalid')
544
578
  }
545
579
 
546
580
  //save from
@@ -611,6 +645,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
611
645
  c = replace(c, '/mapi/', '{sfd}/') //方法同genEntry
612
646
  c = replace(c, '{sfd}', subfolder)
613
647
  c = replace(c, '{urlRedirect}', urlRedirect)
648
+ c = replace(c, '{language}', language) //注入初始語系 → window.___pmwperm___.language(前端 getLang 之來源之一)
614
649
  fs.writeFileSync(fpEntryOut, c, 'utf8')
615
650
  }
616
651
  catch (err) {
@@ -636,10 +671,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
636
671
  //check
637
672
  if (!isestr(token)) {
638
673
  console.log('req.query', get(req, 'query'))
639
- console.log('token', token)
674
+ console.log('token', maskTok(token))
640
675
  console.log('[API]getUserByToken/check token: invalid token')
641
- console.log(`token does not have permission`)
642
- return Promise.reject(`token does not have permission`)
676
+ return Promise.reject('errTokenNoPermission')
643
677
  }
644
678
 
645
679
  //getAndVerifyClientUser
@@ -647,12 +681,12 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
647
681
 
648
682
  //check
649
683
  if (!iseobj(user)) {
650
- console.log('token', token)
684
+ console.log('token', maskTok(token))
651
685
  console.log('[API]getUserByToken/check user: invalid user')
652
- console.log(`token does not have permission`)
653
- return Promise.reject(`token does not have permission`)
686
+ return Promise.reject('errTokenNoPermission')
654
687
  }
655
688
 
689
+ srLog.info({ event: 'api/getUserByToken', userId: get(user, 'id', '') })
656
690
  return user
657
691
  }
658
692
 
@@ -683,8 +717,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
683
717
  // console.log('req.query', get(req, 'query'))
684
718
  // console.log('token', token)
685
719
  // console.log('[API]getAPIsList/check token: invalid token')
686
- // console.log(`token does not have permission`)
687
- // return Promise.reject(`token does not have permission`)
720
+ // return Promise.reject('errTokenNoPermission')
688
721
  // }
689
722
 
690
723
  // //getAndVerifyClientUser
@@ -694,8 +727,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
694
727
  // if (!iseobj(user)) {
695
728
  // console.log('token', token)
696
729
  // console.log('[API]getAPIsList/check user: invalid user')
697
- // console.log(`token does not have permission`)
698
- // return Promise.reject(`token does not have permission`)
730
+ // return Promise.reject('errTokenNoPermission')
699
731
  // }
700
732
 
701
733
  // //getAPIsList
@@ -732,8 +764,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
732
764
  // console.log('req.query', get(req, 'query'))
733
765
  // console.log('token', token)
734
766
  // console.log('[API]updateAPIs/check token: invalid token')
735
- // console.log(`token does not have permission`)
736
- // return Promise.reject(`token does not have permission`)
767
+ // return Promise.reject('errTokenNoPermission')
737
768
  // }
738
769
 
739
770
  // //getAndVerifyClientUser
@@ -743,8 +774,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
743
774
  // if (!iseobj(user)) {
744
775
  // console.log('token', token)
745
776
  // console.log('[API]updateAPIs/check user: invalid user')
746
- // console.log(`token does not have permission`)
747
- // return Promise.reject(`token does not have permission`)
777
+ // return Promise.reject('errTokenNoPermission')
748
778
  // }
749
779
 
750
780
  // //parsePayload
@@ -782,10 +812,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
782
812
  //check
783
813
  if (!isestr(token)) {
784
814
  console.log('req.query', get(req, 'query'))
785
- console.log('token', token)
815
+ console.log('token', maskTok(token))
786
816
  console.log('[API]syncAndReplaceTabs/check token: invalid token')
787
- console.log(`token does not have permission`)
788
- return Promise.reject(`token does not have permission`)
817
+ return Promise.reject('errTokenNoPermission')
789
818
  }
790
819
 
791
820
  //keyTable
@@ -796,15 +825,14 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
796
825
  console.log('req.query', get(req, 'query'))
797
826
  console.log('keyTable', keyTable)
798
827
  console.log('[API]syncAndReplaceTabs/check keyTable: invalid keyTable')
799
- console.log(`token does not have permission`)
800
- return Promise.reject(`token does not have permission`)
828
+ return Promise.reject('errKeyTableInvalid')
801
829
  }
802
830
 
803
831
  //check keyTable
804
832
  let allowedTables = ['apis']
805
833
  if (!allowedTables.includes(keyTable)) {
806
834
  console.log('[API]syncAndReplaceTabs/check keyTable: unexpected keyTable', keyTable)
807
- return Promise.reject(`invalid keyTable: ${keyTable}`)
835
+ return Promise.reject('errKeyTableInvalid')
808
836
  }
809
837
 
810
838
  //getAndVerifyAppUser
@@ -812,10 +840,9 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
812
840
 
813
841
  //check
814
842
  if (!iseobj(user)) {
815
- console.log('token', token)
843
+ console.log('token', maskTok(token))
816
844
  console.log('[API]syncAndReplaceTabs/check user: invalid user')
817
- console.log(`token does not have permission`)
818
- return Promise.reject(`token does not have permission`)
845
+ return Promise.reject('errTokenNoPermission')
819
846
  }
820
847
 
821
848
  //userId
@@ -823,11 +850,10 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
823
850
 
824
851
  //check userId
825
852
  if (!isestr(userId)) {
826
- console.log('token', token)
853
+ console.log('token', maskTok(token))
827
854
  console.log('user', user)
828
855
  console.log('[API]syncAndReplaceTabs/check userId: invalid userId')
829
- console.log(`token does not have permission`)
830
- return Promise.reject(`token does not have permission`)
856
+ return Promise.reject('errTokenNoPermission')
831
857
  }
832
858
 
833
859
  //parsePayload
@@ -836,6 +862,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
836
862
  //syncAndReplaceTabs
837
863
  let r = await syncAndReplaceTabs(userId, inp, keyTable)
838
864
 
865
+ srLog.info({ event: 'api/syncAndReplaceTabs', userId, keyTable })
839
866
  return r
840
867
  }
841
868
 
@@ -863,7 +890,7 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
863
890
 
864
891
  //WServHapiServer
865
892
  instWServHapiServer = new WServHapiServer({
866
- port: opt.serverPort,
893
+ port: serverPort,
867
894
  pathStaticFiles,
868
895
  apiName: 'api',
869
896
  apis,
@@ -878,28 +905,28 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
878
905
  //check
879
906
  if (!isestr(token)) {
880
907
  console.log('apiType', apiType)
881
- console.log('authorization', authorization)
908
+ console.log('authorization', maskTok(authorization))
882
909
  console.log('invalid token')
883
910
  return false
884
911
  }
885
912
 
886
- //checkToken
913
+ //checkToken:套件層連線閘僅做「token 認證」(解析 user + 驗欄位齊備)。**授權**(如限管理員)屬
914
+ //套件使用者之責——由其提供之 getUserByToken(可對非授權者回 {})/ verifyClientUser / verifyAppUser,
915
+ //或 WServOrm 之 useCheckUser/useExcludeWhenNotAdmin 等鉤子決定;套件不對連線層強加特定授權政策(避免越界、
916
+ //保留使用者彈性)。詳見 spec/設計要點與取捨.md「套件授權責任」。
887
917
  let b = await p.checkToken(token)
888
- // console.log('b', b)
889
918
 
919
+ srLog.info({ event: 'verifyConn', apiType }) //連線之 token 認證通過(checkToken 失敗會 throw 不到此)
890
920
  return b
891
921
  },
892
922
  getUserIdByToken: async (token) => { //可使用async或sync函數
893
923
  // console.log('getUserIdByToken', token)
894
- return ''
895
- // let user = await getUserByToken(token) //api儲存時須使用
896
- // let userId = get(user, 'id', '')
897
- // if (!isestr(userId)) {
898
- // console.log('token', token)
899
- // console.log('userId', userId)
900
- // return Promise.reject(`can not find user.id`)
901
- // }
902
- // return userId
924
+ if (!isestr(token)) {
925
+ return ''
926
+ }
927
+ let user = await getUserByToken(token)
928
+ let userId = get(user, 'id', '')
929
+ return userId
903
930
  },
904
931
  useDbOrm: true,
905
932
  kpOrm: woItems,
@@ -907,9 +934,29 @@ function WWebApi(WOrm, url, db, getUserByToken, verifyClientUser, verifyAppUser,
907
934
  tableNamesExec,
908
935
  methodsExec: ['select', 'insert', 'save', 'del'], //mix需於procOrm內註冊以提供
909
936
  tableNamesSync,
910
- kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數
911
-
912
- getWebInfor,
937
+ kpFunExt: { //接收參數第1個為userId, 之後才是前端給予參數(皆經 wrapErrLog:錯誤 srLog err-key 後 re-reject)
938
+
939
+ getWebInfor: wrapErrLog('getWebInfor', getWebInfor),
940
+
941
+ proxyRequest: wrapErrLog('proxyRequest', (userId, reqSpec) => {
942
+ return proxyRequest(reqSpec)
943
+ }),
944
+
945
+ getApisList: wrapErrLog('getApisList', (userId) => {
946
+ return getApisList(userId)
947
+ }),
948
+ saveApi: wrapErrLog('saveApi', (userId, row) => {
949
+ return saveApi(userId, row)
950
+ }),
951
+ deleteApi: wrapErrLog('deleteApi', (userId, id) => {
952
+ return deleteApi(userId, id)
953
+ }),
954
+
955
+ //統計資訊頁:回傳各 event 之時段發生頻率(讀 logFd 之 log)。連線之 token 認證由 verifyConn 把關;
956
+ //授權(限管理員)屬套件使用者責任(見 verifyConn 註解與設計要點與取捨「套件授權責任」)。timeLength 天數 / timeInterval 'hr'|'day'。
957
+ getStaEvent: wrapErrLog('getStaEvent', (userId, timeLength = 7, timeInterval = 'hr') => {
958
+ return staEvent(timeLength, timeInterval, { fdLog: logFd })
959
+ }),
913
960
 
914
961
  // getAPIsList: (userId, query = {}) => { //待提供api管理系統界面使用
915
962
  // return getAPIsList(query)
@@ -942,7 +989,7 @@ export default WWebApi
942
989
  <br class="clear">
943
990
 
944
991
  <footer>
945
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Sat Mar 28 2026 23:43:26 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
992
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Thu Jul 23 2026 11:15:32 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
946
993
  </footer>
947
994
 
948
995
  <script>prettyPrint();</script>
@@ -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 Thu Jul 23 2026 11:15:32 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
 
@@ -0,0 +1,6 @@
1
+ {"level":50,"time":1781856410899,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
2
+ {"level":50,"time":1781856420503,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
3
+ {"level":50,"time":1781856490388,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
4
+ {"level":50,"time":1781856524374,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
5
+ {"level":50,"time":1781856931047,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}
6
+ {"level":50,"time":1781856965662,"pid":16564,"hostname":"semi-win-dev3","event":"proxyRequest","err":"errReqUrlInvalid"}