w-serv-orm 1.1.9 → 1.1.10
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.
- package/dist/w-serv-orm.umd.js +2 -2
- package/dist/w-serv-orm.umd.js.map +1 -1
- package/docs/WServOrm.html +2 -2
- package/docs/WServOrm.mjs.html +5 -24
- package/docs/index.html +1 -1
- package/package.json +1 -1
- package/src/WServOrm.mjs +3 -22
- package/src/checkOptRemoved.mjs +25 -0
- package/src/getProc.mjs +9 -7
- package/test/api-procOrm.test.mjs +1 -1
- package/test/unit-WServOrm.test.mjs +86 -43
- package/test/unit-mapOrm.test.mjs +2 -2
- package/src/getItemsFail.mjs +0 -5
package/docs/WServOrm.mjs.html
CHANGED
|
@@ -45,34 +45,15 @@
|
|
|
45
45
|
|
|
46
46
|
<section>
|
|
47
47
|
<article>
|
|
48
|
-
<pre class="prettyprint source linenums"><code>import
|
|
49
|
-
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
50
49
|
import isfun from 'wsemi/src/isfun.mjs'
|
|
50
|
+
import checkOptRemoved from './checkOptRemoved.mjs'
|
|
51
51
|
import getDbBackupAndRecover from './getDbBackupAndRecover.mjs'
|
|
52
52
|
import getWoItems from './getWoItems.mjs'
|
|
53
53
|
import getMapOrm from './getMapOrm.mjs'
|
|
54
54
|
import getProc from './getProc.mjs'
|
|
55
55
|
|
|
56
56
|
|
|
57
|
-
function checkOptRemoved(opt) {
|
|
58
|
-
//已移除之設定: 未給、null或false者接受(使用端現行之設定), 其餘值拋錯, 避免使用端以為仍有檢查而無聲失去
|
|
59
|
-
//useCheckUser只查使用者存在且有效, 屬認證而非授權, 卻曾被當成授權; procOrm不做授權, 須由procOrm開放給前端之處負責
|
|
60
|
-
//useExcludeWhenNotAdmin依賴只有useCheckUser才產生之isAdmin, 未開useCheckUser時會把所有人當非管理者過濾, 一併移除
|
|
61
|
-
let msgAuth = 'procOrm does not authorize users, authorize where procOrm is exposed to clients'
|
|
62
|
-
let ks = [
|
|
63
|
-
['useCheckUser', msgAuth],
|
|
64
|
-
['getUserById', msgAuth],
|
|
65
|
-
['useExcludeWhenNotAdmin', 'procOrm does not filter select results by user, use addFunPostProcessing if needed'],
|
|
66
|
-
]
|
|
67
|
-
for (let [k, hint] of ks) {
|
|
68
|
-
let v = get(opt, k)
|
|
69
|
-
if (v !== undefined && v !== null && v !== false) {
|
|
70
|
-
throw new Error(`opt.${k} has been removed, ${hint}`)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
57
|
/**
|
|
77
58
|
* 產生伺服器ORM的支援物件
|
|
78
59
|
*
|
|
@@ -161,7 +142,7 @@ function checkOptRemoved(opt) {
|
|
|
161
142
|
*/
|
|
162
143
|
function WServOrm(ds, WOrm, url, db, opt = {}) {
|
|
163
144
|
|
|
164
|
-
//checkOptRemoved, 須於建立各資料表ORM之前, 否則拋錯時已開啟之ORM(如lmdb之檔案)
|
|
145
|
+
//checkOptRemoved, 須於建立各資料表ORM之前, 否則拋錯時已開啟之ORM(如lmdb之檔案)無從關閉; getProc收到opt時會再檢查一次, 無副作用
|
|
165
146
|
checkOptRemoved(opt)
|
|
166
147
|
|
|
167
148
|
//getWoItems
|
|
@@ -173,7 +154,7 @@ function WServOrm(ds, WOrm, url, db, opt = {}) {
|
|
|
173
154
|
// console.log('mapOrm', mapOrm)
|
|
174
155
|
|
|
175
156
|
//getProc
|
|
176
|
-
let proc = getProc(mapOrm)
|
|
157
|
+
let proc = getProc(mapOrm, opt)
|
|
177
158
|
// console.log('proc', proc)
|
|
178
159
|
|
|
179
160
|
//closeAll, 逐一關閉woItems內各資料表ORM實例之連線(env), 釋放檔案鎖, 供測試隔離或優雅關機使用
|
|
@@ -210,7 +191,7 @@ export default WServOrm
|
|
|
210
191
|
<br class="clear">
|
|
211
192
|
|
|
212
193
|
<footer>
|
|
213
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Oct 13 2026
|
|
194
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Oct 13 2026 06:34:48 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
214
195
|
</footer>
|
|
215
196
|
|
|
216
197
|
<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.5</a> on Tue Oct 13 2026
|
|
74
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Tue Oct 13 2026 06:34:48 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
75
75
|
</footer>
|
|
76
76
|
|
|
77
77
|
<script>prettyPrint();</script>
|
package/package.json
CHANGED
package/src/WServOrm.mjs
CHANGED
|
@@ -1,31 +1,12 @@
|
|
|
1
|
-
import get from 'lodash-es/get.js'
|
|
2
1
|
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
3
2
|
import isfun from 'wsemi/src/isfun.mjs'
|
|
3
|
+
import checkOptRemoved from './checkOptRemoved.mjs'
|
|
4
4
|
import getDbBackupAndRecover from './getDbBackupAndRecover.mjs'
|
|
5
5
|
import getWoItems from './getWoItems.mjs'
|
|
6
6
|
import getMapOrm from './getMapOrm.mjs'
|
|
7
7
|
import getProc from './getProc.mjs'
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
function checkOptRemoved(opt) {
|
|
11
|
-
//已移除之設定: 未給、null或false者接受(使用端現行之設定), 其餘值拋錯, 避免使用端以為仍有檢查而無聲失去
|
|
12
|
-
//useCheckUser只查使用者存在且有效, 屬認證而非授權, 卻曾被當成授權; procOrm不做授權, 須由procOrm開放給前端之處負責
|
|
13
|
-
//useExcludeWhenNotAdmin依賴只有useCheckUser才產生之isAdmin, 未開useCheckUser時會把所有人當非管理者過濾, 一併移除
|
|
14
|
-
let msgAuth = 'procOrm does not authorize users, authorize where procOrm is exposed to clients'
|
|
15
|
-
let ks = [
|
|
16
|
-
['useCheckUser', msgAuth],
|
|
17
|
-
['getUserById', msgAuth],
|
|
18
|
-
['useExcludeWhenNotAdmin', 'procOrm does not filter select results by user, use addFunPostProcessing if needed'],
|
|
19
|
-
]
|
|
20
|
-
for (let [k, hint] of ks) {
|
|
21
|
-
let v = get(opt, k)
|
|
22
|
-
if (v !== undefined && v !== null && v !== false) {
|
|
23
|
-
throw new Error(`opt.${k} has been removed, ${hint}`)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
10
|
/**
|
|
30
11
|
* 產生伺服器ORM的支援物件
|
|
31
12
|
*
|
|
@@ -114,7 +95,7 @@ function checkOptRemoved(opt) {
|
|
|
114
95
|
*/
|
|
115
96
|
function WServOrm(ds, WOrm, url, db, opt = {}) {
|
|
116
97
|
|
|
117
|
-
//checkOptRemoved, 須於建立各資料表ORM之前, 否則拋錯時已開啟之ORM(如lmdb之檔案)
|
|
98
|
+
//checkOptRemoved, 須於建立各資料表ORM之前, 否則拋錯時已開啟之ORM(如lmdb之檔案)無從關閉; getProc收到opt時會再檢查一次, 無副作用
|
|
118
99
|
checkOptRemoved(opt)
|
|
119
100
|
|
|
120
101
|
//getWoItems
|
|
@@ -126,7 +107,7 @@ function WServOrm(ds, WOrm, url, db, opt = {}) {
|
|
|
126
107
|
// console.log('mapOrm', mapOrm)
|
|
127
108
|
|
|
128
109
|
//getProc
|
|
129
|
-
let proc = getProc(mapOrm)
|
|
110
|
+
let proc = getProc(mapOrm, opt)
|
|
130
111
|
// console.log('proc', proc)
|
|
131
112
|
|
|
132
113
|
//closeAll, 逐一關閉woItems內各資料表ORM實例之連線(env), 釋放檔案鎖, 供測試隔離或優雅關機使用
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import get from 'lodash-es/get.js'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
function checkOptRemoved(opt) {
|
|
5
|
+
//已移除之設定: 未給、null或false者接受(使用端現行之設定), 其餘值拋錯, 避免使用端以為仍有檢查而無聲失去
|
|
6
|
+
//useCheckUser只查使用者存在且有效, 屬認證而非授權, 卻曾被當成授權; procOrm不做授權, 須由procOrm開放給前端之處負責
|
|
7
|
+
//useExcludeWhenNotAdmin依賴只有useCheckUser才產生之isAdmin, 未開useCheckUser時會把所有人當非管理者過濾, 一併移除
|
|
8
|
+
//收opt之進入點(WServOrm、getProc)皆須呼叫, 直接呼叫getProc者亦不得靜默忽略
|
|
9
|
+
//使用端包裝層可直接呼叫以檢查其自身之opt, 只看這三鍵, opt之其他鍵不受影響, 通過時回傳undefined
|
|
10
|
+
let msgAuth = 'procOrm does not authorize users, authorize where procOrm is exposed to clients'
|
|
11
|
+
let ks = [
|
|
12
|
+
['useCheckUser', msgAuth],
|
|
13
|
+
['getUserById', msgAuth],
|
|
14
|
+
['useExcludeWhenNotAdmin', 'procOrm does not filter select results by user, use addFunPostProcessing if needed'],
|
|
15
|
+
]
|
|
16
|
+
for (let [k, hint] of ks) {
|
|
17
|
+
let v = get(opt, k)
|
|
18
|
+
if (v !== undefined && v !== null && v !== false) {
|
|
19
|
+
throw new Error(`opt.${k} has been removed, ${hint}`)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
export default checkOptRemoved
|
package/src/getProc.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
2
2
|
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
3
3
|
import isfun from 'wsemi/src/isfun.mjs'
|
|
4
|
+
import checkOptRemoved from './checkOptRemoved.mjs'
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
function addFun(fs, f, name, useGuard = false) {
|
|
@@ -30,11 +31,7 @@ function addFun(fs, f, name, useGuard = false) {
|
|
|
30
31
|
async function procOrm(st, userId, woName, mode, input) {
|
|
31
32
|
//封裝mapOrm, 依序執行擴充檢查、前處理、ORM操作與後處理, st為該實例之狀態
|
|
32
33
|
//不做授權: 不檢查使用者亦不依使用者過濾數據, userId只供寫入稽核欄位與交給擴充函數; 開放給前端時須由開放處負責授權
|
|
33
|
-
|
|
34
|
-
//check
|
|
35
|
-
if (!isfun(st.mapOrm)) {
|
|
36
|
-
return Promise.reject(`invalid mapOrm`)
|
|
37
|
-
}
|
|
34
|
+
//st.mapOrm已於getProc建立st時驗證為函數, 且st不外露, 故此處不再檢查
|
|
38
35
|
|
|
39
36
|
//funChecks, 擴充檢查, 提供給各 mOrm[OOO].mjs 檢查
|
|
40
37
|
await pmSeries(st.funChecks, (v) => {
|
|
@@ -65,11 +62,16 @@ async function procOrm(st, userId, woName, mode, input) {
|
|
|
65
62
|
}
|
|
66
63
|
|
|
67
64
|
|
|
68
|
-
function getProc(mapOrm) {
|
|
65
|
+
function getProc(mapOrm, opt = {}) {
|
|
66
|
+
//mapOrm為getMapOrm之回傳函數, opt目前無設定鍵, 只檢查已移除之設定; 使用端有直接呼叫者(如測試以getMapOrm與getProc組出procOrm), 故檢查與WServOrm一致
|
|
67
|
+
//建構期之錯誤一律為Error, 與procOrm之字串reject區隔
|
|
68
|
+
|
|
69
|
+
//checkOptRemoved
|
|
70
|
+
checkOptRemoved(opt)
|
|
69
71
|
|
|
70
72
|
//check
|
|
71
73
|
if (!isfun(mapOrm)) {
|
|
72
|
-
|
|
74
|
+
throw new Error(`invalid mapOrm`)
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
//st, 各實例之狀態, 每次呼叫各自建立, 令同一行程內之多個實例互不干擾
|
|
@@ -27,7 +27,7 @@ describe('procOrm接w-orm-lowdb', function() {
|
|
|
27
27
|
before(function() {
|
|
28
28
|
fs.rmSync(fd, { recursive: true, force: true })
|
|
29
29
|
fs.mkdirSync(fd, { recursive: true })
|
|
30
|
-
so = WServOrm(ds, WOrm, `${fd}/db.json`, 'worm'
|
|
30
|
+
so = WServOrm(ds, WOrm, `${fd}/db.json`, 'worm')
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
after(async function() {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import assert from 'assert'
|
|
2
2
|
import WServOrm from '../src/WServOrm.mjs'
|
|
3
3
|
import getMapOrm from '../src/getMapOrm.mjs'
|
|
4
|
-
import
|
|
4
|
+
import getProc from '../src/getProc.mjs'
|
|
5
|
+
import checkOptRemoved from '../src/checkOptRemoved.mjs'
|
|
5
6
|
|
|
6
7
|
|
|
7
8
|
//替身ORM工廠: 以name辨識所屬實例, 呼叫紀錄寫入log; 回傳形狀依w-orm系列規格(save、del回逐筆陣列, insert回聚合物件)
|
|
@@ -29,7 +30,6 @@ function mkWOrm(name, log, behavior = {}) {
|
|
|
29
30
|
|
|
30
31
|
let dsAll = { tests: { keys: ['id', 'name', 'isActive', 'timeUpdate'] } }
|
|
31
32
|
let dsNoTime = { tests: { keys: ['id', 'name', 'isActive'] } }
|
|
32
|
-
let optOff = { useCheckUser: false, useExcludeWhenNotAdmin: false }
|
|
33
33
|
let wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
34
34
|
|
|
35
35
|
async function getReject(pm) {
|
|
@@ -63,8 +63,8 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
63
63
|
it('I01 兩實例之procOrm各自路由至自己的ORM', async function() {
|
|
64
64
|
//R1: 雙向皆打自己的ORM, 解構後呼叫亦然
|
|
65
65
|
let log = []
|
|
66
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
67
|
-
let B = WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b'
|
|
66
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
67
|
+
let B = WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b')
|
|
68
68
|
let { procOrm: pA } = A
|
|
69
69
|
let { procOrm: pB } = B
|
|
70
70
|
await pA('u1', 'tests', 'select', {})
|
|
@@ -77,8 +77,8 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
77
77
|
it('I02 各實例依自己之ds調整數據', async function() {
|
|
78
78
|
//R1: A之ds含timeUpdate而補值, B之ds不含而不補
|
|
79
79
|
let log = []
|
|
80
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
81
|
-
let B = WServOrm(dsNoTime, mkWOrm('B', log), 'url-b', 'db-b'
|
|
80
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
81
|
+
let B = WServOrm(dsNoTime, mkWOrm('B', log), 'url-b', 'db-b')
|
|
82
82
|
await A.procOrm('u1', 'tests', 'save', [{ id: 'x' }])
|
|
83
83
|
await B.procOrm('u1', 'tests', 'save', [{ id: 'y' }])
|
|
84
84
|
assert.strict.deepEqual(log.map((v) => v.name), ['A', 'B'])
|
|
@@ -90,7 +90,7 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
90
90
|
//R3: useCheckUser、getUserById、useExcludeWhenNotAdmin已移除; 給予未給、null、false以外之值即拋錯, 避免使用端以為仍有檢查而無聲失去
|
|
91
91
|
//拋錯於建立各資料表ORM之前, 否則已開啟之ORM(如lmdb之檔案)無從關閉; 亦不影響既有實例
|
|
92
92
|
let log = []
|
|
93
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
93
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
94
94
|
let created = 0
|
|
95
95
|
let WOrmCount = function() {
|
|
96
96
|
created++
|
|
@@ -130,8 +130,8 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
130
130
|
//R1、R4: 雙向隔離; 註冊並等待超過1ms後生效
|
|
131
131
|
let log = []
|
|
132
132
|
let calls = []
|
|
133
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
134
|
-
let B = WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b'
|
|
133
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
134
|
+
let B = WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b')
|
|
135
135
|
for (let [name, ins] of [['A', A], ['B', B]]) {
|
|
136
136
|
ins.addFunCheck(() => {
|
|
137
137
|
calls.push(`${name}-check`)
|
|
@@ -157,12 +157,12 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
157
157
|
//R1d: A註冊後再建C, C之procOrm不呼叫A之hook
|
|
158
158
|
let log = []
|
|
159
159
|
let calls = []
|
|
160
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
160
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
161
161
|
A.addFunCheck(() => {
|
|
162
162
|
calls.push('A-check')
|
|
163
163
|
})
|
|
164
164
|
await wait(20)
|
|
165
|
-
let C = WServOrm(dsAll, mkWOrm('C', log), 'url-c', 'db-c'
|
|
165
|
+
let C = WServOrm(dsAll, mkWOrm('C', log), 'url-c', 'db-c')
|
|
166
166
|
await C.procOrm('u1', 'tests', 'select', {})
|
|
167
167
|
assert.strict.deepEqual(calls, [])
|
|
168
168
|
})
|
|
@@ -187,7 +187,7 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
187
187
|
|
|
188
188
|
it('I08 擴充函數之參數不含isAdmin', async function() {
|
|
189
189
|
//R3: 隨useCheckUser移除, 參數物件只含woName、userId、mode、input, 後處理另含output
|
|
190
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
190
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
191
191
|
let ks = {}
|
|
192
192
|
A.addFunCheck((p) => {
|
|
193
193
|
ks.check = Object.keys(p)
|
|
@@ -216,14 +216,14 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
216
216
|
let gate = new Promise((resolve) => {
|
|
217
217
|
release = resolve
|
|
218
218
|
})
|
|
219
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
219
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
220
220
|
A.addFunCheck(async () => {
|
|
221
221
|
await gate
|
|
222
222
|
})
|
|
223
223
|
await wait(20)
|
|
224
224
|
let pA = A.procOrm('u1', 'tests', 'select', {})
|
|
225
225
|
await wait(5)
|
|
226
|
-
WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b'
|
|
226
|
+
WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b')
|
|
227
227
|
release()
|
|
228
228
|
let rA = await pA
|
|
229
229
|
assert.strict.deepEqual(log.map((v) => v.name), ['A'])
|
|
@@ -233,8 +233,8 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
233
233
|
it('I10 同一實例之woItems直寫與procOrm寫入打同一個ORM', async function() {
|
|
234
234
|
//R1b: 使用端先以woItems直接寫入再經procOrm寫入之用法
|
|
235
235
|
let log = []
|
|
236
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
237
|
-
WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b'
|
|
236
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
237
|
+
WServOrm(dsAll, mkWOrm('B', log), 'url-b', 'db-b')
|
|
238
238
|
await A.woItems.tests.save([{ id: 'x' }])
|
|
239
239
|
await A.procOrm('u1', 'tests', 'save', [{ id: 'y' }])
|
|
240
240
|
assert.strict.deepEqual(log.map((v) => v.name), ['A', 'A'])
|
|
@@ -242,7 +242,7 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
242
242
|
|
|
243
243
|
it('I11 回傳函數之名稱與型別不變', async function() {
|
|
244
244
|
//R2: 使用端以解構取用並當裸函數傳遞; addFun*回傳undefined; procOrm為async函數
|
|
245
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
245
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
246
246
|
assert.strict.equal(A.procOrm.name, 'procOrm')
|
|
247
247
|
assert.strict.equal(Object.prototype.toString.call(A.procOrm), '[object AsyncFunction]')
|
|
248
248
|
for (let k of ['addFunCheck', 'addFunPreProcessing', 'addFunPostProcessing']) {
|
|
@@ -251,6 +251,55 @@ describe('WServOrm實例互不干擾', function() {
|
|
|
251
251
|
}
|
|
252
252
|
})
|
|
253
253
|
|
|
254
|
+
it('I12 直接呼叫getProc: 已移除之設定與無效之mapOrm皆拋Error, 未給、null或false照常', async function() {
|
|
255
|
+
//R3: 使用端有以getMapOrm與getProc直接組出procOrm者(如w-web-sso之測試), 已移除之設定不得被靜默忽略, 訊息同WServOrm
|
|
256
|
+
//建構期錯誤為Error, 不回rejected Promise(原回之Promise被解構時得undefined)
|
|
257
|
+
let getThrow = (fn) => {
|
|
258
|
+
try {
|
|
259
|
+
fn()
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
return e
|
|
263
|
+
}
|
|
264
|
+
throw new Error('預期拋錯但未拋')
|
|
265
|
+
}
|
|
266
|
+
let mapOrm = getMapOrm(dsAll, { tests: { select: async () => [{ id: 'r1' }] } })
|
|
267
|
+
let bads = [
|
|
268
|
+
['useCheckUser', true],
|
|
269
|
+
['getUserById', async () => ({ isActive: 'y' })],
|
|
270
|
+
['useExcludeWhenNotAdmin', true],
|
|
271
|
+
]
|
|
272
|
+
for (let [k, v] of bads) {
|
|
273
|
+
let e1 = getThrow(() => getProc(mapOrm, { [k]: v }))
|
|
274
|
+
let e2 = getThrow(() => WServOrm(dsAll, mkWOrm('X', []), 'url-x', 'db-x', { [k]: v }))
|
|
275
|
+
assert.ok(e1 instanceof Error && e1.message.startsWith(`opt.${k} has been removed, `), `${k}: ${String(v)}`)
|
|
276
|
+
assert.strict.equal(e1.message, e2.message)
|
|
277
|
+
}
|
|
278
|
+
for (let bad of [undefined, null, {}, 'x']) {
|
|
279
|
+
let e = getThrow(() => getProc(bad))
|
|
280
|
+
assert.ok(e instanceof Error, String(bad))
|
|
281
|
+
assert.strict.equal(e.message, 'invalid mapOrm')
|
|
282
|
+
}
|
|
283
|
+
for (let args of [[], [undefined], [null], [{}], [{ useCheckUser: false, getUserById: null, useExcludeWhenNotAdmin: false }]]) {
|
|
284
|
+
let { procOrm } = getProc(mapOrm, ...args)
|
|
285
|
+
let r = await procOrm('u1', 'tests', 'select', {})
|
|
286
|
+
assert.strict.deepEqual(r, [{ id: 'r1' }], JSON.stringify(args))
|
|
287
|
+
}
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('I13 checkOptRemoved可由使用端單獨呼叫: 只看已移除之三鍵, 其他鍵不受影響', async function() {
|
|
291
|
+
//R3: 使用端包裝層(如WWebApi)以自身之opt呼叫, opt含serverPort等其他鍵; 通過時回undefined且不改動opt
|
|
292
|
+
let optWrap = { serverPort: 11005, webName: { eng: 'x' }, useCheckUser: false, getUserById: null }
|
|
293
|
+
assert.strict.equal(checkOptRemoved(optWrap), undefined)
|
|
294
|
+
assert.strict.deepEqual(optWrap, { serverPort: 11005, webName: { eng: 'x' }, useCheckUser: false, getUserById: null })
|
|
295
|
+
for (let opt of [undefined, null, {}, 'x', 1]) {
|
|
296
|
+
assert.strict.equal(checkOptRemoved(opt), undefined, String(opt))
|
|
297
|
+
}
|
|
298
|
+
for (let k of ['useCheckUser', 'getUserById', 'useExcludeWhenNotAdmin']) {
|
|
299
|
+
assert.throws(() => checkOptRemoved({ serverPort: 11005, [k]: true }), (e) => e instanceof Error && e.message.startsWith(`opt.${k} has been removed, `), k)
|
|
300
|
+
}
|
|
301
|
+
})
|
|
302
|
+
|
|
254
303
|
})
|
|
255
304
|
|
|
256
305
|
|
|
@@ -261,7 +310,7 @@ describe('procOrm後處理', function() {
|
|
|
261
310
|
let log = []
|
|
262
311
|
let calls = []
|
|
263
312
|
let save = (d) => d.map((v, k) => (k === 1 ? { n: 1, ok: 0, err: 'E' } : { n: 1, ok: 1 }))
|
|
264
|
-
let A = WServOrm(dsAll, mkWOrm('A', log, { save }), 'url-a', 'db-a'
|
|
313
|
+
let A = WServOrm(dsAll, mkWOrm('A', log, { save }), 'url-a', 'db-a')
|
|
265
314
|
A.addFunPostProcessing((p) => {
|
|
266
315
|
calls.push(p.mode)
|
|
267
316
|
return p.output
|
|
@@ -283,7 +332,7 @@ describe('mapOrm之log標籤與訊息', function() {
|
|
|
283
332
|
//R6: 標籤依實際操作, reject訊息為該操作之整批失敗訊息
|
|
284
333
|
let log = []
|
|
285
334
|
let fail = () => Promise.reject(new Error('E-batch'))
|
|
286
|
-
let A = WServOrm(dsAll, mkWOrm('A', log, { insert: fail, del: fail }), 'url-a', 'db-a'
|
|
335
|
+
let A = WServOrm(dsAll, mkWOrm('A', log, { insert: fail, del: fail }), 'url-a', 'db-a')
|
|
287
336
|
let errs = []
|
|
288
337
|
let logs = await captureLog(async () => {
|
|
289
338
|
errs.push(await getReject(A.procOrm('u1', 'tests', 'insert', [{ id: 'a' }])))
|
|
@@ -297,7 +346,7 @@ describe('mapOrm之log標籤與訊息', function() {
|
|
|
297
346
|
it('L02 adjustData失敗之標籤含表名', async function() {
|
|
298
347
|
//R6: save、mix之add與diff三處adjustData失敗皆記表名, reject訊息為整批失敗訊息
|
|
299
348
|
let log = []
|
|
300
|
-
let A = WServOrm({ tests: {} }, mkWOrm('A', log), 'url-a', 'db-a'
|
|
349
|
+
let A = WServOrm({ tests: {} }, mkWOrm('A', log), 'url-a', 'db-a')
|
|
301
350
|
let errs = []
|
|
302
351
|
let logs = await captureLog(async () => {
|
|
303
352
|
errs.push(await getReject(A.procOrm('u1', 'tests', 'save', [{ id: 'a' }])))
|
|
@@ -313,7 +362,7 @@ describe('mapOrm之log標籤與訊息', function() {
|
|
|
313
362
|
let id150 = 'k'.repeat(150)
|
|
314
363
|
let id100 = 'm'.repeat(100)
|
|
315
364
|
let save = (d) => d.map(() => ({ n: 1, ok: 0, err: 'E' }))
|
|
316
|
-
let A = WServOrm(dsAll, mkWOrm('A', [], { save }), 'url-a', 'db-a'
|
|
365
|
+
let A = WServOrm(dsAll, mkWOrm('A', [], { save }), 'url-a', 'db-a')
|
|
317
366
|
let err1 = null
|
|
318
367
|
let err2 = null
|
|
319
368
|
let logs = await captureLog(async () => {
|
|
@@ -335,7 +384,7 @@ describe('procOrm補主鍵', function() {
|
|
|
335
384
|
it('P01 insert、save、mix之新增未帶主鍵時補值並回傳', async function() {
|
|
336
385
|
//D1: 本套件以genIDSeq補值, 回傳之id即ORM收到之id; 物件輸入回傳單一{id}
|
|
337
386
|
let log = []
|
|
338
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
387
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
339
388
|
let r1 = await A.procOrm('u1', 'tests', 'insert', [{ name: 'a' }])
|
|
340
389
|
let r2 = await A.procOrm('u1', 'tests', 'save', { name: 'b' })
|
|
341
390
|
let r3 = await A.procOrm('u1', 'tests', 'mix', { add: [{ name: 'c' }] })
|
|
@@ -348,7 +397,7 @@ describe('procOrm補主鍵', function() {
|
|
|
348
397
|
it('P02 依主鍵值決定是否補值', async function() {
|
|
349
398
|
//D1: null、空字串、物件補值; 數字與非空字串保留(reladb、mdb視數字為有效主鍵)
|
|
350
399
|
let log = []
|
|
351
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
400
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
352
401
|
let input = [{ id: null }, { id: '' }, { id: { x: 1 } }, { id: 123 }, { id: 'keep' }]
|
|
353
402
|
let r = await A.procOrm('u1', 'tests', 'save', input)
|
|
354
403
|
let got = log[0].data.map((v) => v.id)
|
|
@@ -370,7 +419,7 @@ describe('procOrm補主鍵', function() {
|
|
|
370
419
|
]
|
|
371
420
|
for (let [ds, expectGen] of dsCases) {
|
|
372
421
|
log.length = 0
|
|
373
|
-
let A = WServOrm(ds, mkWOrm('A', log), 'url-a', 'db-a'
|
|
422
|
+
let A = WServOrm(ds, mkWOrm('A', log), 'url-a', 'db-a')
|
|
374
423
|
await A.procOrm('u1', 'tests', 'insert', [{ name: 'a' }])
|
|
375
424
|
assert.strict.equal(isId(log[0].data[0].id), expectGen, JSON.stringify(ds))
|
|
376
425
|
}
|
|
@@ -379,7 +428,7 @@ describe('procOrm補主鍵', function() {
|
|
|
379
428
|
it('P04 單一空物件維持原樣交ORM', async function() {
|
|
380
429
|
//D1: 調整後無欄位之列不補, 保留ORM視空物件為無效輸入之既有行為
|
|
381
430
|
let log = []
|
|
382
|
-
let A = WServOrm({ tests: { keys: ['id', 'name'] } }, mkWOrm('A', log), 'url-a', 'db-a'
|
|
431
|
+
let A = WServOrm({ tests: { keys: ['id', 'name'] } }, mkWOrm('A', log), 'url-a', 'db-a')
|
|
383
432
|
await A.procOrm('u1', 'tests', 'save', {})
|
|
384
433
|
assert.strict.deepEqual(log[0].data, {})
|
|
385
434
|
})
|
|
@@ -387,7 +436,7 @@ describe('procOrm補主鍵', function() {
|
|
|
387
436
|
it('P05 同批多筆各自補值且呼叫端原物件不被加上主鍵', async function() {
|
|
388
437
|
//D1、D1a: 各自唯一; 補值寫在複本, 呼叫端原物件不含補出之主鍵
|
|
389
438
|
let log = []
|
|
390
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
439
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
391
440
|
let input = [{ name: 'a' }, { name: 'b' }, { name: 'c' }]
|
|
392
441
|
let r = await A.procOrm('u1', 'tests', 'insert', input)
|
|
393
442
|
let ids = r.map((v) => v.id)
|
|
@@ -399,7 +448,7 @@ describe('procOrm補主鍵', function() {
|
|
|
399
448
|
//X2: 呼叫端未帶主鍵者仍列第N筆, log保留補出之主鍵
|
|
400
449
|
let log = []
|
|
401
450
|
let save = (d) => d.map((v, k) => (k === 1 ? { n: 1, ok: 0, err: 'E' } : { n: 1, ok: 1 }))
|
|
402
|
-
let A = WServOrm(dsAll, mkWOrm('A', log, { save }), 'url-a', 'db-a'
|
|
451
|
+
let A = WServOrm(dsAll, mkWOrm('A', log, { save }), 'url-a', 'db-a')
|
|
403
452
|
let err = null
|
|
404
453
|
let logs = await captureLog(async () => {
|
|
405
454
|
err = await getReject(A.procOrm('u1', 'tests', 'save', [{ id: 's1' }, { name: 'no-id' }]))
|
|
@@ -418,7 +467,7 @@ describe('hook串接與註冊', function() {
|
|
|
418
467
|
it('K01 多個模組各註冊一個後處理皆正確', async function() {
|
|
419
468
|
//D3: 每個後處理皆收參數物件, output為前一個之回傳值
|
|
420
469
|
let log = []
|
|
421
|
-
let A = WServOrm(dsTwo, mkWOrm('A', log), 'url-a', 'db-a'
|
|
470
|
+
let A = WServOrm(dsTwo, mkWOrm('A', log), 'url-a', 'db-a')
|
|
422
471
|
A.addFunPostProcessing(({ woName, output }) => (woName !== 'users' ? output : output.map((v) => ({ ...v, tagA: 1 }))))
|
|
423
472
|
A.addFunPostProcessing(({ woName, output }) => (woName !== 'items' ? output : output.map((v) => ({ ...v, tagB: 1 }))))
|
|
424
473
|
await wait(20)
|
|
@@ -431,7 +480,7 @@ describe('hook串接與註冊', function() {
|
|
|
431
480
|
it('K02 後處理回傳undefined往下傳且拋錯即中止', async function() {
|
|
432
481
|
//D3: 不加特例; 某個拋錯則procOrm reject且後續不執行
|
|
433
482
|
let calls = []
|
|
434
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
483
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
435
484
|
A.addFunPostProcessing(() => undefined)
|
|
436
485
|
A.addFunPostProcessing((p) => {
|
|
437
486
|
calls.push(p.output)
|
|
@@ -441,7 +490,7 @@ describe('hook串接與註冊', function() {
|
|
|
441
490
|
let r = await A.procOrm('u1', 'tests', 'select', {})
|
|
442
491
|
assert.strict.equal(r, undefined)
|
|
443
492
|
assert.strict.deepEqual(calls, [undefined])
|
|
444
|
-
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b'
|
|
493
|
+
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b')
|
|
445
494
|
let after = []
|
|
446
495
|
B.addFunPostProcessing(() => {
|
|
447
496
|
throw new Error('E-post')
|
|
@@ -460,7 +509,7 @@ describe('hook串接與註冊', function() {
|
|
|
460
509
|
//P3-3: 前一個只回{input}時, 下一個仍收得到woName
|
|
461
510
|
let log = []
|
|
462
511
|
let seen = []
|
|
463
|
-
let A = WServOrm(dsTwo, mkWOrm('A', log), 'url-a', 'db-a'
|
|
512
|
+
let A = WServOrm(dsTwo, mkWOrm('A', log), 'url-a', 'db-a')
|
|
464
513
|
A.addFunPreProcessing((p) => ({ input: p.input.map((v) => ({ ...v, preA: 1 })) }))
|
|
465
514
|
A.addFunPreProcessing((p) => {
|
|
466
515
|
seen.push(p.woName)
|
|
@@ -477,7 +526,7 @@ describe('hook串接與註冊', function() {
|
|
|
477
526
|
//P3-3: 防止input成為undefined而令select回全表
|
|
478
527
|
for (let bad of [undefined, [1], { woName: 'tests' }]) {
|
|
479
528
|
let log = []
|
|
480
|
-
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a'
|
|
529
|
+
let A = WServOrm(dsAll, mkWOrm('A', log), 'url-a', 'db-a')
|
|
481
530
|
A.addFunPreProcessing(() => bad)
|
|
482
531
|
await wait(20)
|
|
483
532
|
let err = await getReject(A.procOrm('u1', 'tests', 'select', {}))
|
|
@@ -493,7 +542,7 @@ describe('hook串接與註冊', function() {
|
|
|
493
542
|
release = resolve
|
|
494
543
|
})
|
|
495
544
|
let calls = []
|
|
496
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
545
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
497
546
|
A.addFunPostProcessing(async (p) => {
|
|
498
547
|
calls.push('h1')
|
|
499
548
|
await gate
|
|
@@ -516,13 +565,13 @@ describe('hook串接與註冊', function() {
|
|
|
516
565
|
|
|
517
566
|
it('K06 註冊非函數即同步拋錯, 函數與async函數可註冊', async function() {
|
|
518
567
|
//D4: 訊息含hook名稱; 合法註冊之實例另建(A之check已因非函數註冊而被守門, 見K07)
|
|
519
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
568
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
520
569
|
for (let k of ['addFunCheck', 'addFunPreProcessing', 'addFunPostProcessing']) {
|
|
521
570
|
for (let bad of [undefined, null, 'x', {}]) {
|
|
522
571
|
assert.throws(() => A[k](bad), (e) => e instanceof Error && e.message.includes(k))
|
|
523
572
|
}
|
|
524
573
|
}
|
|
525
|
-
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b'
|
|
574
|
+
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b')
|
|
526
575
|
for (let k of ['addFunCheck', 'addFunPreProcessing', 'addFunPostProcessing']) {
|
|
527
576
|
B[k](function(p) {
|
|
528
577
|
return k === 'addFunCheck' ? undefined : (k === 'addFunPreProcessing' ? p : p.output)
|
|
@@ -536,7 +585,7 @@ describe('hook串接與註冊', function() {
|
|
|
536
585
|
|
|
537
586
|
it('K07 check註冊失敗被吞掉仍擋下呼叫, 前後處理則不影響', async function() {
|
|
538
587
|
//P3-4: check維持fail-closed; 前後處理註冊失敗時陣列不變
|
|
539
|
-
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a'
|
|
588
|
+
let A = WServOrm(dsAll, mkWOrm('A', []), 'url-a', 'db-a')
|
|
540
589
|
try {
|
|
541
590
|
A.addFunCheck(null)
|
|
542
591
|
}
|
|
@@ -546,7 +595,7 @@ describe('hook串接與註冊', function() {
|
|
|
546
595
|
assert.ok(String(err).includes('addFunCheck'))
|
|
547
596
|
//錯誤型別: 守門於procOrm內reject, 與procOrm其餘拒絕一致為字串
|
|
548
597
|
assert.strict.equal(typeof err, 'string')
|
|
549
|
-
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b'
|
|
598
|
+
let B = WServOrm(dsAll, mkWOrm('B', []), 'url-b', 'db-b')
|
|
550
599
|
for (let k of ['addFunPreProcessing', 'addFunPostProcessing']) {
|
|
551
600
|
try {
|
|
552
601
|
B[k](null)
|
|
@@ -558,10 +607,4 @@ describe('hook串接與註冊', function() {
|
|
|
558
607
|
assert.strict.equal(r.length, 2)
|
|
559
608
|
})
|
|
560
609
|
|
|
561
|
-
it('K08 src/getItemsFail.mjs相容檔轉出w-data-collector之版本', async function() {
|
|
562
|
-
//X1: 使用端以深層路徑引用(如w-web-sso server/ormWrite.mjs)
|
|
563
|
-
let m = await import('../src/getItemsFail.mjs')
|
|
564
|
-
assert.strict.equal(m.default, getItemsFailWdc)
|
|
565
|
-
})
|
|
566
|
-
|
|
567
610
|
})
|
|
@@ -41,7 +41,7 @@ async function getReject(pm) {
|
|
|
41
41
|
|
|
42
42
|
describe('mapOrm逐筆失敗', function() {
|
|
43
43
|
|
|
44
|
-
let so = WServOrm(ds, WOrmStub, 'stub-url', 'stub-db'
|
|
44
|
+
let so = WServOrm(ds, WOrmStub, 'stub-url', 'stub-db')
|
|
45
45
|
let proc = (mode, input) => so.procOrm('u1', 'tests', mode, input)
|
|
46
46
|
|
|
47
47
|
beforeEach(function() {
|
|
@@ -232,7 +232,7 @@ describe('mapOrm逐筆失敗', function() {
|
|
|
232
232
|
|
|
233
233
|
describe('mapOrm主鍵與clearXSS', function() {
|
|
234
234
|
|
|
235
|
-
let so = WServOrm(ds, WOrmStub, 'stub-url', 'stub-db'
|
|
235
|
+
let so = WServOrm(ds, WOrmStub, 'stub-url', 'stub-db')
|
|
236
236
|
let proc = (mode, input) => so.procOrm('u1', 'tests', mode, input)
|
|
237
237
|
|
|
238
238
|
beforeEach(function() {
|