memx 0.0.4 → 0.0.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/dist/index.js CHANGED
@@ -40,10 +40,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
40
40
  var src_exports = {};
41
41
  __export(src_exports, {
42
42
  Bundle: () => Bundle,
43
- Client: () => Client,
44
43
  ClusterAdapter: () => ClusterAdapter,
45
44
  Factory: () => Factory,
46
45
  FakeAdapter: () => FakeAdapter,
46
+ MemxClient: () => MemxClient,
47
+ MemxFakeClient: () => MemxFakeClient,
47
48
  PoorManLock: () => PoorManLock,
48
49
  ServerAdapter: () => ServerAdapter,
49
50
  connection: () => connection_exports,
@@ -305,13 +306,13 @@ __export(connection_exports, {
305
306
 
306
307
  // src/internals.ts
307
308
  var import_assert2 = __toESM(require("assert"));
308
- var import_types = require("util/types");
309
+ var import_util = require("util");
309
310
  var socketFinalizationRegistry = new FinalizationRegistry((socket) => {
310
311
  if (!socket.destroyed)
311
312
  socket.destroy();
312
313
  });
313
314
  function typedArrayFlags(value) {
314
- const flags = (0, import_types.isUint8Array)(value) ? 3402235920 /* UINT8ARRAY */ : (0, import_types.isUint8ClampedArray)(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : (0, import_types.isUint16Array)(value) ? 3402235922 /* UINT16ARRAY */ : (0, import_types.isUint32Array)(value) ? 3402235923 /* UINT32ARRAY */ : (0, import_types.isInt8Array)(value) ? 3402235924 /* INT8ARRAY */ : (0, import_types.isInt16Array)(value) ? 3402235925 /* INT16ARRAY */ : (0, import_types.isInt32Array)(value) ? 3402235926 /* INT32ARRAY */ : (0, import_types.isBigUint64Array)(value) ? 3402235927 /* BIGUINT64ARRAY */ : (0, import_types.isBigInt64Array)(value) ? 3402235928 /* BIGINT64ARRAY */ : (0, import_types.isFloat32Array)(value) ? 3402235929 /* FLOAT32ARRAY */ : (0, import_types.isFloat64Array)(value) ? 3402235930 /* FLOAT64ARRAY */ : import_assert2.default.fail("Unsupported kind of TypedArray");
315
+ const flags = import_util.types.isUint8Array(value) ? 3402235920 /* UINT8ARRAY */ : import_util.types.isUint8ClampedArray(value) ? 3402235921 /* UINT8CLAMPEDARRAY */ : import_util.types.isUint16Array(value) ? 3402235922 /* UINT16ARRAY */ : import_util.types.isUint32Array(value) ? 3402235923 /* UINT32ARRAY */ : import_util.types.isInt8Array(value) ? 3402235924 /* INT8ARRAY */ : import_util.types.isInt16Array(value) ? 3402235925 /* INT16ARRAY */ : import_util.types.isInt32Array(value) ? 3402235926 /* INT32ARRAY */ : import_util.types.isBigUint64Array(value) ? 3402235927 /* BIGUINT64ARRAY */ : import_util.types.isBigInt64Array(value) ? 3402235928 /* BIGINT64ARRAY */ : import_util.types.isFloat32Array(value) ? 3402235929 /* FLOAT32ARRAY */ : import_util.types.isFloat64Array(value) ? 3402235930 /* FLOAT64ARRAY */ : import_assert2.default.fail("Unsupported kind of TypedArray");
315
316
  return flags;
316
317
  }
317
318
  function logPromiseError(promise, message) {
@@ -460,144 +461,6 @@ var Connection = class {
460
461
  }
461
462
  };
462
463
 
463
- // src/fake.ts
464
- function toExp(ttl = 0) {
465
- if (ttl === 0)
466
- return Number.MAX_SAFE_INTEGER;
467
- return Date.now() + ttl * 1e3;
468
- }
469
- var FakeAdapter = class {
470
- #cache = /* @__PURE__ */ new Map();
471
- #cas = 1n;
472
- #get(key) {
473
- if (key.length > 250)
474
- throw new TypeError(`Key too long (len=${key.length})`);
475
- const entry = this.#cache.get(key);
476
- if (!entry)
477
- return;
478
- if (Date.now() > entry.exp) {
479
- this.#cache.delete(key);
480
- return;
481
- }
482
- return entry;
483
- }
484
- #set(key, value, flags, ttl) {
485
- this.#cache.set(key, {
486
- value,
487
- flags: flags || 0,
488
- cas: ++this.#cas,
489
- exp: toExp(ttl)
490
- });
491
- return this.#cas;
492
- }
493
- async get(key, options = {}) {
494
- const entry = this.#get(key);
495
- if (!entry)
496
- return;
497
- if (options.ttl !== void 0) {
498
- const exp = toExp(options.ttl);
499
- entry.exp = exp;
500
- }
501
- return {
502
- value: entry.value,
503
- flags: entry.flags,
504
- cas: entry.cas,
505
- recycle: () => void 0
506
- };
507
- }
508
- async touch(key, ttl) {
509
- const entry = this.#get(key);
510
- if (entry)
511
- entry.exp = toExp(ttl);
512
- return !!entry;
513
- }
514
- async set(key, value, options = {}) {
515
- const entry = this.#get(key);
516
- if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
517
- return;
518
- }
519
- return this.#set(key, value, options.flags, options.ttl);
520
- }
521
- async add(key, value, options = {}) {
522
- if (this.#get(key))
523
- return;
524
- return this.#set(key, value, options.flags, options.ttl);
525
- }
526
- async replace(key, value, options = {}) {
527
- if (!this.#get(key))
528
- return;
529
- return this.#set(key, value, options.flags, options.ttl);
530
- }
531
- async append(key, value, options = {}) {
532
- const entry = this.#get(key);
533
- if (!entry)
534
- return false;
535
- if (options.cas !== void 0 && options.cas !== entry.cas)
536
- return false;
537
- entry.value = Buffer.concat([entry.value, value]);
538
- return true;
539
- }
540
- async prepend(key, value, options = {}) {
541
- const entry = this.#get(key);
542
- if (!entry)
543
- return false;
544
- if (options.cas !== void 0 && options.cas !== entry.cas)
545
- return false;
546
- entry.value = Buffer.concat([value, entry.value]);
547
- return true;
548
- }
549
- async #counter(key, delta, options) {
550
- const entry = this.#get(key);
551
- if (!entry) {
552
- if (options.initial !== void 0) {
553
- const value = Buffer.from(options.initial.toString());
554
- this.#set(key, value, void 0, options.ttl);
555
- return { value: BigInt(options.initial), cas: this.#cas };
556
- } else {
557
- return;
558
- }
559
- }
560
- if (options.cas !== void 0 && options.cas !== entry.cas)
561
- return;
562
- try {
563
- const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
564
- this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
565
- return { value, cas: this.#cas };
566
- } catch (error) {
567
- throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
568
- }
569
- }
570
- increment(key, delta = 1n, options = {}) {
571
- return this.#counter(key, delta, options);
572
- }
573
- decrement(key, delta = 1n, options = {}) {
574
- return this.#counter(key, -delta, options);
575
- }
576
- async delete(key, options = {}) {
577
- const entry = this.#get(key);
578
- if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
579
- return false;
580
- }
581
- return this.#cache.delete(key);
582
- }
583
- async flush(ttl) {
584
- if (!ttl)
585
- return this.#cache.clear();
586
- const wait = toExp(ttl) - Date.now();
587
- setTimeout(() => this.#cache.clear(), wait);
588
- }
589
- async noop() {
590
- }
591
- async quit() {
592
- }
593
- async version() {
594
- return { fake: "0.0.0-fake" };
595
- }
596
- async stats() {
597
- return { fake: { version: "0.0.0-fake" } };
598
- }
599
- };
600
-
601
464
  // src/server.ts
602
465
  var statsBigInt = [
603
466
  "auth_cmds",
@@ -745,10 +608,9 @@ var ServerAdapter = class {
745
608
  throw new Error(`Key too long (len=${keyLength})`);
746
609
  return keyLength;
747
610
  }
748
- async get(key, options = {}) {
749
- const { ttl } = options;
611
+ async #get(key, ttl) {
750
612
  let keyOffset = 0;
751
- if (ttl)
613
+ if (ttl !== void 0)
752
614
  keyOffset = this.#buffer.writeUInt32BE(ttl);
753
615
  const keyLength = this.#writeKey(key, keyOffset);
754
616
  const [response] = await this.#connection.send({
@@ -774,8 +636,14 @@ var ServerAdapter = class {
774
636
  fail(response, key);
775
637
  }
776
638
  }
639
+ async get(key) {
640
+ return this.#get(key);
641
+ }
642
+ async gat(key, ttl) {
643
+ return this.#get(key, ttl || 2592e3);
644
+ }
777
645
  async touch(key, ttl) {
778
- const timeToLive = ttl === void 0 ? this.#ttl : ttl;
646
+ const timeToLive = ttl ?? this.#ttl;
779
647
  const keyOffset = this.#buffer.writeUInt32BE(timeToLive);
780
648
  const keyLength = this.#writeKey(key, keyOffset);
781
649
  const [response] = await this.#connection.send({
@@ -1023,6 +891,7 @@ var ServerAdapter = class {
1023
891
  };
1024
892
 
1025
893
  // src/cluster.ts
894
+ var import_assert4 = __toESM(require("assert"));
1026
895
  function parseHosts(hosts) {
1027
896
  const result = [];
1028
897
  if (!hosts)
@@ -1036,6 +905,7 @@ function parseHosts(hosts) {
1036
905
  }
1037
906
  var ClusterAdapter = class {
1038
907
  servers;
908
+ ttl;
1039
909
  constructor(serversOrOptions) {
1040
910
  if (Array.isArray(serversOrOptions)) {
1041
911
  this.servers = [...serversOrOptions];
@@ -1063,6 +933,10 @@ var ClusterAdapter = class {
1063
933
  throw new Error("No hosts configured");
1064
934
  if (this.servers.length === 1)
1065
935
  this.server = () => this.servers[0];
936
+ this.ttl = this.servers[0].ttl;
937
+ this.servers.slice(1).forEach((server) => {
938
+ import_assert4.default.equal(server.ttl, this.ttl, `TTL Mismatch (${server.ttl} != ${this.ttl})`);
939
+ });
1066
940
  Object.freeze(this.servers);
1067
941
  }
1068
942
  server(key) {
@@ -1072,8 +946,11 @@ var ClusterAdapter = class {
1072
946
  hash = hash * 31 + key.charCodeAt(i);
1073
947
  return this.servers[hash % this.servers.length];
1074
948
  }
1075
- get(key, options) {
1076
- return this.server(key).get(key, options);
949
+ get(key) {
950
+ return this.server(key).get(key);
951
+ }
952
+ gat(key, ttl) {
953
+ return this.server(key).gat(key, ttl);
1077
954
  }
1078
955
  touch(key, ttl) {
1079
956
  return this.server(key).touch(key, ttl);
@@ -1122,8 +999,8 @@ var ClusterAdapter = class {
1122
999
  };
1123
1000
 
1124
1001
  // src/client.ts
1125
- var import_assert4 = __toESM(require("assert"));
1126
- var import_types5 = require("util/types");
1002
+ var import_assert5 = __toESM(require("assert"));
1003
+ var import_util2 = require("util");
1127
1004
  function replacer(key, value) {
1128
1005
  if (typeof this[key] === "bigint")
1129
1006
  return ["\0__$BIGINT$__\0", this[key].toString()];
@@ -1165,9 +1042,9 @@ function toBuffer(value, options) {
1165
1042
  case "object":
1166
1043
  break;
1167
1044
  default:
1168
- import_assert4.default.fail(`Unable to store value of type "${typeof value}"`);
1045
+ import_assert5.default.fail(`Unable to store value of type "${typeof value}"`);
1169
1046
  }
1170
- if ((0, import_types5.isTypedArray)(value)) {
1047
+ if (import_util2.types.isTypedArray(value)) {
1171
1048
  const flags = typedArrayFlags(value);
1172
1049
  const buffer = Buffer.from(value.buffer, value.byteOffset, value.byteLength);
1173
1050
  return [buffer, __spreadProps(__spreadValues({}, options), { flags })];
@@ -1177,12 +1054,58 @@ function toBuffer(value, options) {
1177
1054
  const json = JSON.stringify(value, replacer);
1178
1055
  return [Buffer.from(json, "utf-8"), __spreadProps(__spreadValues({}, options), { flags: 3402235919 /* JSON */ })];
1179
1056
  }
1057
+ function fromBuffer(result) {
1058
+ try {
1059
+ const { flags, value, cas } = result;
1060
+ switch (flags) {
1061
+ case 3402235904 /* BIGINT */:
1062
+ return { value: BigInt(value.toString("utf-8")), cas };
1063
+ case 3402235905 /* BOOLEAN */:
1064
+ return { value: !!value[0], cas };
1065
+ case 3402235906 /* NUMBER */:
1066
+ return { value: Number(value.toString("utf-8")), cas };
1067
+ case 3402235907 /* STRING */:
1068
+ return { value: value.toString("utf-8"), cas };
1069
+ case 3402235918 /* NULL */:
1070
+ return { value: null, cas };
1071
+ case 3402235919 /* JSON */:
1072
+ return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
1073
+ case 3402235920 /* UINT8ARRAY */:
1074
+ return { value: makeTypedArray(Uint8Array, value), cas };
1075
+ case 3402235921 /* UINT8CLAMPEDARRAY */:
1076
+ return { value: makeTypedArray(Uint8ClampedArray, value), cas };
1077
+ case 3402235922 /* UINT16ARRAY */:
1078
+ return { value: makeTypedArray(Uint16Array, value), cas };
1079
+ case 3402235923 /* UINT32ARRAY */:
1080
+ return { value: makeTypedArray(Uint32Array, value), cas };
1081
+ case 3402235924 /* INT8ARRAY */:
1082
+ return { value: makeTypedArray(Int8Array, value), cas };
1083
+ case 3402235925 /* INT16ARRAY */:
1084
+ return { value: makeTypedArray(Int16Array, value), cas };
1085
+ case 3402235926 /* INT32ARRAY */:
1086
+ return { value: makeTypedArray(Int32Array, value), cas };
1087
+ case 3402235927 /* BIGUINT64ARRAY */:
1088
+ return { value: makeTypedArray(BigUint64Array, value), cas };
1089
+ case 3402235928 /* BIGINT64ARRAY */:
1090
+ return { value: makeTypedArray(BigInt64Array, value), cas };
1091
+ case 3402235929 /* FLOAT32ARRAY */:
1092
+ return { value: makeTypedArray(Float32Array, value), cas };
1093
+ case 3402235930 /* FLOAT64ARRAY */:
1094
+ return { value: makeTypedArray(Float64Array, value), cas };
1095
+ case 0 /* BUFFER */:
1096
+ default:
1097
+ return { value: Buffer.from(value), cas };
1098
+ }
1099
+ } finally {
1100
+ result.recycle();
1101
+ }
1102
+ }
1180
1103
  function makeTypedArray(constructor, source) {
1181
1104
  const clone = Buffer.from(source);
1182
1105
  const { buffer, byteOffset, byteLength } = clone;
1183
1106
  return new constructor(buffer, byteOffset, byteLength / constructor.BYTES_PER_ELEMENT);
1184
1107
  }
1185
- var Client = class {
1108
+ var MemxClient = class {
1186
1109
  #adapter;
1187
1110
  #prefix;
1188
1111
  constructor(adapterOrOptions) {
@@ -1194,7 +1117,7 @@ var Client = class {
1194
1117
  this.#adapter = new ClusterAdapter(adapterOrOptions);
1195
1118
  }
1196
1119
  this.#prefix = "";
1197
- (0, import_assert4.default)(this.#adapter, "Invalid client constructor arguments");
1120
+ (0, import_assert5.default)(this.#adapter, "Invalid client constructor arguments");
1198
1121
  }
1199
1122
  get adapter() {
1200
1123
  return this.#adapter;
@@ -1203,59 +1126,26 @@ var Client = class {
1203
1126
  return this.#prefix;
1204
1127
  }
1205
1128
  withPrefix(prefix) {
1206
- (0, import_assert4.default)(prefix, "Invalid prefix");
1207
- const client = new Client(this.#adapter);
1129
+ (0, import_assert5.default)(prefix, "Invalid prefix");
1130
+ const client = new MemxClient(this.#adapter);
1208
1131
  client.#prefix = prefix;
1209
1132
  return client;
1210
1133
  }
1211
- async get(key, options) {
1212
- const result = await this.#adapter.get(this.#prefix + key, options);
1213
- if (!result)
1214
- return;
1215
- try {
1216
- const { flags, value, cas } = result;
1217
- switch (flags) {
1218
- case 3402235904 /* BIGINT */:
1219
- return { value: BigInt(value.toString("utf-8")), cas };
1220
- case 3402235905 /* BOOLEAN */:
1221
- return { value: !!value[0], cas };
1222
- case 3402235906 /* NUMBER */:
1223
- return { value: Number(value.toString("utf-8")), cas };
1224
- case 3402235907 /* STRING */:
1225
- return { value: value.toString("utf-8"), cas };
1226
- case 3402235918 /* NULL */:
1227
- return { value: null, cas };
1228
- case 3402235919 /* JSON */:
1229
- return { value: JSON.parse(value.toString("utf-8"), reviver), cas };
1230
- case 3402235920 /* UINT8ARRAY */:
1231
- return { value: makeTypedArray(Uint8Array, value), cas };
1232
- case 3402235921 /* UINT8CLAMPEDARRAY */:
1233
- return { value: makeTypedArray(Uint8ClampedArray, value), cas };
1234
- case 3402235922 /* UINT16ARRAY */:
1235
- return { value: makeTypedArray(Uint16Array, value), cas };
1236
- case 3402235923 /* UINT32ARRAY */:
1237
- return { value: makeTypedArray(Uint32Array, value), cas };
1238
- case 3402235924 /* INT8ARRAY */:
1239
- return { value: makeTypedArray(Int8Array, value), cas };
1240
- case 3402235925 /* INT16ARRAY */:
1241
- return { value: makeTypedArray(Int16Array, value), cas };
1242
- case 3402235926 /* INT32ARRAY */:
1243
- return { value: makeTypedArray(Int32Array, value), cas };
1244
- case 3402235927 /* BIGUINT64ARRAY */:
1245
- return { value: makeTypedArray(BigUint64Array, value), cas };
1246
- case 3402235928 /* BIGINT64ARRAY */:
1247
- return { value: makeTypedArray(BigInt64Array, value), cas };
1248
- case 3402235929 /* FLOAT32ARRAY */:
1249
- return { value: makeTypedArray(Float32Array, value), cas };
1250
- case 3402235930 /* FLOAT64ARRAY */:
1251
- return { value: makeTypedArray(Float64Array, value), cas };
1252
- case 0 /* BUFFER */:
1253
- default:
1254
- return { value: Buffer.from(value), cas };
1255
- }
1256
- } finally {
1257
- result.recycle();
1258
- }
1134
+ async get(key) {
1135
+ const result = await this.#adapter.get(this.#prefix + key);
1136
+ return result && fromBuffer(result).value;
1137
+ }
1138
+ async gat(key, ttl) {
1139
+ const result = await this.#adapter.gat(this.#prefix + key, ttl);
1140
+ return result && fromBuffer(result).value;
1141
+ }
1142
+ async getc(key) {
1143
+ const result = await this.#adapter.get(this.#prefix + key);
1144
+ return result && fromBuffer(result);
1145
+ }
1146
+ async gatc(key, ttl) {
1147
+ const result = await this.#adapter.gat(this.#prefix + key, ttl);
1148
+ return result && fromBuffer(result);
1259
1149
  }
1260
1150
  async set(key, value, options) {
1261
1151
  return this.#adapter.set(this.#prefix + key, ...toBuffer(value, options));
@@ -1311,23 +1201,177 @@ var Client = class {
1311
1201
  }
1312
1202
  };
1313
1203
 
1204
+ // src/fake.ts
1205
+ function toExp(ttl = 0) {
1206
+ if (ttl === 0)
1207
+ return Number.MAX_SAFE_INTEGER;
1208
+ return Date.now() + ttl * 1e3;
1209
+ }
1210
+ var FakeAdapter = class {
1211
+ #cache = /* @__PURE__ */ new Map();
1212
+ #cas = 1n;
1213
+ ttl = 0;
1214
+ #get(key) {
1215
+ if (key.length > 250)
1216
+ throw new TypeError(`Key too long (len=${key.length})`);
1217
+ const entry = this.#cache.get(key);
1218
+ if (!entry)
1219
+ return;
1220
+ if (Date.now() > entry.exp) {
1221
+ this.#cache.delete(key);
1222
+ return;
1223
+ }
1224
+ return entry;
1225
+ }
1226
+ #set(key, value, flags, ttl) {
1227
+ this.#cache.set(key, {
1228
+ value,
1229
+ flags: flags || 0,
1230
+ cas: ++this.#cas,
1231
+ exp: toExp(ttl)
1232
+ });
1233
+ return this.#cas;
1234
+ }
1235
+ async get(key) {
1236
+ const entry = this.#get(key);
1237
+ if (!entry)
1238
+ return;
1239
+ return {
1240
+ value: entry.value,
1241
+ flags: entry.flags,
1242
+ cas: entry.cas,
1243
+ recycle: () => void 0
1244
+ };
1245
+ }
1246
+ async gat(key, ttl) {
1247
+ const entry = this.#get(key);
1248
+ if (!entry)
1249
+ return;
1250
+ entry.exp = toExp(ttl);
1251
+ return {
1252
+ value: entry.value,
1253
+ flags: entry.flags,
1254
+ cas: entry.cas,
1255
+ recycle: () => void 0
1256
+ };
1257
+ }
1258
+ async touch(key, ttl) {
1259
+ const entry = this.#get(key);
1260
+ if (entry)
1261
+ entry.exp = toExp(ttl);
1262
+ return !!entry;
1263
+ }
1264
+ async set(key, value, options = {}) {
1265
+ const entry = this.#get(key);
1266
+ if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
1267
+ return;
1268
+ }
1269
+ return this.#set(key, value, options.flags, options.ttl);
1270
+ }
1271
+ async add(key, value, options = {}) {
1272
+ if (this.#get(key))
1273
+ return;
1274
+ return this.#set(key, value, options.flags, options.ttl);
1275
+ }
1276
+ async replace(key, value, options = {}) {
1277
+ if (!this.#get(key))
1278
+ return;
1279
+ return this.#set(key, value, options.flags, options.ttl);
1280
+ }
1281
+ async append(key, value, options = {}) {
1282
+ const entry = this.#get(key);
1283
+ if (!entry)
1284
+ return false;
1285
+ if (options.cas !== void 0 && options.cas !== entry.cas)
1286
+ return false;
1287
+ entry.value = Buffer.concat([entry.value, value]);
1288
+ return true;
1289
+ }
1290
+ async prepend(key, value, options = {}) {
1291
+ const entry = this.#get(key);
1292
+ if (!entry)
1293
+ return false;
1294
+ if (options.cas !== void 0 && options.cas !== entry.cas)
1295
+ return false;
1296
+ entry.value = Buffer.concat([value, entry.value]);
1297
+ return true;
1298
+ }
1299
+ async #counter(key, delta, options) {
1300
+ const entry = this.#get(key);
1301
+ if (!entry) {
1302
+ if (options.initial !== void 0) {
1303
+ const value = Buffer.from(options.initial.toString());
1304
+ this.#set(key, value, void 0, options.ttl);
1305
+ return { value: BigInt(options.initial), cas: this.#cas };
1306
+ } else {
1307
+ return;
1308
+ }
1309
+ }
1310
+ if (options.cas !== void 0 && options.cas !== entry.cas)
1311
+ return;
1312
+ try {
1313
+ const value = BigInt(entry.value.toString("utf-8")) + BigInt(delta);
1314
+ this.#set(key, Buffer.from(value.toString()), void 0, options.ttl);
1315
+ return { value, cas: this.#cas };
1316
+ } catch (error) {
1317
+ throw new TypeError(`${error.message} (status=NON_NUMERIC_VALUE, key=${key})`);
1318
+ }
1319
+ }
1320
+ increment(key, delta = 1n, options = {}) {
1321
+ return this.#counter(key, delta, options);
1322
+ }
1323
+ decrement(key, delta = 1n, options = {}) {
1324
+ return this.#counter(key, -delta, options);
1325
+ }
1326
+ async delete(key, options = {}) {
1327
+ const entry = this.#get(key);
1328
+ if (entry && options.cas !== void 0 && entry.cas !== options.cas) {
1329
+ return false;
1330
+ }
1331
+ return this.#cache.delete(key);
1332
+ }
1333
+ async flush(ttl) {
1334
+ if (!ttl)
1335
+ return this.#cache.clear();
1336
+ const wait = toExp(ttl) - Date.now();
1337
+ setTimeout(() => this.#cache.clear(), wait);
1338
+ }
1339
+ async noop() {
1340
+ }
1341
+ async quit() {
1342
+ }
1343
+ async version() {
1344
+ return { fake: "0.0.0-fake" };
1345
+ }
1346
+ async stats() {
1347
+ return { fake: { version: "0.0.0-fake" } };
1348
+ }
1349
+ };
1350
+ var MemxFakeClient = class extends MemxClient {
1351
+ constructor() {
1352
+ super(new FakeAdapter());
1353
+ }
1354
+ };
1355
+
1314
1356
  // src/utils.ts
1315
- var import_assert5 = __toESM(require("assert"));
1357
+ var import_assert6 = __toESM(require("assert"));
1316
1358
  var Factory = class {
1317
1359
  #factory;
1318
1360
  #client;
1319
1361
  #ttl;
1320
1362
  constructor(client, factory, ttl) {
1321
- (0, import_assert5.default)(typeof factory === "function", "Invalid or no factory specified");
1322
- (0, import_assert5.default)(client, "No client specified");
1363
+ (0, import_assert6.default)(typeof factory === "function", "Invalid or no factory specified");
1364
+ (0, import_assert6.default)(client, "No client specified");
1323
1365
  this.#factory = factory;
1324
1366
  this.#client = client;
1325
1367
  this.#ttl = ttl;
1326
1368
  }
1327
1369
  async get(key) {
1328
- const cached = await this.#client.get(key, { ttl: this.#ttl });
1329
- if (cached)
1370
+ const cached = await this.#client.getc(key);
1371
+ if (cached) {
1372
+ void logPromiseError(this.#client.touch(key), `Factory error touching key "${this.#client.prefix}${key}"`);
1330
1373
  return cached.value;
1374
+ }
1331
1375
  const created = await this.#factory(key);
1332
1376
  if (created) {
1333
1377
  void logPromiseError(this.#client.set(key, created, { ttl: this.#ttl }), `Factory error setting key "${this.#client.prefix}${key}"`);
@@ -1340,8 +1384,8 @@ var Bundle = class {
1340
1384
  #name;
1341
1385
  #ttl;
1342
1386
  constructor(client, name, ttl) {
1343
- (0, import_assert5.default)(client, "No client specified");
1344
- (0, import_assert5.default)(name, "No bundle name specified");
1387
+ (0, import_assert6.default)(client, "No client specified");
1388
+ (0, import_assert6.default)(name, "No bundle name specified");
1345
1389
  this.#client = client;
1346
1390
  this.#name = name;
1347
1391
  this.#ttl = ttl || 0;
@@ -1357,7 +1401,7 @@ var Bundle = class {
1357
1401
  }
1358
1402
  async #removeKey(key) {
1359
1403
  await logPromiseError((async () => {
1360
- const result = await this.#client.get(this.#name);
1404
+ const result = await this.#client.getc(this.#name);
1361
1405
  if (!result)
1362
1406
  return;
1363
1407
  const keys = result.value.split("\0").filter((k) => k !== key).join("\0");
@@ -1369,7 +1413,7 @@ var Bundle = class {
1369
1413
  await this.#appendKey(key);
1370
1414
  }
1371
1415
  async get(key) {
1372
- const result = await this.#client.get(`${this.#name}:${key}`);
1416
+ const result = await this.#client.getc(`${this.#name}:${key}`);
1373
1417
  if (result)
1374
1418
  return result.value;
1375
1419
  await this.#removeKey(key);
@@ -1379,13 +1423,13 @@ var Bundle = class {
1379
1423
  await this.#removeKey(key);
1380
1424
  }
1381
1425
  async list() {
1382
- const result = await this.#client.get(this.#name);
1426
+ const result = await this.#client.getc(this.#name);
1383
1427
  if (!result)
1384
1428
  return {};
1385
1429
  const results = {};
1386
1430
  const promises = [];
1387
1431
  for (const key of new Set(result.value.split("\0"))) {
1388
- promises.push(this.#client.get(`${this.#name}:${key}`).then((result2) => {
1432
+ promises.push(this.#client.getc(`${this.#name}:${key}`).then((result2) => {
1389
1433
  if (result2)
1390
1434
  results[key] = result2.value;
1391
1435
  }));
@@ -1399,8 +1443,8 @@ var PoorManLock = class {
1399
1443
  #client;
1400
1444
  #name;
1401
1445
  constructor(client, name) {
1402
- (0, import_assert5.default)(client, "No client specified");
1403
- (0, import_assert5.default)(name, "No lock name specified");
1446
+ (0, import_assert6.default)(client, "No client specified");
1447
+ (0, import_assert6.default)(name, "No lock name specified");
1404
1448
  this.#client = client;
1405
1449
  this.#name = name;
1406
1450
  }
@@ -1415,14 +1459,14 @@ var PoorManLock = class {
1415
1459
  await new Promise((resolve) => setTimeout(resolve, 100));
1416
1460
  } while (Date.now() < end);
1417
1461
  if (cas === void 0) {
1418
- const other = await this.#client.get(this.#name);
1462
+ const other = await this.#client.getc(this.#name);
1419
1463
  const owner2 = other && other.value ? `"${other.value}"` : "anonymous";
1420
1464
  throw new Error(`Lock "${this.#client.prefix}${this.#name}" timeout (owner=${owner2})`);
1421
1465
  }
1422
1466
  const interval = setInterval(() => {
1423
1467
  void logPromiseError((async () => {
1424
1468
  const replaced = await this.#client.replace(this.#name, owner, { ttl: 2, cas });
1425
- (0, import_assert5.default)(replaced !== void 0, `Lock "${this.#client.prefix}${this.#name}" not replaced`);
1469
+ (0, import_assert6.default)(replaced !== void 0, `Lock "${this.#client.prefix}${this.#name}" not replaced`);
1426
1470
  cas = replaced;
1427
1471
  })(), `Error extending lock "${this.#client.prefix}${this.#name}"`);
1428
1472
  }, 100);
@@ -1437,10 +1481,11 @@ var PoorManLock = class {
1437
1481
  // Annotate the CommonJS export names for ESM import in node:
1438
1482
  0 && (module.exports = {
1439
1483
  Bundle,
1440
- Client,
1441
1484
  ClusterAdapter,
1442
1485
  Factory,
1443
1486
  FakeAdapter,
1487
+ MemxClient,
1488
+ MemxFakeClient,
1444
1489
  PoorManLock,
1445
1490
  ServerAdapter,
1446
1491
  connection,