w-web-perm 1.1.11 → 1.1.13

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 (122) hide show
  1. package/README.md +158 -117
  2. package/dist/css/app.f09c7433.css +1 -0
  3. package/dist/index.tmp +1 -1
  4. package/dist/js/app-legacy.8af87052.js +1 -0
  5. package/dist/js/app.8af87052.js +1 -0
  6. package/dist/js/{chunk-vendors.3e9e3ef1.js → chunk-vendors-legacy.ece5a361.js} +1 -1
  7. package/dist/js/{chunk-vendors-legacy.3e9e3ef1.js → chunk-vendors.ece5a361.js} +1 -1
  8. package/dist/w-web-perm.umd.js +2 -2
  9. package/dist/w-web-perm.umd.js.map +1 -1
  10. package/docs/WWebPerm.html +84 -4
  11. package/docs/global.html +24747 -832
  12. package/docs/index.html +2 -2
  13. package/docs/server_WWebPerm.mjs.html +245 -32
  14. package/docs/server_cascadeWrite.mjs.html +225 -0
  15. package/docs/server_dataChannel.mjs.html +2 -2
  16. package/docs/server_keyCheck.mjs.html +353 -0
  17. package/docs/server_lockSave.mjs.html +2 -2
  18. package/docs/server_maskLog.mjs.html +2 -2
  19. package/docs/server_procCore.mjs.html +180 -41
  20. package/docs/server_staLogs_resolveShellWorker.mjs.html +2 -2
  21. package/docs/server_syncKeep.mjs.html +311 -0
  22. package/docs/server_tools_authRefsAudit.mjs.html +247 -0
  23. package/docs/server_tools_authRefsClean.mjs.html +335 -0
  24. package/docs/server_tools_fromTools.mjs.html +797 -0
  25. package/docs/server_tools_isMain.mjs.html +103 -0
  26. package/docs/server_tools_nameDupReport.mjs.html +280 -0
  27. package/docs/server_validateRows.mjs.html +15 -4
  28. package/docs/server_wrapInjected.mjs.html +3 -3
  29. package/docs/src_fetchJson.mjs.html +2 -2
  30. package/docs/src_js_cvKpToArr.mjs.html +125 -0
  31. package/docs/src_js_cvKpToObj.mjs.html +210 -0
  32. package/docs/src_js_draftSync.mjs.html +142 -0
  33. package/docs/src_js_eachOwn.mjs.html +3 -3
  34. package/docs/src_js_editorRefRows.mjs.html +356 -0
  35. package/docs/src_js_externalRows.mjs.html +338 -0
  36. package/docs/src_js_externalUi.mjs.html +230 -0
  37. package/docs/src_js_findRefRows.mjs.html +107 -0
  38. package/docs/src_js_findTouchedDup.mjs.html +150 -0
  39. package/docs/src_js_fmtLossyMsg.mjs.html +95 -0
  40. package/docs/src_js_fromAudit.mjs.html +489 -0
  41. package/docs/src_js_getAddImpact.mjs.html +269 -0
  42. package/docs/src_js_getAuthWarn.mjs.html +463 -0
  43. package/docs/src_js_getCascadePreview.mjs.html +258 -0
  44. package/docs/src_js_getDelRefCount.mjs.html +210 -0
  45. package/docs/src_js_getEffMode.mjs.html +92 -0
  46. package/docs/src_js_getKpLossy.mjs.html +155 -0
  47. package/docs/src_js_getNameErrs.mjs.html +266 -0
  48. package/docs/src_js_getOwn.mjs.html +3 -3
  49. package/docs/src_js_getPropKey.mjs.html +109 -0
  50. package/docs/src_js_getRuleEnable.mjs.html +2 -2
  51. package/docs/src_js_isAuthMode.mjs.html +92 -0
  52. package/docs/src_js_joinNames.mjs.html +96 -0
  53. package/docs/src_js_legendFit.mjs.html +2 -2
  54. package/docs/src_js_pairRowsToSnapshot.mjs.html +156 -0
  55. package/docs/src_js_refAudit.mjs.html +359 -0
  56. package/docs/src_js_refCascade.mjs.html +572 -0
  57. package/docs/src_js_relDialogSend.mjs.html +199 -0
  58. package/docs/src_js_rowDigest.mjs.html +265 -0
  59. package/docs/src_plugins_dataReloadGuard.mjs.html +109 -0
  60. package/docs/src_plugins_reuseDeletedIds.mjs.html +2 -2
  61. package/docs/src_plugins_submitGuard.mjs.html +2 -2
  62. package/g_authRefsClean.mjs +79 -0
  63. package/g_fixFromType.mjs +92 -0
  64. package/g_initialData.mjs +3 -3
  65. package/g_purgeFrom.mjs +127 -0
  66. package/package.json +1 -1
  67. package/server/WWebPerm.mjs +243 -30
  68. package/server/cascadeWrite.mjs +153 -0
  69. package/server/keyCheck.mjs +281 -0
  70. package/server/procCore.mjs +178 -39
  71. package/server/procLang.mjs +271 -0
  72. package/server/syncKeep.mjs +239 -0
  73. package/server/tools/authRefsAudit.mjs +175 -0
  74. package/server/tools/authRefsClean.mjs +263 -0
  75. package/server/tools/fromTools.mjs +725 -0
  76. package/server/tools/isMain.mjs +31 -0
  77. package/server/tools/nameDupReport.mjs +208 -0
  78. package/server/validateRows.mjs +13 -2
  79. package/server/wrapInjected.mjs +1 -1
  80. package/src/components/LayoutContentGrups.vue +399 -77
  81. package/src/components/LayoutContentPemis.vue +400 -78
  82. package/src/components/LayoutContentTargets.vue +261 -25
  83. package/src/components/LayoutContentUsers.vue +336 -98
  84. package/src/components/VeCgrups.vue +119 -115
  85. package/src/components/VeCpemis.vue +117 -115
  86. package/src/components/VeCrules.vue +18 -2
  87. package/src/components/VeGrupBlngUsers.vue +240 -73
  88. package/src/components/VePemiBlngGrups.vue +247 -83
  89. package/src/js/cvKpToArr.mjs +53 -0
  90. package/src/js/cvKpToObj.mjs +138 -0
  91. package/src/js/draftSync.mjs +70 -0
  92. package/src/js/eachOwn.mjs +1 -1
  93. package/src/js/editorRefRows.mjs +284 -0
  94. package/src/js/externalRows.mjs +266 -0
  95. package/src/js/externalUi.mjs +158 -0
  96. package/src/js/findRefRows.mjs +35 -0
  97. package/src/js/findTouchedDup.mjs +78 -0
  98. package/src/js/fmtLossyMsg.mjs +23 -0
  99. package/src/js/fromAudit.mjs +417 -0
  100. package/src/js/getAddImpact.mjs +197 -0
  101. package/src/js/getAuthWarn.mjs +391 -0
  102. package/src/js/getCascadePreview.mjs +186 -0
  103. package/src/js/getDelRefCount.mjs +138 -0
  104. package/src/js/getEffMode.mjs +20 -0
  105. package/src/js/getKpLossy.mjs +83 -0
  106. package/src/js/getNameErrs.mjs +194 -0
  107. package/src/js/getOwn.mjs +1 -1
  108. package/src/js/getPropKey.mjs +37 -0
  109. package/src/js/isAuthMode.mjs +20 -0
  110. package/src/js/joinNames.mjs +24 -0
  111. package/src/js/pairRowsToSnapshot.mjs +84 -0
  112. package/src/js/refAudit.mjs +287 -0
  113. package/src/js/refCascade.mjs +500 -0
  114. package/src/js/relDialogSend.mjs +127 -0
  115. package/src/js/rowDigest.mjs +193 -0
  116. package/src/plugins/dataReloadGuard.mjs +37 -0
  117. package/src/plugins/mShare.mjs +147 -174
  118. package/src/plugins/mUI.mjs +3 -8
  119. package/src/schema/tables/users.mjs +152 -152
  120. package/dist/css/app.6918ec45.css +0 -1
  121. package/dist/js/app-legacy.963e800c.js +0 -1
  122. package/dist/js/app.963e800c.js +0 -1
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebPerm.html">WWebPerm</a></li></ul><h3>Global</h3><ul><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLegendMeasurer">createLegendMeasurer</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#decideLegendType">decideLegendType</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#eachOwn">eachOwn</a></li><li><a href="global.html#fetchJson">fetchJson</a></li><li><a href="global.html#genLegend">genLegend</a></li><li><a href="global.html#getOwn">getOwn</a></li><li><a href="global.html#getRuleEnable">getRuleEnable</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#mergePickKeysOnly">mergePickKeysOnly</a></li><li><a href="global.html#resolveShellWorker">resolveShellWorker</a></li><li><a href="global.html#reuseDeletedIds">reuseDeletedIds</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#validateRowsBeforeWrite">validateRowsBeforeWrite</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li><li><a href="global.html#wrapOperOrm">wrapOperOrm</a></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WWebPerm.html">WWebPerm</a></li></ul><h3>Global</h3><ul><li><a href="global.html#applyPurgePlan">applyPurgePlan</a></li><li><a href="global.html#auditFrom">auditFrom</a></li><li><a href="global.html#auditRefs">auditRefs</a></li><li><a href="global.html#buildReport">buildReport</a></li><li><a href="global.html#buildRowsSend">buildRowsSend</a></li><li><a href="global.html#buildSyncRowsNew">buildSyncRowsNew</a></li><li><a href="global.html#checkBaseline">checkBaseline</a></li><li><a href="global.html#checkCascadePlan">checkCascadePlan</a></li><li><a href="global.html#checkDbNotInUse">checkDbNotInUse</a></li><li><a href="global.html#checkExternalWrite">checkExternalWrite</a></li><li><a href="global.html#checkMapKeyBatch">checkMapKeyBatch</a></li><li><a href="global.html#checkUsersWrite">checkUsersWrite</a></li><li><a href="global.html#cleanOutOf">cleanOutOf</a></li><li><a href="global.html#compareBaseline">compareBaseline</a></li><li><a href="global.html#countAndRefs">countAndRefs</a></li><li><a href="global.html#countExternalRows">countExternalRows</a></li><li><a href="global.html#countIdRenumber">countIdRenumber</a></li><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLegendMeasurer">createLegendMeasurer</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#cvKpToArr">cvKpToArr</a></li><li><a href="global.html#cvKpToObj">cvKpToObj</a></li><li><a href="global.html#decideLegendType">decideLegendType</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#diffRefTargets">diffRefTargets</a></li><li><a href="global.html#dropServerOnlyDiff">dropServerOnlyDiff</a></li><li><a href="global.html#eachOwn">eachOwn</a></li><li><a href="global.html#fetchJson">fetchJson</a></li><li><a href="global.html#fillIdlessIds">fillIdlessIds</a></li><li><a href="global.html#findDupIndex">findDupIndex</a></li><li><a href="global.html#findKeyOtherFrom">findKeyOtherFrom</a></li><li><a href="global.html#findRefRows">findRefRows</a></li><li><a href="global.html#findTouchedDup">findTouchedDup</a></li><li><a href="global.html#fmtLossyMsg">fmtLossyMsg</a></li><li><a href="global.html#fmtVars">fmtVars</a></li><li><a href="global.html#fmtWarn">fmtWarn</a></li><li><a href="global.html#formatFixReport">formatFixReport</a></li><li><a href="global.html#formatFromAudit">formatFromAudit</a></li><li><a href="global.html#formatPurgeReport">formatPurgeReport</a></li><li><a href="global.html#genLegend">genLegend</a></li><li><a href="global.html#getAddConfirmText">getAddConfirmText</a></li><li><a href="global.html#getAddImpact">getAddImpact</a></li><li><a href="global.html#getBannerLines">getBannerLines</a></li><li><a href="global.html#getBaselineDigest">getBaselineDigest</a></li><li><a href="global.html#getCascadePreview">getCascadePreview</a></li><li><a href="global.html#getChangedIdx">getChangedIdx</a></li><li><a href="global.html#getDelConfirmText">getDelConfirmText</a></li><li><a href="global.html#getDelImpact">getDelImpact</a></li><li><a href="global.html#getDelRefCount">getDelRefCount</a></li><li><a href="global.html#getDigestFields">getDigestFields</a></li><li><a href="global.html#getDupRowsInconsistent">getDupRowsInconsistent</a></li><li><a href="global.html#getEffMode">getEffMode</a></li><li><a href="global.html#getExternalEdits">getExternalEdits</a></li><li><a href="global.html#getItemWarnText">getItemWarnText</a></li><li><a href="global.html#getKpLossy">getKpLossy</a></li><li><a href="global.html#getLockFields">getLockFields</a></li><li><a href="global.html#getNameErrs">getNameErrs</a></li><li><a href="global.html#getOwn">getOwn</a></li><li><a href="global.html#getPropKey">getPropKey</a></li><li><a href="global.html#getRawModeMap">getRawModeMap</a></li><li><a href="global.html#getRefRowsExtra">getRefRowsExtra</a></li><li><a href="global.html#getRefState">getRefState</a></li><li><a href="global.html#getRefWarnText">getRefWarnText</a></li><li><a href="global.html#getRefWarns">getRefWarns</a></li><li><a href="global.html#getRowIdxs">getRowIdxs</a></li><li><a href="global.html#getRowState">getRowState</a></li><li><a href="global.html#getRuleEnable">getRuleEnable</a></li><li><a href="global.html#getRuleWarnText">getRuleWarnText</a></li><li><a href="global.html#getRuleWarns">getRuleWarns</a></li><li><a href="global.html#getSavePreview">getSavePreview</a></li><li><a href="global.html#getSyncWarnLines">getSyncWarnLines</a></li><li><a href="global.html#hasDupKey">hasDupKey</a></li><li><a href="global.html#hasExternalDiff">hasExternalDiff</a></li><li><a href="global.html#isAuthMode">isAuthMode</a></li><li><a href="global.html#isBaselineStale">isBaselineStale</a></li><li><a href="global.html#isBaselineValid">isBaselineValid</a></li><li><a href="global.html#isDraftStale">isDraftStale</a></li><li><a href="global.html#isExternalRow">isExternalRow</a></li><li><a href="global.html#isJsonLossy">isJsonLossy</a></li><li><a href="global.html#isMain">isMain</a></li><li><a href="global.html#joinList">joinList</a></li><li><a href="global.html#joinNames">joinNames</a></li><li><a href="global.html#keepAssignByEntity">keepAssignByEntity</a></li><li><a href="global.html#keepAssignOnMissing">keepAssignOnMissing</a></li><li><a href="global.html#makeBaseline">makeBaseline</a></li><li><a href="global.html#makeRowStates">makeRowStates</a></li><li><a href="global.html#mapKeyOf">mapKeyOf</a></li><li><a href="global.html#mapNameKp">mapNameKp</a></li><li><a href="global.html#markDataReload">markDataReload</a></li><li><a href="global.html#markHasKey">markHasKey</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#mergePickKeysOnly">mergePickKeysOnly</a></li><li><a href="global.html#pairRowsToSnapshot">pairRowsToSnapshot</a></li><li><a href="global.html#pickUniqueUser">pickUniqueUser</a></li><li><a href="global.html#planDraftSync">planDraftSync</a></li><li><a href="global.html#planFixFromType">planFixFromType</a></li><li><a href="global.html#planPurgeChain">planPurgeChain</a></li><li><a href="global.html#planPurgeFrom">planPurgeFrom</a></li><li><a href="global.html#planRefChanges">planRefChanges</a></li><li><a href="global.html#putRefEntry">putRefEntry</a></li><li><a href="global.html#putRowsToKp">putRowsToKp</a></li><li><a href="global.html#refsChanged">refsChanged</a></li><li><a href="global.html#resolveShellWorker">resolveShellWorker</a></li><li><a href="global.html#restoreExternalOrder">restoreExternalOrder</a></li><li><a href="global.html#restoreServerFields">restoreServerFields</a></li><li><a href="global.html#reuseDeletedIds">reuseDeletedIds</a></li><li><a href="global.html#rewriteRefs">rewriteRefs</a></li><li><a href="global.html#rowDigest">rowDigest</a></li><li><a href="global.html#runAuditFrom">runAuditFrom</a></li><li><a href="global.html#runClean">runClean</a></li><li><a href="global.html#runFixFromType">runFixFromType</a></li><li><a href="global.html#runPurgeFrom">runPurgeFrom</a></li><li><a href="global.html#splitCheckedRows">splitCheckedRows</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#tabWriteKey">tabWriteKey</a></li><li><a href="global.html#validateRowsBeforeWrite">validateRowsBeforeWrite</a></li><li><a href="global.html#withTabLocks">withTabLocks</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li><li><a href="global.html#wrapOperOrm">wrapOperOrm</a></li><li><a href="global.html#writeWithCascade">writeWithCascade</a></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -46,7 +46,7 @@
46
46
  <section>
