@pi-r/redis 0.5.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 CHANGED
@@ -8,10 +8,10 @@ const Db = require("@e-mc/db");
8
8
  const DbPool = require('@e-mc/db/pool');
9
9
  const REDIS_V4 = Db.checkSemVer("redis" /* STRINGS.MODULE_NAME */, 4);
10
10
  class RedisPool extends DbPool {
11
- getConnection() {
12
- return Promise.resolve(this.client);
11
+ async getConnection() {
12
+ return this.client;
13
13
  }
14
- close() {
14
+ async close() {
15
15
  return this.client.disconnect();
16
16
  }
17
17
  isEmpty() {
@@ -22,7 +22,7 @@ class RedisPool extends DbPool {
22
22
  }
23
23
  }
24
24
  const POOL_STATE = {};
25
- function getClient(db, options, poolKey) {
25
+ async function getClient(db, options, poolKey) {
26
26
  const socket = options.socket || (options.socket = {});
27
27
  if (!poolKey) {
28
28
  socket.keepAlive = false;
@@ -93,55 +93,55 @@ async function setCredential(item) {
93
93
  client.password = password;
94
94
  }
95
95
  const usePool = item.usePool;
96
- if (usePool) {
97
- let pool;
98
- username = undefined;
99
- password = undefined;
100
- if (typeof usePool === 'string' && (username = client.username || (0, util_1.parseConnectionString)(uri)?.username)) {
101
- [password, pool] = DbPool.validateKey(POOL_STATE, username, usePool);
102
- if (pool) {
103
- pool.add(item, password);
104
- return;
105
- }
96
+ if (!usePool) {
97
+ return;
98
+ }
99
+ let pool;
100
+ username = undefined;
101
+ password = undefined;
102
+ if (typeof usePool === 'string' && (username = client.username || (0, util_1.parseConnectionString)(uri)?.username)) {
103
+ [password, pool] = DbPool.validateKey(POOL_STATE, username, usePool);
104
+ if (pool) {
105
+ pool.add(item, password);
106
+ return;
106
107
  }
107
- const poolKey = getPoolKey(client);
108
- if (!(pool = POOL_STATE[poolKey]) || pool.closed) {
109
- const config = this.getPoolConfig("redis" /* STRINGS.MODULE_NAME */, password);
110
- const poolOptions = client.isolationPoolOptions || (client.isolationPoolOptions = {});
111
- if (config) {
112
- const { min, max, idle, queue_max, queue_idle, timeout } = config;
113
- if (min >= 0) {
114
- poolOptions.min ?? (poolOptions.min = min);
115
- }
116
- if (max > 0) {
117
- poolOptions.max ?? (poolOptions.max = max);
118
- }
119
- if (idle > 0) {
120
- poolOptions.idleTimeoutMillis ?? (poolOptions.idleTimeoutMillis = idle);
121
- }
122
- if (queue_max >= 0) {
123
- poolOptions.maxWaitingClients ?? (poolOptions.maxWaitingClients = queue_max);
124
- }
125
- if (queue_idle > 0) {
126
- poolOptions.softIdleTimeoutMillis ?? (poolOptions.softIdleTimeoutMillis = queue_idle);
127
- }
128
- if (timeout > 0) {
129
- poolOptions.acquireTimeoutMillis ?? (poolOptions.acquireTimeoutMillis = timeout);
130
- }
131
- }
132
- try {
133
- const target = new RedisPool(await getClient(redis, client, poolKey), poolKey, username && password ? { username, password } : undefined).add(item);
134
- target.parent = POOL_STATE;
135
- target.success = 1;
136
- }
137
- catch {
138
- item.usePool = false;
139
- delete client.isolationPoolOptions;
140
- }
108
+ }
109
+ const poolKey = getPoolKey(client);
110
+ if ((pool = POOL_STATE[poolKey]) && !pool.closed) {
111
+ pool.add(item);
112
+ return;
113
+ }
114
+ const config = this.getPoolConfig("redis" /* STRINGS.MODULE_NAME */, password);
115
+ const poolOptions = client.isolationPoolOptions || (client.isolationPoolOptions = {});
116
+ if (config) {
117
+ const { min, max, idle, queue_max, queue_idle, timeout } = config;
118
+ if (min >= 0) {
119
+ poolOptions.min ?? (poolOptions.min = min);
120
+ }
121
+ if (max > 0) {
122
+ poolOptions.max ?? (poolOptions.max = max);
123
+ }
124
+ if (idle > 0) {
125
+ poolOptions.idleTimeoutMillis ?? (poolOptions.idleTimeoutMillis = idle);
126
+ }
127
+ if (queue_max >= 0) {
128
+ poolOptions.maxWaitingClients ?? (poolOptions.maxWaitingClients = queue_max);
141
129
  }
142
- else {
143
- pool.add(item);
130
+ if (queue_idle > 0) {
131
+ poolOptions.softIdleTimeoutMillis ?? (poolOptions.softIdleTimeoutMillis = queue_idle);
144
132
  }
133
+ if (timeout > 0) {
134
+ poolOptions.acquireTimeoutMillis ?? (poolOptions.acquireTimeoutMillis = timeout);
135
+ }
136
+ }
137
+ try {
138
+ const target = new RedisPool(await getClient(redis, client, poolKey), poolKey, username && password ? { username, password } : undefined).add(item);
139
+ target.parent = POOL_STATE;
140
+ target.success = 1;
141
+ }
142
+ catch {
143
+ item.usePool = false;
144
+ delete client.isolationPoolOptions;
145
145
  }
146
146
  }
147
147
  exports.setCredential = setCredential;
@@ -204,6 +204,9 @@ async function executeBatchQuery(batch, options = '', outResult) {
204
204
  item.transactionState &= ~64 /* DB_TRANSACTION.AUTH */;
205
205
  return client;
206
206
  };
207
+ if (this.host?.username) {
208
+ this.applyCommand(...batch);
209
+ }
207
210
  for (let i = 0; i < length; ++i) {
208
211
  const item = batch[i];
209
212
  const { source, uri, key, format = 'HASH', search, aggregate, update, options: clientOptions = {}, cacheObjectKey, ignoreCache } = item;
@@ -226,13 +229,12 @@ async function executeBatchQuery(batch, options = '', outResult) {
226
229
  continue;
227
230
  }
228
231
  item.transactionState = 1 /* DB_TRANSACTION.ACTIVE */;
232
+ const command = (0, types_1.isPlainObject)(clientOptions.command) ? redis.commandOptions(clientOptions.command) : null;
229
233
  const uuidKey = (credential.uuidKey || (credential.uuidKey = (onceCredential ? batch[0] : item).credential?.uuidKey));
230
234
  const targetObject = typeof checkObject === 'string' ? this.hasCoerce("redis" /* STRINGS.MODULE_NAME */, 'options', uuidKey) && (0, types_1.asFunction)(checkObject) : checkObject;
231
- const renewCache = ignoreCache === 0;
232
- const cacheValue = renewCache ? { sessionKey, renewCache } : sessionKey;
233
- 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 };
234
236
  let queryString = '', rows;
235
- if (caching && ignoreCache !== true || ignoreCache === false || ignoreCache === 1 || renewCache) {
237
+ if (caching && ignoreCache !== true) {
236
238
  if ((0, types_1.isObject)(search)) {
237
239
  queryString = Db.asString(search, true);
238
240
  }
@@ -240,10 +242,10 @@ async function executeBatchQuery(batch, options = '', outResult) {
240
242
  queryString = Db.asString(aggregate, true);
241
243
  }
242
244
  else if (!targetObject) {
243
- queryString = Db.asString(key);
245
+ queryString = Db.asString(key, true);
244
246
  }
245
247
  else if (cacheObjectKey) {
246
- queryString = Db.asString(key) + '_' + targetObject.toString() + cacheObjectKey;
248
+ queryString = Db.asString(key, true) + '_' + targetObject.toString() + cacheObjectKey;
247
249
  }
248
250
  if (queryString) {
249
251
  queryString += '_' + format;
@@ -283,65 +285,130 @@ async function executeBatchQuery(batch, options = '', outResult) {
283
285
  const b = (arg) => typeof arg === 'number' || Buffer.isBuffer(arg) ? arg.toString() : arg;
284
286
  if (update) {
285
287
  commandType = this.commandType.UPDATE;
286
- const values = (!Array.isArray(update) ? [update] : update).map(target => {
288
+ const values = (!Array.isArray(update) ? [update] : update).map(async (target) => {
287
289
  return new Promise(async (success, failed) => {
288
- let { key: k, value: v, format: f = 'HASH', NX, XX, EX = 0, PX = 0, EXAT = 0, PXAT = 0, options: setOptions = {} } = target;
289
- if (v === undefined) {
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') {
290
293
  success(target);
291
294
  return;
292
295
  }
296
+ const has = (n) => typeof n === 'number' && n > 0;
293
297
  const failKey = () => failed((0, types_1.errorMessage)(f, "Invalid key" /* ERR_DB.KEY */, Db.asString(k) || "Unknown" /* ERR_MESSAGE.UNKNOWN */));
294
298
  const failValue = () => failed((0, types_1.errorMessage)(f, "Invalid value" /* ERR_DB.VALUE */, Db.asString(v) || "Unknown" /* ERR_MESSAGE.UNKNOWN */));
295
299
  const commandSet = (0, types_1.isPlainObject)(setOptions.command) && redis.commandOptions(setOptions.command);
296
- let pending;
297
- if ((f = f.toUpperCase()) === 'JSON') {
300
+ let pending, codeMin = 0, EX, PX, EXAT, PXAT, KEEPTTL;
301
+ if (f === 'JSON') {
298
302
  if (typeof k !== 'string') {
299
303
  failKey();
300
304
  return;
301
305
  }
302
- const path = target.path || '$';
303
306
  if (this.hasCoerce("redis" /* STRINGS.MODULE_NAME */, 'options', uuidKey)) {
304
307
  if ((0, types_1.isString)(v) && v.startsWith('new')) {
305
308
  ({ outV: v } = (0, types_1.coerceObject)({ outV: v }));
306
309
  }
307
310
  }
308
- const flags = NX ? { NX } : XX ? { XX } : undefined;
309
- pending = commandSet ? client.json.set(commandSet, k, path, v, flags) : client.json.set(k, path, v, flags);
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
+ }
310
375
  }
311
376
  else if (typeof k === 'string' || Buffer.isBuffer(k)) {
377
+ ({ EX, PX, EXAT, PXAT, KEEPTTL } = target);
312
378
  const field = target.field;
313
379
  if (field === undefined && field === null) {
314
380
  if (a(v)) {
315
- const flags = setOptions.set;
316
- if (flags) {
317
- if ('NX' in flags) {
318
- NX ?? (NX = !!flags.NX);
319
- delete flags.NX;
320
- }
321
- if ('XX' in flags) {
322
- XX ?? (XX = !!flags.XX);
323
- delete flags.XX;
324
- }
325
- if ('EX' in flags) {
326
- EX || (EX = flags.EX);
327
- delete flags.EX;
328
- }
329
- if ('PX' in flags) {
330
- PX || (PX = flags.PX);
331
- delete flags.PX;
332
- }
333
- if ('EXAT' in flags) {
334
- EXAT || (EXAT = flags.EXAT);
335
- delete flags.EXAT;
336
- }
337
- if ('PXAT' in flags) {
338
- PXAT || (PXAT = flags.PXAT);
339
- delete flags.PXAT;
340
- }
381
+ const flags = setOptions.set || {};
382
+ if (NX) {
383
+ flags.NX = true;
384
+ }
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;
341
403
  }
342
- pending = (commandSet ? client.set(commandSet, k, v, setOptions.set) : client.set(k, v, setOptions.set));
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);
343
410
  }
344
- else if (typeof v === 'object') {
411
+ else if ((0, types_1.isObject)(v)) {
345
412
  let valid = true;
346
413
  if (NX || XX) {
347
414
  valid = await client.exists(k) === 1;
@@ -358,6 +425,7 @@ async function executeBatchQuery(batch, options = '', outResult) {
358
425
  }
359
426
  else if (NX) {
360
427
  if (a(field) && a(v)) {
428
+ codeMin = -1;
361
429
  pending = commandSet ? client.hSetNX(commandSet, k, b(field), b(v)) : client.hSetNX(k, b(field), b(v));
362
430
  }
363
431
  }
@@ -380,43 +448,52 @@ async function executeBatchQuery(batch, options = '', outResult) {
380
448
  return;
381
449
  }
382
450
  if (pending) {
383
- pending.then(code => {
384
- if (code === 'OK' || typeof code === 'number' || code === true) {
385
- const has = (n) => typeof n === 'number' && n !== 0;
386
- if (has(EX) || has(PX) || EXAT > 0 || PXAT > 0) {
387
- const expire = setOptions.expire;
388
- let mode;
389
- if (expire) {
390
- if (expire.NX) {
391
- mode = 'NX';
392
- }
393
- else if (expire.XX) {
394
- mode = 'XX';
395
- }
396
- else if (expire.GT) {
397
- mode = 'GT';
398
- }
399
- else if (expire.LT) {
400
- mode = 'LT';
401
- }
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';
402
472
  }
403
- (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))
404
- .then(valid => {
405
- if (valid) {
406
- success(target);
407
- }
408
- else {
409
- 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));
410
- }
411
- })
412
- .catch(err => failed(err));
413
473
  }
414
- else {
415
- success(target);
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
+ }
416
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));
417
494
  }
418
495
  else {
419
- failValue();
496
+ success(target);
420
497
  }
421
498
  })
422
499
  .catch(err => failed(err));
@@ -460,13 +537,14 @@ async function executeBatchQuery(batch, options = '', outResult) {
460
537
  }
461
538
  }
462
539
  catch (err) {
463
- error = err;
464
- }
465
- if (idx && idx !== index) {
466
- client.ft.dropIndex(idx).catch(err => this.writeFail([`Unable to drop ${target === search ? 'search' : 'aggregate'} index`, idx], err, { type: 65536 /* LOG_TYPE.DB */, fatal: false }));
540
+ if (err instanceof Error) {
541
+ throw err;
542
+ }
467
543
  }
468
- if (error instanceof Error) {
469
- throw error;
544
+ finally {
545
+ if (idx && idx !== index) {
546
+ client.ft.dropIndex(idx).catch(err => this.writeFail([`Unable to drop ${target === search ? 'search' : 'aggregate'} index`, idx], err, { type: 65536 /* LOG_TYPE.DB */, fatal: false }));
547
+ }
470
548
  }
471
549
  }
472
550
  else if (key) {
@@ -474,10 +552,10 @@ async function executeBatchQuery(batch, options = '', outResult) {
474
552
  if (Array.isArray(key)) {
475
553
  switch (format.toUpperCase()) {
476
554
  case 'HKEYS':
477
- data = await Promise.all(key.map(k => client.hKeys(...command ? [command, k] : [k])));
555
+ data = await Promise.all(key.map(async (k) => client.hKeys(...command ? [command, k] : [k])));
478
556
  break;
479
557
  case 'HVALS':
480
- data = await Promise.all(key.map(k => client.hVals(...command ? [command, k] : [k])));
558
+ data = await Promise.all(key.map(async (k) => client.hVals(...command ? [command, k] : [k])));
481
559
  break;
482
560
  case 'JSON':
483
561
  data = (await (command ? client.json.mGet(command, key.map(c => b(c)), item.path || '$') : client.json.mGet(key.map(c => b(c)), item.path || '$'))).flat();
@@ -548,12 +626,12 @@ async function executeBatchQuery(batch, options = '', outResult) {
548
626
  }
549
627
  }
550
628
  return this.processRows(batch, tasks, {
551
- disconnect: () => clients.forEach(item => item.disconnect()),
629
+ disconnect: () => clients.forEach(async (item) => item.disconnect()),
552
630
  parallel
553
631
  }, outResult);
554
632
  }
555
633
  exports.executeBatchQuery = executeBatchQuery;
556
- function checkTimeout(value, limit = 0) {
634
+ async function checkTimeout(value, limit = 0) {
557
635
  return DbPool.checkTimeout(POOL_STATE, value, limit);
558
636
  }
559
637
  exports.checkTimeout = checkTimeout;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-r/redis",
3
- "version": "0.5.0",
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.7.0",
25
- "@e-mc/types": "^0.7.0",
26
- "redis": "^4.6.11"
24
+ "@e-mc/db": "^0.8.1",
25
+ "@e-mc/types": "^0.8.1",
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 RedisSetValue<T = "HASH" | undefined, U = RedisCommandArgument, V = RedisCommandValue | RedisHSETObject> {
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?: PlainObject;
40
+ set?: SetOptions;
45
41
  expire?: { [K in RedisExpireCondition]?: boolean; };
46
42
  command?: RedisCommandOptions;
47
43
  };
48
44
  }
49
45
 
50
- export interface RedisJSONValue extends Omit<RedisSetValue<"JSON", string, RedisJSON>, "field" | "EX" | "PX" | "EXAT" | "PXAT"> {
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>;