@rivetkit/rivetkit-native 0.0.0-pr.4651.b85b389 → 0.0.0-pr.4653.7179278

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 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): Promise<JsNativeDatabase>
21
+ export declare function openDatabaseFromEnvoy(jsHandle: JsEnvoyHandle, actorId: string, preloadedEntries?: Array<JsKvEntry> | undefined | null): Promise<JsNativeDatabase>
22
22
  /** Configuration for starting the native envoy client. */
23
23
  export interface JsEnvoyConfig {
24
24
  endpoint: string
@@ -27,6 +27,7 @@ export interface JsEnvoyConfig {
27
27
  poolName: string
28
28
  version: number
29
29
  metadata?: any
30
+ notGlobal: boolean
30
31
  /**
31
32
  * Log level for the Rust tracing subscriber (e.g. "trace", "debug", "info", "warn", "error").
32
33
  * Falls back to RIVET_LOG_LEVEL, then LOG_LEVEL, then RUST_LOG env vars. Defaults to "warn".
@@ -47,6 +48,10 @@ export interface JsKvEntry {
47
48
  export interface HibernatingRequestEntry {
48
49
  gatewayId: Buffer
49
50
  requestId: Buffer
51
+ envoyMessageIndex: number
52
+ rivetMessageIndex: number
53
+ path: string
54
+ headers?: Record<string, string>
50
55
  }
51
56
  /**
52
57
  * Start the native envoy client synchronously.
@@ -59,6 +64,7 @@ export declare function startEnvoySyncJs(config: JsEnvoyConfig, eventCallback: (
59
64
  export declare function startEnvoyJs(config: JsEnvoyConfig, eventCallback: (event: any) => void): JsEnvoyHandle
60
65
  /** Native SQLite database handle exposed to JavaScript. */
61
66
  export declare class JsNativeDatabase {
67
+ takeLastKvError(): string | null
62
68
  run(sql: string, params?: Array<JsBindParam> | undefined | null): Promise<ExecuteResult>
63
69
  query(sql: string, params?: Array<JsBindParam> | undefined | null): Promise<QueryResult>
64
70
  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.4651.b85b389",
3
+ "version": "0.0.0-pr.4653.7179278",
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.4651.b85b389"
52
+ "@rivetkit/engine-envoy-protocol": "0.0.0-pr.4653.7179278"
53
53
  },
54
54
  "optionalDependencies": {
55
- "@rivetkit/rivetkit-native-darwin-arm64": "0.0.0-pr.4651.b85b389",
56
- "@rivetkit/rivetkit-native-darwin-x64": "0.0.0-pr.4651.b85b389",
57
- "@rivetkit/rivetkit-native-linux-arm64-gnu": "0.0.0-pr.4651.b85b389",
58
- "@rivetkit/rivetkit-native-linux-arm64-musl": "0.0.0-pr.4651.b85b389",
59
- "@rivetkit/rivetkit-native-linux-x64-gnu": "0.0.0-pr.4651.b85b389",
60
- "@rivetkit/rivetkit-native-linux-x64-musl": "0.0.0-pr.4651.b85b389",
61
- "@rivetkit/rivetkit-native-win32-x64-msvc": "0.0.0-pr.4651.b85b389"
55
+ "@rivetkit/rivetkit-native-darwin-arm64": "0.0.0-pr.4653.7179278",
56
+ "@rivetkit/rivetkit-native-darwin-x64": "0.0.0-pr.4653.7179278",
57
+ "@rivetkit/rivetkit-native-linux-arm64-gnu": "0.0.0-pr.4653.7179278",
58
+ "@rivetkit/rivetkit-native-linux-arm64-musl": "0.0.0-pr.4653.7179278",
59
+ "@rivetkit/rivetkit-native-linux-x64-gnu": "0.0.0-pr.4653.7179278",
60
+ "@rivetkit/rivetkit-native-linux-x64-musl": "0.0.0-pr.4653.7179278",
61
+ "@rivetkit/rivetkit-native-win32-x64-msvc": "0.0.0-pr.4653.7179278"
62
62
  }
63
63
  }
package/wrapper.d.ts CHANGED
@@ -126,19 +126,6 @@ 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,
129
130
  ): 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
-
144
131
  export declare const utils: {};
package/wrapper.js CHANGED
@@ -98,6 +98,10 @@ 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 ?? {},
101
105
  }));
102
106
  jsHandle.restoreHibernatingRequests(actorId, requests);
103
107
  },
@@ -134,7 +138,7 @@ function startEnvoySync(config) {
134
138
  poolName: config.poolName,
135
139
  version: config.version,
136
140
  metadata: config.metadata || null,
137
- notGlobal: config.notGlobal,
141
+ notGlobal: config.notGlobal ?? false,
138
142
  },
139
143
  (event) => {
140
144
  handleEvent(event, config, wrappedHandle);
@@ -158,154 +162,39 @@ async function startEnvoy(config) {
158
162
  /**
159
163
  * Open a native database backed by envoy KV.
160
164
  */
161
- async function openDatabaseFromEnvoy(handle, actorId) {
165
+ async function openDatabaseFromEnvoy(handle, actorId, preloadedEntries) {
162
166
  const rawHandle = handle._raw || handle;
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
167
+ const nativePreloadedEntries = preloadedEntries
168
+ ? preloadedEntries.map(([key, value]) => ({
169
+ key: Buffer.from(key),
170
+ value: Buffer.from(value),
171
+ }))
172
+ : null;
173
+ return native.openDatabaseFromEnvoy(
174
+ rawHandle,
175
+ actorId,
176
+ nativePreloadedEntries,
172
177
  );
173
178
  }
174
179
 
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
- };
180
+ function decodePreloadedKv(preloadedKv) {
181
+ if (!preloadedKv) {
182
+ return null;
198
183
  }
199
184
 
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
- };
185
+ const decodeBytes = (value) => Uint8Array.from(Buffer.from(value, "base64"));
276
186
 
277
187
  return {
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
- },
188
+ entries: (preloadedKv.entries || []).map((entry) => ({
189
+ key: decodeBytes(entry.key),
190
+ value: decodeBytes(entry.value),
191
+ metadata: {
192
+ version: decodeBytes(entry.metadata.version),
193
+ updateTs: entry.metadata.updateTs,
194
+ },
195
+ })),
196
+ requestedGetKeys: (preloadedKv.requestedGetKeys || []).map(decodeBytes),
197
+ requestedPrefixes: (preloadedKv.requestedPrefixes || []).map(decodeBytes),
309
198
  };
310
199
  }
311
200
 
@@ -330,7 +219,7 @@ function handleEvent(event, config, wrappedHandle) {
330
219
  event.actorId,
331
220
  event.generation,
332
221
  actorConfig,
333
- null, // preloadedKv
222
+ decodePreloadedKv(event.preloadedKv),
334
223
  ),
335
224
  ).then(
336
225
  async () => {
@@ -423,6 +312,46 @@ function handleEvent(event, config, wrappedHandle) {
423
312
  );
424
313
  break;
425
314
  }
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
+ }
426
355
  case "websocket_open": {
427
356
  if (config.websocket) {
428
357
  const messageId = Buffer.from(event.messageId);
@@ -574,4 +503,3 @@ function handleEvent(event, config, wrappedHandle) {
574
503
  module.exports.startEnvoy = startEnvoy;
575
504
  module.exports.startEnvoySync = startEnvoySync;
576
505
  module.exports.openDatabaseFromEnvoy = openDatabaseFromEnvoy;
577
- module.exports.openRawDatabaseFromEnvoy = openRawDatabaseFromEnvoy;