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