@romedb/node 0.2.13 → 0.2.14
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/README.md +26 -4
- package/THIRD_PARTY_CRATE_NOTICES.md +4 -4
- package/client.cjs +10 -4
- package/client.d.ts +13 -1
- package/client.mjs +10 -4
- package/embedded-client.cjs +4 -3
- package/embedded-client.d.ts +2 -2
- package/embedded-worker.cjs +2 -1
- package/index.cjs +6 -1
- package/index.d.ts +7 -1
- package/package.json +1 -1
- package/romedb.node +2 -2
- package/values.cjs +11 -1
- package/values.d.ts +1 -1
- package/values.mjs +12 -2
- package/worker.cjs +1 -1
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ version, 0.2.12, differs from its asset only in `package.json` and this README.
|
|
|
23
23
|
project can also depend on the asset of a GitHub release by URL:
|
|
24
24
|
|
|
25
25
|
```sh
|
|
26
|
-
pnpm add https://github.com/romedb/romedb/releases/download/romedb-v0.2.
|
|
26
|
+
pnpm add https://github.com/romedb/romedb/releases/download/romedb-v0.2.14/romedb-node-0.2.14.tgz
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## A first database
|
|
@@ -125,7 +125,7 @@ own connection.
|
|
|
125
125
|
| `boolean`, `null`, `string` | The same type |
|
|
126
126
|
| Array, plain object | Array, object |
|
|
127
127
|
| `Buffer`, `Uint8Array` | Binary |
|
|
128
|
-
| `Record(table, key)` | A record ID. The key is a string or a `bigint`. |
|
|
128
|
+
| `Record(table, key)` | A record ID. The key is a string or a `bigint`. `String(record)` gives `table:key`, and `record.equals(other)` compares the table and the key. |
|
|
129
129
|
| `Vector` | A vector of validated native-format bytes. See [typed vectors](#typed-vectors). |
|
|
130
130
|
|
|
131
131
|
RomeDB never makes a reference from a string. Unsupported JavaScript types,
|
|
@@ -702,8 +702,30 @@ it. Exports have no deadline unless you pass `timeoutMs`. `signal`, `timeoutMs`
|
|
|
702
702
|
`close()` cancel a running export. It then rejects with `RDB_CANCELLED`, unless it
|
|
703
703
|
finished first.
|
|
704
704
|
|
|
705
|
-
|
|
706
|
-
|
|
705
|
+
#### Leaving data out of a copy
|
|
706
|
+
|
|
707
|
+
A whole copy holds everything, including sessions and tokens. Use `emptyTables` when
|
|
708
|
+
someone else gets the file:
|
|
709
|
+
|
|
710
|
+
```js
|
|
711
|
+
await rql.exportFile('site.romedb', { emptyTables: ['cms_auth_sessions', 'cms_cache'] });
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
- The named tables keep their schema and indexes, but no rows.
|
|
715
|
+
- Their rows are never read, so they cannot reach the file. They are not in freed
|
|
716
|
+
pages, a log or a receipt.
|
|
717
|
+
- A name that is not a table fails with `RDB_VALIDATION`.
|
|
718
|
+
- An edge table must be emptied together with the tables it connects.
|
|
719
|
+
- Rows in other tables keep their references to the emptied rows.
|
|
720
|
+
- The copy also gets a new identity, because a receipt can hold row data.
|
|
721
|
+
|
|
722
|
+
Use `newIdentity: true` to copy every row into a new database, for example to
|
|
723
|
+
duplicate a site. The copy leaves out the database ID, the sequence and the receipts.
|
|
724
|
+
Its sequence starts at 0, and it gets a new ID the first time it opens.
|
|
725
|
+
|
|
726
|
+
The URL client has the streaming form, `rql.exportFile({ signal, timeoutMs, emptyTables,
|
|
727
|
+
newIdentity })`, for `romedb serve`, `serve --directory` and Cloud. On Cloud, set
|
|
728
|
+
`timeoutMs` high enough for the size of the database: a job builds the file first. See
|
|
707
729
|
[database files](https://github.com/romedb/romedb/blob/main/romedb/docs/service-protocol.md#database-files) for how the copy is
|
|
708
730
|
made.
|
|
709
731
|
|
|
@@ -4,7 +4,7 @@ Generated from the pinned Cargo dependency inventory and checksummed source arch
|
|
|
4
4
|
|
|
5
5
|
This is a partial notice collection. It supplements LICENSE.md and THIRD_PARTY_NOTICES.md. Inline attributions, unconventional filenames and other bundled components require further review before a complete distribution-notice claim.
|
|
6
6
|
|
|
7
|
-
Target: `x86_64-unknown-linux-gnu`. Cargo.lock SHA-256: `
|
|
7
|
+
Target: `x86_64-unknown-linux-gnu`. Cargo.lock SHA-256: `1bceceb035554db77bd940502707e4fea905a961d66b28cdbb2ca9b7206c5964`.
|
|
8
8
|
|
|
9
9
|
## Packages without collected archive or supplemental texts
|
|
10
10
|
|
|
@@ -703,13 +703,13 @@ Target: `x86_64-unknown-linux-gnu`. Cargo.lock SHA-256: `092e973bbc52cf5defe48c0
|
|
|
703
703
|
- `LICENSE-APACHE`: [source text a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2](#text-a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2)
|
|
704
704
|
- `LICENSE-MIT`: [source text 42d3bf7e7d4d49d72c0555d14ed99c3ee7ce9ce3cbffbc38bbafe8c103f50969](#text-42d3bf7e7d4d49d72c0555d14ed99c3ee7ce9ce3cbffbc38bbafe8c103f50969)
|
|
705
705
|
|
|
706
|
-
### romedb-node 0.2.
|
|
706
|
+
### romedb-node 0.2.14
|
|
707
707
|
- Workspace `LICENSE.md`: [source text b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5](#text-b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5)
|
|
708
708
|
|
|
709
|
-
### romedb 0.2.
|
|
709
|
+
### romedb 0.2.14
|
|
710
710
|
- Workspace `LICENSE.md`: [source text b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5](#text-b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5)
|
|
711
711
|
|
|
712
|
-
### romeql-parser 0.2.
|
|
712
|
+
### romeql-parser 0.2.14
|
|
713
713
|
- Workspace `LICENSE.md`: [source text b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5](#text-b646f9ee8bcaf87e8de75153b9df7a2861c7ac445c87e741768b3c2bccf47bc5)
|
|
714
714
|
|
|
715
715
|
### rquickjs-core 0.13.0
|
package/client.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
// Web APIs only: this file also runs in Workers and browsers through client.mjs.
|
|
3
|
-
const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text } = require('./values.cjs');
|
|
3
|
+
const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text, checkCopyOptions } = require('./values.cjs');
|
|
4
4
|
|
|
5
5
|
const MAX_REQUEST = 65_536;
|
|
6
6
|
const MAX_CLOUD_REQUEST = 1_048_576;
|
|
@@ -161,8 +161,8 @@ class RemoteDatabase {
|
|
|
161
161
|
async exportFile(options = {}) {
|
|
162
162
|
this.#assertOpen();
|
|
163
163
|
if (this.#transport) throw new ClientError('RDB_UNSUPPORTED', 'Export embedded databases through EmbeddedDatabase.exportFile', 'not-sent');
|
|
164
|
-
if (
|
|
165
|
-
|
|
164
|
+
if (!plainObject(options) || Object.keys(options).some(key => !['signal', 'timeoutMs', 'emptyTables', 'newIdentity'].includes(key))) throw new TypeError('export options take signal, timeoutMs, emptyTables and newIdentity');
|
|
165
|
+
checkCopyOptions(options);
|
|
166
166
|
const duration = timeout(options.timeoutMs ?? this.#timeout);
|
|
167
167
|
if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
168
168
|
if (options.signal?.aborted) throw new ClientError('RDB_CANCELLED', 'Request cancelled before dispatch', 'not-sent');
|
|
@@ -183,7 +183,7 @@ class RemoteDatabase {
|
|
|
183
183
|
const credential = this.#token;
|
|
184
184
|
let status;
|
|
185
185
|
try {
|
|
186
|
-
const response = await this.#fetch(this.#url + '/file', {
|
|
186
|
+
const response = await this.#fetch(this.#url + '/file' + fileQuery(options), {
|
|
187
187
|
method: 'GET',
|
|
188
188
|
headers: { authorization: `Bearer ${credential}`, accept: `${DATABASE_FILE_TYPE}, application/json`, ...(this.#id === undefined ? {} : { 'x-romedb-database-id': this.#id }) },
|
|
189
189
|
redirect: 'manual', signal: controller.signal,
|
|
@@ -473,6 +473,12 @@ function pause(ms, signal) {
|
|
|
473
473
|
signal.addEventListener('abort', stop, { once: true });
|
|
474
474
|
});
|
|
475
475
|
}
|
|
476
|
+
function fileQuery({ emptyTables, newIdentity }) {
|
|
477
|
+
const parts = [];
|
|
478
|
+
if (emptyTables?.length) parts.push(`empty=${emptyTables.map(encodeURIComponent).join(',')}`);
|
|
479
|
+
if (newIdentity) parts.push('identity=new');
|
|
480
|
+
return parts.length ? `?${parts.join('&')}` : '';
|
|
481
|
+
}
|
|
476
482
|
function httpCode(status) { return status === 401 ? 'RDB_AUTH' : status === 403 ? 'RDB_FORBIDDEN' : status === 409 ? 'RDB_CONFLICT' : status === 429 || status === 413 ? 'RDB_LIMIT' : 'RDB_REMOTE'; }
|
|
477
483
|
function redactMessage(message, token) { return (token ? message.replaceAll(token, '[redacted]') : message).slice(0, 2048); }
|
|
478
484
|
function safeMessage(reply, token) { return redactMessage(typeof reply?.error === 'string' ? reply.error : typeof reply?.error?.message === 'string' ? reply.error.message : 'Database request was rejected', token); }
|
package/client.d.ts
CHANGED
|
@@ -2,6 +2,18 @@ import type { Value } from './values';
|
|
|
2
2
|
export { Float64, Record, Vector, Value, PortableValue, encodeValue, decodeValue } from './values';
|
|
3
3
|
export interface Statement { sql: string; params?: { [key: string]: Value }; }
|
|
4
4
|
export interface RequestOptions { signal?: AbortSignal; timeoutMs?: number; }
|
|
5
|
+
/** What a copy of the database leaves out. */
|
|
6
|
+
export interface CopyOptions {
|
|
7
|
+
/**
|
|
8
|
+
* These tables keep their schema and indexes but no rows. Their rows are never read, so
|
|
9
|
+
* they cannot reach the file. Unknown names fail with RDB_VALIDATION. The copy also gets
|
|
10
|
+
* a new identity, because a receipt can hold row data.
|
|
11
|
+
*/
|
|
12
|
+
emptyTables?: readonly string[];
|
|
13
|
+
/** Leave out the database ID, the sequence and the receipts: the copy is a new database. */
|
|
14
|
+
newIdentity?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface FileExportOptions extends RequestOptions, CopyOptions {}
|
|
5
17
|
export interface WorkLimits { rowsRead?: number; rowMutations?: number; vmSteps?: number; }
|
|
6
18
|
export interface ReadOptions extends RequestOptions { afterSequence?: number; workLimits?: WorkLimits; }
|
|
7
19
|
export interface WriteOptions extends ReadOptions { requestId?: string; ifSequence?: number; }
|
|
@@ -73,7 +85,7 @@ export class RemoteDatabase implements Client {
|
|
|
73
85
|
* Download the database as a .romedb file (romedb serve and serve --directory; not Cloud yet).
|
|
74
86
|
* timeoutMs covers building the copy, until the file starts arriving; signal also stops the download.
|
|
75
87
|
*/
|
|
76
|
-
exportFile(options?:
|
|
88
|
+
exportFile(options?: FileExportOptions): Promise<DatabaseFile>;
|
|
77
89
|
readonly sequence: number;
|
|
78
90
|
readonly databaseId: string;
|
|
79
91
|
info(options?: RequestOptions): Promise<DatabaseInfo>;
|
package/client.mjs
CHANGED
|
@@ -5,7 +5,7 @@ const commonjs = { exports: {} };
|
|
|
5
5
|
(function (module, exports, require) {
|
|
6
6
|
'use strict';
|
|
7
7
|
// Web APIs only: this file also runs in Workers and browsers through client.mjs.
|
|
8
|
-
const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text } = require('./values.cjs');
|
|
8
|
+
const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text, checkCopyOptions } = require('./values.cjs');
|
|
9
9
|
|
|
10
10
|
const MAX_REQUEST = 65_536;
|
|
11
11
|
const MAX_CLOUD_REQUEST = 1_048_576;
|
|
@@ -166,8 +166,8 @@ class RemoteDatabase {
|
|
|
166
166
|
async exportFile(options = {}) {
|
|
167
167
|
this.#assertOpen();
|
|
168
168
|
if (this.#transport) throw new ClientError('RDB_UNSUPPORTED', 'Export embedded databases through EmbeddedDatabase.exportFile', 'not-sent');
|
|
169
|
-
if (
|
|
170
|
-
|
|
169
|
+
if (!plainObject(options) || Object.keys(options).some(key => !['signal', 'timeoutMs', 'emptyTables', 'newIdentity'].includes(key))) throw new TypeError('export options take signal, timeoutMs, emptyTables and newIdentity');
|
|
170
|
+
checkCopyOptions(options);
|
|
171
171
|
const duration = timeout(options.timeoutMs ?? this.#timeout);
|
|
172
172
|
if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
173
173
|
if (options.signal?.aborted) throw new ClientError('RDB_CANCELLED', 'Request cancelled before dispatch', 'not-sent');
|
|
@@ -188,7 +188,7 @@ class RemoteDatabase {
|
|
|
188
188
|
const credential = this.#token;
|
|
189
189
|
let status;
|
|
190
190
|
try {
|
|
191
|
-
const response = await this.#fetch(this.#url + '/file', {
|
|
191
|
+
const response = await this.#fetch(this.#url + '/file' + fileQuery(options), {
|
|
192
192
|
method: 'GET',
|
|
193
193
|
headers: { authorization: `Bearer ${credential}`, accept: `${DATABASE_FILE_TYPE}, application/json`, ...(this.#id === undefined ? {} : { 'x-romedb-database-id': this.#id }) },
|
|
194
194
|
redirect: 'manual', signal: controller.signal,
|
|
@@ -478,6 +478,12 @@ function pause(ms, signal) {
|
|
|
478
478
|
signal.addEventListener('abort', stop, { once: true });
|
|
479
479
|
});
|
|
480
480
|
}
|
|
481
|
+
function fileQuery({ emptyTables, newIdentity }) {
|
|
482
|
+
const parts = [];
|
|
483
|
+
if (emptyTables?.length) parts.push(`empty=${emptyTables.map(encodeURIComponent).join(',')}`);
|
|
484
|
+
if (newIdentity) parts.push('identity=new');
|
|
485
|
+
return parts.length ? `?${parts.join('&')}` : '';
|
|
486
|
+
}
|
|
481
487
|
function httpCode(status) { return status === 401 ? 'RDB_AUTH' : status === 403 ? 'RDB_FORBIDDEN' : status === 409 ? 'RDB_CONFLICT' : status === 429 || status === 413 ? 'RDB_LIMIT' : 'RDB_REMOTE'; }
|
|
482
488
|
function redactMessage(message, token) { return (token ? message.replaceAll(token, '[redacted]') : message).slice(0, 2048); }
|
|
483
489
|
function safeMessage(reply, token) { return redactMessage(typeof reply?.error === 'string' ? reply.error : typeof reply?.error?.message === 'string' ? reply.error.message : 'Database request was rejected', token); }
|
package/embedded-client.cjs
CHANGED
|
@@ -7,7 +7,7 @@ const path = require('node:path');
|
|
|
7
7
|
const { pathToFileURL } = require('node:url');
|
|
8
8
|
const common = require('./client.cjs');
|
|
9
9
|
const { connect, RemoteDatabase, ClientError, Float64, Record, Vector, encodeValue, decodeValue, normalizeUrl, validatePrepared, saveRequest, loadRequest } = common;
|
|
10
|
-
const { plainObject } = require('./values.cjs');
|
|
10
|
+
const { plainObject, checkCopyOptions } = require('./values.cjs');
|
|
11
11
|
const { createEmbeddedClient } = require('./client-internal.cjs');
|
|
12
12
|
const native = require('./native.cjs');
|
|
13
13
|
const sessions = new Map();
|
|
@@ -73,7 +73,8 @@ async function openEmbeddedFile(options) {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
function checkExportOptions(options) {
|
|
76
|
-
if (!plainObject(options) || Object.keys(options).some(key => !['signal', 'timeoutMs'].includes(key))) throw new TypeError('export options take signal and
|
|
76
|
+
if (!plainObject(options) || Object.keys(options).some(key => !['signal', 'timeoutMs', 'emptyTables', 'newIdentity'].includes(key))) throw new TypeError('export options take signal, timeoutMs, emptyTables and newIdentity');
|
|
77
|
+
checkCopyOptions(options);
|
|
77
78
|
if (options.signal !== undefined && !(options.signal instanceof AbortSignal)) throw new TypeError('signal must be an AbortSignal');
|
|
78
79
|
if (options.timeoutMs !== undefined && (!Number.isInteger(options.timeoutMs) || options.timeoutMs < 1 || options.timeoutMs > 4294967295)) throw new RangeError('timeoutMs must be 1..4294967295');
|
|
79
80
|
}
|
|
@@ -131,7 +132,7 @@ class EmbeddedDatabase {
|
|
|
131
132
|
async #exportTo(destination, options) {
|
|
132
133
|
checkExportOptions(options);
|
|
133
134
|
if (!destination || destination.length > 4096 || destination.includes('\0')) throw new TypeError('exportFile requires a bounded destination path');
|
|
134
|
-
const { sequence, bytes } = await this.#session.request('export', JSON.stringify({ destination: path.resolve(destination) }), options.signal, options.timeoutMs);
|
|
135
|
+
const { sequence, bytes } = await this.#session.request('export', JSON.stringify({ destination: path.resolve(destination), emptyTables: options.emptyTables, newIdentity: options.newIdentity }), options.signal, options.timeoutMs);
|
|
135
136
|
return { sequence, bytes };
|
|
136
137
|
}
|
|
137
138
|
async #exportStream(options) {
|
package/embedded-client.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from './client';
|
|
2
|
-
import type { Client, DatabaseInfo, Statement, RequestOptions, ReadOptions, WriteOptions, BatchResult, PreparedWrite, DatabaseFile } from './client';
|
|
2
|
+
import type { Client, DatabaseInfo, Statement, RequestOptions, ReadOptions, WriteOptions, BatchResult, PreparedWrite, DatabaseFile, FileExportOptions } from './client';
|
|
3
3
|
/** timeoutMs has no default for exports: without it, an export runs until it finishes or signal aborts it. */
|
|
4
|
-
export interface ExportOptions
|
|
4
|
+
export interface ExportOptions extends FileExportOptions {}
|
|
5
5
|
export interface ExportedFile { sequence: number; bytes: number; }
|
|
6
6
|
export interface EmbeddedOptions { path: string; create?: boolean; timeoutMs?: number; maxOpen?: number; }
|
|
7
7
|
export class EmbeddedDatabase implements Client {
|
package/embedded-worker.cjs
CHANGED
|
@@ -35,7 +35,8 @@ if (database) parentPort.on('message', ({ id, operation, body, cancellationKey }
|
|
|
35
35
|
if (fenced) fail('RDB_STORAGE', 'Embedded outcome is uncertain; close and reconcile the database', 'unknown');
|
|
36
36
|
if (operation === 'export') {
|
|
37
37
|
// Writes run on this thread, so none commits between the start of the copy's snapshot and reading the sequence.
|
|
38
|
-
const
|
|
38
|
+
const copy = JSON.parse(body);
|
|
39
|
+
const pending = database.startFileExport(copy.destination, cancellationKey, copy.emptyTables, copy.newIdentity);
|
|
39
40
|
const snapshot = sequence;
|
|
40
41
|
const finished = pending.finish().then(
|
|
41
42
|
bytes => parentPort.postMessage({ id, result: { sequence: snapshot, bytes: Number(bytes) } }),
|
package/index.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
+
const { checkCopyOptions } = require('./values.cjs');
|
|
2
3
|
const { NativeDatabase, interruptConnection, createCancellationToken, cancelOperation, releaseCancellationToken, vectorFromComponents, vectorFromSparseEntries } = require('./native.cjs');
|
|
3
4
|
class Record {
|
|
4
5
|
constructor(table, key) {
|
|
@@ -6,6 +7,8 @@ class Record {
|
|
|
6
7
|
this.table = table; this.key = key;
|
|
7
8
|
Object.freeze(this);
|
|
8
9
|
}
|
|
10
|
+
toString() { return `${this.table}:${this.key}`; }
|
|
11
|
+
equals(other) { return other instanceof Record && other.table === this.table && other.key === this.key; }
|
|
9
12
|
}
|
|
10
13
|
class Vector {
|
|
11
14
|
static float32(values) { return constructVector('float32', values); }
|
|
@@ -414,7 +417,9 @@ class AsyncDatabase {
|
|
|
414
417
|
}
|
|
415
418
|
async exportFile(destination, options = {}) {
|
|
416
419
|
if (typeof destination !== 'string' || !destination || destination.length > 4096 || destination.includes('\0')) throw new TypeError('exportFile requires a bounded destination path');
|
|
417
|
-
|
|
420
|
+
checkCopyOptions(options);
|
|
421
|
+
const copy = JSON.stringify({ emptyTables: options.emptyTables, newIdentity: options.newIdentity });
|
|
422
|
+
try { return await this.#request('exportFile', [require('node:path').resolve(destination), copy], false, options.signal, options.timeoutMs); }
|
|
418
423
|
catch (error) {
|
|
419
424
|
const coded = /^(RDB_[A-Z0-9_]+): (.*)$/s.exec(error.message);
|
|
420
425
|
if (!coded) throw error;
|
package/index.d.ts
CHANGED
|
@@ -67,6 +67,12 @@ export class Database {
|
|
|
67
67
|
|
|
68
68
|
export interface ExecuteOptions { signal?: AbortSignal; timeoutMs?: number; }
|
|
69
69
|
export interface FileExport { bytes: number; }
|
|
70
|
+
export interface FileExportOptions extends ExecuteOptions {
|
|
71
|
+
/** These tables keep their schema and indexes but no rows, and the copy gets a new identity. */
|
|
72
|
+
emptyTables?: readonly string[];
|
|
73
|
+
/** Leave out the database ID, the sequence and the receipts: the copy is a new database. */
|
|
74
|
+
newIdentity?: boolean;
|
|
75
|
+
}
|
|
70
76
|
export class AsyncDatabase {
|
|
71
77
|
collection<T extends object = Document>(name: string): AsyncCollection<T>;
|
|
72
78
|
private constructor();
|
|
@@ -77,7 +83,7 @@ export class AsyncDatabase {
|
|
|
77
83
|
exportDocuments(table: string, format?: TransferFormat, options?: ExecuteOptions): Promise<string>;
|
|
78
84
|
importDocuments(table: string, input: string, format?: TransferFormat, options?: ExecuteOptions): Promise<ImportReport>;
|
|
79
85
|
/** Copy an MVCC database into a new private file while queries continue; the destination and its log files must not exist. */
|
|
80
|
-
exportFile(destination: string, options?:
|
|
86
|
+
exportFile(destination: string, options?: FileExportOptions): Promise<FileExport>;
|
|
81
87
|
execute(sql: string, parameters?: Parameters, options?: ExecuteOptions): Promise<QueryResult>;
|
|
82
88
|
profileSelect(sql: string, parameters?: Parameters, options?: ExecuteOptions): Promise<ProfiledQuery>;
|
|
83
89
|
/** Checks write results atomically; does not bound engine or logical materialization memory. */
|
package/package.json
CHANGED
package/romedb.node
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
[diffend] Oversized file quarantined before diffing.
|
|
2
2
|
name: package/romedb.node
|
|
3
|
-
size:
|
|
4
|
-
sha256:
|
|
3
|
+
size: 41464424 bytes
|
|
4
|
+
sha256: d98971746cedc29b00b8333f763433c47db42f65306b933966e636e0221aac3c
|
package/values.cjs
CHANGED
|
@@ -18,6 +18,8 @@ class Record {
|
|
|
18
18
|
this.key = key;
|
|
19
19
|
Object.freeze(this);
|
|
20
20
|
}
|
|
21
|
+
toString() { return `${this.table}:${this.key}`; }
|
|
22
|
+
equals(other) { return other instanceof Record && other.table === this.table && other.key === this.key; }
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
class Vector {
|
|
@@ -204,8 +206,16 @@ function checkDepth(depth) {
|
|
|
204
206
|
if (depth > 64) throw new RangeError('value nesting exceeds 64');
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
function checkCopyOptions(options) {
|
|
210
|
+
const { emptyTables, newIdentity } = options;
|
|
211
|
+
if (emptyTables !== undefined && (!Array.isArray(emptyTables) || emptyTables.length > 256 || emptyTables.some(name => typeof name !== 'string' || !name || name.length > 255 || /[,\0]/.test(name)))) {
|
|
212
|
+
throw new TypeError('emptyTables takes up to 256 table names without commas');
|
|
213
|
+
}
|
|
214
|
+
if (newIdentity !== undefined && typeof newIdentity !== 'boolean') throw new TypeError('newIdentity must be a boolean');
|
|
215
|
+
}
|
|
216
|
+
|
|
207
217
|
function plainObject(value) {
|
|
208
218
|
return value !== null && typeof value === 'object' && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
209
219
|
}
|
|
210
220
|
|
|
211
|
-
module.exports = { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text };
|
|
221
|
+
module.exports = { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text, checkCopyOptions };
|
package/values.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export class Float64 { constructor(value: number); readonly value: number; }
|
|
2
|
-
export class Record { constructor(table: string, key: string | bigint); readonly table: string; readonly key: string | bigint; }
|
|
2
|
+
export class Record { constructor(table: string, key: string | bigint); readonly table: string; readonly key: string | bigint; /** `table:key`. */ toString(): string; /** The same table and key, including the key's type. */ equals(other: unknown): boolean; }
|
|
3
3
|
export class Vector {
|
|
4
4
|
constructor(bytes: Uint8Array);
|
|
5
5
|
/** A copy of the encoded bytes. */
|
package/values.mjs
CHANGED
|
@@ -22,6 +22,8 @@ class Record {
|
|
|
22
22
|
this.key = key;
|
|
23
23
|
Object.freeze(this);
|
|
24
24
|
}
|
|
25
|
+
toString() { return `${this.table}:${this.key}`; }
|
|
26
|
+
equals(other) { return other instanceof Record && other.table === this.table && other.key === this.key; }
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
class Vector {
|
|
@@ -208,13 +210,21 @@ function checkDepth(depth) {
|
|
|
208
210
|
if (depth > 64) throw new RangeError('value nesting exceeds 64');
|
|
209
211
|
}
|
|
210
212
|
|
|
213
|
+
function checkCopyOptions(options) {
|
|
214
|
+
const { emptyTables, newIdentity } = options;
|
|
215
|
+
if (emptyTables !== undefined && (!Array.isArray(emptyTables) || emptyTables.length > 256 || emptyTables.some(name => typeof name !== 'string' || !name || name.length > 255 || /[,\0]/.test(name)))) {
|
|
216
|
+
throw new TypeError('emptyTables takes up to 256 table names without commas');
|
|
217
|
+
}
|
|
218
|
+
if (newIdentity !== undefined && typeof newIdentity !== 'boolean') throw new TypeError('newIdentity must be a boolean');
|
|
219
|
+
}
|
|
220
|
+
|
|
211
221
|
function plainObject(value) {
|
|
212
222
|
return value !== null && typeof value === 'object' && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
213
223
|
}
|
|
214
224
|
|
|
215
|
-
module.exports = { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text };
|
|
225
|
+
module.exports = { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text, checkCopyOptions };
|
|
216
226
|
})(commonjs, commonjs.exports, specifier => {
|
|
217
227
|
throw new TypeError(`Cannot load ${specifier}`);
|
|
218
228
|
});
|
|
219
229
|
|
|
220
|
-
export const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text } = commonjs.exports;
|
|
230
|
+
export const { Float64, Record, Vector, encodeValue, decodeValue, plainObject, text, checkCopyOptions } = commonjs.exports;
|
package/worker.cjs
CHANGED
|
@@ -10,7 +10,7 @@ parentPort.on('message', ({ id, method, args, cancellationKey }) => {
|
|
|
10
10
|
if (method === 'exportFile') {
|
|
11
11
|
const key = cancellationKey ?? createCancellationToken();
|
|
12
12
|
const finished = Promise.resolve()
|
|
13
|
-
.then(() => db.startFileExport(args[0], key).finish())
|
|
13
|
+
.then(() => { const copy = JSON.parse(args[1]); return db.startFileExport(args[0], key, copy.emptyTables, copy.newIdentity).finish(); })
|
|
14
14
|
.then(bytes => parentPort.postMessage({ id, result: { bytes: Number(bytes) } }), error => parentPort.postMessage({ id, error: { message: error.message } }))
|
|
15
15
|
.finally(() => { copies.delete(key); if (cancellationKey === undefined) releaseCancellationToken(key); });
|
|
16
16
|
copies.set(key, finished);
|