w-orm-mongodb 1.2.6 → 1.2.7
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/README.md +57 -2
- package/dist/w-orm-mongodb.umd.js +2 -2
- package/dist/w-orm-mongodb.umd.js.map +1 -1
- package/docs/WOrmMongodb.html +60 -21
- package/docs/WOrmMongodb.mjs.html +99 -18
- package/docs/index.html +1 -1
- package/g-basic.mjs +4 -2
- package/package.json +2 -2
- package/src/WOrmMongodb.mjs +98 -17
- package/test/api-basic.test.mjs +4 -4
- package/test/api-find-whitelist-gfs.test.mjs +489 -0
- package/test/api-find-whitelist.test.mjs +540 -0
package/src/WOrmMongodb.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import get from 'lodash-es/get.js'
|
|
|
8
8
|
import map from 'lodash-es/map.js'
|
|
9
9
|
import omit from 'lodash-es/omit.js'
|
|
10
10
|
import size from 'lodash-es/size.js'
|
|
11
|
+
import cvOrmFind from 'wsemi/src/cvOrmFind.mjs'
|
|
11
12
|
import evem from 'wsemi/src/evem.mjs'
|
|
12
13
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
13
14
|
import genIDSeq from 'wsemi/src/genIDSeq.mjs'
|
|
@@ -300,20 +301,34 @@ function WOrmMongodb(opt = {}) {
|
|
|
300
301
|
/**
|
|
301
302
|
* 查詢數據
|
|
302
303
|
*
|
|
304
|
+
* 條件(find)僅支援系列白名單,規則同delAll之第1-3點,詳見README之條件(find)白名單:
|
|
305
|
+
* 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與$in $nin(值為純量陣列)、
|
|
306
|
+
* 文件層$and $or(值為條件物件之非空陣列);未給、undefined或{}回傳全部數據;
|
|
307
|
+
* 非條件物件或白名單外之輸入(如$regex $where $exists $not $nor、點路徑、undefined值、函數值)整批reject,
|
|
308
|
+
* 訊息為invalid find: 原因 at [路徑],且不連線、不讀取。
|
|
309
|
+
* 語意差異(MongoDB式):$ne(比較值非null)與$nin會命中欄位為null或缺欄之數據,$ne:null則僅命中欄位存在且非null者,需明確表達時可用可攜寫法,
|
|
310
|
+
* 排除null為{$and:[{f:{$ne:null}},{f:{$ne:x}}]},含null為{$or:[{f:null},{f:{$ne:x}}]}。
|
|
311
|
+
*
|
|
303
312
|
* @memberOf WOrmMongodb
|
|
304
|
-
* @param {Object} [find={}] 輸入查詢條件物件
|
|
313
|
+
* @param {Object} [find={}] 輸入查詢條件物件(系列白名單,規則同delAll之第1-3點),未給、undefined或{}回傳全部數據,非條件物件或白名單外運算子整批reject
|
|
305
314
|
* @returns {Promise} 回傳Promise,resolve回傳數據陣列,無符合數據回傳空陣列,reject回傳錯誤訊息
|
|
306
315
|
*/
|
|
307
316
|
async function select(find = {}) {
|
|
308
317
|
let isErr = false
|
|
309
318
|
|
|
310
319
|
//client
|
|
311
|
-
let client =
|
|
320
|
+
let client = null
|
|
312
321
|
|
|
313
322
|
//res
|
|
314
323
|
let res = null
|
|
315
324
|
try {
|
|
316
325
|
|
|
326
|
+
//cvOrmFind, 須先於建立client與任何讀取, 不合白名單者往外拋(整批性錯誤), 其後一律只用檢核後之複本(檢查之值即使用之值)
|
|
327
|
+
find = cvOrmFind(find)
|
|
328
|
+
|
|
329
|
+
//client
|
|
330
|
+
client = new MongoClient(opt.url)
|
|
331
|
+
|
|
317
332
|
//database, collection
|
|
318
333
|
let database = client.db(opt.db)
|
|
319
334
|
let collection = database.collection(opt.cl)
|
|
@@ -336,8 +351,13 @@ function WOrmMongodb(opt = {}) {
|
|
|
336
351
|
res = err
|
|
337
352
|
}
|
|
338
353
|
finally {
|
|
339
|
-
|
|
340
|
-
client
|
|
354
|
+
|
|
355
|
+
//client, 條件檢核失敗時尚未建立
|
|
356
|
+
if (client !== null) {
|
|
357
|
+
await client.close()
|
|
358
|
+
client = null
|
|
359
|
+
}
|
|
360
|
+
|
|
341
361
|
}
|
|
342
362
|
|
|
343
363
|
//check
|
|
@@ -1098,23 +1118,46 @@ function WOrmMongodb(opt = {}) {
|
|
|
1098
1118
|
|
|
1099
1119
|
|
|
1100
1120
|
/**
|
|
1101
|
-
*
|
|
1121
|
+
* 依條件刪除多筆數據(破壞性操作,須審慎使用,非必要不用;刪除單筆請用del),需與del分開,避免未傳數據導致直接刪除全表
|
|
1122
|
+
*
|
|
1123
|
+
* 使用須知:
|
|
1124
|
+
* 1. 不給條件即刪除全部數據:find未給、為undefined或為{}時,刪除資料表內全部數據,不另行確認。給了條件才是部分刪除。
|
|
1125
|
+
* 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等),
|
|
1126
|
+
* 一律整批reject,不視為{},不刪除任何數據。
|
|
1127
|
+
* 3. 條件僅支援系列白名單:欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與
|
|
1128
|
+
* $in $nin(值為純量陣列)、文件層$and $or(值為條件物件之非空陣列,最多1000項)。純量為字串、有限數字、布林、有效Date;
|
|
1129
|
+
* null僅可用於欄位等值、$eq、$ne。白名單外之運算子($not $nor $regex $options $exists $where $expr $text等)、
|
|
1130
|
+
* 欄位層$and/$or、點路徑、函數值、Symbol鍵、undefined值、空的$nin/$and/$or等一律整批reject,
|
|
1131
|
+
* 訊息為invalid find: 原因 at [路徑],且不連線、不刪除任何數據。
|
|
1132
|
+
* 4. 與select共用同一檢核與同一條件,select(find)命中之數據即本函數刪除之數據;
|
|
1133
|
+
* 建議先以select(find)確認命中範圍再刪除。
|
|
1134
|
+
* 5. 條件值若來自可能為undefined、null或空陣列之變數,呼叫端須先自行判斷;undefined值會reject而非被忽略,
|
|
1135
|
+
* 空的$nin會reject,$in:[]則為恆假(刪除0筆)。
|
|
1136
|
+
* 6. 語意差異(MongoDB式,依伺服器原生行為,見README):$ne(比較值非null)與$nin會命中欄位為null或缺欄之數據,$ne:null則僅命中欄位存在且非null者。
|
|
1137
|
+
* 需明確表達時可用可攜寫法:排除null為{$and:[{f:{$ne:null}},{f:{$ne:x}}]},含null為{$or:[{f:null},{f:{$ne:x}}]}。
|
|
1138
|
+
*
|
|
1102
1139
|
* 註: n為實際刪除筆數,恆等於nDeleted;條件無命中時回傳0亦屬正常結果
|
|
1103
1140
|
*
|
|
1104
1141
|
* @memberOf WOrmMongodb
|
|
1105
|
-
* @param {Object} [find={}] 輸入刪除條件物件
|
|
1142
|
+
* @param {Object} [find={}] 輸入刪除條件物件(系列白名單,規則見使用須知),不給予find則代表刪除全部數據
|
|
1106
1143
|
* @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
|
|
1107
1144
|
*/
|
|
1108
1145
|
async function delAll(find = {}) {
|
|
1109
1146
|
let isErr = false
|
|
1110
1147
|
|
|
1111
1148
|
//client
|
|
1112
|
-
let client =
|
|
1149
|
+
let client = null
|
|
1113
1150
|
|
|
1114
1151
|
//res
|
|
1115
1152
|
let res = null
|
|
1116
1153
|
try {
|
|
1117
1154
|
|
|
1155
|
+
//cvOrmFind, 須先於建立client與任何刪除, 不合白名單者往外拋(整批性錯誤), 其後一律只用檢核後之複本(檢查之值即使用之值), 複本無自有鍵代表全部
|
|
1156
|
+
find = cvOrmFind(find)
|
|
1157
|
+
|
|
1158
|
+
//client
|
|
1159
|
+
client = new MongoClient(opt.url)
|
|
1160
|
+
|
|
1118
1161
|
//database, collection
|
|
1119
1162
|
let database = client.db(opt.db)
|
|
1120
1163
|
let collection = database.collection(opt.cl)
|
|
@@ -1138,8 +1181,13 @@ function WOrmMongodb(opt = {}) {
|
|
|
1138
1181
|
res = err
|
|
1139
1182
|
}
|
|
1140
1183
|
finally {
|
|
1141
|
-
|
|
1142
|
-
client
|
|
1184
|
+
|
|
1185
|
+
//client, 條件檢核失敗時尚未建立
|
|
1186
|
+
if (client !== null) {
|
|
1187
|
+
await client.close()
|
|
1188
|
+
client = null
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1143
1191
|
}
|
|
1144
1192
|
|
|
1145
1193
|
//emit
|
|
@@ -1380,6 +1428,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
1380
1428
|
|
|
1381
1429
|
|
|
1382
1430
|
//_findGfs, 內部查找函數, 其reject由delGfs與delAllGfs之catch接住並於該處發出error事件, 故本函數不自行發出
|
|
1431
|
+
//註: bucket.find之唯一入口, 條件(find)須符合系列白名單, 故於查找前再經cvOrmFind(對delAllGfs已檢核之複本為冪等), delGfs逐筆之{ filename: id }亦經此
|
|
1383
1432
|
async function _findGfs(find = {}, bucket) {
|
|
1384
1433
|
let isErr = false
|
|
1385
1434
|
|
|
@@ -1387,6 +1436,9 @@ function WOrmMongodb(opt = {}) {
|
|
|
1387
1436
|
let res = null
|
|
1388
1437
|
try {
|
|
1389
1438
|
|
|
1439
|
+
//cvOrmFind, 不合白名單者往外拋, 其後只用檢核後之複本
|
|
1440
|
+
find = cvOrmFind(find)
|
|
1441
|
+
|
|
1390
1442
|
//find
|
|
1391
1443
|
let cursor = bucket.find(find)
|
|
1392
1444
|
|
|
@@ -1409,6 +1461,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
1409
1461
|
/**
|
|
1410
1462
|
* 使用GridFS,刪除數據
|
|
1411
1463
|
* 註: n為id命中筆數;未帶有效id者視為本筆無法處理,以ok為0並附err回報;
|
|
1464
|
+
* id含NUL或孤立代理字元者不符系列條件白名單,尚未查找即以ok為0、n為0並附err(invalid find: ...)回報,不影響同批其他筆;
|
|
1412
1465
|
* 判斷本筆是否真的被刪除一律以nDeleted為準
|
|
1413
1466
|
*
|
|
1414
1467
|
* @memberOf WOrmMongodb
|
|
@@ -1495,12 +1548,15 @@ function WOrmMongodb(opt = {}) {
|
|
|
1495
1548
|
|
|
1496
1549
|
//本筆失敗不中斷整批
|
|
1497
1550
|
|
|
1498
|
-
//
|
|
1551
|
+
//errMsg
|
|
1552
|
+
let errMsg = getErrMsg(err)
|
|
1553
|
+
|
|
1554
|
+
//rest, 條件未通過白名單檢核者(id含NUL或孤立代理字元)尚未查找, 視同無效id而n為0, 其餘為查找或刪除途中失敗, 本筆已嘗試而n為1
|
|
1499
1555
|
rest = {
|
|
1500
|
-
n: 1,
|
|
1556
|
+
n: errMsg.indexOf('invalid find: ') === 0 ? 0 : 1,
|
|
1501
1557
|
nDeleted: 0,
|
|
1502
1558
|
ok: 0,
|
|
1503
|
-
err:
|
|
1559
|
+
err: errMsg,
|
|
1504
1560
|
}
|
|
1505
1561
|
|
|
1506
1562
|
}
|
|
@@ -1551,24 +1607,44 @@ function WOrmMongodb(opt = {}) {
|
|
|
1551
1607
|
|
|
1552
1608
|
|
|
1553
1609
|
/**
|
|
1554
|
-
* 使用GridFS
|
|
1610
|
+
* 使用GridFS,依條件刪除多筆數據(破壞性操作,須審慎使用,非必要不用;刪除單筆請用delGfs),需與delGfs分開,避免未傳數據導致直接刪除全部
|
|
1611
|
+
*
|
|
1612
|
+
* 使用須知:
|
|
1613
|
+
* 1. 不給條件即刪除全部數據:find未給、為undefined或為{}時,刪除全部檔案,不另行確認。給了條件才是部分刪除。
|
|
1614
|
+
* 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等),
|
|
1615
|
+
* 一律整批reject,不視為{},不刪除任何數據。
|
|
1616
|
+
* 3. 條件僅支援系列白名單,規則與delAll相同,條件作用於GridFS之<cl>.files文件(欄位如filename、length、uploadDate):
|
|
1617
|
+
* 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與$in $nin(值為純量陣列)、
|
|
1618
|
+
* 文件層$and $or(值為條件物件之非空陣列,最多1000項)。白名單外之運算子($not $nor $regex $options $exists $where $expr $text等)、
|
|
1619
|
+
* 欄位層$and/$or、點路徑(如metadata.*)、函數值、Symbol鍵、undefined值、空的$nin/$and/$or等一律整批reject,
|
|
1620
|
+
* 訊息為invalid find: 原因 at [路徑],且不連線、不刪除任何數據。
|
|
1621
|
+
* 4. 條件值若來自可能為undefined、null或空陣列之變數,呼叫端須先自行判斷;undefined值會reject而非被忽略,
|
|
1622
|
+
* 空的$nin會reject,$in:[]則為恆假(刪除0筆)。
|
|
1623
|
+
* 5. 語意差異(MongoDB式,依伺服器原生行為):$ne(比較值非null)與$nin會命中欄位為null或缺欄之數據,$ne:null則僅命中欄位存在且非null者。
|
|
1624
|
+
*
|
|
1555
1625
|
* 註: n為實際刪除筆數,恆等於nDeleted;條件無命中時回傳0亦屬正常結果
|
|
1556
1626
|
* 本函數不建立唯一索引,以免既有數據尚存重複id時無法清除
|
|
1557
1627
|
*
|
|
1558
1628
|
* @memberOf WOrmMongodb
|
|
1559
|
-
* @param {Object} [find={}] 輸入刪除條件物件
|
|
1629
|
+
* @param {Object} [find={}] 輸入刪除條件物件(系列白名單,規則見使用須知),不給予find則代表刪除全部數據
|
|
1560
1630
|
* @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
|
|
1561
1631
|
*/
|
|
1562
1632
|
async function delAllGfs(find = {}) {
|
|
1563
1633
|
let isErr = false
|
|
1564
1634
|
|
|
1565
1635
|
//client
|
|
1566
|
-
let client =
|
|
1636
|
+
let client = null
|
|
1567
1637
|
|
|
1568
1638
|
//res
|
|
1569
1639
|
let res = null
|
|
1570
1640
|
try {
|
|
1571
1641
|
|
|
1642
|
+
//cvOrmFind, 須先於建立client與任何刪除, 不合白名單者往外拋(整批性錯誤), 其後一律只用檢核後之複本(檢查之值即使用之值), 複本無自有鍵代表全部
|
|
1643
|
+
find = cvOrmFind(find)
|
|
1644
|
+
|
|
1645
|
+
//client
|
|
1646
|
+
client = new MongoClient(opt.url)
|
|
1647
|
+
|
|
1572
1648
|
//database
|
|
1573
1649
|
let database = client.db(opt.db)
|
|
1574
1650
|
|
|
@@ -1606,8 +1682,13 @@ function WOrmMongodb(opt = {}) {
|
|
|
1606
1682
|
res = err
|
|
1607
1683
|
}
|
|
1608
1684
|
finally {
|
|
1609
|
-
|
|
1610
|
-
client
|
|
1685
|
+
|
|
1686
|
+
//client, 條件檢核失敗時尚未建立
|
|
1687
|
+
if (client !== null) {
|
|
1688
|
+
await client.close()
|
|
1689
|
+
client = null
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1611
1692
|
}
|
|
1612
1693
|
|
|
1613
1694
|
//emit
|
package/test/api-basic.test.mjs
CHANGED
|
@@ -290,9 +290,9 @@ describe('basic', function() {
|
|
|
290
290
|
})
|
|
291
291
|
vget[8] = rt
|
|
292
292
|
|
|
293
|
-
//select by regex, $options
|
|
293
|
+
//select by regex, $regex與$options不在系列條件白名單內, 須於到達伺服器之前reject
|
|
294
294
|
rt = null
|
|
295
|
-
// vans[9] =
|
|
295
|
+
// vans[9] = 'Error: invalid find: unsupported operator [$regex] at [find.name.$regex]'
|
|
296
296
|
await wo.select({ name: { $regex: 'PeT', $options: 'i' } })
|
|
297
297
|
.then(function(msg) {
|
|
298
298
|
rt = msg
|
|
@@ -421,8 +421,8 @@ describe('basic', function() {
|
|
|
421
421
|
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
422
422
|
})
|
|
423
423
|
|
|
424
|
-
vans[9] =
|
|
425
|
-
it(`should get ${JSON.stringify(vans[9])} for select by regex`, async function() {
|
|
424
|
+
vans[9] = 'Error: invalid find: unsupported operator [$regex] at [find.name.$regex]'
|
|
425
|
+
it(`should get ${JSON.stringify(vans[9])} for select by regex (not in whitelist)`, async function() {
|
|
426
426
|
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
427
427
|
})
|
|
428
428
|
|