@velarscript/node 0.11.1 → 0.12.1
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 +102 -14
- package/dist/compiler.d.ts +3 -0
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +300 -76
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/node-host-runtime.d.ts.map +1 -1
- package/dist/node-host-runtime.js +30 -14
- package/dist/node-host-runtime.js.map +1 -1
- package/dist/node-host-worker-runtime.d.ts.map +1 -1
- package/dist/node-host-worker-runtime.js +495 -93
- package/dist/node-host-worker-runtime.js.map +1 -1
- package/dist/project-config.d.ts +17 -0
- package/dist/project-config.d.ts.map +1 -0
- package/dist/project-config.js +66 -0
- package/dist/project-config.js.map +1 -0
- package/dist/serve-runtime.d.ts.map +1 -1
- package/dist/serve-runtime.js +2942 -158
- package/dist/serve-runtime.js.map +1 -1
- package/dist/server-analyzer.d.ts +35 -0
- package/dist/server-analyzer.d.ts.map +1 -0
- package/dist/server-analyzer.js +692 -0
- package/dist/server-analyzer.js.map +1 -0
- package/dist/server-ast.d.ts +54 -0
- package/dist/server-ast.d.ts.map +1 -0
- package/dist/server-ast.js +16 -0
- package/dist/server-ast.js.map +1 -0
- package/dist/server-emitter.d.ts +17 -0
- package/dist/server-emitter.d.ts.map +1 -0
- package/dist/server-emitter.js +177 -0
- package/dist/server-emitter.js.map +1 -0
- package/dist/server-inspection.d.ts +3 -0
- package/dist/server-inspection.d.ts.map +1 -0
- package/dist/server-inspection.js +12 -0
- package/dist/server-inspection.js.map +1 -0
- package/dist/server-lexer.d.ts +13 -0
- package/dist/server-lexer.d.ts.map +1 -0
- package/dist/server-lexer.js +65 -0
- package/dist/server-lexer.js.map +1 -0
- package/dist/server-parser.d.ts +18 -0
- package/dist/server-parser.d.ts.map +1 -0
- package/dist/server-parser.js +232 -0
- package/dist/server-parser.js.map +1 -0
- package/dist/server-semantic.d.ts +3 -0
- package/dist/server-semantic.d.ts.map +1 -0
- package/dist/server-semantic.js +31 -0
- package/dist/server-semantic.js.map +1 -0
- package/dist/server-types.d.ts +25 -0
- package/dist/server-types.d.ts.map +1 -0
- package/dist/server-types.js +60 -0
- package/dist/server-types.js.map +1 -0
- package/dist/websocket-runtime.d.ts.map +1 -1
- package/dist/websocket-runtime.js +169 -15
- package/dist/websocket-runtime.js.map +1 -1
- package/package.json +10 -2
- package/dist/sqlite-runtime.d.ts +0 -3
- package/dist/sqlite-runtime.d.ts.map +0 -1
- package/dist/sqlite-runtime.js +0 -92
- package/dist/sqlite-runtime.js.map +0 -1
|
@@ -1,46 +1,200 @@
|
|
|
1
1
|
export const VELAR_NODE_WEBSOCKET_RUNTIME = String.raw `
|
|
2
2
|
import __VelarWebSocket, { WebSocketServer as __VelarWebSocketServer } from "ws";
|
|
3
3
|
import { createServer as __velarCreateHttpServer } from "node:http";
|
|
4
|
+
import { createReadStream as __velarServeCreateReadStream } from "node:fs";
|
|
4
5
|
import { readFile as __velarServeReadFile, realpath as __velarServeRealpath, stat as __velarServeStat } from "node:fs/promises";
|
|
5
|
-
import { isAbsolute as __velarServeIsAbsolute, relative as __velarServeRelative, resolve as __velarServeResolve } from "node:path";
|
|
6
|
-
import {
|
|
6
|
+
import { extname as __velarServeExtname, isAbsolute as __velarServeIsAbsolute, relative as __velarServeRelative, resolve as __velarServeResolve } from "node:path";
|
|
7
|
+
import { brotliCompress as __velarServeBrotliNode, gzip as __velarServeGzipNode } from "node:zlib";
|
|
8
|
+
import { promisify as __velarServePromisify } from "node:util";
|
|
9
|
+
import { ServeRequest as __velarServeRuntime, ServeApp as __velarServeApp } from "velar/serve";
|
|
7
10
|
|
|
8
11
|
const __velarWebSocketConnections = new WeakMap();
|
|
9
12
|
const __velarWebSocketServers = new WeakMap();
|
|
10
|
-
const
|
|
13
|
+
const __velarWsPromise = globalThis.Promise;
|
|
14
|
+
const __velarWsPromiseAll = __velarWsPromise.all.bind(__velarWsPromise);
|
|
15
|
+
const __velarWsReflectApply = globalThis.Reflect.apply;
|
|
16
|
+
const __velarWsFinalizationRegistry = globalThis.FinalizationRegistry;
|
|
17
|
+
const __velarWsFinalizerRegister = __velarWsFinalizationRegistry.prototype.register;
|
|
18
|
+
const __velarWsSetTimeout = globalThis.setTimeout;
|
|
19
|
+
const __velarWsClearTimeout = globalThis.clearTimeout;
|
|
20
|
+
const __velarServeGzip = __velarServePromisify(__velarServeGzipNode);
|
|
21
|
+
const __velarServeBrotli = __velarServePromisify(__velarServeBrotliNode);
|
|
22
|
+
const __velarWsAggregateByteLimit = 128 * 1024 * 1024;
|
|
23
|
+
const __velarWsAggregateQueuedMessageLimit = 65536;
|
|
24
|
+
const __velarWsAggregatePendingSendLimit = 8192;
|
|
25
|
+
const __velarWsActiveConnectionLimit = 4096;
|
|
26
|
+
const __velarWsPendingConnectionLimit = 4096;
|
|
27
|
+
let __velarWsAggregateBytes = 0;
|
|
28
|
+
let __velarWsAggregateQueuedMessages = 0;
|
|
29
|
+
let __velarWsAggregatePendingSends = 0;
|
|
30
|
+
let __velarWsActiveConnections = 0;
|
|
31
|
+
let __velarWsPendingConnections = 0;
|
|
32
|
+
let __velarWsActiveHttpSockets = 0;
|
|
33
|
+
const __velarServeNativeOperations = Object.freeze({readFile: __velarServeReadFile, createReadStream: __velarServeCreateReadStream, realpath: __velarServeRealpath, stat: __velarServeStat, extname: __velarServeExtname, isAbsolute: __velarServeIsAbsolute, relative: __velarServeRelative, resolve: __velarServeResolve, compress: (encoding, value) => encoding === "br" ? __velarServeBrotli(value) : __velarServeGzip(value)});
|
|
11
34
|
function __velarWsInteger(value, fallback, minimum, maximum, name) { if (value === undefined || value === null) return fallback; if (!Number.isSafeInteger(value) || value < minimum || value > maximum) throw new RangeError(name + " must be an integer from " + minimum + " through " + maximum); return value; }
|
|
12
35
|
function __velarWsDuration(value, fallback) { if (value === undefined || value === null) return fallback; if (typeof value !== "string") throw new TypeError("WebSocket timeout must be Duration"); const match = /^([+-]?(?:\d+(?:\.\d+)?|\.\d+))(ms|s)$/.exec(value); if (!match) throw new TypeError("WebSocket timeout must be Duration such as 5s"); const result = Number(match[1]) * (match[2] === "s" ? 1000 : 1); if (!Number.isFinite(result) || result < 0 || result > 2147483647) throw new RangeError("WebSocket timeout is outside the supported range"); return result; }
|
|
13
36
|
function __velarWsOptions(options = {}) { if (options === null || typeof options !== "object" || Array.isArray(options)) throw new TypeError("WebSocket options must be a record"); return { maxMessageBytes: __velarWsInteger(options.maxMessageBytes, 16 * 1024 * 1024, 1, 64 * 1024 * 1024, "maxMessageBytes"), maxQueuedMessages: __velarWsInteger(options.maxQueuedMessages, 256, 1, 10000, "maxQueuedMessages"), maxQueuedBytes: __velarWsInteger(options.maxQueuedBytes, 16 * 1024 * 1024, 1, 64 * 1024 * 1024, "maxQueuedBytes"), maxPendingSendBytes: __velarWsInteger(options.maxPendingSendBytes, 16 * 1024 * 1024, 1, 64 * 1024 * 1024, "maxPendingSendBytes") }; }
|
|
14
37
|
function __velarWsBytes(value) { if (value instanceof Uint8Array) { const output = new Uint8Array(value.byteLength); output.set(value); return output; } return null; }
|
|
15
|
-
function __velarWsMessageBytes(value) { if (typeof value === "string") return Buffer.byteLength(value, "utf8");
|
|
38
|
+
function __velarWsMessageBytes(value) { if (typeof value === "string") return Buffer.byteLength(value, "utf8"); if (value instanceof Uint8Array) return value.byteLength; throw new TypeError("WebSocket.send requires text or Bytes"); }
|
|
39
|
+
function __velarWsReserve(size) { if (!Number.isSafeInteger(size) || size < 0 || __velarWsAggregateBytes + size > __velarWsAggregateByteLimit) return false; __velarWsAggregateBytes += size; return true; }
|
|
40
|
+
function __velarWsRelease(size) { __velarWsAggregateBytes -= size; if (__velarWsAggregateBytes < 0) __velarWsAggregateBytes = 0; }
|
|
41
|
+
function __velarWsReserveQueue(size) { if (__velarWsAggregateQueuedMessages >= __velarWsAggregateQueuedMessageLimit || !__velarWsReserve(size)) return false; __velarWsAggregateQueuedMessages += 1; return true; }
|
|
42
|
+
function __velarWsReleaseQueue(size, count = 1) { __velarWsRelease(size); __velarWsAggregateQueuedMessages -= count; if (__velarWsAggregateQueuedMessages < 0) __velarWsAggregateQueuedMessages = 0; }
|
|
43
|
+
function __velarWsReserveSend(size) { if (__velarWsAggregatePendingSends >= __velarWsAggregatePendingSendLimit || !__velarWsReserve(size)) return false; __velarWsAggregatePendingSends += 1; return true; }
|
|
44
|
+
function __velarWsReleaseSend(size) { __velarWsRelease(size); __velarWsAggregatePendingSends -= 1; if (__velarWsAggregatePendingSends < 0) __velarWsAggregatePendingSends = 0; }
|
|
45
|
+
function __velarWsReleaseActive(state) { if (!state.active) return; state.active = false; __velarWsActiveConnections -= 1; if (__velarWsActiveConnections < 0) __velarWsActiveConnections = 0; }
|
|
46
|
+
function __velarWsDiscardQueue(state) { if (state.queueReleased) return; state.queueReleased = true; __velarWsReleaseQueue(state.queuedBytes, state.queue.length); state.queue.length = 0; state.queuedBytes = 0; }
|
|
16
47
|
export class WebSocketBackpressureError extends Error { constructor(message = "WebSocket backpressure limit exceeded") { super(message); this.name = "WebSocketBackpressureError"; } }
|
|
17
48
|
export class WebSocketClosedError extends Error { constructor(message = "WebSocket is closed") { super(message); this.name = "WebSocketClosedError"; } }
|
|
18
49
|
export class WebSocketProtocolError extends Error { constructor(message = "WebSocket protocol error") { super(message); this.name = "WebSocketProtocolError"; } }
|
|
19
50
|
export class WebSocketTimeoutError extends Error { constructor(message = "WebSocket timed out") { super(message); this.name = "WebSocketTimeoutError"; } }
|
|
20
|
-
function
|
|
21
|
-
|
|
51
|
+
function __velarWsReleasePendingSends(state) { for (const complete of state.pendingSends) complete(new Error("WebSocket is closed")); state.pendingSends.clear(); }
|
|
52
|
+
const __velarWsFinalizer = new __velarWsFinalizationRegistry(state => { __velarWsAbort(state); try { state.socket.terminate(); } catch {} });
|
|
53
|
+
function __velarWsFinish(state) { if (state.finished) return; state.finished = true; __velarWsReleaseActive(state); if (state.queue.length === 0) __velarWsDiscardQueue(state); __velarWsReleasePendingSends(state); if (state.waiter) { const waiter = state.waiter; state.waiter = null; waiter.resolve(null); } }
|
|
54
|
+
function __velarWsAbort(state) { state.finished = true; __velarWsReleaseActive(state); __velarWsDiscardQueue(state); __velarWsReleasePendingSends(state); if (state.waiter) { const waiter = state.waiter; state.waiter = null; waiter.resolve(null); } }
|
|
22
55
|
function __velarWsRejectReceive(state, socket, code, reason) { __velarWsAbort(state); socket.close(code, reason); }
|
|
56
|
+
function __velarWsReceive(state, socket, data, binary) {
|
|
57
|
+
if (state.finished) return;
|
|
58
|
+
let source = null; let message = null; let size;
|
|
59
|
+
if (binary) { source = data instanceof Uint8Array ? data : new Uint8Array(data); size = source.byteLength; }
|
|
60
|
+
else { message = typeof data === "string" ? data : data.toString("utf8"); size = Buffer.byteLength(message, "utf8"); }
|
|
61
|
+
if (size > state.options.maxMessageBytes) { __velarWsRejectReceive(state, socket, 1009, "Message too large"); return; }
|
|
62
|
+
if (state.waiter) { if (source) { message = new Uint8Array(size); message.set(source); } const waiter = state.waiter; state.waiter = null; waiter.resolve(message); return; }
|
|
63
|
+
if (state.queue.length >= state.options.maxQueuedMessages || state.queuedBytes + size > state.options.maxQueuedBytes || !__velarWsReserveQueue(size)) { __velarWsRejectReceive(state, socket, 1009, "Unread message queue full"); return; }
|
|
64
|
+
try { if (source) { message = new Uint8Array(size); message.set(source); } state.queue.push(message); state.queuedBytes += size; }
|
|
65
|
+
catch (error) { __velarWsReleaseQueue(size); throw error; }
|
|
66
|
+
}
|
|
23
67
|
function __velarWsWrap(socket, options) {
|
|
24
|
-
|
|
68
|
+
__velarWsActiveConnections += 1;
|
|
69
|
+
const value = Object.create(__velarWsConnectionPrototype); const state = { socket, options, queue: [], queuedBytes: 0, queueReleased: false, waiter: null, pendingSendBytes: 0, pendingSends: new Set(), finished: false, active: true, closePromise: null }; __velarWebSocketConnections.set(value, state);
|
|
70
|
+
__velarWsReflectApply(__velarWsFinalizerRegister, __velarWsFinalizer, [value, state]);
|
|
25
71
|
socket.binaryType = "arraybuffer";
|
|
26
|
-
socket.on("message", (data, binary) => {
|
|
72
|
+
socket.on("message", (data, binary) => { try { __velarWsReceive(state, socket, data, binary); } catch { __velarWsRejectReceive(state, socket, 1011, "Message handling failed"); } });
|
|
27
73
|
socket.on("close", () => __velarWsFinish(state)); socket.on("error", error => { if (state.waiter) { const waiter = state.waiter; state.waiter = null; waiter.reject(new WebSocketProtocolError(error instanceof Error ? error.message : "WebSocket error")); } __velarWsAbort(state); });
|
|
28
74
|
return Object.freeze(value);
|
|
29
75
|
}
|
|
76
|
+
function __velarWsCloseForStop(connection) {
|
|
77
|
+
const state = __velarWebSocketConnections.get(connection);
|
|
78
|
+
if (!state || state.finished) return new __velarWsPromise(resolve => resolve(null));
|
|
79
|
+
__velarWsAbort(state);
|
|
80
|
+
return new __velarWsPromise(resolve => {
|
|
81
|
+
let settled = false; let timer = null;
|
|
82
|
+
const finish = () => { if (settled) return; settled = true; if (timer !== null) __velarWsClearTimeout(timer); state.socket.off("close", finish); resolve(null); };
|
|
83
|
+
state.socket.once("close", finish);
|
|
84
|
+
try { state.socket.close(1001, "Server stopping"); }
|
|
85
|
+
catch { try { state.socket.terminate(); } catch {} finish(); return; }
|
|
86
|
+
if (!settled) timer = __velarWsSetTimeout(() => { try { state.socket.terminate(); } catch {} finish(); }, 5000);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function __velarWsCompactPendingConnections(state) { if (state.queue.length <= state.pendingConnections.size * 2 + 64) return; const compact = []; for (const connection of state.queue) if (state.pendingConnections.has(connection)) compact.push(connection); state.queue = compact; }
|
|
90
|
+
function __velarWsCloseHttpServer(state, grace = 30000) {
|
|
91
|
+
return new __velarWsPromise((resolve, reject) => {
|
|
92
|
+
let settled = false; let forceTimer = null; let finalTimer = null;
|
|
93
|
+
const finish = action => { if (settled) return; settled = true; if (forceTimer !== null) __velarWsClearTimeout(forceTimer); if (finalTimer !== null) __velarWsClearTimeout(finalTimer); action(); };
|
|
94
|
+
try { state.httpServer.close(error => error ? finish(() => reject(error)) : finish(() => resolve(null))); }
|
|
95
|
+
catch (error) { finish(() => reject(error)); return; }
|
|
96
|
+
try { state.httpServer.closeIdleConnections?.(); } catch {}
|
|
97
|
+
forceTimer = __velarWsSetTimeout(() => {
|
|
98
|
+
try { state.httpServer.closeAllConnections?.(); } catch {}
|
|
99
|
+
for (const socket of state.sockets) try { socket.destroy(); } catch {}
|
|
100
|
+
finalTimer = __velarWsSetTimeout(() => finish(() => reject(new Error("WebSocket HTTP transport did not stop within its graceful shutdown deadline"))), 1000);
|
|
101
|
+
finalTimer.unref?.();
|
|
102
|
+
}, grace);
|
|
103
|
+
forceTimer.unref?.();
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
function __velarWsStopState(state) {
|
|
107
|
+
if (state.stopPromise !== null) return state.stopPromise;
|
|
108
|
+
state.stopped = true;
|
|
109
|
+
if (state.waiter) { state.waiter.resolve(null); state.waiter = null; }
|
|
110
|
+
__velarWsPendingConnections -= state.pendingConnections.size;
|
|
111
|
+
if (__velarWsPendingConnections < 0) __velarWsPendingConnections = 0;
|
|
112
|
+
state.pendingConnections.clear(); state.queue.length = 0;
|
|
113
|
+
const applicationClose = state.application ? state.application.close(30000) : new __velarWsPromise(resolve => resolve(null));
|
|
114
|
+
const httpClose = __velarWsCloseHttpServer(state);
|
|
115
|
+
const pending = (async () => {
|
|
116
|
+
try {
|
|
117
|
+
const closing = [];
|
|
118
|
+
for (const connection of state.connections) closing.push(__velarWsCloseForStop(connection));
|
|
119
|
+
await __velarWsPromiseAll(closing);
|
|
120
|
+
await new __velarWsPromise((resolve, reject) => state.server.close(error => error ? reject(error) : resolve(null)));
|
|
121
|
+
await __velarWsPromiseAll([httpClose, applicationClose]);
|
|
122
|
+
} finally { state.connections.clear(); }
|
|
123
|
+
return null;
|
|
124
|
+
})();
|
|
125
|
+
state.stopPromise = pending;
|
|
126
|
+
return pending;
|
|
127
|
+
}
|
|
30
128
|
const __velarWsConnectionPrototype = Object.freeze({
|
|
31
129
|
state() { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket state requires a connection"); return state.socket.readyState === __VelarWebSocket.CONNECTING ? "connecting" : state.socket.readyState === __VelarWebSocket.OPEN ? "open" : state.socket.readyState === __VelarWebSocket.CLOSING ? "closing" : "closed"; },
|
|
32
|
-
send(message) { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.send requires a connection"); if (state.socket.readyState !== __VelarWebSocket.OPEN) return Promise.reject(new WebSocketClosedError()); const size = __velarWsMessageBytes(message); if (size > state.options.maxMessageBytes) return Promise.reject(new RangeError("WebSocket message exceeds maxMessageBytes")); if (state.pendingSendBytes + size > state.options.maxPendingSendBytes) return Promise.reject(new WebSocketBackpressureError());
|
|
33
|
-
next() { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.next requires a connection"); if (state.queue.length) { const message = state.queue.shift(); state.queuedBytes -=
|
|
34
|
-
close(code = 1000, reason = "") { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.close requires a connection"); if (!Number.isSafeInteger(code) || code < 1000 || code > 4999) return Promise.reject(new RangeError("WebSocket close code must be from 1000 through 4999")); if (typeof reason !== "string" || Buffer.byteLength(reason, "utf8") > 123) return Promise.reject(new RangeError("WebSocket close reason cannot exceed 123 UTF-8 bytes")); if (state.finished) return Promise.resolve(null); if (!state.closePromise) { state.closePromise = new Promise(resolve => state.socket.
|
|
130
|
+
send(message) { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.send requires a connection"); if (state.socket.readyState !== __VelarWebSocket.OPEN) return Promise.reject(new WebSocketClosedError()); const size = __velarWsMessageBytes(message); if (size > state.options.maxMessageBytes) return Promise.reject(new RangeError("WebSocket message exceeds maxMessageBytes")); if (state.pendingSendBytes + size > state.options.maxPendingSendBytes || !__velarWsReserveSend(size)) return Promise.reject(new WebSocketBackpressureError()); let bytes; try { bytes = typeof message === "string" ? null : __velarWsBytes(message); } catch (error) { __velarWsReleaseSend(size); throw error; } state.pendingSendBytes += size; return new Promise((resolve, reject) => { let completed = false; const complete = error => { if (completed) return; completed = true; state.pendingSends.delete(complete); state.pendingSendBytes -= size; __velarWsReleaseSend(size); if (error) reject(new WebSocketClosedError(error.message)); else resolve(null); }; state.pendingSends.add(complete); try { state.socket.send(bytes ?? message, { binary: bytes !== null }, complete); } catch (error) { complete(error instanceof Error ? error : new Error("WebSocket send failed")); } }); },
|
|
131
|
+
next() { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.next requires a connection"); if (state.queue.length) { const message = state.queue.shift(); const size = __velarWsMessageBytes(message); state.queuedBytes -= size; __velarWsReleaseQueue(size); if (state.finished && state.queue.length === 0) __velarWsDiscardQueue(state); return Promise.resolve(message); } if (state.finished) return Promise.resolve(null); if (state.waiter) return Promise.reject(new WebSocketBackpressureError("Only one WebSocket.next call may wait at a time")); return new Promise((resolve, reject) => { state.waiter = { resolve, reject }; }); },
|
|
132
|
+
close(code = 1000, reason = "") { const state = __velarWebSocketConnections.get(this); if (!state) throw new TypeError("WebSocket.close requires a connection"); if (!Number.isSafeInteger(code) || code < 1000 || code > 4999) return Promise.reject(new RangeError("WebSocket close code must be from 1000 through 4999")); if (typeof reason !== "string" || Buffer.byteLength(reason, "utf8") > 123) return Promise.reject(new RangeError("WebSocket close reason cannot exceed 123 UTF-8 bytes")); if (state.finished) return Promise.resolve(null); if (!state.closePromise) { state.closePromise = new Promise(resolve => { let settled = false; let timer = null; const finish = () => { if (settled) return; settled = true; if (timer !== null) __velarWsClearTimeout(timer); state.socket.off("close", finish); resolve(null); }; state.socket.once("close", finish); try { state.socket.close(code, reason); } catch { try { state.socket.terminate(); } catch {} finish(); return; } timer = __velarWsSetTimeout(() => { try { state.socket.terminate(); } catch {} finish(); }, 5000); }); } return state.closePromise; },
|
|
35
133
|
});
|
|
36
134
|
const __velarWsServerPrototype = Object.freeze({
|
|
37
|
-
next() { const state = __velarWebSocketServers.get(this); if (!state) throw new TypeError("WebSocketServer.next requires a server");
|
|
38
|
-
|
|
135
|
+
next() { const state = __velarWebSocketServers.get(this); if (!state) throw new TypeError("WebSocketServer.next requires a server"); while (state.queue.length) { const connection = state.queue.shift(); if (!state.pendingConnections.delete(connection)) continue; __velarWsPendingConnections -= 1; if (__velarWsPendingConnections < 0) __velarWsPendingConnections = 0; return Promise.resolve(connection); } if (state.stopped) return Promise.resolve(null); if (state.waiter) return Promise.reject(new WebSocketBackpressureError("Only one WebSocketServer.next call may wait at a time")); return new Promise((resolve, reject) => { state.waiter = { resolve, reject }; }); },
|
|
136
|
+
stop() { const state = __velarWebSocketServers.get(this); if (!state) throw new TypeError("WebSocketServer.stop requires a server"); return __velarWsStopState(state); },
|
|
39
137
|
});
|
|
40
138
|
const __velarWsConnectionType = Object.freeze({ is(value) { return __velarWebSocketConnections.has(value); }, parse(value) { if (!this.is(value)) throw new TypeError("Value does not match WebSocketConnection"); return value; } });
|
|
41
139
|
const __velarWsServerType = Object.freeze({ is(value) { return __velarWebSocketServers.has(value); }, parse(value) { if (!this.is(value)) throw new TypeError("Value does not match WebSocketServer"); return value; } });
|
|
42
140
|
export const WebSocketConnection = __velarWsConnectionType; export const WebSocketServer = __velarWsServerType;
|
|
43
|
-
export function connect(url, options = {}) { if (typeof url !== "string" || !/^wss?:\/\//u.test(url)) return
|
|
44
|
-
export function listen(options) {
|
|
141
|
+
export function connect(url, options = {}) { if (typeof url !== "string" || !/^wss?:\/\//u.test(url)) return __velarWsPromise.reject(new TypeError("WebSocket URL must start with ws:// or wss://")); const limits = __velarWsOptions(options); const timeout = __velarWsDuration(options.timeout, 10000); return new __velarWsPromise((resolve, reject) => { const socket = new __VelarWebSocket(url, { maxPayload: limits.maxMessageBytes }); let settled = false; const finish = (action) => { if (settled) return false; settled = true; __velarWsClearTimeout(timer); socket.off("open", opened); socket.off("error", failed); action(); return true; }; const absorbTerminalError = () => socket.once("error", () => {}); const opened = () => { if (__velarWsActiveConnections >= __velarWsActiveConnectionLimit) { if (finish(() => reject(new WebSocketBackpressureError("WebSocket connection limit exceeded")))) { absorbTerminalError(); socket.close(1013, "Client connection limit reached"); } return; } finish(() => resolve(__velarWsWrap(socket, limits))); }; const failed = error => finish(() => reject(new WebSocketProtocolError(error instanceof Error ? error.message : "WebSocket connection failed"))); const timer = __velarWsSetTimeout(() => { if (finish(() => reject(new WebSocketTimeoutError("WebSocket connection timed out")))) { absorbTerminalError(); socket.terminate(); } }, timeout); socket.once("open", opened); socket.once("error", failed); }); }
|
|
142
|
+
export async function listen(options) {
|
|
143
|
+
if (options === null || typeof options !== "object" || Array.isArray(options)) throw new TypeError("listen requires an options record");
|
|
144
|
+
const limits = __velarWsOptions(options);
|
|
145
|
+
const port = __velarWsInteger(options.port, 0, 0, 65535, "port");
|
|
146
|
+
const maxConnections = __velarWsInteger(options.maxConnections, 1024, 1, 4096, "maxConnections");
|
|
147
|
+
const maxPendingConnections = __velarWsInteger(options.maxPendingConnections, 128, 1, 4096, "maxPendingConnections");
|
|
148
|
+
if (options.host !== undefined && typeof options.host !== "string") throw new TypeError("WebSocket host must be text");
|
|
149
|
+
if (options.path !== undefined && (typeof options.path !== "string" || !options.path.startsWith("/"))) throw new TypeError("WebSocket path must start with '/'");
|
|
150
|
+
const application = __velarServeApp.is(options.http) ? await __velarServeApp.__velarCompilerBridge.nativeApp(options.http) : null;
|
|
151
|
+
const handler = application ? application.handle : options.http;
|
|
152
|
+
if (handler !== undefined && typeof handler !== "function") { if (application) await application.close(); throw new TypeError("WebSocket http must be a ServeApp or velar/serve handler"); }
|
|
153
|
+
try {
|
|
154
|
+
return await new __velarWsPromise((resolve, reject) => {
|
|
155
|
+
const httpServer = __velarCreateHttpServer({maxHeaderSize: 64 * 1024, headersTimeout: 10000, requestTimeout: 60000, keepAliveTimeout: 5000, connectionsCheckingInterval: 1000}, (request, response) => {
|
|
156
|
+
if (handler) void __velarServeRuntime.__velarHandleNative(handler, request, response, __velarServeNativeOperations);
|
|
157
|
+
else { response.statusCode = 404; response.setHeader("content-type", "text/plain; charset=utf-8"); response.end(request.method === "HEAD" ? undefined : "Not found"); }
|
|
158
|
+
});
|
|
159
|
+
httpServer.maxConnections = 2048;
|
|
160
|
+
httpServer.maxRequestsPerSocket = 1000;
|
|
161
|
+
const server = new __VelarWebSocketServer({server: httpServer, path: options.path, maxPayload: limits.maxMessageBytes, perMessageDeflate: false, clientTracking: true});
|
|
162
|
+
const value = Object.create(__velarWsServerPrototype);
|
|
163
|
+
const state = {server, httpServer, application, queue: [], pendingConnections: new Set(), waiter: null, stopped: false, stopPromise: null, connections: new Set(), sockets: new Set()};
|
|
164
|
+
__velarWebSocketServers.set(value, state);
|
|
165
|
+
httpServer.on("connection", socket => {
|
|
166
|
+
if (state.stopped || state.sockets.size >= 2048 || __velarWsActiveHttpSockets >= 4096) { socket.destroy(); return; }
|
|
167
|
+
state.sockets.add(socket); __velarWsActiveHttpSockets += 1; socket.setNoDelay(true); socket.setKeepAlive(true, 5000);
|
|
168
|
+
socket.once("close", () => { if (!state.sockets.delete(socket)) return; __velarWsActiveHttpSockets -= 1; if (__velarWsActiveHttpSockets < 0) __velarWsActiveHttpSockets = 0; });
|
|
169
|
+
});
|
|
170
|
+
server.on("connection", socket => {
|
|
171
|
+
const willQueue = !state.waiter;
|
|
172
|
+
if (state.stopped || state.connections.size >= maxConnections || __velarWsActiveConnections >= __velarWsActiveConnectionLimit || (willQueue && (state.pendingConnections.size >= maxPendingConnections || __velarWsPendingConnections >= __velarWsPendingConnectionLimit))) { socket.close(1013, "Server busy"); return; }
|
|
173
|
+
const connection = __velarWsWrap(socket, limits); state.connections.add(connection);
|
|
174
|
+
socket.once("close", () => { state.connections.delete(connection); if (state.pendingConnections.delete(connection)) { __velarWsPendingConnections -= 1; if (__velarWsPendingConnections < 0) __velarWsPendingConnections = 0; __velarWsCompactPendingConnections(state); } });
|
|
175
|
+
if (state.waiter) { const waiter = state.waiter; state.waiter = null; waiter.resolve(connection); }
|
|
176
|
+
else { state.queue.push(connection); state.pendingConnections.add(connection); __velarWsPendingConnections += 1; }
|
|
177
|
+
});
|
|
178
|
+
let settled = false;
|
|
179
|
+
const fail = error => {
|
|
180
|
+
if (settled) { void __velarWsStopState(state).catch(() => {}); return; }
|
|
181
|
+
settled = true;
|
|
182
|
+
try { server.close(); } catch {}
|
|
183
|
+
try { httpServer.close(); } catch {}
|
|
184
|
+
reject(error);
|
|
185
|
+
};
|
|
186
|
+
server.on("error", fail);
|
|
187
|
+
httpServer.on("error", fail);
|
|
188
|
+
httpServer.listen({port, host: options.host ?? "127.0.0.1"}, () => {
|
|
189
|
+
if (settled) return;
|
|
190
|
+
const address = httpServer.address();
|
|
191
|
+
if (!address || typeof address === "string") { fail(new Error("WebSocket server could not determine its bound port")); return; }
|
|
192
|
+
settled = true;
|
|
193
|
+
Object.defineProperty(value, "port", {value: address.port, enumerable: true});
|
|
194
|
+
resolve(Object.freeze(value));
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
} catch (error) { if (application) await application.close(); throw error; }
|
|
198
|
+
}
|
|
45
199
|
`.trimStart();
|
|
46
200
|
//# sourceMappingURL=websocket-runtime.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"websocket-runtime.js","sourceRoot":"","sources":["../src/websocket-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC,GAAG,CAAA
|
|
1
|
+
{"version":3,"file":"websocket-runtime.js","sourceRoot":"","sources":["../src/websocket-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsMrD,CAAC,SAAS,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velarscript/node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.1",
|
|
4
4
|
"description": "The official VelarScript Node.js module contract and runtime.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -24,8 +24,16 @@
|
|
|
24
24
|
"publishConfig": {
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
|
+
"velar": {
|
|
28
|
+
"extension": {
|
|
29
|
+
"kind": "capability",
|
|
30
|
+
"apiVersion": "0.10",
|
|
31
|
+
"manifestKey": "node",
|
|
32
|
+
"extends": {}
|
|
33
|
+
}
|
|
34
|
+
},
|
|
27
35
|
"dependencies": {
|
|
28
|
-
"@velarscript/compiler": "0.
|
|
36
|
+
"@velarscript/compiler": "0.12.1",
|
|
29
37
|
"ws": "^8.21.1"
|
|
30
38
|
},
|
|
31
39
|
"exports": {
|
package/dist/sqlite-runtime.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-runtime.d.ts","sourceRoot":"","sources":["../src/sqlite-runtime.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,+BAA+B,QA8C3C,CAAC;AAEF,eAAO,MAAM,yBAAyB,QA2CzB,CAAC"}
|
package/dist/sqlite-runtime.js
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
export const VELAR_NODE_SQLITE_WORKER_SOURCE = String.raw `
|
|
2
|
-
const { parentPort, workerData } = require("node:worker_threads");
|
|
3
|
-
const { DatabaseSync } = require("node:sqlite");
|
|
4
|
-
const database = new DatabaseSync(workerData.path, { timeout: workerData.busyTimeout });
|
|
5
|
-
const statements = new Map();
|
|
6
|
-
let nextStatement = 1;
|
|
7
|
-
let transaction = 0;
|
|
8
|
-
function params(value) { if (!Array.isArray(value) || value.length > 10000) throw new TypeError("SQLite parameters must be a bounded List"); return value; }
|
|
9
|
-
function sql(value) { if (typeof value !== "string" || value.length === 0 || value.length > 1024 * 1024) throw new TypeError("SQLite SQL must be non-empty text no longer than 1 MiB"); return value; }
|
|
10
|
-
function statement(id) { const value = statements.get(id); if (!value) throw new Error("SQLite statement is closed"); return value; }
|
|
11
|
-
function normalize(value, transfers, seen = new WeakSet()) {
|
|
12
|
-
if (value === null || typeof value !== "object") return value;
|
|
13
|
-
if (value instanceof Uint8Array) { const bytes = new Uint8Array(value.byteLength); bytes.set(value); transfers.push(bytes.buffer); return bytes; }
|
|
14
|
-
if (seen.has(value)) throw new TypeError("SQLite returned cyclic data"); seen.add(value);
|
|
15
|
-
if (Array.isArray(value)) return value.map(item => normalize(item, transfers, seen));
|
|
16
|
-
const output = Object.create(null); for (const key of Object.keys(value)) output[key] = normalize(value[key], transfers, seen); return output;
|
|
17
|
-
}
|
|
18
|
-
function resultSize(value, seen = new WeakSet()) { if (value === null) return 4; if (typeof value === "string") return Buffer.byteLength(value, "utf8"); if (typeof value === "number") return 8; if (value instanceof Uint8Array) return value.byteLength; if (typeof value !== "object" || seen.has(value)) return 0; seen.add(value); if (Array.isArray(value)) return value.reduce((sum, item) => sum + resultSize(item, seen), 0); return Object.entries(value).reduce((sum, [key, item]) => sum + Buffer.byteLength(key, "utf8") + resultSize(item, seen), 0); }
|
|
19
|
-
function bounded(value) { if (Array.isArray(value) && value.length > workerData.maxRows) throw new RangeError("SQLite result exceeds maxRows"); if (resultSize(value) > workerData.maxResultBytes) throw new RangeError("SQLite result exceeds maxResultBytes"); return value; }
|
|
20
|
-
function execute(target, values) { const result = target.run(...params(values)); return Number(result.changes); }
|
|
21
|
-
function one(target, values) { return target.get(...params(values)) ?? null; }
|
|
22
|
-
function all(target, values) { return target.all(...params(values)); }
|
|
23
|
-
function transactionId(value) { if (value === 0) { if (transaction !== 0) throw new Error("Use the active Transaction handle while a transaction is open"); return; } if (value !== transaction) throw new Error("SQLite transaction is no longer active"); }
|
|
24
|
-
parentPort.on("message", message => {
|
|
25
|
-
const transfers = [];
|
|
26
|
-
try {
|
|
27
|
-
const tx = Number.isSafeInteger(message.transaction) ? message.transaction : 0;
|
|
28
|
-
if (message.operation !== "close") transactionId(tx);
|
|
29
|
-
let value = null;
|
|
30
|
-
if (message.operation === "execute") value = execute(database.prepare(sql(message.sql)), message.params ?? []);
|
|
31
|
-
else if (message.operation === "one") value = bounded(one(database.prepare(sql(message.sql)), message.params ?? []));
|
|
32
|
-
else if (message.operation === "all") value = bounded(all(database.prepare(sql(message.sql)), message.params ?? []));
|
|
33
|
-
else if (message.operation === "prepare") { const id = nextStatement++; statements.set(id, database.prepare(sql(message.sql))); value = id; }
|
|
34
|
-
else if (message.operation === "statement.execute") value = execute(statement(message.statement), message.params ?? []);
|
|
35
|
-
else if (message.operation === "statement.one") value = bounded(one(statement(message.statement), message.params ?? []));
|
|
36
|
-
else if (message.operation === "statement.all") value = bounded(all(statement(message.statement), message.params ?? []));
|
|
37
|
-
else if (message.operation === "statement.close") { statements.delete(message.statement); value = null; }
|
|
38
|
-
else if (message.operation === "transaction") { if (transaction !== 0) throw new Error("SQLite transaction is already active"); database.exec("BEGIN IMMEDIATE"); transaction = message.transactionId; value = transaction; }
|
|
39
|
-
else if (message.operation === "commit") { database.exec("COMMIT"); transaction = 0; value = null; }
|
|
40
|
-
else if (message.operation === "rollback") { database.exec("ROLLBACK"); transaction = 0; value = null; }
|
|
41
|
-
else if (message.operation === "close") { if (transaction !== 0) { database.exec("ROLLBACK"); transaction = 0; } statements.clear(); database.close(); value = null; }
|
|
42
|
-
else throw new Error("Unknown SQLite operation");
|
|
43
|
-
const normalized = normalize(value, transfers); parentPort.postMessage({ id: message.id, ok: true, value: normalized }, transfers);
|
|
44
|
-
} catch (error) { parentPort.postMessage({ id: message.id, ok: false, error: { name: error?.name ?? "Error", message: error?.message ?? String(error), code: error?.code ?? null } }); }
|
|
45
|
-
});
|
|
46
|
-
parentPort.postMessage({ ready: true });
|
|
47
|
-
`;
|
|
48
|
-
export const VELAR_NODE_SQLITE_RUNTIME = String.raw `
|
|
49
|
-
import { Worker as __VelarSqliteWorker } from "node:worker_threads";
|
|
50
|
-
const __velarSqliteDatabases = new WeakMap();
|
|
51
|
-
const __velarSqliteStatements = new WeakMap();
|
|
52
|
-
const __velarSqliteTransactions = new WeakMap();
|
|
53
|
-
export class SqliteError extends Error { constructor(message = "SQLite operation failed", code = null) { super(message); this.name = "SqliteError"; this.code = code; } }
|
|
54
|
-
export class SqliteBackpressureError extends Error { constructor(message = "SQLite queue is full") { super(message); this.name = "SqliteBackpressureError"; } }
|
|
55
|
-
function __velarSqliteInteger(value, fallback, minimum, maximum, name) { if (value === undefined || value === null) return fallback; if (!Number.isSafeInteger(value) || value < minimum || value > maximum) throw new RangeError(name + " must be an integer from " + minimum + " through " + maximum); return value; }
|
|
56
|
-
function __velarSqliteOptions(options = {}) { if (options === null || typeof options !== "object" || Array.isArray(options)) throw new TypeError("SQLite options must be a record"); return { busyTimeout: __velarSqliteInteger(options.busyTimeout, 5000, 0, 2147483647, "busyTimeout"), queueCapacity: __velarSqliteInteger(options.queueCapacity, 256, 1, 10000, "queueCapacity"), maxRows: __velarSqliteInteger(options.maxRows, 10000, 1, 1000000, "maxRows"), maxResultBytes: __velarSqliteInteger(options.maxResultBytes, 16 * 1024 * 1024, 1, 64 * 1024 * 1024, "maxResultBytes") }; }
|
|
57
|
-
function __velarSqliteDatabase(value) { const state = __velarSqliteDatabases.get(value); if (!state) throw new TypeError("SQLite method requires a Database receiver"); return state; }
|
|
58
|
-
function __velarSqliteStatement(value) { const state = __velarSqliteStatements.get(value); if (!state) throw new TypeError("SQLite method requires a Statement receiver"); return state; }
|
|
59
|
-
function __velarSqliteTransaction(value) { const state = __velarSqliteTransactions.get(value); if (!state) throw new TypeError("SQLite method requires a Transaction receiver"); return state; }
|
|
60
|
-
function __velarSqliteParams(value = []) { if (!Array.isArray(value) || value.length > 10000) throw new TypeError("SQLite parameters must be a bounded List"); return value; }
|
|
61
|
-
function __velarSqliteRequest(state, message) { if (state.closed) return Promise.reject(new SqliteError("SQLite database is closed")); if (state.pending.size >= state.options.queueCapacity) return Promise.reject(new SqliteBackpressureError("SQLite queue capacity " + state.options.queueCapacity + " is full")); const id = state.nextId++; return new Promise((resolve, reject) => { state.pending.set(id, { resolve, reject }); state.worker.postMessage({ ...message, id }); }); }
|
|
62
|
-
function __velarSqliteRead(state, operation, sql, params, Type, transaction = 0, statement = 0) { if ((typeof Type !== "object" && typeof Type !== "function") || Type === null || typeof Type.parse !== "function") return Promise.reject(new TypeError("SQLite row validation requires a runtime Type")); return __velarSqliteRequest(state, { operation, sql, params: __velarSqliteParams(params), transaction, statement }).then(value => operation.endsWith("one") ? value === null ? null : Type.parse(value) : value.map(row => Type.parse(row))); }
|
|
63
|
-
const __velarSqliteDatabasePrototype = Object.freeze({
|
|
64
|
-
execute(sql, params = []) { return __velarSqliteRequest(__velarSqliteDatabase(this), { operation: "execute", sql, params: __velarSqliteParams(params), transaction: 0 }); },
|
|
65
|
-
one(sql, params, Type) { const state = __velarSqliteDatabase(this); return __velarSqliteRead(state, "one", sql, params, Type); }, all(sql, params, Type) { const state = __velarSqliteDatabase(this); return __velarSqliteRead(state, "all", sql, params, Type); },
|
|
66
|
-
async prepare(sql) { const state = __velarSqliteDatabase(this); const id = await __velarSqliteRequest(state, { operation: "prepare", sql, transaction: 0 }); return __velarSqliteMakeStatement(state, id, 0); },
|
|
67
|
-
async transaction() { const state = __velarSqliteDatabase(this); const transaction = state.nextTransaction++; await __velarSqliteRequest(state, { operation: "transaction", transaction: 0, transactionId: transaction }); return __velarSqliteMakeTransaction(state, transaction); },
|
|
68
|
-
async close() { const state = __velarSqliteDatabase(this); if (state.closed) return null; await __velarSqliteRequest(state, { operation: "close", transaction: 0 }); state.closed = true; await state.worker.terminate(); return null; },
|
|
69
|
-
});
|
|
70
|
-
const __velarSqliteStatementPrototype = Object.freeze({
|
|
71
|
-
execute(params = []) { const item = __velarSqliteStatement(this); return __velarSqliteRequest(item.database, { operation: "statement.execute", statement: item.id, params: __velarSqliteParams(params), transaction: item.transaction }); },
|
|
72
|
-
one(params, Type) { const item = __velarSqliteStatement(this); return __velarSqliteRead(item.database, "statement.one", null, params, Type, item.transaction, item.id); }, all(params, Type) { const item = __velarSqliteStatement(this); return __velarSqliteRead(item.database, "statement.all", null, params, Type, item.transaction, item.id); },
|
|
73
|
-
async close() { const item = __velarSqliteStatement(this); if (item.closed) return null; await __velarSqliteRequest(item.database, { operation: "statement.close", statement: item.id, transaction: item.transaction }); item.closed = true; if (item.owner) item.owner.statements.delete(item); return null; },
|
|
74
|
-
});
|
|
75
|
-
async function __velarSqliteCloseTransactionStatements(item) { for (const statement of [...item.statements]) { if (statement.closed) continue; await __velarSqliteRequest(item.database, { operation: "statement.close", statement: statement.id, transaction: item.id }); statement.closed = true; } item.statements.clear(); }
|
|
76
|
-
const __velarSqliteTransactionPrototype = Object.freeze({
|
|
77
|
-
execute(sql, params = []) { const item = __velarSqliteTransaction(this); return __velarSqliteRequest(item.database, { operation: "execute", sql, params: __velarSqliteParams(params), transaction: item.id }); },
|
|
78
|
-
one(sql, params, Type) { const item = __velarSqliteTransaction(this); return __velarSqliteRead(item.database, "one", sql, params, Type, item.id); }, all(sql, params, Type) { const item = __velarSqliteTransaction(this); return __velarSqliteRead(item.database, "all", sql, params, Type, item.id); },
|
|
79
|
-
async prepare(sql) { const item = __velarSqliteTransaction(this); if (!item.active) throw new SqliteError("SQLite transaction is no longer active"); const id = await __velarSqliteRequest(item.database, { operation: "prepare", sql, transaction: item.id }); return __velarSqliteMakeStatement(item.database, id, item.id, item); },
|
|
80
|
-
async commit() { const item = __velarSqliteTransaction(this); if (!item.active) throw new SqliteError("SQLite transaction is no longer active"); await __velarSqliteCloseTransactionStatements(item); await __velarSqliteRequest(item.database, { operation: "commit", transaction: item.id }); item.active = false; return null; },
|
|
81
|
-
async rollback() { const item = __velarSqliteTransaction(this); if (!item.active) return null; await __velarSqliteCloseTransactionStatements(item); await __velarSqliteRequest(item.database, { operation: "rollback", transaction: item.id }); item.active = false; return null; },
|
|
82
|
-
async close() { return this.rollback(); },
|
|
83
|
-
});
|
|
84
|
-
function __velarSqliteMakeStatement(database, id, transaction, owner = null) { const value = Object.create(__velarSqliteStatementPrototype); const state = { database, id, transaction, owner, closed: false }; __velarSqliteStatements.set(value, state); if (owner) owner.statements.add(state); return Object.freeze(value); }
|
|
85
|
-
function __velarSqliteMakeTransaction(database, id) { const value = Object.create(__velarSqliteTransactionPrototype); __velarSqliteTransactions.set(value, { database, id, active: true, statements: new Set() }); return Object.freeze(value); }
|
|
86
|
-
const __velarSqliteDatabaseType = Object.freeze({ is(value) { return __velarSqliteDatabases.has(value); }, parse(value) { if (!this.is(value)) throw new TypeError("Value does not match Database"); return value; } });
|
|
87
|
-
const __velarSqliteStatementType = Object.freeze({ is(value) { return __velarSqliteStatements.has(value); }, parse(value) { if (!this.is(value)) throw new TypeError("Value does not match Statement"); return value; } });
|
|
88
|
-
const __velarSqliteTransactionType = Object.freeze({ is(value) { return __velarSqliteTransactions.has(value); }, parse(value) { if (!this.is(value)) throw new TypeError("Value does not match Transaction"); return value; } });
|
|
89
|
-
export const Database = __velarSqliteDatabaseType; export const Statement = __velarSqliteStatementType; export const Transaction = __velarSqliteTransactionType;
|
|
90
|
-
export function open(path, options = {}) { if (typeof path !== "string" || path.length === 0 || path.includes("\0")) return Promise.reject(new TypeError("SQLite path must be non-empty text without NUL")); const checked = __velarSqliteOptions(options); return new Promise((resolve, reject) => { const worker = new __VelarSqliteWorker(WORKER_SOURCE, { eval: true, workerData: { path, ...checked } }); const value = Object.create(__velarSqliteDatabasePrototype); const state = { worker, options: checked, pending: new Map(), nextId: 1, nextTransaction: 1, closed: false }; __velarSqliteDatabases.set(value, state); worker.on("message", message => { if (message?.ready) { resolve(Object.freeze(value)); return; } const pending = state.pending.get(message?.id); if (!pending) return; state.pending.delete(message.id); if (message.ok) pending.resolve(message.value); else pending.reject(new SqliteError(message.error?.message ?? "SQLite operation failed", message.error?.code ?? null)); }); worker.on("error", error => { state.closed = true; for (const pending of state.pending.values()) pending.reject(new SqliteError(error.message)); state.pending.clear(); reject(error); }); worker.on("exit", code => { if (!state.closed && code !== 0) { state.closed = true; for (const pending of state.pending.values()) pending.reject(new SqliteError("SQLite worker exited with code " + code)); state.pending.clear(); } }); }); }
|
|
91
|
-
`.trimStart();
|
|
92
|
-
//# sourceMappingURL=sqlite-runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite-runtime.js","sourceRoot":"","sources":["../src/sqlite-runtime.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,+BAA+B,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CxD,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ClD,CAAC,SAAS,EAAE,CAAC"}
|