spindb 0.58.5 → 0.59.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.
@@ -0,0 +1,275 @@
1
+ // Minimal, dependency-free RESP2 client for the one job spindb's external CLI
2
+ // tools cannot do: a binary-safe `SCAN` + `DUMP`/`PTTL` -> `RESTORE` copy
3
+ // between a remote Redis/Valkey (including Upstash over `rediss://`) and a
4
+ // target. `redis-cli` mangles binary `DUMP` payloads in text mode, and the
5
+ // `--rdb`/`BGSAVE` full-snapshot shortcut is blocked on Upstash and most
6
+ // managed Redis - so for the migration path we speak RESP directly over a
7
+ // socket. Scope is deliberately tiny: AUTH, SELECT, PING, DBSIZE, SCAN, DUMP,
8
+ // PTTL, RESTORE, plus pipelining. Keys and payloads are Buffers end to end, so
9
+ // binary values and binary keys round-trip exactly.
10
+ import { connect as netConnect } from 'node:net';
11
+ import { connect as tlsConnect } from 'node:tls';
12
+ const CR = 0x0d;
13
+ const LF = 0x0a;
14
+ // Encode a command as a RESP array of bulk strings. Each argument may be a
15
+ // string (UTF-8) or a Buffer (raw bytes - used for binary keys + DUMP payloads).
16
+ function encodeCommand(args) {
17
+ const parts = [Buffer.from(`*${args.length}\r\n`)];
18
+ for (const arg of args) {
19
+ const buf = Buffer.isBuffer(arg) ? arg : Buffer.from(arg);
20
+ parts.push(Buffer.from(`$${buf.length}\r\n`), buf, Buffer.from('\r\n'));
21
+ }
22
+ return Buffer.concat(parts);
23
+ }
24
+ // Find the index just past the next CRLF at or after `from`, or -1 if the
25
+ // buffer does not yet contain a complete line.
26
+ function indexAfterCrlf(buf, from) {
27
+ for (let i = from; i + 1 < buf.length; i++) {
28
+ if (buf[i] === CR && buf[i + 1] === LF)
29
+ return i + 2;
30
+ }
31
+ return -1;
32
+ }
33
+ // Parse one RESP reply starting at `offset`. Returns the value + the offset
34
+ // just past it, or null when the buffer does not yet hold a complete reply
35
+ // (the caller waits for more bytes and retries). Binary-safe: bulk strings are
36
+ // sliced by their length prefix, never by scanning for delimiters.
37
+ function parseReply(buf, offset) {
38
+ if (offset >= buf.length)
39
+ return null;
40
+ const type = buf[offset];
41
+ const lineEnd = indexAfterCrlf(buf, offset + 1);
42
+ if (lineEnd === -1)
43
+ return null;
44
+ const line = buf.toString('latin1', offset + 1, lineEnd - 2);
45
+ switch (type) {
46
+ case 0x2b: // '+' simple string
47
+ return { value: line, offset: lineEnd };
48
+ case 0x2d: // '-' error
49
+ return { value: new Error(line), offset: lineEnd };
50
+ case 0x3a: // ':' integer
51
+ return { value: Number(line), offset: lineEnd };
52
+ case 0x24: {
53
+ // '$' bulk string
54
+ const len = Number(line);
55
+ if (len === -1)
56
+ return { value: null, offset: lineEnd };
57
+ const end = lineEnd + len;
58
+ if (end + 2 > buf.length)
59
+ return null; // value + trailing CRLF not in yet
60
+ return { value: buf.subarray(lineEnd, end), offset: end + 2 };
61
+ }
62
+ case 0x2a: {
63
+ // '*' array
64
+ const count = Number(line);
65
+ if (count === -1)
66
+ return { value: null, offset: lineEnd };
67
+ const items = [];
68
+ let cur = lineEnd;
69
+ for (let i = 0; i < count; i++) {
70
+ const parsed = parseReply(buf, cur);
71
+ if (!parsed)
72
+ return null;
73
+ items.push(parsed.value);
74
+ cur = parsed.offset;
75
+ }
76
+ return { value: items, offset: cur };
77
+ }
78
+ default:
79
+ throw new Error(`Unsupported RESP reply type: ${String.fromCharCode(type)}`);
80
+ }
81
+ }
82
+ export class RespClient {
83
+ socket;
84
+ inbox = Buffer.alloc(0);
85
+ // FIFO of resolvers, one per in-flight command (pipelining-friendly).
86
+ queue = [];
87
+ fatal = null;
88
+ constructor(socket) {
89
+ this.socket = socket;
90
+ socket.on('data', (chunk) => this.onData(chunk));
91
+ socket.on('error', (err) => this.onFatal(err));
92
+ socket.on('close', () => this.onFatal(new Error('Redis connection closed')));
93
+ }
94
+ onData(chunk) {
95
+ this.inbox = this.inbox.length === 0 ? chunk : Buffer.concat([this.inbox, chunk]);
96
+ let offset = 0;
97
+ for (;;) {
98
+ const parsed = parseReply(this.inbox, offset);
99
+ if (!parsed)
100
+ break;
101
+ offset = parsed.offset;
102
+ const waiter = this.queue.shift();
103
+ if (!waiter)
104
+ continue; // unexpected push (e.g. server-side); ignore
105
+ if (parsed.value instanceof Error)
106
+ waiter.reject(parsed.value);
107
+ else
108
+ waiter.resolve(parsed.value);
109
+ }
110
+ this.inbox = offset === 0 ? this.inbox : this.inbox.subarray(offset);
111
+ }
112
+ onFatal(err) {
113
+ if (this.fatal)
114
+ return;
115
+ this.fatal = err;
116
+ for (const waiter of this.queue)
117
+ waiter.reject(err);
118
+ this.queue = [];
119
+ }
120
+ // Send one command and await its reply.
121
+ command(args) {
122
+ if (this.fatal)
123
+ return Promise.reject(this.fatal);
124
+ const promise = new Promise((resolve, reject) => {
125
+ this.queue.push({ resolve, reject });
126
+ });
127
+ this.socket.write(encodeCommand(args));
128
+ return promise;
129
+ }
130
+ // Send a batch of commands in one write and await all replies in order. This
131
+ // is the throughput lever: dump N keys (DUMP+PTTL) or restore N keys per
132
+ // round-trip instead of one command at a time.
133
+ pipeline(commands) {
134
+ if (this.fatal)
135
+ return Promise.reject(this.fatal);
136
+ const promises = commands.map(() => new Promise((resolve, reject) => {
137
+ this.queue.push({ resolve, reject });
138
+ }));
139
+ this.socket.write(Buffer.concat(commands.map(encodeCommand)));
140
+ return Promise.all(promises);
141
+ }
142
+ close() {
143
+ this.socket.destroy();
144
+ }
145
+ static async connect(opts) {
146
+ const socket = await new Promise((resolve, reject) => {
147
+ const onError = (err) => reject(err);
148
+ const timeoutMs = opts.connectTimeoutMs ?? 15000;
149
+ const s = opts.tls
150
+ ? tlsConnect({
151
+ host: opts.host,
152
+ port: opts.port,
153
+ servername: opts.host,
154
+ rejectUnauthorized: opts.rejectUnauthorized ?? false,
155
+ })
156
+ : netConnect({ host: opts.host, port: opts.port });
157
+ const onReady = () => {
158
+ s.removeListener('error', onError);
159
+ s.setTimeout(0);
160
+ resolve(s);
161
+ };
162
+ s.setTimeout(timeoutMs, () => {
163
+ s.destroy();
164
+ reject(new Error(`Redis connection timed out after ${timeoutMs}ms`));
165
+ });
166
+ s.once('error', onError);
167
+ s.once(opts.tls ? 'secureConnect' : 'connect', onReady);
168
+ });
169
+ const client = new RespClient(socket);
170
+ if (opts.password) {
171
+ const authArgs = opts.username && opts.username !== 'default'
172
+ ? ['AUTH', opts.username, opts.password]
173
+ : ['AUTH', opts.password];
174
+ await client.command(authArgs);
175
+ }
176
+ if (opts.database && opts.database > 0) {
177
+ await client.command(['SELECT', String(opts.database)]);
178
+ }
179
+ return client;
180
+ }
181
+ // ─── Typed helpers for the migration ops ──────────────────────────
182
+ async ping() {
183
+ await this.command(['PING']);
184
+ }
185
+ async dbsize() {
186
+ const reply = await this.command(['DBSIZE']);
187
+ return typeof reply === 'number' ? reply : 0;
188
+ }
189
+ // One SCAN step. Returns the next cursor ('0' when complete) and the batch of
190
+ // keys as Buffers (binary-safe).
191
+ async scan(cursor, count) {
192
+ const reply = await this.command(['SCAN', cursor, 'COUNT', String(count)]);
193
+ if (!Array.isArray(reply) || reply.length < 2) {
194
+ throw new Error('Unexpected SCAN reply');
195
+ }
196
+ const nextCursor = Buffer.isBuffer(reply[0])
197
+ ? reply[0].toString('latin1')
198
+ : String(reply[0]);
199
+ const keysField = reply[1];
200
+ const keys = Array.isArray(keysField)
201
+ ? keysField.filter((k) => Buffer.isBuffer(k))
202
+ : [];
203
+ return { cursor: nextCursor, keys };
204
+ }
205
+ }
206
+ // Binary-safe keyspace copy: SCAN the source, pipeline DUMP+PTTL per batch, and
207
+ // RESTORE (with TTL, REPLACE) into the target. Preserves every type and TTL
208
+ // exactly because DUMP/RESTORE moves Redis's own serialization. Used by the
209
+ // `restore --from-url` path for redis/valkey. Returns the number of keys copied.
210
+ export async function copyRedisKeyspace(source, target, options = {}) {
211
+ const batchSize = options.batchSize ?? 200;
212
+ const src = await RespClient.connect(source);
213
+ let dst = null;
214
+ try {
215
+ await src.ping();
216
+ const total = await src.dbsize();
217
+ dst = await RespClient.connect(target);
218
+ await dst.ping();
219
+ let cursor = '0';
220
+ let scanned = 0;
221
+ let restored = 0;
222
+ do {
223
+ const { cursor: next, keys } = await src.scan(cursor, batchSize);
224
+ cursor = next;
225
+ if (keys.length === 0)
226
+ continue;
227
+ // DUMP + PTTL for every key in the batch, in one round-trip.
228
+ const probe = await src.pipeline(keys.flatMap((k) => [
229
+ ['DUMP', k],
230
+ ['PTTL', k],
231
+ ]));
232
+ const restoreCmds = [];
233
+ for (let i = 0; i < keys.length; i++) {
234
+ const payload = probe[i * 2];
235
+ const pttl = probe[i * 2 + 1];
236
+ // A key can vanish between SCAN and DUMP; DUMP returns null - skip it.
237
+ if (!Buffer.isBuffer(payload))
238
+ continue;
239
+ const ttlMs = typeof pttl === 'number' && pttl > 0 ? pttl : 0;
240
+ restoreCmds.push([
241
+ 'RESTORE',
242
+ keys[i],
243
+ String(ttlMs),
244
+ payload,
245
+ 'REPLACE',
246
+ ]);
247
+ }
248
+ scanned += keys.length;
249
+ if (restoreCmds.length > 0) {
250
+ try {
251
+ await dst.pipeline(restoreCmds);
252
+ }
253
+ catch (error) {
254
+ const message = error.message;
255
+ // RESTORE rejects a DUMP payload whose RDB version is newer than the
256
+ // target supports - i.e. the source is a newer engine version than
257
+ // the target. Surface that plainly instead of the raw checksum error.
258
+ if (/DUMP payload version|checksum are wrong/i.test(message)) {
259
+ throw new Error(`The target is an older engine version than the source, so its binary format is incompatible (${message}). Provision the target at the same major version as the source, or newer, and retry.`);
260
+ }
261
+ throw error;
262
+ }
263
+ restored += restoreCmds.length;
264
+ }
265
+ options.onProgress?.({ scanned, restored, total });
266
+ } while (cursor !== '0');
267
+ return { keysCopied: restored, total };
268
+ }
269
+ finally {
270
+ src.close();
271
+ if (dst)
272
+ dst.close();
273
+ }
274
+ }
275
+ //# sourceMappingURL=resp-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resp-client.js","sourceRoot":"","sources":["../../../engines/redis/resp-client.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,yEAAyE;AACzE,0EAA0E;AAC1E,8EAA8E;AAC9E,+EAA+E;AAC/E,oDAAoD;AAEpD,OAAO,EAAe,OAAO,IAAI,UAAU,EAAE,MAAM,UAAU,CAAA;AAC7D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,UAAU,CAAA;AAMhD,MAAM,EAAE,GAAG,IAAI,CAAA;AACf,MAAM,EAAE,GAAG,IAAI,CAAA;AAEf,2EAA2E;AAC3E,iFAAiF;AACjF,SAAS,aAAa,CAAC,IAA4B;IACjD,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,MAAM,CAAC,CAAC,CAAA;IAC5D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QACzD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAA;IACzE,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;AAC7B,CAAC;AAED,0EAA0E;AAC1E,+CAA+C;AAC/C,SAAS,cAAc,CAAC,GAAW,EAAE,IAAY;IAC/C,KAAK,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3C,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE;YAAE,OAAO,CAAC,GAAG,CAAC,CAAA;IACtD,CAAC;IACD,OAAO,CAAC,CAAC,CAAA;AACX,CAAC;AAED,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,mEAAmE;AACnE,SAAS,UAAU,CACjB,GAAW,EACX,MAAc;IAEd,IAAI,MAAM,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,IAAI,CAAA;IACrC,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAA;IACxB,MAAM,OAAO,GAAG,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,CAAA;IAC/C,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IAC/B,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,CAAA;IAE5D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,IAAI,EAAE,oBAAoB;YAC7B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;QACzC,KAAK,IAAI,EAAE,YAAY;YACrB,OAAO,EAAE,KAAK,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;QACpD,KAAK,IAAI,EAAE,cAAc;YACvB,OAAO,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;QACjD,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,kBAAkB;YAClB,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;YACxB,IAAI,GAAG,KAAK,CAAC,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;YACvD,MAAM,GAAG,GAAG,OAAO,GAAG,GAAG,CAAA;YACzB,IAAI,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM;gBAAE,OAAO,IAAI,CAAA,CAAC,mCAAmC;YACzE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,EAAE,CAAA;QAC/D,CAAC;QACD,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,YAAY;YACZ,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAA;YAC1B,IAAI,KAAK,KAAK,CAAC,CAAC;gBAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;YACzD,MAAM,KAAK,GAAgB,EAAE,CAAA;YAC7B,IAAI,GAAG,GAAG,OAAO,CAAA;YACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;gBACnC,IAAI,CAAC,MAAM;oBAAE,OAAO,IAAI,CAAA;gBACxB,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACxB,GAAG,GAAG,MAAM,CAAC,MAAM,CAAA;YACrB,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAA;QACtC,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAChF,CAAC;AACH,CAAC;AAgBD,MAAM,OAAO,UAAU;IACb,MAAM,CAAQ;IACd,KAAK,GAAW,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACvC,sEAAsE;IAC9D,KAAK,GAGR,EAAE,CAAA;IACC,KAAK,GAAiB,IAAI,CAAA;IAElC,YAAoB,MAAc;QAChC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;QACxD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;QACrD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CACtB,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CACnD,CAAA;IACH,CAAC;IAEO,MAAM,CAAC,KAAa;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;QACjF,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,SAAS,CAAC;YACR,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;YAC7C,IAAI,CAAC,MAAM;gBAAE,MAAK;YAClB,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;YACtB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;YACjC,IAAI,CAAC,MAAM;gBAAE,SAAQ,CAAC,6CAA6C;YACnE,IAAI,MAAM,CAAC,KAAK,YAAY,KAAK;gBAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;;gBACzD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QACnC,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IACtE,CAAC;IAEO,OAAO,CAAC,GAAU;QACxB,IAAI,IAAI,CAAC,KAAK;YAAE,OAAM;QACtB,IAAI,CAAC,KAAK,GAAG,GAAG,CAAA;QAChB,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,KAAK;YAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QACnD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAA;IACjB,CAAC;IAED,wCAAwC;IACxC,OAAO,CAAC,IAA4B;QAClC,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,OAAO,GAAG,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;QACtC,CAAC,CAAC,CAAA;QACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAA;QACtC,OAAO,OAAO,CAAA;IAChB,CAAC;IAED,6EAA6E;IAC7E,yEAAyE;IACzE,+CAA+C;IAC/C,QAAQ,CAAC,QAAuC;QAC9C,IAAI,IAAI,CAAC,KAAK;YAAE,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACjD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAC3B,GAAG,EAAE,CACH,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACzC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;QACtC,CAAC,CAAC,CACL,CAAA;QACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;QAC7D,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;IACvB,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,IAAwB;QAC3C,MAAM,MAAM,GAAW,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3D,MAAM,OAAO,GAAG,CAAC,GAAU,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,IAAI,KAAK,CAAA;YAChD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG;gBAChB,CAAC,CAAC,UAAU,CAAC;oBACT,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,UAAU,EAAE,IAAI,CAAC,IAAI;oBACrB,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,IAAI,KAAK;iBACrD,CAAC;gBACJ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;YACpD,MAAM,OAAO,GAAG,GAAG,EAAE;gBACnB,CAAC,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;gBAClC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;gBACf,OAAO,CAAC,CAAC,CAAC,CAAA;YACZ,CAAC,CAAA;YACD,CAAC,CAAC,UAAU,CAAC,SAAS,EAAE,GAAG,EAAE;gBAC3B,CAAC,CAAC,OAAO,EAAE,CAAA;gBACX,MAAM,CAAC,IAAI,KAAK,CAAC,oCAAoC,SAAS,IAAI,CAAC,CAAC,CAAA;YACtE,CAAC,CAAC,CAAA;YACF,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;YACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QACzD,CAAC,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAA;QACrC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,QAAQ,GACZ,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;gBAC1C,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC;gBACxC,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;YAC7B,MAAM,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAChC,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;QACzD,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED,qEAAqE;IAErE,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,MAAM;QACV,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAA;QAC5C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED,8EAA8E;IAC9E,iCAAiC;IACjC,KAAK,CAAC,IAAI,CAAC,MAAc,EAAE,KAAa;QAItC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;QAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;QAC1C,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC1C,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC7B,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;QACpB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAC1B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;YACnC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1D,CAAC,CAAC,EAAE,CAAA;QACN,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;IACrC,CAAC;CACF;AAQD,gFAAgF;AAChF,4EAA4E;AAC5E,4EAA4E;AAC5E,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAA0B,EAC1B,MAA0B,EAC1B,UAGI,EAAE;IAEN,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAA;IAC1C,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,GAAG,GAAsB,IAAI,CAAA;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAChB,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,MAAM,EAAE,CAAA;QAChC,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QACtC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAEhB,IAAI,MAAM,GAAG,GAAG,CAAA;QAChB,IAAI,OAAO,GAAG,CAAC,CAAA;QACf,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,GAAG,CAAC;YACF,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAA;YAChE,MAAM,GAAG,IAAI,CAAA;YACb,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAQ;YAE/B,6DAA6D;YAC7D,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,QAAQ,CAC9B,IAAI,CAAC,OAAO,CACV,CAAC,CAAC,EAAiC,EAAE,CAAC;gBACpC,CAAC,MAAM,EAAE,CAAC,CAAC;gBACX,CAAC,MAAM,EAAE,CAAC,CAAC;aACZ,CACF,CACF,CAAA;YAED,MAAM,WAAW,GAAkC,EAAE,CAAA;YACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACrC,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;gBAC5B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;gBAC7B,uEAAuE;gBACvE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,SAAQ;gBACvC,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;gBAC7D,WAAW,CAAC,IAAI,CAAC;oBACf,SAAS;oBACT,IAAI,CAAC,CAAC,CAAC;oBACP,MAAM,CAAC,KAAK,CAAC;oBACb,OAAO;oBACP,SAAS;iBACV,CAAC,CAAA;YACJ,CAAC;YAED,OAAO,IAAI,IAAI,CAAC,MAAM,CAAA;YACtB,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC;oBACH,MAAM,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAA;gBACjC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,OAAO,GAAI,KAAe,CAAC,OAAO,CAAA;oBACxC,qEAAqE;oBACrE,mEAAmE;oBACnE,sEAAsE;oBACtE,IAAI,0CAA0C,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC7D,MAAM,IAAI,KAAK,CACb,gGAAgG,OAAO,uFAAuF,CAC/L,CAAA;oBACH,CAAC;oBACD,MAAM,KAAK,CAAA;gBACb,CAAC;gBACD,QAAQ,IAAI,WAAW,CAAC,MAAM,CAAA;YAChC,CAAC;YACD,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAA;QACpD,CAAC,QAAQ,MAAM,KAAK,GAAG,EAAC;QAExB,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAA;IACxC,CAAC;YAAS,CAAC;QACT,GAAG,CAAC,KAAK,EAAE,CAAA;QACX,IAAI,GAAG;YAAE,GAAG,CAAC,KAAK,EAAE,CAAA;IACtB,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spindb",
3
- "version": "0.58.5",
3
+ "version": "0.59.0",
4
4
  "author": "Bob Bass <bob@bbass.co>",
5
5
  "license": "PolyForm-Noncommercial-1.0.0",
6
6
  "description": "Zero-config Docker-free local database containers. Create, backup, and clone a variety of popular databases.",