@meshagent/meshagent 0.29.4 → 0.30.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/browser/agent-client.js +3 -28
  3. package/dist/browser/agent.js +6 -6
  4. package/dist/browser/containers-client.d.ts +125 -0
  5. package/dist/browser/containers-client.js +458 -0
  6. package/dist/browser/database-client.d.ts +42 -6
  7. package/dist/browser/database-client.js +610 -77
  8. package/dist/browser/developer-client.d.ts +2 -2
  9. package/dist/browser/developer-client.js +60 -15
  10. package/dist/browser/helpers.js +4 -3
  11. package/dist/browser/index.d.ts +1 -0
  12. package/dist/browser/index.js +1 -0
  13. package/dist/browser/lk-client.js +12 -3
  14. package/dist/browser/meshagent-client.d.ts +5 -0
  15. package/dist/browser/messaging-client.d.ts +1 -0
  16. package/dist/browser/messaging-client.js +52 -8
  17. package/dist/browser/queues-client.d.ts +2 -0
  18. package/dist/browser/queues-client.js +34 -7
  19. package/dist/browser/response.d.ts +28 -0
  20. package/dist/browser/response.js +76 -1
  21. package/dist/browser/room-client.d.ts +43 -1
  22. package/dist/browser/room-client.js +204 -0
  23. package/dist/browser/secrets-client.d.ts +1 -0
  24. package/dist/browser/secrets-client.js +32 -27
  25. package/dist/browser/storage-client.d.ts +22 -7
  26. package/dist/browser/storage-client.js +353 -15
  27. package/dist/browser/sync-client.d.ts +12 -13
  28. package/dist/browser/sync-client.js +263 -65
  29. package/dist/esm/agent-client.js +3 -28
  30. package/dist/esm/agent.js +6 -6
  31. package/dist/esm/containers-client.d.ts +125 -0
  32. package/dist/esm/containers-client.js +453 -0
  33. package/dist/esm/database-client.d.ts +42 -6
  34. package/dist/esm/database-client.js +611 -78
  35. package/dist/esm/developer-client.d.ts +2 -2
  36. package/dist/esm/developer-client.js +61 -16
  37. package/dist/esm/helpers.js +4 -3
  38. package/dist/esm/index.d.ts +1 -0
  39. package/dist/esm/index.js +1 -0
  40. package/dist/esm/lk-client.js +12 -3
  41. package/dist/esm/meshagent-client.d.ts +5 -0
  42. package/dist/esm/messaging-client.d.ts +1 -0
  43. package/dist/esm/messaging-client.js +52 -8
  44. package/dist/esm/queues-client.d.ts +2 -0
  45. package/dist/esm/queues-client.js +35 -8
  46. package/dist/esm/response.d.ts +28 -0
  47. package/dist/esm/response.js +73 -0
  48. package/dist/esm/room-client.d.ts +43 -1
  49. package/dist/esm/room-client.js +207 -3
  50. package/dist/esm/secrets-client.d.ts +1 -0
  51. package/dist/esm/secrets-client.js +33 -28
  52. package/dist/esm/storage-client.d.ts +22 -7
  53. package/dist/esm/storage-client.js +353 -15
  54. package/dist/esm/sync-client.d.ts +12 -13
  55. package/dist/esm/sync-client.js +263 -64
  56. package/dist/node/agent-client.js +3 -28
  57. package/dist/node/agent.js +6 -6
  58. package/dist/node/containers-client.d.ts +125 -0
  59. package/dist/node/containers-client.js +458 -0
  60. package/dist/node/database-client.d.ts +42 -6
  61. package/dist/node/database-client.js +610 -77
  62. package/dist/node/developer-client.d.ts +2 -2
  63. package/dist/node/developer-client.js +60 -15
  64. package/dist/node/helpers.js +4 -3
  65. package/dist/node/index.d.ts +1 -0
  66. package/dist/node/index.js +1 -0
  67. package/dist/node/lk-client.js +12 -3
  68. package/dist/node/meshagent-client.d.ts +5 -0
  69. package/dist/node/messaging-client.d.ts +1 -0
  70. package/dist/node/messaging-client.js +52 -8
  71. package/dist/node/queues-client.d.ts +2 -0
  72. package/dist/node/queues-client.js +34 -7
  73. package/dist/node/response.d.ts +28 -0
  74. package/dist/node/response.js +76 -1
  75. package/dist/node/room-client.d.ts +43 -1
  76. package/dist/node/room-client.js +204 -0
  77. package/dist/node/secrets-client.d.ts +1 -0
  78. package/dist/node/secrets-client.js +32 -27
  79. package/dist/node/storage-client.d.ts +22 -7
  80. package/dist/node/storage-client.js +353 -15
  81. package/dist/node/sync-client.d.ts +12 -13
  82. package/dist/node/sync-client.js +263 -65
  83. package/package.json +1 -1
