@pi-r/redis 0.6.0 → 0.6.1
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/client/index.js +145 -71
- package/package.json +3 -3
- package/types/index.d.ts +26 -10
package/client/index.js
CHANGED
|
@@ -229,13 +229,12 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
229
229
|
continue;
|
|
230
230
|
}
|
|
231
231
|
item.transactionState = 1 /* DB_TRANSACTION.ACTIVE */;
|
|
232
|
+
const command = (0, types_1.isPlainObject)(clientOptions.command) ? redis.commandOptions(clientOptions.command) : null;
|
|
232
233
|
const uuidKey = (credential.uuidKey || (credential.uuidKey = (onceCredential ? batch[0] : item).credential?.uuidKey));
|
|
233
234
|
const targetObject = typeof checkObject === 'string' ? this.hasCoerce("redis" /* STRINGS.MODULE_NAME */, 'options', uuidKey) && (0, types_1.asFunction)(checkObject) : checkObject;
|
|
234
|
-
const
|
|
235
|
-
const cacheValue = renewCache ? { sessionKey, renewCache } : sessionKey;
|
|
236
|
-
const command = (0, types_1.isPlainObject)(clientOptions.command) ? redis.commandOptions(clientOptions.command) : null;
|
|
235
|
+
const cacheValue = ignoreCache === undefined ? sessionKey : Array.isArray(ignoreCache) ? { sessionKey, exclusiveOf: ignoreCache } : { sessionKey, renewCache: ignoreCache === 0 };
|
|
237
236
|
let queryString = '', rows;
|
|
238
|
-
if (caching && ignoreCache !== true
|
|
237
|
+
if (caching && ignoreCache !== true) {
|
|
239
238
|
if ((0, types_1.isObject)(search)) {
|
|
240
239
|
queryString = Db.asString(search, true);
|
|
241
240
|
}
|
|
@@ -288,63 +287,128 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
288
287
|
commandType = this.commandType.UPDATE;
|
|
289
288
|
const values = (!Array.isArray(update) ? [update] : update).map(async (target) => {
|
|
290
289
|
return new Promise(async (success, failed) => {
|
|
291
|
-
let { key: k, value: v, format: f
|
|
292
|
-
|
|
290
|
+
let { key: k, value: v, format: f, NX, XX, options: setOptions = {} } = target;
|
|
291
|
+
f = ((0, types_1.isString)(f) ? f.toUpperCase() : 'HASH');
|
|
292
|
+
if (v === undefined && f !== 'JSON') {
|
|
293
293
|
success(target);
|
|
294
294
|
return;
|
|
295
295
|
}
|
|
296
|
+
const has = (n) => typeof n === 'number' && n > 0;
|
|
296
297
|
const failKey = () => failed((0, types_1.errorMessage)(f, "Invalid key" /* ERR_DB.KEY */, Db.asString(k) || "Unknown" /* ERR_MESSAGE.UNKNOWN */));
|
|
297
298
|
const failValue = () => failed((0, types_1.errorMessage)(f, "Invalid value" /* ERR_DB.VALUE */, Db.asString(v) || "Unknown" /* ERR_MESSAGE.UNKNOWN */));
|
|
298
299
|
const commandSet = (0, types_1.isPlainObject)(setOptions.command) && redis.commandOptions(setOptions.command);
|
|
299
|
-
let pending;
|
|
300
|
-
if (
|
|
300
|
+
let pending, codeMin = 0, EX, PX, EXAT, PXAT, KEEPTTL;
|
|
301
|
+
if (f === 'JSON') {
|
|
301
302
|
if (typeof k !== 'string') {
|
|
302
303
|
failKey();
|
|
303
304
|
return;
|
|
304
305
|
}
|
|
305
|
-
const path = target.path || '$';
|
|
306
306
|
if (this.hasCoerce("redis" /* STRINGS.MODULE_NAME */, 'options', uuidKey)) {
|
|
307
307
|
if ((0, types_1.isString)(v) && v.startsWith('new')) {
|
|
308
308
|
({ outV: v } = (0, types_1.coerceObject)({ outV: v }));
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
|
-
|
|
312
|
-
|
|
311
|
+
let { path = '$', command: cmd, start, stop, index } = target;
|
|
312
|
+
const name = ((0, types_1.isString)(cmd) ? cmd.toUpperCase() : 'SET');
|
|
313
|
+
if (Array.isArray(v) && name !== 'ARRAPPEND' && name !== 'ARRINSERT' && name !== 'MSET') {
|
|
314
|
+
v = v[0];
|
|
315
|
+
}
|
|
316
|
+
switch (name) {
|
|
317
|
+
case 'ARRAPPEND':
|
|
318
|
+
pending = commandSet ? client.json.arrAppend(commandSet, k, path, ...(Array.isArray(v) ? v : [v])) : client.json.arrAppend(k, path, ...(Array.isArray(v) ? v : [v]));
|
|
319
|
+
break;
|
|
320
|
+
case 'ARRINDEX':
|
|
321
|
+
codeMin = -1;
|
|
322
|
+
pending = commandSet ? client.json.arrIndex(commandSet, k, path, v, start, stop) : client.json.arrIndex(k, path, v, start, stop);
|
|
323
|
+
break;
|
|
324
|
+
case 'ARRINSERT':
|
|
325
|
+
if (typeof index === 'number' || (0, types_1.isString)(index) && !isNaN(index = parseInt(index))) {
|
|
326
|
+
pending = commandSet ? client.json.arrInsert(commandSet, k, path, index, ...(Array.isArray(v) ? v : [v])) : client.json.arrInsert(k, path, index, ...(Array.isArray(v) ? v : [v]));
|
|
327
|
+
}
|
|
328
|
+
break;
|
|
329
|
+
case 'ARRPOP':
|
|
330
|
+
codeMin = -Infinity;
|
|
331
|
+
pending = commandSet ? client.json.arrPop(commandSet, k, path, index) : client.json.arrPop(k, path, index);
|
|
332
|
+
break;
|
|
333
|
+
case 'ARRTRIM':
|
|
334
|
+
if ((typeof start === 'number' || (0, types_1.isString)(start) && !isNaN(start = parseInt(start))) && (typeof stop === 'number' || (0, types_1.isString)(stop) && !isNaN(stop = parseInt(stop)))) {
|
|
335
|
+
pending = commandSet ? client.json.arrTrim(commandSet, k, path, start, stop) : client.json.arrTrim(k, path, start, stop);
|
|
336
|
+
}
|
|
337
|
+
break;
|
|
338
|
+
case 'DEL':
|
|
339
|
+
case 'FORGET':
|
|
340
|
+
pending = commandSet ? client.json[name === 'DEL' ? 'del' : 'forget'](commandSet, k, path) : client.json[name === 'DEL' ? 'del' : 'forget'](k, path);
|
|
341
|
+
break;
|
|
342
|
+
case 'MERGE':
|
|
343
|
+
pending = commandSet ? client.json.merge(commandSet, k, path, v) : client.json.merge(k, path, v);
|
|
344
|
+
break;
|
|
345
|
+
case 'MSET': {
|
|
346
|
+
const data = (Array.isArray(v) ? v : [v])
|
|
347
|
+
.filter((m) => m.value !== undefined)
|
|
348
|
+
.map((m) => {
|
|
349
|
+
m.key || (m.key = k);
|
|
350
|
+
m.path || (m.path = path);
|
|
351
|
+
return m;
|
|
352
|
+
});
|
|
353
|
+
if (data.length) {
|
|
354
|
+
pending = commandSet ? client.json.mSet(commandSet, data) : client.json.mSet(data);
|
|
355
|
+
}
|
|
356
|
+
break;
|
|
357
|
+
}
|
|
358
|
+
case 'NUMINCRBY':
|
|
359
|
+
case 'NUMMULTBY':
|
|
360
|
+
if (typeof v === 'number' || (0, types_1.isString)(v) && !isNaN(v = parseFloat(v))) {
|
|
361
|
+
pending = commandSet ? client.json[name === 'NUMINCRBY' ? 'numIncrBy' : 'numMultBy'](commandSet, k, path, v) : client.json[name === 'NUMINCRBY' ? 'numIncrBy' : 'numMultBy'](k, path, v);
|
|
362
|
+
}
|
|
363
|
+
break;
|
|
364
|
+
case 'STRAPPEND':
|
|
365
|
+
if ((0, types_1.isString)(v)) {
|
|
366
|
+
pending = commandSet ? client.json.strAppend(commandSet, k, path, v) : client.json.strAppend(k, path, v);
|
|
367
|
+
}
|
|
368
|
+
break;
|
|
369
|
+
default: {
|
|
370
|
+
const flags = NX ? { NX } : XX ? { XX } : undefined;
|
|
371
|
+
pending = commandSet ? client.json.set(commandSet, k, path, v, flags) : client.json.set(k, path, v, flags);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
313
375
|
}
|
|
314
376
|
else if (typeof k === 'string' || Buffer.isBuffer(k)) {
|
|
377
|
+
({ EX, PX, EXAT, PXAT, KEEPTTL } = target);
|
|
315
378
|
const field = target.field;
|
|
316
379
|
if (field === undefined && field === null) {
|
|
317
380
|
if (a(v)) {
|
|
318
|
-
const flags = setOptions.set;
|
|
319
|
-
if (
|
|
320
|
-
|
|
321
|
-
NX ?? (NX = !!flags.NX);
|
|
322
|
-
delete flags.NX;
|
|
323
|
-
}
|
|
324
|
-
if ('XX' in flags) {
|
|
325
|
-
XX ?? (XX = !!flags.XX);
|
|
326
|
-
delete flags.XX;
|
|
327
|
-
}
|
|
328
|
-
if ('EX' in flags) {
|
|
329
|
-
EX || (EX = flags.EX);
|
|
330
|
-
delete flags.EX;
|
|
331
|
-
}
|
|
332
|
-
if ('PX' in flags) {
|
|
333
|
-
PX || (PX = flags.PX);
|
|
334
|
-
delete flags.PX;
|
|
335
|
-
}
|
|
336
|
-
if ('EXAT' in flags) {
|
|
337
|
-
EXAT || (EXAT = flags.EXAT);
|
|
338
|
-
delete flags.EXAT;
|
|
339
|
-
}
|
|
340
|
-
if ('PXAT' in flags) {
|
|
341
|
-
PXAT || (PXAT = flags.PXAT);
|
|
342
|
-
delete flags.PXAT;
|
|
343
|
-
}
|
|
381
|
+
const flags = setOptions.set || {};
|
|
382
|
+
if (NX) {
|
|
383
|
+
flags.NX = true;
|
|
344
384
|
}
|
|
345
|
-
|
|
385
|
+
if (XX) {
|
|
386
|
+
flags.XX = true;
|
|
387
|
+
}
|
|
388
|
+
if (has(EX)) {
|
|
389
|
+
flags.EX = EX;
|
|
390
|
+
EX = 0;
|
|
391
|
+
}
|
|
392
|
+
if (has(PX)) {
|
|
393
|
+
flags.PX = PX;
|
|
394
|
+
PX = 0;
|
|
395
|
+
}
|
|
396
|
+
if (has(EXAT)) {
|
|
397
|
+
flags.EXAT = EXAT;
|
|
398
|
+
EXAT = 0;
|
|
399
|
+
}
|
|
400
|
+
if (has(PXAT)) {
|
|
401
|
+
flags.PXAT = PXAT;
|
|
402
|
+
PXAT = 0;
|
|
403
|
+
}
|
|
404
|
+
if (KEEPTTL) {
|
|
405
|
+
flags.KEEPTTL = true;
|
|
406
|
+
KEEPTTL = false;
|
|
407
|
+
}
|
|
408
|
+
codeMin = NaN;
|
|
409
|
+
pending = commandSet ? client.set(commandSet, k, v, flags) : client.set(k, v, flags);
|
|
346
410
|
}
|
|
347
|
-
else if (
|
|
411
|
+
else if ((0, types_1.isObject)(v)) {
|
|
348
412
|
let valid = true;
|
|
349
413
|
if (NX || XX) {
|
|
350
414
|
valid = await client.exists(k) === 1;
|
|
@@ -361,6 +425,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
361
425
|
}
|
|
362
426
|
else if (NX) {
|
|
363
427
|
if (a(field) && a(v)) {
|
|
428
|
+
codeMin = -1;
|
|
364
429
|
pending = commandSet ? client.hSetNX(commandSet, k, b(field), b(v)) : client.hSetNX(k, b(field), b(v));
|
|
365
430
|
}
|
|
366
431
|
}
|
|
@@ -383,43 +448,52 @@ async function executeBatchQuery(batch, options = '', outResult) {
|
|
|
383
448
|
return;
|
|
384
449
|
}
|
|
385
450
|
if (pending) {
|
|
386
|
-
pending.then(code => {
|
|
387
|
-
if (code === 'OK' || typeof code === 'number' || code ===
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
451
|
+
pending.then(async (code) => {
|
|
452
|
+
if (code === undefined || code === null || code !== -Infinity && (0, types_1.isString)(code) && code !== 'OK' || typeof code === 'number' && code <= codeMin || Array.isArray(code) && code.every(resp => resp === null || typeof resp === 'number' && resp <= codeMin)) {
|
|
453
|
+
failValue();
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
let ttl = false;
|
|
457
|
+
if (!isNaN(codeMin) && (has(EX) || has(PX) || has(EXAT) || has(PXAT) || (ttl = !!KEEPTTL))) {
|
|
458
|
+
const expire = setOptions.expire;
|
|
459
|
+
let mode;
|
|
460
|
+
if (expire) {
|
|
461
|
+
if (expire.NX) {
|
|
462
|
+
mode = 'NX';
|
|
463
|
+
}
|
|
464
|
+
else if (expire.XX) {
|
|
465
|
+
mode = 'XX';
|
|
466
|
+
}
|
|
467
|
+
else if (expire.GT) {
|
|
468
|
+
mode = 'GT';
|
|
469
|
+
}
|
|
470
|
+
else if (expire.LT) {
|
|
471
|
+
mode = 'LT';
|
|
405
472
|
}
|
|
406
|
-
(has(EX) ? client.expire(k, EX, mode) : has(PX) ? client.pExpire(k, PX, mode) : EXAT > 0 ? client.expireAt(k, EXAT, mode) : client.pExpireAt(k, PXAT, mode))
|
|
407
|
-
.then(valid => {
|
|
408
|
-
if (valid) {
|
|
409
|
-
success(target);
|
|
410
|
-
}
|
|
411
|
-
else {
|
|
412
|
-
failed((0, types_1.errorMessage)(f, "Invalid value" /* ERR_DB.VALUE */, has(EX) ? 'EX: ' + EX : has(PX) ? 'PX: ' + PX : EXAT > 0 ? 'EXAT: ' + EX : 'PXAT: ' + PXAT));
|
|
413
|
-
}
|
|
414
|
-
})
|
|
415
|
-
.catch(err => failed(err));
|
|
416
473
|
}
|
|
417
|
-
|
|
418
|
-
|
|
474
|
+
if (ttl) {
|
|
475
|
+
PX = await client.pTTL(k).catch(err => {
|
|
476
|
+
failed(err);
|
|
477
|
+
return 0;
|
|
478
|
+
});
|
|
479
|
+
if (PX <= 0) {
|
|
480
|
+
success(target);
|
|
481
|
+
return;
|
|
482
|
+
}
|
|
419
483
|
}
|
|
484
|
+
(has(EX) ? client.expire(k, EX, mode) : has(PX) ? client.pExpire(k, PX, mode) : has(EXAT) ? client.expireAt(k, EXAT, mode) : client.pExpireAt(k, PXAT, mode))
|
|
485
|
+
.then(valid => {
|
|
486
|
+
if (valid) {
|
|
487
|
+
success(target);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
failed((0, types_1.errorMessage)(f, "Invalid value" /* ERR_DB.VALUE */, has(EX) ? 'EX: ' + EX : has(PX) ? 'PX: ' + PX : has(EXAT) ? 'EXAT: ' + EX : 'PXAT: ' + PXAT));
|
|
491
|
+
}
|
|
492
|
+
})
|
|
493
|
+
.catch(err => failed(err));
|
|
420
494
|
}
|
|
421
495
|
else {
|
|
422
|
-
|
|
496
|
+
success(target);
|
|
423
497
|
}
|
|
424
498
|
})
|
|
425
499
|
.catch(err => failed(err));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-r/redis",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Redis client driver for E-mc.",
|
|
5
5
|
"main": "client/index.js",
|
|
6
6
|
"types": "client/index.d.ts",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"homepage": "https://github.com/anpham6/pi-r#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@e-mc/db": "^0.8.
|
|
25
|
-
"@e-mc/types": "^0.8.
|
|
24
|
+
"@e-mc/db": "^0.8.1",
|
|
25
|
+
"@e-mc/types": "^0.8.1",
|
|
26
26
|
"redis": "^4.6.12"
|
|
27
27
|
}
|
|
28
28
|
}
|
package/types/index.d.ts
CHANGED
|
@@ -3,11 +3,11 @@ import type { DbDataSource } from '@e-mc/types/lib/squared';
|
|
|
3
3
|
import type { CascadeAction, ExecuteAction, ServerAuth } from '@e-mc/types/lib/db';
|
|
4
4
|
|
|
5
5
|
import type { CommandOptions } from '@redis/client/dist/lib/command-options';
|
|
6
|
-
import type { ClientCommandOptions } from '@redis/client/dist/lib/client';
|
|
6
|
+
import type { ClientCommandOptions, JMSetItem } from '@redis/client/dist/lib/client';
|
|
7
7
|
import type { RedisClientOptions } from '@redis/client';
|
|
8
8
|
import type { RedisCommandArgument } from '@redis/client/dist/lib/commands';
|
|
9
9
|
import type { RedisJSON } from '@redis/json/dist/commands';
|
|
10
|
-
import type { AggregateOptions, RediSearchSchema, SearchOptions } from 'redis';
|
|
10
|
+
import type { AggregateOptions, RediSearchSchema, SearchOptions, SetOptions } from 'redis';
|
|
11
11
|
|
|
12
12
|
export interface RedisDataSource extends DbDataSource<string, PlainObject, ArrayOf<RedisSetValue> | ArrayOf<RedisJSONValue>, string | RedisCredential, string>, CascadeAction, AuthValue {
|
|
13
13
|
source: "redis";
|
|
@@ -29,26 +29,35 @@ export interface RedisDataSource extends DbDataSource<string, PlainObject, Array
|
|
|
29
29
|
|
|
30
30
|
export type RedisCredential = ServerAuth;
|
|
31
31
|
|
|
32
|
-
export interface
|
|
32
|
+
export interface RedisCommand<T = "HASH" | "JSON" | undefined, U = unknown, V = unknown> {
|
|
33
33
|
format: T;
|
|
34
|
+
command?: string;
|
|
34
35
|
key?: U;
|
|
35
|
-
field?: V;
|
|
36
36
|
value?: V;
|
|
37
37
|
NX?: boolean;
|
|
38
38
|
XX?: boolean;
|
|
39
|
-
EX?: number;
|
|
40
|
-
PX?: number;
|
|
41
|
-
EXAT?: number;
|
|
42
|
-
PXAT?: number;
|
|
43
39
|
options?: {
|
|
44
|
-
set?:
|
|
40
|
+
set?: SetOptions;
|
|
45
41
|
expire?: { [K in RedisExpireCondition]?: boolean; };
|
|
46
42
|
command?: RedisCommandOptions;
|
|
47
43
|
};
|
|
48
44
|
}
|
|
49
45
|
|
|
50
|
-
export interface
|
|
46
|
+
export interface RedisSetValue extends RedisCommand<"HASH", RedisCommandArgument, RedisCommandValue | RedisHSETObject> {
|
|
47
|
+
field?: RedisCommandValue | RedisHSETObject;
|
|
48
|
+
EX?: number;
|
|
49
|
+
PX?: number;
|
|
50
|
+
EXAT?: number;
|
|
51
|
+
PXAT?: number;
|
|
52
|
+
KEEPTTL?: boolean;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface RedisJSONValue extends RedisCommand<"JSON", string, ArrayOf<RedisJSON>> {
|
|
56
|
+
command?: RedisCommandJSON;
|
|
51
57
|
path?: string;
|
|
58
|
+
start?: NumString;
|
|
59
|
+
stop?: NumString;
|
|
60
|
+
index?: NumString;
|
|
52
61
|
}
|
|
53
62
|
|
|
54
63
|
export interface RedisQuery {
|
|
@@ -58,7 +67,14 @@ export interface RedisQuery {
|
|
|
58
67
|
options?: PlainObject;
|
|
59
68
|
}
|
|
60
69
|
|
|
70
|
+
export interface JsonMSetItem {
|
|
71
|
+
key: RedisCommandArgument;
|
|
72
|
+
path: RedisCommandArgument;
|
|
73
|
+
value: RedisJSON;
|
|
74
|
+
}
|
|
75
|
+
|
|
61
76
|
export type RedisFormat = "HASH" | "JSON";
|
|
77
|
+
export type RedisCommandJSON = "ARRAPPEND" | "ARRINDEX" | "ARRINSERT" | "ARRPOP" | "ARRTRIM" | "DEL" | "FORGET" | "MERGE" | "MSET" | "NUMINCRBY" | "NUMMULTBY" | "SET" | "STRAPPEND";
|
|
62
78
|
export type RedisExpireCondition = "NX" | "XX" | "GT" | "LT";
|
|
63
79
|
export type RedisCommandValue = RedisCommandArgument | number;
|
|
64
80
|
export type RedisCommandOptions = CommandOptions<ClientCommandOptions>;
|