@tablecraft-app/plugin-redis 1.5.1 → 1.7.0
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/index.js +106 -14
- package/package.json +2 -2
- package/table-craft-plugin.json +2 -2
package/index.js
CHANGED
|
@@ -52106,6 +52106,10 @@ var KEY_COLUMN = {
|
|
|
52106
52106
|
name: "key",
|
|
52107
52107
|
type: null
|
|
52108
52108
|
};
|
|
52109
|
+
var FIELD_COLUMN = {
|
|
52110
|
+
name: "field",
|
|
52111
|
+
type: null
|
|
52112
|
+
};
|
|
52109
52113
|
var MEMBER_COLUMN = {
|
|
52110
52114
|
name: "member",
|
|
52111
52115
|
type: null
|
|
@@ -52216,24 +52220,62 @@ async function* yieldRows(rows) {
|
|
|
52216
52220
|
for (const row of rows) yield row;
|
|
52217
52221
|
return Promise.resolve();
|
|
52218
52222
|
}
|
|
52219
|
-
/**
|
|
52220
|
-
|
|
52223
|
+
/**
|
|
52224
|
+
* A command's reply as an `ExecuteResult`: a scalar as `reply`, anything else as rows. A bulk
|
|
52225
|
+
* string, or the nil of a command that reads one key, is a value read (decision 119).
|
|
52226
|
+
*/
|
|
52227
|
+
function resultOf(reply, options = {}, readsKey = false) {
|
|
52221
52228
|
const table = tableOf(reply, options);
|
|
52222
|
-
if (table === null)
|
|
52223
|
-
|
|
52224
|
-
|
|
52225
|
-
|
|
52226
|
-
|
|
52227
|
-
|
|
52228
|
-
|
|
52229
|
-
|
|
52230
|
-
|
|
52229
|
+
if (table === null) {
|
|
52230
|
+
const read = reply instanceof Uint8Array || readsKey && (reply === null || reply === void 0);
|
|
52231
|
+
return {
|
|
52232
|
+
columns: [],
|
|
52233
|
+
rows: yieldRows([]),
|
|
52234
|
+
rowsAffected: null,
|
|
52235
|
+
reply: {
|
|
52236
|
+
value: cellOf(reply, options),
|
|
52237
|
+
text: replyText(reply),
|
|
52238
|
+
...read ? { read } : {}
|
|
52239
|
+
}
|
|
52240
|
+
};
|
|
52241
|
+
}
|
|
52231
52242
|
return {
|
|
52232
52243
|
columns: table.columns,
|
|
52233
52244
|
rows: yieldRows(table.rows),
|
|
52234
52245
|
rowsAffected: null
|
|
52235
52246
|
};
|
|
52236
52247
|
}
|
|
52248
|
+
function membersOf(reply) {
|
|
52249
|
+
return Array.isArray(reply) || reply instanceof Set ? [...reply] : null;
|
|
52250
|
+
}
|
|
52251
|
+
/**
|
|
52252
|
+
* A reply holding a whole key in the columns a key tab reads that type with (decision 119), so an
|
|
52253
|
+
* edit maps to the key the same way: list positions count from 0 as `LSET` does. Null when the
|
|
52254
|
+
* reply is not that shape, or the type is not one a console result edits as rows.
|
|
52255
|
+
*/
|
|
52256
|
+
function wholeKeyResult(reply, type, options = {}) {
|
|
52257
|
+
const result = (columns, rows) => ({
|
|
52258
|
+
columns,
|
|
52259
|
+
rows: yieldRows(rows),
|
|
52260
|
+
rowsAffected: null
|
|
52261
|
+
});
|
|
52262
|
+
const members = membersOf(reply);
|
|
52263
|
+
switch (type) {
|
|
52264
|
+
case "hash":
|
|
52265
|
+
if (!(reply instanceof Map)) return null;
|
|
52266
|
+
return result([FIELD_COLUMN, VALUE_COLUMN], [...reply].map(([field, value]) => [cellOf(field, options), cellOf(value, options)]));
|
|
52267
|
+
case "set": return members === null ? null : result([MEMBER_COLUMN], members.map((member) => [cellOf(member, options)]));
|
|
52268
|
+
case "list": return members === null ? null : result([INDEX_COLUMN, VALUE_COLUMN], members.map((element, index) => [index, cellOf(element, options)]));
|
|
52269
|
+
case "zset":
|
|
52270
|
+
if (members === null) return null;
|
|
52271
|
+
if (members.length > 0 && members.every(isScoredPair)) return result([MEMBER_COLUMN, SCORE_COLUMN], members.map((element) => {
|
|
52272
|
+
const [member, score] = element;
|
|
52273
|
+
return [cellOf(member, options), score];
|
|
52274
|
+
}));
|
|
52275
|
+
return result([MEMBER_COLUMN], members.map((member) => [cellOf(member, options)]));
|
|
52276
|
+
default: return null;
|
|
52277
|
+
}
|
|
52278
|
+
}
|
|
52237
52279
|
/** One reply per primary, each row led by the node it came from (decision 114). */
|
|
52238
52280
|
function fannedOutResult(replies, options = {}) {
|
|
52239
52281
|
const tables = replies.map(({ node, reply }) => ({
|
|
@@ -55096,6 +55138,33 @@ var RedisSessionMonitor = class {
|
|
|
55096
55138
|
});
|
|
55097
55139
|
}
|
|
55098
55140
|
};
|
|
55141
|
+
var FIRST = "0";
|
|
55142
|
+
var LAST = "-1";
|
|
55143
|
+
var STREAM_START = "-";
|
|
55144
|
+
var STREAM_END = "+";
|
|
55145
|
+
/** The one key a read-only command reads, or null for writes, keyless and multi-key commands. */
|
|
55146
|
+
function keyRead(table, words, args) {
|
|
55147
|
+
if (!flagsOf(table, words).includes("readonly")) return null;
|
|
55148
|
+
const keys = keyArguments(table, words, args);
|
|
55149
|
+
return keys === "movable" || keys.length !== 1 ? null : keys[0] ?? null;
|
|
55150
|
+
}
|
|
55151
|
+
/**
|
|
55152
|
+
* Whether the command's reply holds the whole of a key of `type` (decision 119): `GET`, `HGETALL`,
|
|
55153
|
+
* `SMEMBERS`, `LRANGE k 0 -1`, `ZRANGE k 0 -1 [WITHSCORES]` and `XRANGE k - +`, with no other
|
|
55154
|
+
* option that narrows or reorders them.
|
|
55155
|
+
*/
|
|
55156
|
+
function readsWholeKey(words, type) {
|
|
55157
|
+
const [name, , from, to, option] = words;
|
|
55158
|
+
switch (type) {
|
|
55159
|
+
case "string": return name === "GET" && words.length === 2;
|
|
55160
|
+
case "hash": return name === "HGETALL" && words.length === 2;
|
|
55161
|
+
case "set": return name === "SMEMBERS" && words.length === 2;
|
|
55162
|
+
case "list": return name === "LRANGE" && words.length === 4 && from === FIRST && to === LAST;
|
|
55163
|
+
case "zset": return name === "ZRANGE" && from === FIRST && to === LAST && (words.length === 4 || words.length === 5 && option === "WITHSCORES");
|
|
55164
|
+
case "stream": return name === "XRANGE" && words.length === 4 && from === STREAM_START && to === STREAM_END;
|
|
55165
|
+
default: return false;
|
|
55166
|
+
}
|
|
55167
|
+
}
|
|
55099
55168
|
// ../../plugins/redis/src/session.ts
|
|
55100
55169
|
var CLOSE_GRACE_MS = 3e3;
|
|
55101
55170
|
var BUSY_MESSAGE = "Another command is still running in this session.";
|
|
@@ -55235,10 +55304,18 @@ var RedisSession = class RedisSession {
|
|
|
55235
55304
|
const refusal = readOnlyRefusal(await this.commandTable(), words);
|
|
55236
55305
|
if (refusal !== null) throw new PluginError("statementFailed", refusal);
|
|
55237
55306
|
}
|
|
55238
|
-
const
|
|
55307
|
+
const args = tokens.map((token) => token.bytes);
|
|
55308
|
+
const routed = await this.#run(args, words, options?.node);
|
|
55239
55309
|
if (words[0] === "SELECT" && !routed.fanned) this.#database = Number(words[1]);
|
|
55240
|
-
|
|
55241
|
-
|
|
55310
|
+
if (routed.fanned) return fannedOutResult(routed.replies, { fullBytes: options?.fullBytes === true });
|
|
55311
|
+
const key = routed.reply === "QUEUED" ? null : keyRead(await this.commandTable(), words, args);
|
|
55312
|
+
const source = key === null ? null : await this.#sourceOf(key, words);
|
|
55313
|
+
const wire = { fullBytes: options?.fullBytes === true || key !== null };
|
|
55314
|
+
const result = (source?.whole === true ? wholeKeyResult(routed.reply, source.type, wire) : null) ?? resultOf(routed.reply, wire, key !== null);
|
|
55315
|
+
return source === null ? result : {
|
|
55316
|
+
...result,
|
|
55317
|
+
source
|
|
55318
|
+
};
|
|
55242
55319
|
} finally {
|
|
55243
55320
|
this.#running = false;
|
|
55244
55321
|
}
|
|
@@ -55352,6 +55429,21 @@ var RedisSession = class RedisSession {
|
|
|
55352
55429
|
this.#queue = run.catch(() => void 0);
|
|
55353
55430
|
return run;
|
|
55354
55431
|
}
|
|
55432
|
+
/** The key the command read, typed by `TYPE` (decision 119); null when it is gone or `TYPE` is refused. */
|
|
55433
|
+
async #sourceOf(key, words) {
|
|
55434
|
+
try {
|
|
55435
|
+
const type = keyTypeOf(String(await this.#router.onKey(key, ["TYPE", key])));
|
|
55436
|
+
if (type === null) return null;
|
|
55437
|
+
return {
|
|
55438
|
+
database: this.#database,
|
|
55439
|
+
key: keyBytesOf(key),
|
|
55440
|
+
type,
|
|
55441
|
+
whole: readsWholeKey(words, type)
|
|
55442
|
+
};
|
|
55443
|
+
} catch {
|
|
55444
|
+
return null;
|
|
55445
|
+
}
|
|
55446
|
+
}
|
|
55355
55447
|
#run(args, words, node) {
|
|
55356
55448
|
return this.#failures(() => this.#router.run(args, words, node));
|
|
55357
55449
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tablecraft-app/plugin-redis",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "The Redis datasource plugin for TableCraft, downloaded by the app when a data source needs it.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,6 +24,6 @@
|
|
|
24
24
|
},
|
|
25
25
|
"tableCraft": {
|
|
26
26
|
"id": "redis",
|
|
27
|
-
"apiVersion": "1.
|
|
27
|
+
"apiVersion": "1.3.0"
|
|
28
28
|
}
|
|
29
29
|
}
|