@@ -1,123 +1,656 @@
1
- import { JsonContent } from "./response";
1
+ import { DataType } from "./data-types";
2
+ import { RoomServerException } from "./room-server-client";
3
+ import { ControlContent, ErrorContent, JsonContent } from "./response";
4
+ const globalScope = globalThis;
5
+ function bytesToBase64(bytes) {
6
+ if (globalScope.Buffer) {
7
+ return globalScope.Buffer.from(bytes).toString("base64");
8
+ }
9
+ if (!globalScope.btoa) {
10
+ throw new Error("base64 encoding is not available in this runtime");
11
+ }
12
+ let binary = "";
13
+ for (const byte of bytes) {
14
+ binary += String.fromCharCode(byte);
15
+ }
16
+ return globalScope.btoa(binary);
17
+ }
18
+ function base64ToBytes(base64) {
19
+ if (globalScope.Buffer) {
20
+ return Uint8Array.from(globalScope.Buffer.from(base64, "base64"));
21
+ }
22
+ if (!globalScope.atob) {
23
+ throw new Error("base64 decoding is not available in this runtime");
24
+ }
25
+ const binary = globalScope.atob(base64);
26
+ const bytes = new Uint8Array(binary.length);
27
+ for (let index = 0; index < binary.length; index += 1) {
28
+ bytes[index] = binary.charCodeAt(index);
29
+ }
30
+ return bytes;
31
+ }
32
+ function isRecord(value) {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+ function metadataEntries(metadata) {
36
+ if (metadata == null) {
37
+ return null;
38
+ }
39
+ return Object.entries(metadata).map(([key, value]) => ({
40
+ key,
41
+ value: typeof value === "string" ? value : JSON.stringify(encodeLegacyValue(value)),
42
+ }));
43
+ }
44
+ function toolkitDataTypeJson(dataType) {
45
+ const json = dataType.toJson();
46
+ const payload = {
47
+ type: json.type,
48
+ nullable: json.nullable ?? null,
49
+ metadata: metadataEntries(json.metadata),
50
+ };
51
+ if (json.type === "vector" || json.type === "list") {
52
+ payload.element_type = toolkitDataTypeJson(DataType.fromJson(json.element_type));
53
+ }
54
+ else if (json.type === "struct") {
55
+ const fields = json.fields;
56
+ if (!Array.isArray(fields)) {
57
+ throw new RoomServerException("unexpected return type from database.inspect");
58
+ }
59
+ payload.fields = fields.map((field) => {
60
+ if (!isRecord(field) || typeof field.name !== "string" || !isRecord(field.data_type)) {
61
+ throw new RoomServerException("unexpected return type from database.inspect");
62
+ }
63
+ return {
64
+ name: field.name,
65
+ data_type: toolkitDataTypeJson(DataType.fromJson(field.data_type)),
66
+ };
67
+ });
68
+ }
69
+ if (json.type === "vector") {
70
+ payload.size = json.size;
71
+ }
72
+ return payload;
73
+ }
74
+ function schemaEntries(schema) {
75
+ if (schema == null) {
76
+ return null;
77
+ }
78
+ return Object.entries(schema).map(([name, dataType]) => ({
79
+ name,
80
+ data_type: toolkitDataTypeJson(dataType),
81
+ }));
82
+ }
83
+ function publicDataTypeJson(value) {
84
+ if (!isRecord(value)) {
85
+ throw new RoomServerException("unexpected return type from database.inspect");
86
+ }
87
+ const type = value.type;
88
+ if (typeof type !== "string") {
89
+ throw new RoomServerException("unexpected return type from database.inspect");
90
+ }
91
+ const metadataList = value.metadata;
92
+ let metadata;
93
+ if (metadataList != null) {
94
+ if (!Array.isArray(metadataList)) {
95
+ throw new RoomServerException("unexpected return type from database.inspect");
96
+ }
97
+ metadata = {};
98
+ for (const entry of metadataList) {
99
+ if (!isRecord(entry) || typeof entry.key !== "string" || typeof entry.value !== "string") {
100
+ throw new RoomServerException("unexpected return type from database.inspect");
101
+ }
102
+ metadata[entry.key] = entry.value;
103
+ }
104
+ }
105
+ const payload = {
106
+ type,
107
+ nullable: value.nullable,
108
+ metadata,
109
+ };
110
+ if (type === "vector") {
111
+ payload.size = value.size;
112
+ payload.element_type = publicDataTypeJson(value.element_type);
113
+ }
114
+ else if (type === "list") {
115
+ payload.element_type = publicDataTypeJson(value.element_type);
116
+ }
117
+ else if (type === "struct") {
118
+ const rawFields = value.fields;
119
+ if (!Array.isArray(rawFields)) {
120
+ throw new RoomServerException("unexpected return type from database.inspect");
121
+ }
122
+ payload.fields = Object.fromEntries(rawFields.map((field) => {
123
+ if (!isRecord(field) || typeof field.name !== "string") {
124
+ throw new RoomServerException("unexpected return type from database.inspect");
125
+ }
126
+ return [field.name, publicDataTypeJson(field.data_type)];
127
+ }));
128
+ }
129
+ return payload;
130
+ }
131
+ function encodeLegacyValue(value) {
132
+ if (value instanceof Uint8Array) {
133
+ return {
134
+ encoding: "base64",
135
+ data: bytesToBase64(value),
136
+ };
137
+ }
138
+ if (value instanceof Date) {
139
+ return value.toISOString().replace("+00:00", "Z");
140
+ }
141
+ if (Array.isArray(value)) {
142
+ return value.map((item) => encodeLegacyValue(item));
143
+ }
144
+ if (isRecord(value)) {
145
+ return Object.fromEntries(Object.entries(value).map(([key, entryValue]) => [key, encodeLegacyValue(entryValue)]));
146
+ }
147
+ return value;
148
+ }
149
+ function encodeStreamValue(value) {
150
+ if (value == null) {
151
+ return { type: "null" };
152
+ }
153
+ if (typeof value === "boolean") {
154
+ return { type: "bool", value };
155
+ }
156
+ if (typeof value === "number") {
157
+ if (Number.isInteger(value)) {
158
+ return { type: "int", value };
159
+ }
160
+ return { type: "float", value };
161
+ }
162
+ if (typeof value === "string") {
163
+ return { type: "text", value };
164
+ }
165
+ if (value instanceof Uint8Array) {
166
+ return {
167
+ type: "binary",
168
+ data: bytesToBase64(value),
169
+ };
170
+ }
171
+ if (value instanceof Date) {
172
+ return {
173
+ type: "timestamp",
174
+ value: value.toISOString().replace("+00:00", "Z"),
175
+ };
176
+ }
177
+ if (Array.isArray(value)) {
178
+ return {
179
+ type: "list",
180
+ items: value.map((item) => encodeStreamValue(item)),
181
+ };
182
+ }
183
+ if (isRecord(value)) {
184
+ return {
185
+ type: "struct",
186
+ fields: Object.entries(value).map(([name, fieldValue]) => ({
187
+ name,
188
+ value: encodeStreamValue(fieldValue),
189
+ })),
190
+ };
191
+ }
192
+ throw new RoomServerException(`database stream does not support value type ${typeof value}`);
193
+ }
194
+ function decodeStreamValue(value, operation) {
195
+ if (!isRecord(value) || typeof value.type !== "string") {
196
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
197
+ }
198
+ switch (value.type) {
199
+ case "null":
200
+ return null;
201
+ case "bool":
202
+ if (typeof value.value !== "boolean") {
203
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
204
+ }
205
+ return value.value;
206
+ case "int":
207
+ case "float":
208
+ if (typeof value.value !== "number") {
209
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
210
+ }
211
+ return value.value;
212
+ case "text":
213
+ case "date":
214
+ case "timestamp":
215
+ if (typeof value.value !== "string") {
216
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
217
+ }
218
+ return value.value;
219
+ case "binary":
220
+ if (typeof value.data !== "string") {
221
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
222
+ }
223
+ return base64ToBytes(value.data);
224
+ case "list":
225
+ if (!Array.isArray(value.items)) {
226
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
227
+ }
228
+ return value.items.map((item) => decodeStreamValue(item, operation));
229
+ case "struct":
230
+ if (!Array.isArray(value.fields)) {
231
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
232
+ }
233
+ return Object.fromEntries(value.fields.map((field) => {
234
+ if (!isRecord(field) || typeof field.name !== "string") {
235
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
236
+ }
237
+ return [field.name, decodeStreamValue(field.value, operation)];
238
+ }));
239
+ default:
240
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
241
+ }
242
+ }
243
+ function rowsChunk(records) {
244
+ return {
245
+ kind: "rows",
246
+ rows: records.map((record) => ({
247
+ columns: Object.entries(record).map(([name, value]) => ({
248
+ name,
249
+ value: encodeStreamValue(value),
250
+ })),
251
+ })),
252
+ };
253
+ }
254
+ function recordsFromRowsChunk(payload, operation) {
255
+ if (!isRecord(payload) || payload.kind !== "rows" || !Array.isArray(payload.rows)) {
256
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
257
+ }
258
+ return payload.rows.map((row) => {
259
+ if (!isRecord(row) || !Array.isArray(row.columns)) {
260
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
261
+ }
262
+ return Object.fromEntries(row.columns.map((column) => {
263
+ if (!isRecord(column) || typeof column.name !== "string") {
264
+ throw new RoomServerException(`unexpected return type from database.${operation}`);
265
+ }
266
+ return [column.name, decodeStreamValue(column.value, operation)];
267
+ }));
268
+ });
269
+ }
270
+ function rowChunkList(records, rowsPerChunk = 128) {
271
+ if (rowsPerChunk <= 0) {
272
+ throw new RoomServerException("rowsPerChunk must be greater than zero");
273
+ }
274
+ const chunks = [];
275
+ for (let index = 0; index < records.length; index += rowsPerChunk) {
276
+ chunks.push(records.slice(index, index + rowsPerChunk));
277
+ }
278
+ return chunks;
279
+ }
280
+ async function* toAsyncIterable(chunks) {
281
+ if (Symbol.asyncIterator in Object(chunks)) {
282
+ for await (const chunk of chunks) {
283
+ yield chunk;
284
+ }
285
+ return;
286
+ }
287
+ for (const chunk of chunks) {
288
+ yield chunk;
289
+ }
290
+ }
291
+ function buildWhereClause(where) {
292
+ if (where != null && typeof where === "object" && !Array.isArray(where)) {
293
+ return Object.entries(where)
294
+ .map(([key, value]) => `${key} = ${JSON.stringify(encodeLegacyValue(value))}`)
295
+ .join(" AND ");
296
+ }
297
+ if (typeof where === "string") {
298
+ return where;
299
+ }
300
+ return null;
301
+ }
302
+ class DatabaseWriteInputStream {
303
+ constructor(start, chunks) {
304
+ this.start = start;
305
+ this.pulls = [];
306
+ this.closed = false;
307
+ this.source = toAsyncIterable(chunks)[Symbol.asyncIterator]();
308
+ }
309
+ requestNext() {
310
+ if (this.closed) {
311
+ return;
312
+ }
313
+ const waiter = this.pulls.shift();
314
+ if (waiter) {
315
+ waiter();
316
+ return;
317
+ }
318
+ this.pulls.push(() => undefined);
319
+ }
320
+ close() {
321
+ if (this.closed) {
322
+ return;
323
+ }
324
+ this.closed = true;
325
+ while (this.pulls.length > 0) {
326
+ const waiter = this.pulls.shift();
327
+ waiter?.();
328
+ }
329
+ void this.source.return?.();
330
+ }
331
+ async waitForPull() {
332
+ if (this.closed) {
333
+ return;
334
+ }
335
+ const waiter = this.pulls.shift();
336
+ if (waiter) {
337
+ waiter();
338
+ return;
339
+ }
340
+ await new Promise((resolve) => {
341
+ this.pulls.push(resolve);
342
+ });
343
+ }
344
+ async *stream() {
345
+ yield new JsonContent({ json: this.start });
346
+ while (!this.closed) {
347
+ await this.waitForPull();
348
+ if (this.closed) {
349
+ return;
350
+ }
351
+ const nextChunk = await this.source.next();
352
+ if (nextChunk.done) {
353
+ return;
354
+ }
355
+ if (nextChunk.value.length === 0) {
356
+ continue;
357
+ }
358
+ yield new JsonContent({ json: rowsChunk(nextChunk.value) });
359
+ }
360
+ }
361
+ }
362
+ class DatabaseReadInputStream {
363
+ constructor(start) {
364
+ this.start = start;
365
+ this.pulls = [];
366
+ this.closed = false;
367
+ }
368
+ requestNext() {
369
+ if (this.closed) {
370
+ return;
371
+ }
372
+ const waiter = this.pulls.shift();
373
+ if (waiter) {
374
+ waiter();
375
+ return;
376
+ }
377
+ this.pulls.push(() => undefined);
378
+ }
379
+ close() {
380
+ if (this.closed) {
381
+ return;
382
+ }
383
+ this.closed = true;
384
+ while (this.pulls.length > 0) {
385
+ const waiter = this.pulls.shift();
386
+ waiter?.();
387
+ }
388
+ }
389
+ async waitForPull() {
390
+ if (this.closed) {
391
+ return;
392
+ }
393
+ const waiter = this.pulls.shift();
394
+ if (waiter) {
395
+ waiter();
396
+ return;
397
+ }
398
+ await new Promise((resolve) => {
399
+ this.pulls.push(resolve);
400
+ });
401
+ }
402
+ async *stream() {
403
+ yield new JsonContent({ json: this.start });
404
+ while (!this.closed) {
405
+ await this.waitForPull();
406
+ if (this.closed) {
407
+ return;
408
+ }
409
+ yield new JsonContent({ json: { kind: "pull" } });
410
+ }
411
+ }
412
+ }
2
413
  export class DatabaseClient {
3
414
  constructor({ room }) {
4
415
  this.room = room;
5
416
  }
6
- async listTables() {
7
- const response = await this.room.sendRequest("database.list_tables", {});
8
- return response?.json?.tables ?? [];
417
+ _unexpectedResponseError(operation) {
418
+ return new RoomServerException(`unexpected return type from database.${operation}`);
419
+ }
420
+ async invoke(operation, input) {
421
+ const response = await this.room.invoke({ toolkit: "database", tool: operation, input });
422
+ if (response instanceof JsonContent) {
423
+ return response;
424
+ }
425
+ if (response == null) {
426
+ return null;
427
+ }
428
+ return null;
9
429
  }
10
- async createTable({ name, data, schema, mode = "create" }) {
11
- let schemaDict;
12
- if (schema) {
13
- schemaDict = {};
14
- for (const [key, value] of Object.entries(schema)) {
15
- schemaDict[key] = value.toJson();
430
+ async invokeStream(operation, input) {
431
+ return await this.room.invokeStream({ toolkit: "database", tool: operation, input });
432
+ }
433
+ async drainWriteStream(operation, input) {
434
+ const response = await this.invokeStream(operation, input.stream());
435
+ try {
436
+ for await (const chunk of response) {
437
+ if (chunk instanceof ErrorContent) {
438
+ throw new RoomServerException(chunk.text, chunk.code);
439
+ }
440
+ if (chunk instanceof ControlContent) {
441
+ if (chunk.method === "close") {
442
+ return;
443
+ }
444
+ throw this._unexpectedResponseError(operation);
445
+ }
446
+ if (!(chunk instanceof JsonContent) || chunk.json.kind !== "pull") {
447
+ throw this._unexpectedResponseError(operation);
448
+ }
449
+ input.requestNext();
450
+ }
451
+ }
452
+ finally {
453
+ input.close();
454
+ }
455
+ }
456
+ async *streamRows(operation, start) {
457
+ const input = new DatabaseReadInputStream(start);
458
+ const response = await this.invokeStream(operation, input.stream());
459
+ input.requestNext();
460
+ try {
461
+ for await (const chunk of response) {
462
+ if (chunk instanceof ErrorContent) {
463
+ throw new RoomServerException(chunk.text, chunk.code);
464
+ }
465
+ if (chunk instanceof ControlContent) {
466
+ if (chunk.method === "close") {
467
+ return;
468
+ }
469
+ throw this._unexpectedResponseError(operation);
470
+ }
471
+ if (!(chunk instanceof JsonContent)) {
472
+ throw this._unexpectedResponseError(operation);
473
+ }
474
+ yield recordsFromRowsChunk(chunk.json, operation);
475
+ input.requestNext();
16
476
  }
17
477
  }
18
- const payload = {
478
+ finally {
479
+ input.close();
480
+ }
481
+ }
482
+ async listTables() {
483
+ const response = await this.invoke("list_tables", { namespace: null });
484
+ if (!(response instanceof JsonContent)) {
485
+ throw this._unexpectedResponseError("list_tables");
486
+ }
487
+ return Array.isArray(response.json.tables) ? response.json.tables : [];
488
+ }
489
+ async createTable({ name, data, schema, mode = "create", }) {
490
+ const input = new DatabaseWriteInputStream({
491
+ kind: "start",
19
492
  name,
20
- data,
21
- schema: schemaDict,
493
+ fields: schemaEntries(schema),
22
494
  mode,
23
- };
24
- await this.room.sendRequest("database.create_table", payload);
495
+ namespace: null,
496
+ metadata: null,
497
+ }, data ?? []);
498
+ await this.drainWriteStream("create_table", input);
25
499
  }
26
500
  async createTableWithSchema({ name, schema, data, mode = "create" }) {
27
- return this.createTable({ name, schema, data, mode });
501
+ return this.createTable({
502
+ name,
503
+ schema,
504
+ data: data == null ? undefined : rowChunkList(data),
505
+ mode,
506
+ });
28
507
  }
29
508
  async createTableFromData({ name, data, mode = "create" }) {
30
- return this.createTable({ name, data, mode });
509
+ return this.createTable({
510
+ name,
511
+ data: data == null ? undefined : rowChunkList(data),
512
+ mode,
513
+ });
514
+ }
515
+ async createTableFromDataStream({ name, chunks, schema, mode = "create" }) {
516
+ return this.createTable({ name, data: chunks, schema, mode });
31
517
  }
32
518
  async dropTable({ name, ignoreMissing = false }) {
33
- await this.room.sendRequest("database.drop_table", { name, ignoreMissing });
519
+ await this.room.invoke({
520
+ toolkit: "database",
521
+ tool: "drop_table",
522
+ input: { name, ignore_missing: ignoreMissing, namespace: null },
523
+ });
34
524
  }
35
525
  async addColumns({ table, newColumns }) {
36
- await this.room.sendRequest("database.add_columns", {
37
- table,
38
- new_columns: newColumns
526
+ await this.room.invoke({
527
+ toolkit: "database",
528
+ tool: "add_columns",
529
+ input: {
530
+ table,
531
+ columns: Object.entries(newColumns).map(([name, valueSql]) => ({ name, value_sql: valueSql, data_type: null })),
532
+ namespace: null,
533
+ },
39
534
  });
40
535
  }
41
536
  async dropColumns({ table, columns }) {
42
- await this.room.sendRequest("database.drop_columns", { table, columns });
537
+ await this.room.invoke({
538
+ toolkit: "database",
539
+ tool: "drop_columns",
540
+ input: { table, columns, namespace: null },
541
+ });
43
542
  }
44
543
  async insert({ table, records }) {
45
- await this.room.sendRequest("database.insert", { table, records });
544
+ await this.insertStream({ table, chunks: rowChunkList(records) });
46
545
  }
47
- async update({ table, where, values, valuesSql }) {
48
- const payload = {
546
+ async insertStream({ table, chunks }) {
547
+ const input = new DatabaseWriteInputStream({
548
+ kind: "start",
49
549
  table,
50
- where,
51
- values,
52
- valuesSql,
53
- };
54
- await this.room.sendRequest("database.update", payload);
550
+ namespace: null,
551
+ }, chunks);
552
+ await this.drainWriteStream("insert", input);
553
+ }
554
+ async update({ table, where, values, valuesSql }) {
555
+ await this.room.invoke({
556
+ toolkit: "database",
557
+ tool: "update",
558
+ input: {
559
+ table,
560
+ where,
561
+ values: values == null ? null : Object.entries(values).map(([column, value]) => ({ column, value_json: JSON.stringify(encodeLegacyValue(value)) })),
562
+ values_sql: valuesSql == null ? null : Object.entries(valuesSql).map(([column, expression]) => ({ column, expression })),
563
+ namespace: null,
564
+ },
565
+ });
55
566
  }
56
567
  async delete({ table, where }) {
57
- await this.room.sendRequest("database.delete", { table, where });
568
+ await this.room.invoke({
569
+ toolkit: "database",
570
+ tool: "delete",
571
+ input: { table, where, namespace: null },
572
+ });
58
573
  }
59
574
  async merge({ table, on, records }) {
60
- await this.room.sendRequest("database.merge", { table, on, records });
575
+ await this.mergeStream({ table, on, chunks: rowChunkList(records) });
576
+ }
577
+ async mergeStream({ table, on, chunks }) {
578
+ const input = new DatabaseWriteInputStream({
579
+ kind: "start",
580
+ table,
581
+ on,
582
+ namespace: null,
583
+ }, chunks);
584
+ await this.drainWriteStream("merge", input);
61
585
  }
62
586
  async sql({ query, tables, params }) {
63
- const payload = {
587
+ const rows = [];
588
+ for await (const chunk of this.sqlStream({ query, tables, params })) {
589
+ rows.push(...chunk);
590
+ }
591
+ return rows;
592
+ }
593
+ async *sqlStream({ query, tables, params }) {
594
+ yield* this.streamRows("sql", {
595
+ kind: "start",
64
596
  query,
65
597
  tables,
66
- params,
67
- };
68
- const response = await this.room.sendRequest("database.sql", payload);
69
- if (response instanceof JsonContent) {
70
- if (response?.json?.results) {
71
- return response.json.results;
72
- }
73
- }
74
- return [];
598
+ params_json: params == null ? null : JSON.stringify(encodeLegacyValue(params)),
599
+ });
75
600
  }
76
601
  async search({ table, text, vector, where, limit, select }) {
77
- let whereClause = where;
78
- if (where && typeof where === "object" && !Array.isArray(where)) {
79
- const parts = [];
80
- for (const [key, value] of Object.entries(where)) {
81
- parts.push(`${key} = ${JSON.stringify(value)}`);
82
- }
83
- whereClause = parts.join(" AND ");
602
+ const rows = [];
603
+ for await (const chunk of this.searchStream({ table, text, vector, where, limit, select })) {
604
+ rows.push(...chunk);
84
605
  }
85
- const payload = {
606
+ return rows;
607
+ }
608
+ async *searchStream({ table, text, vector, where, limit, select }) {
609
+ yield* this.streamRows("search", {
610
+ kind: "start",
86
611
  table,
87
- where: whereClause,
88
- text,
89
- };
90
- if (limit !== undefined) {
91
- payload.limit = limit;
92
- }
93
- if (select !== undefined) {
94
- payload.select = select;
95
- }
96
- if (vector !== undefined) {
97
- payload.vector = vector;
98
- }
99
- const response = await this.room.sendRequest("database.search", payload);
100
- if (response instanceof JsonContent) {
101
- if (response?.json?.results) {
102
- return response.json.results;
103
- }
104
- }
105
- return [];
612
+ text: text ?? null,
613
+ vector: vector ?? null,
614
+ text_columns: null,
615
+ where: buildWhereClause(where),
616
+ offset: null,
617
+ limit: limit ?? null,
618
+ select: select ?? null,
619
+ namespace: null,
620
+ });
106
621
  }
107
622
  async optimize(table) {
108
- await this.room.sendRequest("database.optimize", { table });
623
+ await this.room.invoke({ toolkit: "database", tool: "optimize", input: { table, namespace: null } });
109
624
  }
110
- async createVectorIndex({ table, column }) {
111
- await this.room.sendRequest("database.create_vector_index", { table, column });
625
+ async createVectorIndex({ table, column, replace = false }) {
626
+ await this.room.invoke({
627
+ toolkit: "database",
628
+ tool: "create_vector_index",
629
+ input: { table, column, replace, namespace: null },
630
+ });
112
631
  }
113
- async createScalarIndex({ table, column }) {
114
- await this.room.sendRequest("database.create_scalar_index", { table, column });
632
+ async createScalarIndex({ table, column, replace = false }) {
633
+ await this.room.invoke({
634
+ toolkit: "database",
635
+ tool: "create_scalar_index",
636
+ input: { table, column, replace, namespace: null },
637
+ });
115
638
  }
116
- async createFullTextSearchIndex({ table, column }) {
117
- await this.room.sendRequest("database.create_full_text_search_index", { table, column });
639
+ async createFullTextSearchIndex({ table, column, replace = false }) {
640
+ await this.room.invoke({
641
+ toolkit: "database",
642
+ tool: "create_full_text_search_index",
643
+ input: { table, column, replace, namespace: null },
644
+ });
118
645
  }
119
646
  async listIndexes({ table }) {
120
- const response = await this.room.sendRequest("database.list_indexes", { table });
121
- return response?.json ?? {};
647
+ const response = await this.invoke("list_indexes", { table, namespace: null });
648
+ if (!(response instanceof JsonContent)) {
649
+ throw this._unexpectedResponseError("list_indexes");
650
+ }
651
+ if (!Array.isArray(response.json.indexes)) {
652
+ throw this._unexpectedResponseError("list_indexes");
653
+ }
654
+ return response.json.indexes;
122
655
  }
123
656
  }