@rivetkit/rivetkit-native 0.0.0-pr.4657.155d8c3 → 0.0.0-pr.4662.be7407a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +1 -6
- package/package.json +9 -9
- package/wrapper.d.ts +14 -1
- package/wrapper.js +143 -71
package/index.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export interface QueryResult {
|
|
|
18
18
|
rows: Array<Array<any>>
|
|
19
19
|
}
|
|
20
20
|
/** Open a native SQLite database backed by the envoy's KV channel. */
|
|
21
|
-
export declare function openDatabaseFromEnvoy(jsHandle: JsEnvoyHandle, actorId: string
|
|
21
|
+
export declare function openDatabaseFromEnvoy(jsHandle: JsEnvoyHandle, actorId: string): Promise<JsNativeDatabase>
|
|
22
22
|
/** Configuration for starting the native envoy client. */
|
|
23
23
|
export interface JsEnvoyConfig {
|
|
24
24
|
endpoint: string
|
|
@@ -48,10 +48,6 @@ export interface JsKvEntry {
|
|
|
48
48
|
export interface HibernatingRequestEntry {
|
|
49
49
|
gatewayId: Buffer
|
|
50
50
|
requestId: Buffer
|
|
51
|
-
envoyMessageIndex: number
|
|
52
|
-
rivetMessageIndex: number
|
|
53
|
-
path: string
|
|
54
|
-
headers?: Record<string, string>
|
|
55
51
|
}
|
|
56
52
|
/**
|
|
57
53
|
* Start the native envoy client synchronously.
|
|
@@ -64,7 +60,6 @@ export declare function startEnvoySyncJs(config: JsEnvoyConfig, eventCallback: (
|
|
|
64
60
|
export declare function startEnvoyJs(config: JsEnvoyConfig, eventCallback: (event: any) => void): JsEnvoyHandle
|
|
65
61
|
/** Native SQLite database handle exposed to JavaScript. */
|
|
66
62
|
export declare class JsNativeDatabase {
|
|
67
|
-
takeLastKvError(): string | null
|
|
68
63
|
run(sql: string, params?: Array<JsBindParam> | undefined | null): Promise<ExecuteResult>
|
|
69
64
|
query(sql: string, params?: Array<JsBindParam> | undefined | null): Promise<QueryResult>
|
|
70
65
|
exec(sql: string): Promise<QueryResult>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rivetkit/rivetkit-native",
|
|
3
|
-
"version": "0.0.0-pr.
|
|
3
|
+
"version": "0.0.0-pr.4662.be7407a",
|
|
4
4
|
"description": "Native N-API addon for RivetKit providing envoy client and SQLite access",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "index.js",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
51
|
"@napi-rs/cli": "^2.18.4",
|
|
52
|
-
"@rivetkit/engine-envoy-protocol": "0.0.0-pr.
|
|
52
|
+
"@rivetkit/engine-envoy-protocol": "0.0.0-pr.4662.be7407a"
|
|
53
53
|
},
|
|
54
54
|
"optionalDependencies": {
|
|
55
|
-
"@rivetkit/rivetkit-native-darwin-arm64": "0.0.0-pr.
|
|
56
|
-
"@rivetkit/rivetkit-native-darwin-x64": "0.0.0-pr.
|
|
57
|
-
"@rivetkit/rivetkit-native-linux-arm64-gnu": "0.0.0-pr.
|
|
58
|
-
"@rivetkit/rivetkit-native-linux-arm64-musl": "0.0.0-pr.
|
|
59
|
-
"@rivetkit/rivetkit-native-linux-x64-gnu": "0.0.0-pr.
|
|
60
|
-
"@rivetkit/rivetkit-native-linux-x64-musl": "0.0.0-pr.
|
|
61
|
-
"@rivetkit/rivetkit-native-win32-x64-msvc": "0.0.0-pr.
|
|
55
|
+
"@rivetkit/rivetkit-native-darwin-arm64": "0.0.0-pr.4662.be7407a",
|
|
56
|
+
"@rivetkit/rivetkit-native-darwin-x64": "0.0.0-pr.4662.be7407a",
|
|
57
|
+
"@rivetkit/rivetkit-native-linux-arm64-gnu": "0.0.0-pr.4662.be7407a",
|
|
58
|
+
"@rivetkit/rivetkit-native-linux-arm64-musl": "0.0.0-pr.4662.be7407a",
|
|
59
|
+
"@rivetkit/rivetkit-native-linux-x64-gnu": "0.0.0-pr.4662.be7407a",
|
|
60
|
+
"@rivetkit/rivetkit-native-linux-x64-musl": "0.0.0-pr.4662.be7407a",
|
|
61
|
+
"@rivetkit/rivetkit-native-win32-x64-msvc": "0.0.0-pr.4662.be7407a"
|
|
62
62
|
}
|
|
63
63
|
}
|
package/wrapper.d.ts
CHANGED
|
@@ -126,6 +126,19 @@ export declare function startEnvoy(config: EnvoyConfig): Promise<EnvoyHandle>;
|
|
|
126
126
|
export declare function openDatabaseFromEnvoy(
|
|
127
127
|
handle: EnvoyHandle,
|
|
128
128
|
actorId: string,
|
|
129
|
-
preloadedEntries?: readonly [Uint8Array, Uint8Array][] | null,
|
|
130
129
|
): Promise<JsNativeDatabase>;
|
|
130
|
+
|
|
131
|
+
export interface NativeRawDatabase {
|
|
132
|
+
execute: <TRow extends Record<string, unknown> = Record<string, unknown>>(
|
|
133
|
+
query: string,
|
|
134
|
+
...args: unknown[]
|
|
135
|
+
) => Promise<TRow[]>;
|
|
136
|
+
close: () => Promise<void>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export declare function openRawDatabaseFromEnvoy(
|
|
140
|
+
handle: EnvoyHandle,
|
|
141
|
+
actorId: string,
|
|
142
|
+
): Promise<NativeRawDatabase>;
|
|
143
|
+
|
|
131
144
|
export declare const utils: {};
|
package/wrapper.js
CHANGED
|
@@ -98,10 +98,6 @@ function wrapHandle(jsHandle) {
|
|
|
98
98
|
const requests = (metaEntries || []).map((e) => ({
|
|
99
99
|
gatewayId: Buffer.from(e.gatewayId),
|
|
100
100
|
requestId: Buffer.from(e.requestId),
|
|
101
|
-
envoyMessageIndex: e.envoyMessageIndex ?? 0,
|
|
102
|
-
rivetMessageIndex: e.rivetMessageIndex ?? 0,
|
|
103
|
-
path: e.path ?? "",
|
|
104
|
-
headers: e.headers ?? {},
|
|
105
101
|
}));
|
|
106
102
|
jsHandle.restoreHibernatingRequests(actorId, requests);
|
|
107
103
|
},
|
|
@@ -138,7 +134,7 @@ function startEnvoySync(config) {
|
|
|
138
134
|
poolName: config.poolName,
|
|
139
135
|
version: config.version,
|
|
140
136
|
metadata: config.metadata || null,
|
|
141
|
-
notGlobal: config.notGlobal
|
|
137
|
+
notGlobal: config.notGlobal,
|
|
142
138
|
},
|
|
143
139
|
(event) => {
|
|
144
140
|
handleEvent(event, config, wrappedHandle);
|
|
@@ -162,39 +158,154 @@ async function startEnvoy(config) {
|
|
|
162
158
|
/**
|
|
163
159
|
* Open a native database backed by envoy KV.
|
|
164
160
|
*/
|
|
165
|
-
async function openDatabaseFromEnvoy(handle, actorId
|
|
161
|
+
async function openDatabaseFromEnvoy(handle, actorId) {
|
|
166
162
|
const rawHandle = handle._raw || handle;
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
nativePreloadedEntries,
|
|
163
|
+
return native.openDatabaseFromEnvoy(rawHandle, actorId);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function isPlainObject(value) {
|
|
167
|
+
return (
|
|
168
|
+
!!value &&
|
|
169
|
+
typeof value === "object" &&
|
|
170
|
+
!Array.isArray(value) &&
|
|
171
|
+
Object.getPrototypeOf(value) === Object.prototype
|
|
177
172
|
);
|
|
178
173
|
}
|
|
179
174
|
|
|
180
|
-
function
|
|
181
|
-
if (
|
|
182
|
-
return null;
|
|
175
|
+
function toNativeBinding(value) {
|
|
176
|
+
if (value === null || value === undefined) {
|
|
177
|
+
return { kind: "null" };
|
|
178
|
+
}
|
|
179
|
+
if (typeof value === "bigint") {
|
|
180
|
+
return { kind: "int", intValue: Number(value) };
|
|
181
|
+
}
|
|
182
|
+
if (typeof value === "number") {
|
|
183
|
+
return Number.isInteger(value)
|
|
184
|
+
? { kind: "int", intValue: value }
|
|
185
|
+
: { kind: "float", floatValue: value };
|
|
186
|
+
}
|
|
187
|
+
if (typeof value === "string") {
|
|
188
|
+
return { kind: "text", textValue: value };
|
|
189
|
+
}
|
|
190
|
+
if (value instanceof ArrayBuffer) {
|
|
191
|
+
return { kind: "blob", blobValue: Buffer.from(value) };
|
|
192
|
+
}
|
|
193
|
+
if (ArrayBuffer.isView(value)) {
|
|
194
|
+
return {
|
|
195
|
+
kind: "blob",
|
|
196
|
+
blobValue: Buffer.from(value.buffer, value.byteOffset, value.byteLength),
|
|
197
|
+
};
|
|
183
198
|
}
|
|
184
199
|
|
|
185
|
-
|
|
200
|
+
throw new Error(`unsupported sqlite binding type: ${typeof value}`);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function extractNamedSqliteParameters(sql) {
|
|
204
|
+
return [...sql.matchAll(/([:@$][A-Za-z_][A-Za-z0-9_]*)/g)].map(
|
|
205
|
+
(match) => match[1],
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function getNamedSqliteBinding(bindings, name) {
|
|
210
|
+
if (name in bindings) {
|
|
211
|
+
return bindings[name];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const bareName = name.slice(1);
|
|
215
|
+
if (bareName in bindings) {
|
|
216
|
+
return bindings[bareName];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
for (const prefix of [":", "@", "$"]) {
|
|
220
|
+
const candidate = `${prefix}${bareName}`;
|
|
221
|
+
if (candidate in bindings) {
|
|
222
|
+
return bindings[candidate];
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function normalizeBindings(sql, args) {
|
|
230
|
+
if (!args || args.length === 0) {
|
|
231
|
+
return [];
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (
|
|
235
|
+
args.length === 1 &&
|
|
236
|
+
isPlainObject(args[0]) &&
|
|
237
|
+
!(args[0] instanceof Uint8Array)
|
|
238
|
+
) {
|
|
239
|
+
const names = extractNamedSqliteParameters(sql);
|
|
240
|
+
if (names.length === 0) {
|
|
241
|
+
throw new Error(
|
|
242
|
+
"native sqlite object bindings require named placeholders in the SQL statement",
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
return names.map((name) => {
|
|
246
|
+
const value = getNamedSqliteBinding(args[0], name);
|
|
247
|
+
if (value === undefined) {
|
|
248
|
+
throw new Error(`missing bind parameter: ${name}`);
|
|
249
|
+
}
|
|
250
|
+
return toNativeBinding(value);
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return args.map(toNativeBinding);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
function mapRows(rows, columns) {
|
|
258
|
+
return rows.map((row) => {
|
|
259
|
+
const rowObject = {};
|
|
260
|
+
for (let i = 0; i < columns.length; i++) {
|
|
261
|
+
rowObject[columns[i]] = row[i];
|
|
262
|
+
}
|
|
263
|
+
return rowObject;
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async function openRawDatabaseFromEnvoy(handle, actorId) {
|
|
268
|
+
const nativeDb = await openDatabaseFromEnvoy(handle, actorId);
|
|
269
|
+
let closed = false;
|
|
270
|
+
|
|
271
|
+
const ensureOpen = () => {
|
|
272
|
+
if (closed) {
|
|
273
|
+
throw new Error("database is closed");
|
|
274
|
+
}
|
|
275
|
+
};
|
|
186
276
|
|
|
187
277
|
return {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
278
|
+
execute: async (query, ...args) => {
|
|
279
|
+
ensureOpen();
|
|
280
|
+
|
|
281
|
+
if (args.length > 0) {
|
|
282
|
+
const bindings = normalizeBindings(query, args);
|
|
283
|
+
const token = query.trimStart().slice(0, 16).toUpperCase();
|
|
284
|
+
const returnsRows =
|
|
285
|
+
token.startsWith("SELECT") ||
|
|
286
|
+
token.startsWith("PRAGMA") ||
|
|
287
|
+
token.startsWith("WITH") ||
|
|
288
|
+
/\bRETURNING\b/i.test(query);
|
|
289
|
+
|
|
290
|
+
if (returnsRows) {
|
|
291
|
+
const result = await nativeDb.query(query, bindings);
|
|
292
|
+
return mapRows(result.rows, result.columns);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
await nativeDb.run(query, bindings);
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
const result = await nativeDb.exec(query);
|
|
300
|
+
return mapRows(result.rows, result.columns);
|
|
301
|
+
},
|
|
302
|
+
close: async () => {
|
|
303
|
+
if (closed) {
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
closed = true;
|
|
307
|
+
await nativeDb.close();
|
|
308
|
+
},
|
|
198
309
|
};
|
|
199
310
|
}
|
|
200
311
|
|
|
@@ -219,7 +330,7 @@ function handleEvent(event, config, wrappedHandle) {
|
|
|
219
330
|
event.actorId,
|
|
220
331
|
event.generation,
|
|
221
332
|
actorConfig,
|
|
222
|
-
|
|
333
|
+
null, // preloadedKv
|
|
223
334
|
),
|
|
224
335
|
).then(
|
|
225
336
|
async () => {
|
|
@@ -312,46 +423,6 @@ function handleEvent(event, config, wrappedHandle) {
|
|
|
312
423
|
);
|
|
313
424
|
break;
|
|
314
425
|
}
|
|
315
|
-
case "websocket_can_hibernate": {
|
|
316
|
-
const gatewayId = Buffer.from(event.gatewayId);
|
|
317
|
-
const requestId = Buffer.from(event.requestId);
|
|
318
|
-
const headers = new Headers(event.headers || {});
|
|
319
|
-
headers.set("Upgrade", "websocket");
|
|
320
|
-
headers.set("Connection", "Upgrade");
|
|
321
|
-
const request = new Request(`http://actor${event.path}`, {
|
|
322
|
-
method: event.method,
|
|
323
|
-
headers,
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
Promise.resolve(
|
|
327
|
-
config.hibernatableWebSocket
|
|
328
|
-
? config.hibernatableWebSocket.canHibernate(
|
|
329
|
-
event.actorId,
|
|
330
|
-
gatewayId,
|
|
331
|
-
requestId,
|
|
332
|
-
request,
|
|
333
|
-
)
|
|
334
|
-
: false,
|
|
335
|
-
).then(
|
|
336
|
-
async (canHibernate) => {
|
|
337
|
-
if (handle._raw) {
|
|
338
|
-
await handle._raw.respondCallback(event.responseId, {
|
|
339
|
-
canHibernate: Boolean(canHibernate),
|
|
340
|
-
});
|
|
341
|
-
}
|
|
342
|
-
},
|
|
343
|
-
async (err) => {
|
|
344
|
-
console.error("canHibernate error:", err);
|
|
345
|
-
if (handle._raw) {
|
|
346
|
-
await handle._raw.respondCallback(event.responseId, {
|
|
347
|
-
canHibernate: false,
|
|
348
|
-
error: String(err),
|
|
349
|
-
});
|
|
350
|
-
}
|
|
351
|
-
},
|
|
352
|
-
);
|
|
353
|
-
break;
|
|
354
|
-
}
|
|
355
426
|
case "websocket_open": {
|
|
356
427
|
if (config.websocket) {
|
|
357
428
|
const messageId = Buffer.from(event.messageId);
|
|
@@ -503,3 +574,4 @@ function handleEvent(event, config, wrappedHandle) {
|
|
|
503
574
|
module.exports.startEnvoy = startEnvoy;
|
|
504
575
|
module.exports.startEnvoySync = startEnvoySync;
|
|
505
576
|
module.exports.openDatabaseFromEnvoy = openDatabaseFromEnvoy;
|
|
577
|
+
module.exports.openRawDatabaseFromEnvoy = openRawDatabaseFromEnvoy;
|