47
47
  <article>
48
48
  <pre class="prettyprint source linenums"><code>//迭代使用端傳入之物件: 供伺服端寫入前驗證(server/validateRows.mjs)、權限評估(src/plugins/mShare.mjs)與前端清單元件解析 cgrups/cpemis/crules 後之物件共用
49
- //規則見 CLAUDE_rulebook.md「迭代使用端傳入之物件」(R-OBJ-ITER-01)
49
+ //規則見 sgud/rule/rulebook.md「迭代使用端傳入之物件」(R-OBJ-ITER-01)
50
50
  //本檔無外部相依
51
51
 
52
52
 
@@ -106,7 +106,7 @@ export default eachOwn
106
106
  <br class="clear">
107
107
 
108
108
  <footer>
109
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Oct 20 2026 14:44:45 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
109
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Oct 23 2026 10:56:39 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
110
110
  </footer>
111
111
 
112
112
  <script>prettyPrint();</script>
@@ -0,0 +1,356 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <meta charset="utf-8">
6
+ <title>src/js/editorRefRows.mjs - 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="WWebPerm.html">WWebPerm</a></li></ul><h3>Global</h3><ul><li><a href="global.html#applyPurgePlan">applyPurgePlan</a></li><li><a href="global.html#auditFrom">auditFrom</a></li><li><a href="global.html#auditRefs">auditRefs</a></li><li><a href="global.html#buildReport">buildReport</a></li><li><a href="global.html#buildRowsSend">buildRowsSend</a></li><li><a href="global.html#buildSyncRowsNew">buildSyncRowsNew</a></li><li><a href="global.html#checkBaseline">checkBaseline</a></li><li><a href="global.html#checkCascadePlan">checkCascadePlan</a></li><li><a href="global.html#checkDbNotInUse">checkDbNotInUse</a></li><li><a href="global.html#checkExternalWrite">checkExternalWrite</a></li><li><a href="global.html#checkMapKeyBatch">checkMapKeyBatch</a></li><li><a href="global.html#checkUsersWrite">checkUsersWrite</a></li><li><a href="global.html#cleanOutOf">cleanOutOf</a></li><li><a href="global.html#compareBaseline">compareBaseline</a></li><li><a href="global.html#countAndRefs">countAndRefs</a></li><li><a href="global.html#countExternalRows">countExternalRows</a></li><li><a href="global.html#countIdRenumber">countIdRenumber</a></li><li><a href="global.html#createAuthorizeExec">createAuthorizeExec</a></li><li><a href="global.html#createLegendMeasurer">createLegendMeasurer</a></li><li><a href="global.html#createLockSave">createLockSave</a></li><li><a href="global.html#cvKpToArr">cvKpToArr</a></li><li><a href="global.html#cvKpToObj">cvKpToObj</a></li><li><a href="global.html#decideLegendType">decideLegendType</a></li><li><a href="global.html#describeUpstream">describeUpstream</a></li><li><a href="global.html#diffRefTargets">diffRefTargets</a></li><li><a href="global.html#dropServerOnlyDiff">dropServerOnlyDiff</a></li><li><a href="global.html#eachOwn">eachOwn</a></li><li><a href="global.html#fetchJson">fetchJson</a></li><li><a href="global.html#fillIdlessIds">fillIdlessIds</a></li><li><a href="global.html#findDupIndex">findDupIndex</a></li><li><a href="global.html#findKeyOtherFrom">findKeyOtherFrom</a></li><li><a href="global.html#findRefRows">findRefRows</a></li><li><a href="global.html#findTouchedDup">findTouchedDup</a></li><li><a href="global.html#fmtLossyMsg">fmtLossyMsg</a></li><li><a href="global.html#fmtVars">fmtVars</a></li><li><a href="global.html#fmtWarn">fmtWarn</a></li><li><a href="global.html#formatFixReport">formatFixReport</a></li><li><a href="global.html#formatFromAudit">formatFromAudit</a></li><li><a href="global.html#formatPurgeReport">formatPurgeReport</a></li><li><a href="global.html#genLegend">genLegend</a></li><li><a href="global.html#getAddConfirmText">getAddConfirmText</a></li><li><a href="global.html#getAddImpact">getAddImpact</a></li><li><a href="global.html#getBannerLines">getBannerLines</a></li><li><a href="global.html#getBaselineDigest">getBaselineDigest</a></li><li><a href="global.html#getCascadePreview">getCascadePreview</a></li><li><a href="global.html#getChangedIdx">getChangedIdx</a></li><li><a href="global.html#getDelConfirmText">getDelConfirmText</a></li><li><a href="global.html#getDelImpact">getDelImpact</a></li><li><a href="global.html#getDelRefCount">getDelRefCount</a></li><li><a href="global.html#getDigestFields">getDigestFields</a></li><li><a href="global.html#getDupRowsInconsistent">getDupRowsInconsistent</a></li><li><a href="global.html#getEffMode">getEffMode</a></li><li><a href="global.html#getExternalEdits">getExternalEdits</a></li><li><a href="global.html#getItemWarnText">getItemWarnText</a></li><li><a href="global.html#getKpLossy">getKpLossy</a></li><li><a href="global.html#getLockFields">getLockFields</a></li><li><a href="global.html#getNameErrs">getNameErrs</a></li><li><a href="global.html#getOwn">getOwn</a></li><li><a href="global.html#getPropKey">getPropKey</a></li><li><a href="global.html#getRawModeMap">getRawModeMap</a></li><li><a href="global.html#getRefRowsExtra">getRefRowsExtra</a></li><li><a href="global.html#getRefState">getRefState</a></li><li><a href="global.html#getRefWarnText">getRefWarnText</a></li><li><a href="global.html#getRefWarns">getRefWarns</a></li><li><a href="global.html#getRowIdxs">getRowIdxs</a></li><li><a href="global.html#getRowState">getRowState</a></li><li><a href="global.html#getRuleEnable">getRuleEnable</a></li><li><a href="global.html#getRuleWarnText">getRuleWarnText</a></li><li><a href="global.html#getRuleWarns">getRuleWarns</a></li><li><a href="global.html#getSavePreview">getSavePreview</a></li><li><a href="global.html#getSyncWarnLines">getSyncWarnLines</a></li><li><a href="global.html#hasDupKey">hasDupKey</a></li><li><a href="global.html#hasExternalDiff">hasExternalDiff</a></li><li><a href="global.html#isAuthMode">isAuthMode</a></li><li><a href="global.html#isBaselineStale">isBaselineStale</a></li><li><a href="global.html#isBaselineValid">isBaselineValid</a></li><li><a href="global.html#isDraftStale">isDraftStale</a></li><li><a href="global.html#isExternalRow">isExternalRow</a></li><li><a href="global.html#isJsonLossy">isJsonLossy</a></li><li><a href="global.html#isMain">isMain</a></li><li><a href="global.html#joinList">joinList</a></li><li><a href="global.html#joinNames">joinNames</a></li><li><a href="global.html#keepAssignByEntity">keepAssignByEntity</a></li><li><a href="global.html#keepAssignOnMissing">keepAssignOnMissing</a></li><li><a href="global.html#makeBaseline">makeBaseline</a></li><li><a href="global.html#makeRowStates">makeRowStates</a></li><li><a href="global.html#mapKeyOf">mapKeyOf</a></li><li><a href="global.html#mapNameKp">mapNameKp</a></li><li><a href="global.html#markDataReload">markDataReload</a></li><li><a href="global.html#markHasKey">markHasKey</a></li><li><a href="global.html#maskQuery">maskQuery</a></li><li><a href="global.html#maskTok">maskTok</a></li><li><a href="global.html#maskUrl">maskUrl</a></li><li><a href="global.html#mergePickKeysOnly">mergePickKeysOnly</a></li><li><a href="global.html#pairRowsToSnapshot">pairRowsToSnapshot</a></li><li><a href="global.html#pickUniqueUser">pickUniqueUser</a></li><li><a href="global.html#planDraftSync">planDraftSync</a></li><li><a href="global.html#planFixFromType">planFixFromType</a></li><li><a href="global.html#planPurgeChain">planPurgeChain</a></li><li><a href="global.html#planPurgeFrom">planPurgeFrom</a></li><li><a href="global.html#planRefChanges">planRefChanges</a></li><li><a href="global.html#putRefEntry">putRefEntry</a></li><li><a href="global.html#putRowsToKp">putRowsToKp</a></li><li><a href="global.html#refsChanged">refsChanged</a></li><li><a href="global.html#resolveShellWorker">resolveShellWorker</a></li><li><a href="global.html#restoreExternalOrder">restoreExternalOrder</a></li><li><a href="global.html#restoreServerFields">restoreServerFields</a></li><li><a href="global.html#reuseDeletedIds">reuseDeletedIds</a></li><li><a href="global.html#rewriteRefs">rewriteRefs</a></li><li><a href="global.html#rowDigest">rowDigest</a></li><li><a href="global.html#runAuditFrom">runAuditFrom</a></li><li><a href="global.html#runClean">runClean</a></li><li><a href="global.html#runFixFromType">runFixFromType</a></li><li><a href="global.html#runPurgeFrom">runPurgeFrom</a></li><li><a href="global.html#splitCheckedRows">splitCheckedRows</a></li><li><a href="global.html#submitGuard">submitGuard</a></li><li><a href="global.html#tabWriteKey">tabWriteKey</a></li><li><a href="global.html#validateRowsBeforeWrite">validateRowsBeforeWrite</a></li><li><a href="global.html#withTabLocks">withTabLocks</a></li><li><a href="global.html#wrapInjected">wrapInjected</a></li><li><a href="global.html#wrapOperOrm">wrapOperOrm</a></li><li><a href="global.html#writeWithCascade">writeWithCascade</a></li></ul>
33
+
34
+ </nav>
35
+
36
+ <div id="main">
37
+
38
+ <h1 class="page-title">src/js/editorRefRows.mjs</h1>
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+ <section>
47
+ <article>
48
+ <pre class="prettyprint source linenums"><code>import eachOwn from './eachOwn.mjs'
49
+ import getOwn from './getOwn.mjs'
50
+ import cvKpToArr from './cvKpToArr.mjs'
51
+ import getEffMode from './getEffMode.mjs'
52
+ import isAuthMode from './isAuthMode.mjs'
53
+
54
+
55
+ //編輯對話框之「引用清單(cgrups/cpemis) ↔ 對話框之列」轉換, 單一擁有者(規則帳本 R-PRINCIPLE-00 c/e/f、R-AUTH-MERGE-00 第 5 條):
56
+ // 直接編輯器 VeCgrups/VeCpemis(列=被引用表之全部列+額外列)與反向關聯對話框 VeGrupBlngUsers/VePemiBlngGrups(每列改寫另一實體之字串)共用.
57
+ // 伺服端 getUserRules 對 isActive 為 'y' 之引用一律參與合併——查無列(懸空)者以其 mode 參與、內容全 n; mode 缺或非法者視為 AND 限制項(有合法項時與 AND 等價); 名稱 '' 照常比對——
58
+ // 故編輯器存檔不得丟棄任何啟用中之引用(丟棄 AND 項即放寬). 輸入為 cvKpToObj(…, { hasMode: true }) 之結果(以名稱為鍵);
59
+ // 純函數, 不依賴 Vue/DOM/lodash, 不解析字串(JSON5.parse 由呼叫端執行, 站點見 unit-cvKpToObj SITE-AD-001). 往返不變式見 unit-editorRows.
60
+
61
+
62
+ let isPlainObj = (v) => v !== null &amp;&amp; typeof v === 'object' &amp;&amp; !Array.isArray(v)
63
+
64
+
65
+ //restoreLim: 限制項(mode 缺或非法之啟用引用)寫回其原始 mode(見 getRawModeMap): 保留解碼值之其他欄位, mode 換回原值(原為缺則不寫 mode 鍵), isActive 為 'y'
66
+ let restoreLim = (v, lim) => {
67
+ let o = isPlainObj(v) ? { ...v } : {}
68
+ delete o.mode
69
+ let m = getOwn(lim, 'mode')
70
+ if (m !== undefined) {
71
+ o.mode = m
72
+ }
73
+ o.isActive = 'y'
74
+ return o
75
+ }
76
+
77
+
78
+ /**
79
+ * 取得「mode 缺或非法之啟用引用」(伺服端之限制項)之原始 mode, 供存檔時原樣寫回(R-PRINCIPLE-00 e; 未被管理者改動之項寫回其原始 mode)
80
+ *
81
+ * 伺服端 mergeRules 把 mode 缺或非 OR/AND 之啟用項當「限制項」: 只當 AND 交集項、不單獨當基底, 該層沒有任何 mode 合法之啟用項時全 n.
82
+ * 編輯器(cvKpToObj)把此類項顯示為「AND、啟用」; 存檔若寫出合法 AND, 限制項即變成可當基底之 AND——例: { G1: 缺 mode, G2: AND } 管理者停用唯一合法項 G2 後存檔,
83
+ * G1 成為唯一基底而授予其內容(預期為全 n, 多給). 故記下原始 mode, 存檔時對仍為「AND、啟用」(開啟時之狀態, 視為未改)者寫回原始 mode(putRowsToKp/putRefEntry);
84
+ * 管理者改過 mode 或停用者照其選擇寫出.
85
+ * 只記「該名稱所有啟用元素皆 mode 缺或非法」者: 同名另有 mode 合法之啟用元素時(如陣列 [AND, 缺 mode]), 伺服端結果同該合法項, 寫出合法 mode 即授權不變, 寫回限制項反而收回.
86
+ * 純量值({ "G1": "y" })伺服端解為 { isActive: 'y' }(無 mode), 視同缺 mode. 名稱非字串之元素不記(由 getKpLossy 拒存).
87
+ *
88
+ * @param {*} raw 輸入 JSON5.parse(cgrups/cpemis) 之結果(物件或陣列形式; 其他視為無引用)
89
+ * @returns {Object} 回傳無原型物件 名稱 → { mode: 原始 mode 值(可為 undefined) }
90
+ * @example
91
+ *
92
+ * let kp = getRawModeMap(JSON.parse('{"G1":{"isActive":"y"},"G2":{"mode":"or","isActive":"y"},"G3":{"mode":"AND","isActive":"y"}}'))
93
+ * console.log(Object.keys(kp), kp.G2.mode)
94
+ * // => ['G1', 'G2'] or
95
+ *
96
+ */
97
+ function getRawModeMap(raw) {
98
+ let kpLim = Object.create(null) //無原型: 鍵為使用者資料(R-KEY-01)
99
+ let kpValid = Object.create(null)
100
+ eachOwn(cvKpToArr(raw), (r) => {
101
+ if (r.isActive !== 'y' || typeof r.name !== 'string') {
102
+ return true //跳出換下一個
103
+ }
104
+ if (isAuthMode(r.mode)) {
105
+ kpValid[r.name] = true
106
+ return true //跳出換下一個
107
+ }
108
+ if (!(r.name in kpLim)) {
109
+ kpLim[r.name] = { mode: r.mode }
110
+ }
111
+ })
112
+ let out = Object.create(null)
113
+ eachOwn(kpLim, (v, name) => {
114
+ if (kpValid[name] !== true) {
115
+ out[name] = v
116
+ }
117
+ })
118
+ return out
119
+ }
120
+
121
+
122
+ /**
123
+ * 由解碼後之單一引用值取得對話框列之狀態, 與伺服端同解讀
124
+ *
125
+ * - 值為物件: isActive 為 'y' 者啟用; 啟用者之 mode 取有效值(getEffMode: 缺或非法 → 'AND'), 停用者 mode 合法則沿用、否則顯示預設 'OR'(停用項不參與合併, mode 無授權效果, 同修前顯示).
126
+ * - 值為純量(物件形式 { "G1": "y" }; cvKpToObj 物件形式對非物件值原樣保留): 伺服端 cvKpToArr 解為 { isActive: 值 }(無 mode → AND), 此處同解讀——
127
+ * 修前以 lodash get(值, 'isActive') 取不到而顯示停用、存檔寫出 { mode: 'OR', isActive: 'n' }, 丟掉該 AND 引用即放寬.
128
+ * - 無此引用(null/undefined): 停用、'OR'.
129
+ *
130
+ * @param {*} p 輸入 getOwn(cvKpToObj 之結果, 名稱, null)
131
+ * @returns {Object} 回傳 { mode: 'OR'|'AND', enable: 'y'|'n' }
132
+ * @example
133
+ *
134
+ * console.log(getRefState({ mode: 'or', isActive: 'y' }))
135
+ * // => { mode: 'AND', enable: 'y' }
136
+ * console.log(getRefState('y'))
137
+ * // => { mode: 'AND', enable: 'y' }
138
+ *
139
+ */
140
+ function getRefState(p) {
141
+ let o = isPlainObj(p) ? p : { isActive: p }
142
+ let m = getOwn(o, 'mode')
143
+ let enable = getOwn(o, 'isActive') === 'y' ? 'y' : 'n'
144
+ let mode = enable === 'y' ? getEffMode(m) : (isAuthMode(m) ? m : 'OR')
145
+ return { mode, enable }
146
+ }
147
+
148
+
149
+ /**
150
+ * 取得「啟用中而對話框之表列未顯示」之引用, 各一列(由呼叫端附於表列之後), 使存檔原樣寫回(R-PRINCIPLE-00 c/f)
151
+ *
152
+ * 對話框之表列以 getOwn(解碼結果, 表列.name) 顯示引用, 存檔只寫出名稱為字串之列; 故「顯示到」以表列 name 為字串且 === 引用名稱判定.
153
+ * 與伺服端 findRefRows 之差異僅在表列無 name(findRefRows 視為 '')或 name 非字串者——此類表列不會以字串名稱寫出, 其所對應之引用仍須以額外列保留.
154
+ * 一般情形即「引用之名稱查無列(懸空; 含名稱 '')」. 停用之引用無授權影響, 不產生額外列(存檔時照舊不寫出). 順序: 解碼結果之鍵序(僅供顯示, 不影響授權).
155
+ *
156
+ * @param {Object} kpDec 輸入 cvKpToObj(…, { hasMode: true }) 之結果(非物件視為無引用)
157
+ * @param {Array} tabRows 輸入被引用表之列(群組表/權限表)
158
+ * @returns {Array} 回傳額外列 [{ name, mode, enable: 'y', dangling: true }]
159
+ */
160
+ function getRefRowsExtra(kpDec, tabRows) {
161
+ let rs = []
162
+ if (!isPlainObj(kpDec)) {
163
+ return rs
164
+ }
165
+ let kpShown = Object.create(null) //無原型: 鍵為使用者資料(R-KEY-01)
166
+ eachOwn(tabRows, (v) => {
167
+ let n = isPlainObj(v) ? v.name : undefined
168
+ if (typeof n === 'string') {
169
+ kpShown[n] = true
170
+ }
171
+ })
172
+ eachOwn(kpDec, (p, name) => {
173
+ let st = getRefState(p)
174
+ if (st.enable !== 'y' || kpShown[name] === true) {
175
+ return true //跳出換下一個
176
+ }
177
+ rs.push({
178
+ name,
179
+ mode: st.mode,
180
+ enable: 'y',
181
+ dangling: true,
182
+ })
183
+ })
184
+ return rs
185
+ }
186
+
187
+
188
+ /**
189
+ * 取得同名多列(被引用表之歷史同名, R-PRINCIPLE-00 d)中 (mode, enable) 不全相同者之名稱
190
+ *
191
+ * 物件形式每個名稱只有一個值, 同名各列設定不同時無法寫出(寫出任一列即靜默捨棄其他列之設定), 編輯器拒存(warnDupRowsInconsistent); 全相同則寫出一次.
192
+ *
193
+ * @param {Array} rows 輸入對話框之列 [{ name, mode, enable }]
194
+ * @returns {Array} 回傳名稱陣列(不重複, 依首次出現序); 名稱非字串之列不計
195
+ */
196
+ function getDupRowsInconsistent(rows) {
197
+ let kpFirst = Object.create(null) //無原型: 鍵為使用者資料(R-KEY-01)
198
+ let out = []
199
+ eachOwn(rows, (r) => {
200
+ if (!isPlainObj(r) || typeof r.name !== 'string') {
201
+ return true //跳出換下一個
202
+ }
203
+ if (!(r.name in kpFirst)) {
204
+ kpFirst[r.name] = r
205
+ return true //跳出換下一個
206
+ }
207
+ let f = kpFirst[r.name]
208
+ if ((f.mode !== r.mode || f.enable !== r.enable) &amp;&amp; !out.includes(r.name)) {
209
+ out.push(r.name)
210
+ }
211
+ })
212
+ return out
213
+ }
214
+
215
+
216
+ /**
217
+ * 由直接編輯器之列寫出引用清單物件 { 名稱: { mode, isActive } }, 寫入呼叫端提供之無原型容器(R-KEY-01: 名稱可為 __proto__ 等原型鍵)
218
+ *
219
+ * 名稱為字串者(含 '', R-PRINCIPLE-00 f: 原樣保留; 含懸空之額外列)寫出; 名稱非字串、mode 非 OR/AND、enable 非非空字串之列略過(對話框不會產生此類列).
220
+ * 同名多列後者覆蓋前者(呼叫端須先以 getDupRowsInconsistent 拒存不一致者; 一致者覆蓋結果相同).
221
+ * rawModeMap(getRawModeMap 之結果, 選填): 限制項之列仍為「啟用、mode 為其有效值(AND)」(開啟時之狀態, 視為未改)者寫回原始 mode(restoreLim), 不寫成合法 AND——
222
+ * 否則限制項變為可當基底之 AND 而多給(見 getRawModeMap); 管理者改過 mode 或停用者照列寫出. 不給=一律照列寫出.
223
+ *
224
+ * @param {Object} kpOut 輸入寫出用之無原型容器(呼叫端建立)
225
+ * @param {Array} rows 輸入對話框之列 [{ name, mode, enable }]
226
+ * @param {Object} [rawModeMap] 輸入 getRawModeMap(原始解析結果)
227
+ * @returns {Object} 回傳 kpOut
228
+ */
229
+ function putRowsToKp(kpOut, rows, rawModeMap) {
230
+ eachOwn(rows, (r) => {
231
+ if (!isPlainObj(r)) {
232
+ return true //跳出換下一個
233
+ }
234
+ let name = r.name
235
+ let mode = r.mode
236
+ let enable = r.enable
237
+ if (typeof name !== 'string' || !isAuthMode(mode) || typeof enable !== 'string' || enable === '') {
238
+ return true //跳出換下一個
239
+ }
240
+ let lim = getOwn(rawModeMap, name, null)
241
+ if (lim !== null &amp;&amp; enable === 'y' &amp;&amp; mode === getEffMode(getOwn(lim, 'mode'))) {
242
+ kpOut[name] = restoreLim(null, lim)
243
+ return true //跳出換下一個
244
+ }
245
+ kpOut[name] = {
246
+ mode,
247
+ isActive: enable,
248
+ }
249
+ })
250
+ return kpOut
251
+ }
252
+
253
+
254
+ /**
255
+ * 反向關聯對話框改寫單一實體(使用者/群組)之引用清單: 只改「名稱為 name」之一項, 其餘引用項(含懸空、名稱 ''、mode 缺/非法〔解碼已為 AND〕、停用項、純量值)原樣保留,
256
+ * 其授權效果不變(R-PRINCIPLE-00 c/e/f; 修前以列上經 fltKp* 篩過之 grups/pemis 重組, 查無列之啟用引用被丟棄即放寬)
257
+ *
258
+ * 目標狀態(enable 為 'y' 時 { mode, isActive: 'y' }; 否則移除該項)與現值(getRefState)相同 → 回 false(未變更: 呼叫端不改寫字串, 逐字元不動);
259
+ * 不同 → 把 kpDec 之自有項(name 除外)複製入 kpOut 並寫入目標狀態, 回 true. mode 取有效值(getEffMode: 非 OR 者為 AND).
260
+ * rawModeMap(getRawModeMap(該實體字串之原始解析結果), 選填): 複製其餘項時, 啟用中之限制項寫回其原始 mode(restoreLim; 解碼值為 AND, 寫成合法 AND 會多給, 見 getRawModeMap).
261
+ *
262
+ * @param {Object} kpOut 輸入寫出用之無原型容器(R-KEY-01; 呼叫端建立)
263
+ * @param {Object} kpDec 輸入 cvKpToObj(…, { hasMode: true }) 之結果(非物件視為無引用)
264
+ * @param {String} name 輸入本對話框所管之群組/權限名稱
265
+ * @param {String} enable 輸入 'y' 為歸屬, 其他為不歸屬
266
+ * @param {String} mode 輸入歸屬時之合併模式
267
+ * @param {Object} [rawModeMap] 輸入 getRawModeMap(原始解析結果)
268
+ * @returns {Boolean} 回傳是否變更(true 時 kpOut 已填入欲寫出之內容)
269
+ * @example
270
+ *
271
+ * let kp = Object.create(null)
272
+ * console.log(putRefEntry(kp, { GX: { mode: 'AND', isActive: 'y' } }, 'G1', 'y', 'OR'), JSON.stringify(kp))
273
+ * // => true {"GX":{"mode":"AND","isActive":"y"},"G1":{"mode":"OR","isActive":"y"}}
274
+ *
275
+ */
276
+ function putRefEntry(kpOut, kpDec, name, enable, mode, rawModeMap) {
277
+ let cur = getRefState(getOwn(kpDec, name, null))
278
+ let on = enable === 'y'
279
+ let m = getEffMode(mode)
280
+ if (on === (cur.enable === 'y') &amp;&amp; (!on || m === cur.mode)) {
281
+ return false
282
+ }
283
+ if (isPlainObj(kpDec)) {
284
+ eachOwn(kpDec, (v, k) => {
285
+ if (k === name) {
286
+ return true //跳出換下一個
287
+ }
288
+ let lim = getOwn(rawModeMap, k, null)
289
+ kpOut[k] = (lim !== null &amp;&amp; getRefState(v).enable === 'y') ? restoreLim(v, lim) : v
290
+ })
291
+ }
292
+ if (on) {
293
+ kpOut[name] = {
294
+ mode: m,
295
+ isActive: 'y',
296
+ }
297
+ }
298
+ return true
299
+ }
300
+
301
+
302
+ /**
303
+ * 對話框之列中 row[key] 精確 === val 之全部索引(單列切換與批次操作用)
304
+ *
305
+ * 直接編輯器之同名多列代表同一個引用(物件形式一個名稱只有一個值), 切換須對所有精確同名列一併套用, 同名列狀態恆一致(warnDupRowsInconsistent 僅作防呆);
306
+ * 修前以 lodash get(row, 'name', '') 找第一列(批次以 kpRow[name] 只剩最後一列): 同名第二列之操作改到第一列、全選後同名列不一致而被拒存,
307
+ * 且表列無 name 欄者(undefined)被當成 '' 搶先命中名稱 '' 之額外列. 反向關聯對話框以列身分 id 定位(群組/使用者之 name 可重複).
308
+ * 比對為精確 ===(undefined 不等於 '', 數字 5 不等於 '5'); 非物件之列略過.
309
+ *
310
+ * @param {Array} rows 輸入對話框之列
311
+ * @param {String} key 輸入欄位名('name' 或 'id')
312
+ * @param {*} val 輸入欲比對之值
313
+ * @returns {Array} 回傳索引陣列(由小到大)
314
+ * @example
315
+ *
316
+ * console.log(getRowIdxs([{ name: 'A' }, { id: 'x' }, { name: 'A' }, { name: '' }], 'name', 'A'))
317
+ * // => [0, 2]
318
+ *
319
+ */
320
+ function getRowIdxs(rows, key, val) {
321
+ let ks = []
322
+ eachOwn(rows, (r, k) => {
323
+ if (isPlainObj(r) &amp;&amp; getOwn(r, key) === val) {
324
+ ks.push(k)
325
+ }
326
+ })
327
+ return ks
328
+ }
329
+
330
+
331
+ export { getRefState, getRefRowsExtra, getDupRowsInconsistent, getRawModeMap, putRowsToKp, putRefEntry, getRowIdxs }
332
+ </code></pre>
333
+ </article>
334
+ </section>
335
+
336
+
337
+
338
+
339
+
340
+
341
+ </div>
342
+
343
+ <br class="clear">
344
+
345
+ <footer>
346
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Fri Oct 23 2026 10:56:39 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
347
+ </footer>
348
+
349
+ <script>prettyPrint();</script>
350
+ <script src="scripts/polyfill.js"></script>
351
+ <script src="scripts/linenumber.js"></script>
352
+
353
+
354
+
355
+ </body>
356
+ </html>