firebird-wasm 0.7.0 → 0.9.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/CHANGELOG.md +266 -0
- package/README.md +31 -15
- package/dist/.tsbuildinfo.build +1 -1
- package/dist/browser/engine-transport.d.ts +2 -0
- package/dist/browser/engine-transport.d.ts.map +1 -1
- package/dist/browser/engine-transport.js +43 -11
- package/dist/browser/engine-transport.js.map +1 -1
- package/dist/browser/firebird-browser.d.ts.map +1 -1
- package/dist/browser/firebird-browser.js +59 -20
- package/dist/browser/firebird-browser.js.map +1 -1
- package/dist/browser/index.d.ts +3 -3
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +6 -3
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/params.d.ts +8 -2
- package/dist/browser/params.d.ts.map +1 -1
- package/dist/browser/params.js +14 -5
- package/dist/browser/params.js.map +1 -1
- package/dist/browser/serve-engine.d.ts +30 -0
- package/dist/browser/serve-engine.d.ts.map +1 -0
- package/dist/browser/serve-engine.js +93 -0
- package/dist/browser/serve-engine.js.map +1 -0
- package/dist/browser/worker-entry.d.ts +8 -22
- package/dist/browser/worker-entry.d.ts.map +1 -1
- package/dist/browser/worker-entry.js +18 -79
- package/dist/browser/worker-entry.js.map +1 -1
- package/dist/electric/apply.d.ts +53 -0
- package/dist/electric/apply.d.ts.map +1 -0
- package/dist/electric/apply.js +88 -0
- package/dist/electric/apply.js.map +1 -0
- package/dist/electric/index.d.ts +133 -0
- package/dist/electric/index.d.ts.map +1 -0
- package/dist/electric/index.js +378 -0
- package/dist/electric/index.js.map +1 -0
- package/dist/electric/serial.d.ts +20 -0
- package/dist/electric/serial.d.ts.map +1 -0
- package/dist/electric/serial.js +29 -0
- package/dist/electric/serial.js.map +1 -0
- package/dist/electric/values.d.ts +65 -0
- package/dist/electric/values.d.ts.map +1 -0
- package/dist/electric/values.js +257 -0
- package/dist/electric/values.js.map +1 -0
- package/dist/electric/writes.d.ts +99 -0
- package/dist/electric/writes.d.ts.map +1 -0
- package/dist/electric/writes.js +282 -0
- package/dist/electric/writes.js.map +1 -0
- package/dist/electric-server/capture.d.ts +51 -0
- package/dist/electric-server/capture.d.ts.map +1 -0
- package/dist/electric-server/capture.js +224 -0
- package/dist/electric-server/capture.js.map +1 -0
- package/dist/electric-server/catalog.d.ts +61 -0
- package/dist/electric-server/catalog.d.ts.map +1 -0
- package/dist/electric-server/catalog.js +137 -0
- package/dist/electric-server/catalog.js.map +1 -0
- package/dist/electric-server/index.d.ts +85 -0
- package/dist/electric-server/index.d.ts.map +1 -0
- package/dist/electric-server/index.js +528 -0
- package/dist/electric-server/index.js.map +1 -0
- package/dist/electric-server/where.d.ts +30 -0
- package/dist/electric-server/where.d.ts.map +1 -0
- package/dist/electric-server/where.js +243 -0
- package/dist/electric-server/where.js.map +1 -0
- package/dist/firebird.d.ts +3 -1
- package/dist/firebird.d.ts.map +1 -1
- package/dist/firebird.js +259 -22
- package/dist/firebird.js.map +1 -1
- package/dist/frameworks/query-store.d.ts +99 -0
- package/dist/frameworks/query-store.d.ts.map +1 -0
- package/dist/frameworks/query-store.js +166 -0
- package/dist/frameworks/query-store.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/react/index.d.ts +68 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +92 -0
- package/dist/react/index.js.map +1 -0
- package/dist/repl/index.d.ts +76 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +328 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/types.d.ts +2 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/vue/index.d.ts +68 -0
- package/dist/vue/index.d.ts.map +1 -0
- package/dist/vue/index.js +107 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/wasm/firebird-embedded-st.js +1 -1
- package/dist/wasm/firebird-embedded-st.wasm +0 -0
- package/dist/wasm/firebird-embedded.js +1 -1
- package/dist/wasm/firebird-embedded.wasm +0 -0
- package/dist/wasm-loader.d.ts +57 -7
- package/dist/wasm-loader.d.ts.map +1 -1
- package/dist/wasm-loader.js +106 -21
- package/dist/wasm-loader.js.map +1 -1
- package/package.json +50 -3
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* firebird-wasm/electric-server – a Firebird server's tables, served over
|
|
4
|
+
* Electric's HTTP shape protocol.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* import * as http from 'node:http';
|
|
8
|
+
* import { createShapeServer } from 'firebird-wasm/electric-server';
|
|
9
|
+
*
|
|
10
|
+
* const shapes = await createShapeServer({
|
|
11
|
+
* database: 'localhost:/data/app.fdb', username: 'SYSDBA', password: '…',
|
|
12
|
+
* tables: ['items'],
|
|
13
|
+
* });
|
|
14
|
+
* http.createServer(shapes.handler).listen(3000);
|
|
15
|
+
* // in the browser: syncShapeToTable(db, { shape: { url: 'http://…:3000/v1/shape', params: { table: 'items' } }, … })
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Electric itself reads only Postgres; this stands in its place for a
|
|
19
|
+
* Firebird source. It installs triggers that log each changed row's key,
|
|
20
|
+
* numbers the log in commit order itself (see
|
|
21
|
+
* docs/plans/firebird-shape-server.md), and serves a snapshot and then the
|
|
22
|
+
* changes after it, in pages for a snapshot, and with a `where` if asked.
|
|
23
|
+
* Several servers can share a database: they number the log one at a time.
|
|
24
|
+
* Node only: it uses the native client (`node-firebird-driver-
|
|
25
|
+
* native`, an optional dependency of this package).
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.shapeName = exports.planColumn = exports.planTable = exports.WhereError = exports.translateWhere = exports.tableTrigger = exports.triggerName = void 0;
|
|
29
|
+
exports.createShapeServer = createShapeServer;
|
|
30
|
+
const node_firebird_driver_1 = require("node-firebird-driver");
|
|
31
|
+
const catalog_1 = require("./catalog");
|
|
32
|
+
const capture_1 = require("./capture");
|
|
33
|
+
const where_1 = require("./where");
|
|
34
|
+
var capture_2 = require("./capture");
|
|
35
|
+
Object.defineProperty(exports, "triggerName", { enumerable: true, get: function () { return capture_2.triggerName; } });
|
|
36
|
+
Object.defineProperty(exports, "tableTrigger", { enumerable: true, get: function () { return capture_2.tableTrigger; } });
|
|
37
|
+
var where_2 = require("./where");
|
|
38
|
+
Object.defineProperty(exports, "translateWhere", { enumerable: true, get: function () { return where_2.translateWhere; } });
|
|
39
|
+
Object.defineProperty(exports, "WhereError", { enumerable: true, get: function () { return where_2.WhereError; } });
|
|
40
|
+
var catalog_2 = require("./catalog");
|
|
41
|
+
Object.defineProperty(exports, "planTable", { enumerable: true, get: function () { return catalog_2.planTable; } });
|
|
42
|
+
Object.defineProperty(exports, "planColumn", { enumerable: true, get: function () { return catalog_2.planColumn; } });
|
|
43
|
+
Object.defineProperty(exports, "shapeName", { enumerable: true, get: function () { return catalog_2.shapeName; } });
|
|
44
|
+
const EXPOSED = 'electric-cursor,electric-handle,electric-offset,electric-schema,electric-up-to-date';
|
|
45
|
+
class HttpError extends Error {
|
|
46
|
+
constructor(status, message) {
|
|
47
|
+
super(message);
|
|
48
|
+
this.status = status;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** Connect, install the capture, and return a handler serving `options.tables`. */
|
|
52
|
+
async function createShapeServer(options) {
|
|
53
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
54
|
+
const native = require('node-firebird-driver-native');
|
|
55
|
+
const client = native.createNativeClient(options.libraryPath ?? native.getDefaultLibraryFilename());
|
|
56
|
+
const credentials = { username: options.username, password: options.password };
|
|
57
|
+
const attachment = await client.connect(options.database, credentials);
|
|
58
|
+
const liveTimeoutMs = options.liveTimeoutMs ?? 20000;
|
|
59
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1000;
|
|
60
|
+
const pageRows = options.snapshotPageRows ?? 10000;
|
|
61
|
+
const retainLogMs = options.retainLogMs === undefined ? 7 * 24 * 60 * 60 * 1000 : options.retainLogMs;
|
|
62
|
+
const tables = new Map();
|
|
63
|
+
try {
|
|
64
|
+
for (const given of options.tables) {
|
|
65
|
+
const name = (0, catalog_1.relationName)(given);
|
|
66
|
+
tables.set(name, await describeTable(attachment, name));
|
|
67
|
+
}
|
|
68
|
+
if (options.install ?? true)
|
|
69
|
+
await (0, capture_1.installCapture)(attachment, [...tables.values()]);
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
await attachment.disconnect().catch(() => undefined);
|
|
73
|
+
await client.dispose().catch(() => undefined);
|
|
74
|
+
throw err;
|
|
75
|
+
}
|
|
76
|
+
const epoch = await readOnly(attachment, async (tx) => {
|
|
77
|
+
const rs = await attachment.executeQuery(tx, `SELECT FIRST 1 EPOCH FROM ${capture_1.META}`);
|
|
78
|
+
const rows = await rs.fetch();
|
|
79
|
+
await rs.close();
|
|
80
|
+
return String(rows[0]?.[0] ?? 'none');
|
|
81
|
+
});
|
|
82
|
+
let closed = false;
|
|
83
|
+
// A commit that logged a change posts ELECTRIC_CHANGES; it wakes every
|
|
84
|
+
// waiting live request at once. Polling stays, as the fallback.
|
|
85
|
+
let wake = () => undefined;
|
|
86
|
+
let woken = new Promise((resolve) => { wake = resolve; });
|
|
87
|
+
const signal = () => {
|
|
88
|
+
const release = wake;
|
|
89
|
+
woken = new Promise((resolve) => { wake = resolve; });
|
|
90
|
+
release();
|
|
91
|
+
};
|
|
92
|
+
let eventAttachment;
|
|
93
|
+
let events;
|
|
94
|
+
if (options.events ?? true) {
|
|
95
|
+
try {
|
|
96
|
+
// A connection of its own: the main one runs one call at a time.
|
|
97
|
+
eventAttachment = await client.connect(options.database, credentials);
|
|
98
|
+
events = await eventAttachment.queueEvents([capture_1.CHANGE_EVENT], async () => {
|
|
99
|
+
signal();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
catch (err) {
|
|
103
|
+
console.warn(`[firebird-wasm/electric-server] no Firebird events (${err instanceof Error ? err.message.split('\n').join(' ') : err}); ` +
|
|
104
|
+
`live requests poll every ${pollIntervalMs} ms. Events need the server's RemoteAuxPort reachable from here.`);
|
|
105
|
+
await eventAttachment?.disconnect().catch(() => undefined);
|
|
106
|
+
eventAttachment = undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Number what has committed since, then read in a snapshot: `top` is the log's position in it. */
|
|
110
|
+
const stampedSnapshot = async (fn) => {
|
|
111
|
+
await serialized(attachment, () => (0, capture_1.stampCommitted)(attachment));
|
|
112
|
+
return readOnly(attachment, async (tx) => {
|
|
113
|
+
const rs = await attachment.executeQuery(tx, `SELECT (SELECT MAX(COMMIT_SEQ) FROM ${capture_1.CHANGES}), MAX(PRUNED_THROUGH) FROM ${capture_1.META}`);
|
|
114
|
+
const row = (await rs.fetch())[0];
|
|
115
|
+
await rs.close();
|
|
116
|
+
const pruned = Number(row?.[1] ?? 0);
|
|
117
|
+
return fn(tx, Math.max(Number(row?.[0] ?? 0), pruned), pruned);
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
// Pages of a snapshot being read, by the cursor number in their offset.
|
|
121
|
+
const cursors = new Map();
|
|
122
|
+
let nextCursor = 1;
|
|
123
|
+
/** One page of a shape's rows, in key order, after the key `after`. */
|
|
124
|
+
const page = async (shape, tx, after) => {
|
|
125
|
+
const conditions = [];
|
|
126
|
+
const params = [];
|
|
127
|
+
if (shape.where) {
|
|
128
|
+
conditions.push(`(${shape.where.sql})`);
|
|
129
|
+
params.push(...shape.where.params);
|
|
130
|
+
}
|
|
131
|
+
if (after) {
|
|
132
|
+
const keyset = keysetAfter(shape.table.key.map(catalog_1.quote), after);
|
|
133
|
+
conditions.push(keyset.sql);
|
|
134
|
+
params.push(...keyset.params);
|
|
135
|
+
}
|
|
136
|
+
const rs = await attachment.executeQuery(tx, `SELECT FIRST ${pageRows + 1} ${shape.columns.map((c) => c.select).join(', ')} FROM ${(0, catalog_1.quote)(shape.table.name)}` +
|
|
137
|
+
(conditions.length ? ` WHERE ${conditions.join(' AND ')}` : '') +
|
|
138
|
+
` ORDER BY ${shape.table.key.map(catalog_1.quote).join(', ')}`, params);
|
|
139
|
+
const rows = await rs.fetch();
|
|
140
|
+
await rs.close();
|
|
141
|
+
const more = rows.length > pageRows;
|
|
142
|
+
const kept = more ? rows.slice(0, pageRows) : rows;
|
|
143
|
+
const messages = [];
|
|
144
|
+
for (const row of kept)
|
|
145
|
+
messages.push(await change('insert', shape.table, shape.columns, row, tx));
|
|
146
|
+
const last = kept[kept.length - 1];
|
|
147
|
+
const keyIndexes = shape.table.key.map((k) => shape.columns.findIndex((c) => c.name === k));
|
|
148
|
+
return { messages, more, last: last ? keyIndexes.map((i) => last[i]) : null };
|
|
149
|
+
};
|
|
150
|
+
/** The changes to a shape after `after`, up to the watermark, one per key. */
|
|
151
|
+
const changesAfter = async (shape, after) => {
|
|
152
|
+
return stampedSnapshot(async (tx, top, pruned) => {
|
|
153
|
+
// What this client needs was pruned: it starts again from a snapshot.
|
|
154
|
+
if (after < pruned)
|
|
155
|
+
return { gone: true, messages: [], offset: after, seen: top };
|
|
156
|
+
if (top <= after)
|
|
157
|
+
return { gone: false, messages: [], offset: after, seen: top };
|
|
158
|
+
const table = shape.table;
|
|
159
|
+
const keys = Array.from({ length: capture_1.KEY_COLUMNS }, (_, i) => `K${i + 1}`).join(', ');
|
|
160
|
+
const rs = await attachment.executeQuery(tx, `SELECT OP, TX_ID, ${keys} FROM ${capture_1.CHANGES} WHERE TABLE_NAME = ? AND COMMIT_SEQ > ? AND COMMIT_SEQ <= ? ` +
|
|
161
|
+
'ORDER BY COMMIT_SEQ, CHANGE_ID', [table.name, after, top]);
|
|
162
|
+
// The last operation per key wins; the row is read as it is now. Every
|
|
163
|
+
// transaction that changed it is named, as Electric's txids, so a
|
|
164
|
+
// client can tell its own writes have come back.
|
|
165
|
+
const last = new Map();
|
|
166
|
+
for (const row of await rs.fetch()) {
|
|
167
|
+
const key = row.slice(2, 2 + table.key.length);
|
|
168
|
+
const id = JSON.stringify(key);
|
|
169
|
+
const txids = last.get(id)?.txids ?? new Set();
|
|
170
|
+
txids.add(String(row[1]));
|
|
171
|
+
last.set(id, { op: String(row[0]), key, txids });
|
|
172
|
+
}
|
|
173
|
+
await rs.close();
|
|
174
|
+
// A row that no longer matches the shape's where has left it: a delete.
|
|
175
|
+
const where = table.key.map((k) => `${(0, catalog_1.quote)(k)} = ?`).join(' AND ') + (shape.where ? ` AND (${shape.where.sql})` : '');
|
|
176
|
+
const select = `SELECT ${shape.columns.map((c) => c.select).join(', ')} FROM ${(0, catalog_1.quote)(table.name)} WHERE ${where}`;
|
|
177
|
+
const messages = [];
|
|
178
|
+
for (const { op, key, txids } of last.values()) {
|
|
179
|
+
let current = null;
|
|
180
|
+
if (op !== 'D') {
|
|
181
|
+
const found = await attachment.executeQuery(tx, select, [...key, ...(shape.where?.params ?? [])]);
|
|
182
|
+
current = (await found.fetch({ fetchSize: 1 }))[0] ?? null;
|
|
183
|
+
await found.close();
|
|
184
|
+
}
|
|
185
|
+
const message = current
|
|
186
|
+
? await change('insert', table, shape.columns, current, tx)
|
|
187
|
+
: deletion(table, key);
|
|
188
|
+
message['headers']['txids'] = [...txids].map(Number);
|
|
189
|
+
messages.push(message);
|
|
190
|
+
}
|
|
191
|
+
return { gone: false, messages, offset: top, seen: top };
|
|
192
|
+
});
|
|
193
|
+
};
|
|
194
|
+
const change = async (operation, table, columns, row, tx) => {
|
|
195
|
+
const value = {};
|
|
196
|
+
for (let i = 0; i < columns.length; i++) {
|
|
197
|
+
const plan = columns[i];
|
|
198
|
+
let raw = row[i];
|
|
199
|
+
if ((plan.render === 'blob' || plan.render === 'bytes') && raw) {
|
|
200
|
+
const bytes = await readBlob(attachment, tx, raw);
|
|
201
|
+
raw = plan.render === 'blob' ? bytes.toString('utf8') : bytes;
|
|
202
|
+
}
|
|
203
|
+
value[plan.shapeName] = (0, catalog_1.renderValue)(plan, raw);
|
|
204
|
+
}
|
|
205
|
+
return { key: keyOf(table, table.key.map((k) => value[shapeOf(table, k)])), value, headers: { operation } };
|
|
206
|
+
};
|
|
207
|
+
const deletion = (table, key) => {
|
|
208
|
+
const value = {};
|
|
209
|
+
table.key.forEach((k, i) => {
|
|
210
|
+
const plan = table.columns.find((c) => c.name === k);
|
|
211
|
+
const text = key[i] === null || key[i] === undefined ? null : String(key[i]);
|
|
212
|
+
// The log keeps the key as Firebird's text; booleans as TRUE/FALSE.
|
|
213
|
+
value[plan.shapeName] = plan.render === 'boolean' && text !== null ? text.toLowerCase() : text;
|
|
214
|
+
});
|
|
215
|
+
return { key: keyOf(table, Object.values(value)), value, headers: { operation: 'delete' } };
|
|
216
|
+
};
|
|
217
|
+
const respond = (res, status, body, headers = {}) => {
|
|
218
|
+
res.writeHead(status, {
|
|
219
|
+
'content-type': 'application/json',
|
|
220
|
+
'cache-control': 'no-store',
|
|
221
|
+
'access-control-allow-origin': '*',
|
|
222
|
+
'access-control-expose-headers': EXPOSED,
|
|
223
|
+
...headers,
|
|
224
|
+
});
|
|
225
|
+
res.end(JSON.stringify(body));
|
|
226
|
+
};
|
|
227
|
+
// As Electric's: the last position of the whole log this response has
|
|
228
|
+
// seen, so a client of several shapes can tell when they are all at the
|
|
229
|
+
// same one (syncShapesToTables).
|
|
230
|
+
const upToDate = (seen) => ({ headers: { control: 'up-to-date', global_last_seen_lsn: String(seen) } });
|
|
231
|
+
/** The rest of a snapshot, or all of it: a page, and where the next one starts. */
|
|
232
|
+
const servePage = async (res, shape, top, messages, more, last) => {
|
|
233
|
+
const schema = JSON.stringify(shape.schema);
|
|
234
|
+
if (!more) {
|
|
235
|
+
respond(res, 200, [...messages, upToDate(top)], {
|
|
236
|
+
'electric-handle': shape.handle,
|
|
237
|
+
'electric-offset': `${top}_0`,
|
|
238
|
+
'electric-schema': schema,
|
|
239
|
+
'electric-up-to-date': '',
|
|
240
|
+
});
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// Forget cursors nobody came back for.
|
|
244
|
+
const now = Date.now();
|
|
245
|
+
for (const [id, c] of cursors)
|
|
246
|
+
if (now - c.used > 10 * 60 * 1000)
|
|
247
|
+
cursors.delete(id);
|
|
248
|
+
const id = nextCursor++;
|
|
249
|
+
cursors.set(id, { handle: shape.handle, top, after: last, used: now });
|
|
250
|
+
respond(res, 200, messages, {
|
|
251
|
+
'electric-handle': shape.handle,
|
|
252
|
+
'electric-offset': `${top}_${id}`,
|
|
253
|
+
'electric-schema': schema,
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
const serve = async (req, res) => {
|
|
257
|
+
if (req.method === 'OPTIONS') {
|
|
258
|
+
res.writeHead(204, {
|
|
259
|
+
'access-control-allow-origin': '*',
|
|
260
|
+
'access-control-allow-methods': 'GET, OPTIONS',
|
|
261
|
+
'access-control-allow-headers': '*',
|
|
262
|
+
});
|
|
263
|
+
res.end();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
const url = new URL(req.url ?? '/', 'http://shape.server');
|
|
267
|
+
if (req.method !== 'GET' || url.pathname !== '/v1/shape') {
|
|
268
|
+
throw new HttpError(404, 'Only GET /v1/shape is served');
|
|
269
|
+
}
|
|
270
|
+
const params = url.searchParams;
|
|
271
|
+
const shape = shapeOfRequest(params, tables, epoch);
|
|
272
|
+
const offsetParam = params.get('offset') ?? '-1';
|
|
273
|
+
if (offsetParam === '-1') {
|
|
274
|
+
await stampedSnapshot(async (tx, top) => {
|
|
275
|
+
const first = await page(shape, tx, null);
|
|
276
|
+
await servePage(res, shape, top, first.messages, first.more, first.last);
|
|
277
|
+
});
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
if (params.get('handle') !== shape.handle) {
|
|
281
|
+
respond(res, 409, [{ headers: { control: 'must-refetch' } }], { 'electric-handle': shape.handle });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const [position, part] = offsetParam === 'now' ? ['now', '0'] : offsetParam.split('_');
|
|
285
|
+
if (part !== undefined && part !== '0') {
|
|
286
|
+
// The next page of a snapshot.
|
|
287
|
+
const cursor = cursors.get(Number(part));
|
|
288
|
+
if (!cursor || cursor.handle !== shape.handle || String(cursor.top) !== position) {
|
|
289
|
+
respond(res, 409, [{ headers: { control: 'must-refetch' } }], { 'electric-handle': shape.handle });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
cursors.delete(Number(part));
|
|
293
|
+
await readOnly(attachment, async (tx) => {
|
|
294
|
+
const next = await page(shape, tx, cursor.after);
|
|
295
|
+
await servePage(res, shape, cursor.top, next.messages, next.more, next.last);
|
|
296
|
+
});
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
const after = position === 'now'
|
|
300
|
+
? await stampedSnapshot(async (_tx, top) => top)
|
|
301
|
+
: Number(position);
|
|
302
|
+
if (!Number.isSafeInteger(after) || after < 0)
|
|
303
|
+
throw new HttpError(400, `offset ${offsetParam} is not one this server gave`);
|
|
304
|
+
const live = params.get('live') === 'true';
|
|
305
|
+
const deadline = Date.now() + (live ? liveTimeoutMs : 0);
|
|
306
|
+
let result = await changesAfter(shape, after);
|
|
307
|
+
while (!result.gone && live && result.messages.length === 0 && Date.now() < deadline && !closed && !req.destroyed) {
|
|
308
|
+
const next = woken;
|
|
309
|
+
let timer;
|
|
310
|
+
await Promise.race([
|
|
311
|
+
next,
|
|
312
|
+
new Promise((r) => { timer = setTimeout(r, Math.min(pollIntervalMs, Math.max(0, deadline - Date.now()))); }),
|
|
313
|
+
]);
|
|
314
|
+
clearTimeout(timer);
|
|
315
|
+
if (closed)
|
|
316
|
+
throw new HttpError(503, 'The shape server is closing');
|
|
317
|
+
result = await changesAfter(shape, after);
|
|
318
|
+
}
|
|
319
|
+
if (result.gone) {
|
|
320
|
+
respond(res, 409, [{ headers: { control: 'must-refetch' } }], { 'electric-handle': shape.handle });
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const headers = {
|
|
324
|
+
'electric-handle': shape.handle,
|
|
325
|
+
'electric-offset': `${result.offset}_0`,
|
|
326
|
+
'electric-up-to-date': '',
|
|
327
|
+
};
|
|
328
|
+
if (live)
|
|
329
|
+
headers['electric-cursor'] = String(Math.floor(Date.now() / 1000));
|
|
330
|
+
else
|
|
331
|
+
headers['electric-schema'] = JSON.stringify(shape.schema);
|
|
332
|
+
respond(res, 200, [...result.messages, upToDate(result.seen)], headers);
|
|
333
|
+
};
|
|
334
|
+
const prune = async (before) => {
|
|
335
|
+
if (closed)
|
|
336
|
+
return 0;
|
|
337
|
+
return serialized(attachment, () => (0, capture_1.pruneLog)(attachment, before ?? new Date(Date.now() - (retainLogMs ?? 0))));
|
|
338
|
+
};
|
|
339
|
+
const pruning = retainLogMs !== null && retainLogMs > 0
|
|
340
|
+
? setInterval(() => { void prune().catch(() => undefined); }, Math.min(retainLogMs, 60 * 60 * 1000))
|
|
341
|
+
: undefined;
|
|
342
|
+
pruning?.unref?.();
|
|
343
|
+
return {
|
|
344
|
+
tables,
|
|
345
|
+
events: events !== undefined,
|
|
346
|
+
handler: (req, res) => {
|
|
347
|
+
if (closed) {
|
|
348
|
+
respond(res, 503, { message: 'The shape server is closing' });
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
serve(req, res).catch((err) => {
|
|
352
|
+
const status = err instanceof HttpError ? err.status : err instanceof where_1.WhereError ? 400 : 500;
|
|
353
|
+
if (!res.headersSent)
|
|
354
|
+
respond(res, status, { message: err instanceof Error ? err.message : String(err) });
|
|
355
|
+
else
|
|
356
|
+
res.end();
|
|
357
|
+
});
|
|
358
|
+
},
|
|
359
|
+
prune,
|
|
360
|
+
close: async () => {
|
|
361
|
+
if (closed)
|
|
362
|
+
return;
|
|
363
|
+
closed = true;
|
|
364
|
+
if (pruning)
|
|
365
|
+
clearInterval(pruning);
|
|
366
|
+
signal();
|
|
367
|
+
await events?.cancel().catch(() => undefined);
|
|
368
|
+
await eventAttachment?.disconnect().catch(() => undefined);
|
|
369
|
+
// In the connection's queue, after whatever is running on it: a live
|
|
370
|
+
// request polls the log, and a native call on a disconnected
|
|
371
|
+
// attachment crashes the process rather than throwing. Whatever is
|
|
372
|
+
// queued after this is refused instead of run.
|
|
373
|
+
await serialized(attachment, async () => {
|
|
374
|
+
disconnected.add(attachment);
|
|
375
|
+
await attachment.disconnect().catch(() => undefined);
|
|
376
|
+
});
|
|
377
|
+
await client.dispose().catch(() => undefined);
|
|
378
|
+
},
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
/** The shape a request asks for. */
|
|
382
|
+
function shapeOfRequest(params, tables, epoch) {
|
|
383
|
+
const given = params.get('table');
|
|
384
|
+
if (!given)
|
|
385
|
+
throw new HttpError(400, 'table is required');
|
|
386
|
+
const table = tables.get((0, catalog_1.relationName)(given));
|
|
387
|
+
if (!table)
|
|
388
|
+
throw new HttpError(404, `Table ${given} is not served`);
|
|
389
|
+
const columnsParam = params.get('columns');
|
|
390
|
+
const columns = selectColumns(table, columnsParam);
|
|
391
|
+
const schema = Object.fromEntries(columns.map((c) => [c.shapeName, table.schema[c.shapeName]]));
|
|
392
|
+
const whereText = params.get('where');
|
|
393
|
+
// Electric's positional parameters: params[1]=…, params[2]=…
|
|
394
|
+
const values = new Map();
|
|
395
|
+
for (const [name, value] of params) {
|
|
396
|
+
const m = /^params\[(\d+)\]$/.exec(name);
|
|
397
|
+
if (m)
|
|
398
|
+
values.set(Number(m[1]), value);
|
|
399
|
+
}
|
|
400
|
+
let where;
|
|
401
|
+
if (whereText) {
|
|
402
|
+
const names = new Map(table.columns.map((c) => [c.shapeName, (0, catalog_1.quote)(c.name)]));
|
|
403
|
+
where = (0, where_1.translateWhere)(whereText, names, values);
|
|
404
|
+
}
|
|
405
|
+
// Each shape of a table its own handle: the table alone, as before, when
|
|
406
|
+
// the shape is the whole table.
|
|
407
|
+
const definition = whereText || columnsParam
|
|
408
|
+
? `${table.name}\u0000${columns.map((c) => c.name).join(',')}\u0000${whereText ?? ''}\u0000${JSON.stringify([...values].sort())}`
|
|
409
|
+
: table.name;
|
|
410
|
+
return { table, columns, schema, where, handle: `${epoch}-${hashName(definition)}` };
|
|
411
|
+
}
|
|
412
|
+
/** `(k1, k2, …) > (v1, v2, …)`, as Firebird 3 can write it. */
|
|
413
|
+
function keysetAfter(keys, values) {
|
|
414
|
+
const ors = [];
|
|
415
|
+
const params = [];
|
|
416
|
+
for (let i = 0; i < keys.length; i++) {
|
|
417
|
+
const ands = keys.slice(0, i).map((k) => `${k} = ?`);
|
|
418
|
+
ands.push(`${keys[i]} > ?`);
|
|
419
|
+
ors.push(`(${ands.join(' AND ')})`);
|
|
420
|
+
params.push(...values.slice(0, i), values[i]);
|
|
421
|
+
}
|
|
422
|
+
return { sql: `(${ors.join(' OR ')})`, params };
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* One transaction at a time on the connection: the native client runs each
|
|
426
|
+
* call on a worker thread, and two at once on one attachment (a live poll
|
|
427
|
+
* beside a snapshot) crashed the process.
|
|
428
|
+
*/
|
|
429
|
+
const queues = new WeakMap();
|
|
430
|
+
/** Connections `close()` has disconnected: nothing more may run on them. */
|
|
431
|
+
const disconnected = new WeakSet();
|
|
432
|
+
/** Run `fn` after whatever else this connection is running; refuse once it is closed. */
|
|
433
|
+
function serialized(attachment, fn) {
|
|
434
|
+
const previous = queues.get(attachment) ?? Promise.resolve();
|
|
435
|
+
const run = () => {
|
|
436
|
+
if (disconnected.has(attachment))
|
|
437
|
+
throw new HttpError(503, 'The shape server is closing');
|
|
438
|
+
return fn();
|
|
439
|
+
};
|
|
440
|
+
const result = previous.then(run, run);
|
|
441
|
+
queues.set(attachment, result.catch(() => undefined));
|
|
442
|
+
return result;
|
|
443
|
+
}
|
|
444
|
+
/** Run `fn` in a read-only snapshot transaction, after any other on this connection. */
|
|
445
|
+
async function readOnly(attachment, fn) {
|
|
446
|
+
return serialized(attachment, async () => {
|
|
447
|
+
// SNAPSHOT is Firebird's concurrency mode (CONSISTENCY would lock the tables).
|
|
448
|
+
const tx = await attachment.startTransaction({ isolation: node_firebird_driver_1.TransactionIsolation.SNAPSHOT, accessMode: 'READ_ONLY' });
|
|
449
|
+
try {
|
|
450
|
+
return await fn(tx);
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
await tx.commit().catch(() => tx.rollback().catch(() => undefined));
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
async function readBlob(attachment, tx, blob) {
|
|
458
|
+
const stream = await attachment.openBlob(tx, blob);
|
|
459
|
+
try {
|
|
460
|
+
const chunks = [];
|
|
461
|
+
for (;;) {
|
|
462
|
+
const buffer = Buffer.alloc(64 * 1024);
|
|
463
|
+
const n = await stream.read(buffer);
|
|
464
|
+
if (n < 0)
|
|
465
|
+
break;
|
|
466
|
+
chunks.push(buffer.subarray(0, n));
|
|
467
|
+
}
|
|
468
|
+
return Buffer.concat(chunks);
|
|
469
|
+
}
|
|
470
|
+
finally {
|
|
471
|
+
await stream.close();
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/** The columns and key of `name`, from the system tables. */
|
|
475
|
+
async function describeTable(attachment, name) {
|
|
476
|
+
return readOnly(attachment, async (tx) => {
|
|
477
|
+
const rs = await attachment.executeQuery(tx, 'SELECT TRIM(rf.RDB$FIELD_NAME), f.RDB$FIELD_TYPE, COALESCE(f.RDB$FIELD_SUB_TYPE, 0), ' +
|
|
478
|
+
'COALESCE(f.RDB$FIELD_SCALE, 0), COALESCE(f.RDB$FIELD_PRECISION, 0), ' +
|
|
479
|
+
'COALESCE(f.RDB$CHARACTER_LENGTH, f.RDB$FIELD_LENGTH, 0), ' +
|
|
480
|
+
'COALESCE(rf.RDB$NULL_FLAG, f.RDB$NULL_FLAG, 0), COALESCE(f.RDB$CHARACTER_SET_ID, 0) ' +
|
|
481
|
+
'FROM RDB$RELATION_FIELDS rf JOIN RDB$FIELDS f ON f.RDB$FIELD_NAME = rf.RDB$FIELD_SOURCE ' +
|
|
482
|
+
'WHERE rf.RDB$RELATION_NAME = ? AND f.RDB$COMPUTED_BLR IS NULL ORDER BY rf.RDB$FIELD_POSITION', [name]);
|
|
483
|
+
const columns = (await rs.fetch()).map((r) => ({
|
|
484
|
+
name: String(r[0]),
|
|
485
|
+
type: Number(r[1]),
|
|
486
|
+
subType: Number(r[2]),
|
|
487
|
+
scale: Number(r[3]),
|
|
488
|
+
precision: Number(r[4]),
|
|
489
|
+
charLength: Number(r[5]),
|
|
490
|
+
notNull: Number(r[6]) === 1,
|
|
491
|
+
charSet: Number(r[7]),
|
|
492
|
+
}));
|
|
493
|
+
await rs.close();
|
|
494
|
+
const keyRs = await attachment.executeQuery(tx, 'SELECT TRIM(s.RDB$FIELD_NAME) FROM RDB$RELATION_CONSTRAINTS c ' +
|
|
495
|
+
'JOIN RDB$INDEX_SEGMENTS s ON s.RDB$INDEX_NAME = c.RDB$INDEX_NAME ' +
|
|
496
|
+
"WHERE c.RDB$RELATION_NAME = ? AND c.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY s.RDB$FIELD_POSITION", [name]);
|
|
497
|
+
const key = (await keyRs.fetch()).map((r) => String(r[0]));
|
|
498
|
+
await keyRs.close();
|
|
499
|
+
return (0, catalog_1.planTable)(name, columns, key);
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
function selectColumns(table, list) {
|
|
503
|
+
if (!list)
|
|
504
|
+
return table.columns;
|
|
505
|
+
const wanted = list.split(',').map((c) => c.trim().replace(/^"(.*)"$/, '$1'));
|
|
506
|
+
const columns = table.columns.filter((c) => wanted.includes(c.shapeName) || wanted.includes(c.name));
|
|
507
|
+
for (const k of table.key) {
|
|
508
|
+
if (!columns.some((c) => c.name === k)) {
|
|
509
|
+
throw new HttpError(400, `columns must include the key column ${shapeOf(table, k)}`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return columns;
|
|
513
|
+
}
|
|
514
|
+
function shapeOf(table, firebirdName) {
|
|
515
|
+
return table.columns.find((c) => c.name === firebirdName).shapeName;
|
|
516
|
+
}
|
|
517
|
+
function keyOf(table, values) {
|
|
518
|
+
return `"${table.name}"/${values.map((v) => `"${String(v)}"`).join('/')}`;
|
|
519
|
+
}
|
|
520
|
+
function hashName(name) {
|
|
521
|
+
let hash = 0x811c9dc5;
|
|
522
|
+
for (const ch of name) {
|
|
523
|
+
hash ^= ch.codePointAt(0);
|
|
524
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
525
|
+
}
|
|
526
|
+
return hash.toString(36);
|
|
527
|
+
}
|
|
528
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/electric-server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* where.ts – a shape's `where`, as Electric's clients write it (Postgres
|
|
3
|
+
* SQL), read and written again as Firebird SQL with every value bound.
|
|
4
|
+
*
|
|
5
|
+
* Only a small, closed part of SQL is taken: column names, literals,
|
|
6
|
+
* Electric's positional parameters (`$1`, given as `params[1]=…`),
|
|
7
|
+
* comparisons, `AND` / `OR` / `NOT`, `IS [NOT] NULL`, `[NOT] IN (…)`,
|
|
8
|
+
* `[NOT] LIKE` / `ILIKE`, `[NOT] BETWEEN … AND …`, and parentheses. Anything
|
|
9
|
+
* else (a function, a subquery, a cast, a column of another table) is
|
|
10
|
+
* refused by name, never passed on: the text comes from a client, and the
|
|
11
|
+
* server runs what it writes. Every literal and parameter is bound, so no
|
|
12
|
+
* text a client sends ever becomes SQL.
|
|
13
|
+
*/
|
|
14
|
+
/** Thrown for a `where` this server does not take; the server answers 400. */
|
|
15
|
+
export declare class WhereError extends Error {
|
|
16
|
+
}
|
|
17
|
+
/** A `where`, as Firebird SQL over the table's own columns, and its values. */
|
|
18
|
+
export interface FirebirdWhere {
|
|
19
|
+
sql: string;
|
|
20
|
+
params: unknown[];
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Translate `text` into Firebird SQL.
|
|
24
|
+
*
|
|
25
|
+
* `columns` maps the names a client writes (the shape's names: `title` for
|
|
26
|
+
* Firebird's `TITLE`) to the Firebird column, quoted. `params` are the
|
|
27
|
+
* values of `$1`, `$2`…, as text.
|
|
28
|
+
*/
|
|
29
|
+
export declare function translateWhere(text: string, columns: ReadonlyMap<string, string>, params: ReadonlyMap<number, string>): FirebirdWhere;
|
|
30
|
+
//# sourceMappingURL=where.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"where.d.ts","sourceRoot":"","sources":["../../src/electric-server/where.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,8EAA8E;AAC9E,qBAAa,UAAW,SAAQ,KAAK;CAAG;AAExC,+EAA+E;AAC/E,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AA6DD;;;;;;GAMG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAClC,aAAa,CAsJf"}
|