@synapcores/sdk 0.1.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/LICENSE +21 -0
- package/README.md +1011 -0
- package/dist/index.d.mts +2473 -0
- package/dist/index.d.ts +2473 -0
- package/dist/index.js +3109 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3055 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +78 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
AuthenticationError: () => AuthenticationError,
|
|
34
|
+
AutoMLClient: () => AutoMLClient,
|
|
35
|
+
AutoMLModel: () => AutoMLModel,
|
|
36
|
+
BackupClient: () => BackupClient,
|
|
37
|
+
BatchOperationError: () => BatchOperationError,
|
|
38
|
+
Collection: () => Collection,
|
|
39
|
+
ConnectionError: () => ConnectionError,
|
|
40
|
+
ImportExportClient: () => ImportExportClient,
|
|
41
|
+
IntegrationClient: () => IntegrationClient,
|
|
42
|
+
NLPClient: () => NLPClient,
|
|
43
|
+
NotFoundError: () => NotFoundError,
|
|
44
|
+
RateLimitError: () => RateLimitError,
|
|
45
|
+
RecipeClient: () => RecipeClient,
|
|
46
|
+
SQLError: () => SQLError,
|
|
47
|
+
SchemaClient: () => SchemaClient,
|
|
48
|
+
ServerError: () => ServerError,
|
|
49
|
+
Subscription: () => Subscription,
|
|
50
|
+
SynapCores: () => SynapCores,
|
|
51
|
+
SynapCoresError: () => SynapCoresError,
|
|
52
|
+
TimeoutError: () => TimeoutError,
|
|
53
|
+
TransactionError: () => TransactionError,
|
|
54
|
+
VERSION: () => VERSION,
|
|
55
|
+
ValidationError: () => ValidationError,
|
|
56
|
+
VectorError: () => VectorError,
|
|
57
|
+
z: () => import_zod.z
|
|
58
|
+
});
|
|
59
|
+
module.exports = __toCommonJS(index_exports);
|
|
60
|
+
|
|
61
|
+
// src/client.ts
|
|
62
|
+
var import_axios = __toESM(require("axios"));
|
|
63
|
+
|
|
64
|
+
// src/subscription.ts
|
|
65
|
+
var import_ws = __toESM(require("ws"));
|
|
66
|
+
var import_events = require("events");
|
|
67
|
+
var Subscription = class extends import_events.EventEmitter {
|
|
68
|
+
constructor(collection, options = {}) {
|
|
69
|
+
super();
|
|
70
|
+
this.collection = collection;
|
|
71
|
+
this.options = options;
|
|
72
|
+
this.running = false;
|
|
73
|
+
this.reconnectAttempts = 0;
|
|
74
|
+
this.maxReconnectAttempts = 5;
|
|
75
|
+
this.reconnectDelay = 1e3;
|
|
76
|
+
}
|
|
77
|
+
async connect() {
|
|
78
|
+
if (this.running) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.running = true;
|
|
82
|
+
await this.createConnection();
|
|
83
|
+
}
|
|
84
|
+
async createConnection() {
|
|
85
|
+
const client = this.collection.client;
|
|
86
|
+
const protocol = client.config.useHttps ? "wss" : "ws";
|
|
87
|
+
const url = `${protocol}://${client.config.host}:${client.config.port}/v1/ws`;
|
|
88
|
+
const headers = {};
|
|
89
|
+
if (client.config.apiKey) {
|
|
90
|
+
headers["Authorization"] = `Bearer ${client.config.apiKey}`;
|
|
91
|
+
}
|
|
92
|
+
this.ws = new import_ws.default(url, { headers });
|
|
93
|
+
this.ws.on("open", () => {
|
|
94
|
+
this.reconnectAttempts = 0;
|
|
95
|
+
this.subscribe();
|
|
96
|
+
});
|
|
97
|
+
this.ws.on("message", (data) => {
|
|
98
|
+
this.handleMessage(data.toString());
|
|
99
|
+
});
|
|
100
|
+
this.ws.on("error", (error) => {
|
|
101
|
+
this.emit("error", error);
|
|
102
|
+
});
|
|
103
|
+
this.ws.on("close", () => {
|
|
104
|
+
if (this.running) {
|
|
105
|
+
this.scheduleReconnect();
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
this.ws.on("ping", () => {
|
|
109
|
+
this.ws?.pong();
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
subscribe() {
|
|
113
|
+
const subscribeMessage = {
|
|
114
|
+
type: "subscribe",
|
|
115
|
+
collection: this.collection.name,
|
|
116
|
+
filter: this.options.filter || {}
|
|
117
|
+
};
|
|
118
|
+
this.ws?.send(JSON.stringify(subscribeMessage));
|
|
119
|
+
}
|
|
120
|
+
handleMessage(message) {
|
|
121
|
+
try {
|
|
122
|
+
const data = JSON.parse(message);
|
|
123
|
+
if (data.type === "error") {
|
|
124
|
+
this.emit("error", new Error(data.message));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (data.type === "change") {
|
|
128
|
+
const event = {
|
|
129
|
+
operation: data.operation,
|
|
130
|
+
collection: data.collection,
|
|
131
|
+
document: data.document,
|
|
132
|
+
timestamp: new Date(data.timestamp),
|
|
133
|
+
sequence: data.sequence
|
|
134
|
+
};
|
|
135
|
+
this.emit("change", event);
|
|
136
|
+
if (this.options.onChange) {
|
|
137
|
+
Promise.resolve(this.options.onChange(event)).catch((error) => {
|
|
138
|
+
this.emit("error", error);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
} catch (error) {
|
|
143
|
+
this.emit("error", error);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
scheduleReconnect() {
|
|
147
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
148
|
+
this.emit("error", new Error("Max reconnection attempts reached"));
|
|
149
|
+
this.close();
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
this.reconnectAttempts++;
|
|
153
|
+
const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
|
|
154
|
+
this.reconnectTimeout = setTimeout(() => {
|
|
155
|
+
this.createConnection().catch((error) => {
|
|
156
|
+
this.emit("error", error);
|
|
157
|
+
});
|
|
158
|
+
}, delay);
|
|
159
|
+
}
|
|
160
|
+
async close() {
|
|
161
|
+
this.running = false;
|
|
162
|
+
if (this.reconnectTimeout) {
|
|
163
|
+
clearTimeout(this.reconnectTimeout);
|
|
164
|
+
this.reconnectTimeout = void 0;
|
|
165
|
+
}
|
|
166
|
+
if (this.ws) {
|
|
167
|
+
this.ws.close();
|
|
168
|
+
this.ws = void 0;
|
|
169
|
+
}
|
|
170
|
+
this.removeAllListeners();
|
|
171
|
+
}
|
|
172
|
+
// Async iterator support
|
|
173
|
+
async *[Symbol.asyncIterator]() {
|
|
174
|
+
const events = [];
|
|
175
|
+
let resolver = null;
|
|
176
|
+
const handleChange = (event) => {
|
|
177
|
+
if (resolver) {
|
|
178
|
+
resolver({ done: false, value: event });
|
|
179
|
+
resolver = null;
|
|
180
|
+
} else {
|
|
181
|
+
events.push(event);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
this.on("change", handleChange);
|
|
185
|
+
try {
|
|
186
|
+
while (this.running) {
|
|
187
|
+
if (events.length > 0) {
|
|
188
|
+
yield events.shift();
|
|
189
|
+
} else {
|
|
190
|
+
yield await new Promise((resolve) => {
|
|
191
|
+
resolver = (result) => {
|
|
192
|
+
if (!result.done) {
|
|
193
|
+
resolve(result.value);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
} finally {
|
|
200
|
+
this.off("change", handleChange);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// src/collection.ts
|
|
206
|
+
var Collection = class {
|
|
207
|
+
constructor(client, name, schema) {
|
|
208
|
+
this.client = client;
|
|
209
|
+
this.name = name;
|
|
210
|
+
this.schema = schema;
|
|
211
|
+
}
|
|
212
|
+
get basePath() {
|
|
213
|
+
return `/collections/${this.name}`;
|
|
214
|
+
}
|
|
215
|
+
async insert(documents, _autoEmbed = true) {
|
|
216
|
+
const isSingle = !Array.isArray(documents);
|
|
217
|
+
const docs = isSingle ? [documents] : documents;
|
|
218
|
+
if (isSingle) {
|
|
219
|
+
const { data } = await this.client._getHttpClient().post(
|
|
220
|
+
`${this.basePath}/documents`,
|
|
221
|
+
documents
|
|
222
|
+
// Send the document directly as the body
|
|
223
|
+
);
|
|
224
|
+
return {
|
|
225
|
+
ids: [data.id],
|
|
226
|
+
inserted: 1
|
|
227
|
+
};
|
|
228
|
+
} else {
|
|
229
|
+
const formattedDocs = docs.map((doc) => ({
|
|
230
|
+
...doc,
|
|
231
|
+
// Spread document fields at root level
|
|
232
|
+
id: null
|
|
233
|
+
// Optional ID field
|
|
234
|
+
}));
|
|
235
|
+
const bulkUrl = `${this.basePath}/documents/bulk`;
|
|
236
|
+
console.log("Calling bulk insert endpoint:", bulkUrl);
|
|
237
|
+
console.log("Payload:", JSON.stringify({ documents: formattedDocs }, null, 2));
|
|
238
|
+
const { data } = await this.client._getHttpClient().post(
|
|
239
|
+
bulkUrl,
|
|
240
|
+
{
|
|
241
|
+
documents: formattedDocs
|
|
242
|
+
}
|
|
243
|
+
);
|
|
244
|
+
return {
|
|
245
|
+
ids: data.ids || [],
|
|
246
|
+
inserted: data.inserted || docs.length
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
async get(documentId) {
|
|
251
|
+
try {
|
|
252
|
+
const { data } = await this.client._getHttpClient().get(
|
|
253
|
+
`${this.basePath}/documents/${documentId}`
|
|
254
|
+
);
|
|
255
|
+
return data;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
if (error.code === "NOT_FOUND") {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async update(documentId, data, options = {}) {
|
|
264
|
+
const response = await this.client._getHttpClient().patch(
|
|
265
|
+
`${this.basePath}/documents/${documentId}`,
|
|
266
|
+
{
|
|
267
|
+
data,
|
|
268
|
+
merge: options.merge !== false
|
|
269
|
+
}
|
|
270
|
+
);
|
|
271
|
+
return response.data;
|
|
272
|
+
}
|
|
273
|
+
async delete(documentId) {
|
|
274
|
+
const ids = Array.isArray(documentId) ? documentId : [documentId];
|
|
275
|
+
const { data } = await this.client._getHttpClient().request({
|
|
276
|
+
method: "DELETE",
|
|
277
|
+
url: `${this.basePath}/documents`,
|
|
278
|
+
data: { ids }
|
|
279
|
+
});
|
|
280
|
+
return { deleted: data.deleted };
|
|
281
|
+
}
|
|
282
|
+
async search(options) {
|
|
283
|
+
const searchUrl = `${this.basePath}/search`;
|
|
284
|
+
console.log("Calling search endpoint:", searchUrl);
|
|
285
|
+
console.log("Request body:", {
|
|
286
|
+
query: options.filter || {},
|
|
287
|
+
limit: options.topK || 10,
|
|
288
|
+
offset: options.offset || 0
|
|
289
|
+
});
|
|
290
|
+
const { data } = await this.client._getHttpClient().post(
|
|
291
|
+
searchUrl,
|
|
292
|
+
{
|
|
293
|
+
query: options.filter || {},
|
|
294
|
+
// Use filter as the query
|
|
295
|
+
limit: options.topK || 10,
|
|
296
|
+
offset: options.offset || 0
|
|
297
|
+
}
|
|
298
|
+
);
|
|
299
|
+
return {
|
|
300
|
+
documents: data.documents || data,
|
|
301
|
+
// Handle different response formats
|
|
302
|
+
total: data.total,
|
|
303
|
+
tookMs: data.took_ms,
|
|
304
|
+
nextOffset: data.next_offset
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
async vectorSearch(options) {
|
|
308
|
+
const { data } = await this.client._getHttpClient().post(
|
|
309
|
+
`${this.basePath}/vector_search`,
|
|
310
|
+
{
|
|
311
|
+
vector: options.vector,
|
|
312
|
+
field: options.field || "embedding",
|
|
313
|
+
top_k: options.topK || 10,
|
|
314
|
+
filter: options.filter,
|
|
315
|
+
distance_metric: options.distanceMetric || "cosine",
|
|
316
|
+
include_metadata: options.includeMetadata
|
|
317
|
+
}
|
|
318
|
+
);
|
|
319
|
+
return {
|
|
320
|
+
documents: data.documents,
|
|
321
|
+
total: data.total,
|
|
322
|
+
tookMs: data.took_ms
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
async query(options = {}) {
|
|
326
|
+
const { data } = await this.client._getHttpClient().post(
|
|
327
|
+
`${this.basePath}/query`,
|
|
328
|
+
{
|
|
329
|
+
filter: options.filter || {},
|
|
330
|
+
limit: options.limit || 100,
|
|
331
|
+
offset: options.offset || 0,
|
|
332
|
+
sort: options.sort,
|
|
333
|
+
projection: options.projection
|
|
334
|
+
}
|
|
335
|
+
);
|
|
336
|
+
return {
|
|
337
|
+
documents: data.documents,
|
|
338
|
+
total: data.total,
|
|
339
|
+
tookMs: data.took_ms,
|
|
340
|
+
nextOffset: data.next_offset
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
async count(filter) {
|
|
344
|
+
const { data } = await this.client._getHttpClient().post(
|
|
345
|
+
`${this.basePath}/count`,
|
|
346
|
+
{ filter: filter || {} }
|
|
347
|
+
);
|
|
348
|
+
return data.count;
|
|
349
|
+
}
|
|
350
|
+
async stats() {
|
|
351
|
+
const { data } = await this.client._getHttpClient().get(
|
|
352
|
+
`${this.basePath}/stats`
|
|
353
|
+
);
|
|
354
|
+
return {
|
|
355
|
+
name: data.name,
|
|
356
|
+
documentCount: data.document_count,
|
|
357
|
+
sizeBytes: data.size_bytes,
|
|
358
|
+
indexCount: data.index_count,
|
|
359
|
+
createdAt: new Date(data.created_at),
|
|
360
|
+
updatedAt: new Date(data.updated_at)
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
async createIndex(options) {
|
|
364
|
+
const { data } = await this.client._getHttpClient().post(
|
|
365
|
+
`${this.basePath}/indexes`,
|
|
366
|
+
{
|
|
367
|
+
field: options.field,
|
|
368
|
+
type: options.type || "btree",
|
|
369
|
+
options: options.options || {}
|
|
370
|
+
}
|
|
371
|
+
);
|
|
372
|
+
return { created: data.created };
|
|
373
|
+
}
|
|
374
|
+
async dropIndex(field) {
|
|
375
|
+
const { data } = await this.client._getHttpClient().delete(
|
|
376
|
+
`${this.basePath}/indexes/${field}`
|
|
377
|
+
);
|
|
378
|
+
return { dropped: data.dropped };
|
|
379
|
+
}
|
|
380
|
+
async subscribe(options = {}) {
|
|
381
|
+
const subscription = new Subscription(this, options);
|
|
382
|
+
await subscription.connect();
|
|
383
|
+
return subscription;
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// src/automl.ts
|
|
388
|
+
var AutoMLModel = class {
|
|
389
|
+
constructor(client, info) {
|
|
390
|
+
this.client = client;
|
|
391
|
+
this.info = info;
|
|
392
|
+
}
|
|
393
|
+
get id() {
|
|
394
|
+
return this.info.id;
|
|
395
|
+
}
|
|
396
|
+
get name() {
|
|
397
|
+
return this.info.name;
|
|
398
|
+
}
|
|
399
|
+
async predict(data) {
|
|
400
|
+
const isSingle = !Array.isArray(data);
|
|
401
|
+
const inputs = isSingle ? [data] : data;
|
|
402
|
+
const response = await this.client.synapCores._getHttpClient().post(
|
|
403
|
+
"/ai/predict",
|
|
404
|
+
{
|
|
405
|
+
model_id: this.id,
|
|
406
|
+
inputs
|
|
407
|
+
}
|
|
408
|
+
);
|
|
409
|
+
const predictions = response.data.predictions;
|
|
410
|
+
return isSingle ? predictions[0] : predictions;
|
|
411
|
+
}
|
|
412
|
+
async evaluate(testData, target) {
|
|
413
|
+
const payload = {
|
|
414
|
+
model_id: this.id
|
|
415
|
+
};
|
|
416
|
+
if (typeof testData === "string") {
|
|
417
|
+
payload.collection = testData;
|
|
418
|
+
} else {
|
|
419
|
+
payload.data = testData;
|
|
420
|
+
if (target) {
|
|
421
|
+
payload.target = target;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const { data } = await this.client.synapCores._getHttpClient().post(
|
|
425
|
+
"/ai/evaluate",
|
|
426
|
+
payload
|
|
427
|
+
);
|
|
428
|
+
return data;
|
|
429
|
+
}
|
|
430
|
+
async delete() {
|
|
431
|
+
await this.client.synapCores._getHttpClient().delete(
|
|
432
|
+
`/ai/models/${this.id}`
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
};
|
|
436
|
+
var AutoMLClient = class {
|
|
437
|
+
constructor(synapCores) {
|
|
438
|
+
this.synapCores = synapCores;
|
|
439
|
+
}
|
|
440
|
+
async train(options) {
|
|
441
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/train", {
|
|
442
|
+
collection: options.collection,
|
|
443
|
+
target: options.target,
|
|
444
|
+
features: options.features,
|
|
445
|
+
task: options.task || "auto",
|
|
446
|
+
name: options.name || `${options.collection}_${options.target}_model`,
|
|
447
|
+
config: options.config || {},
|
|
448
|
+
validation_split: options.validationSplit || 0.2,
|
|
449
|
+
max_trials: options.maxTrials || 10,
|
|
450
|
+
timeout_minutes: options.timeoutMinutes || 60
|
|
451
|
+
});
|
|
452
|
+
const modelInfo = {
|
|
453
|
+
id: data.id,
|
|
454
|
+
name: data.name,
|
|
455
|
+
task: data.task,
|
|
456
|
+
status: data.status,
|
|
457
|
+
accuracy: data.accuracy,
|
|
458
|
+
createdAt: new Date(data.created_at),
|
|
459
|
+
updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
|
|
460
|
+
config: data.config
|
|
461
|
+
};
|
|
462
|
+
return new AutoMLModel(this, modelInfo);
|
|
463
|
+
}
|
|
464
|
+
async getModel(modelId) {
|
|
465
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
466
|
+
`/ai/models/${modelId}`
|
|
467
|
+
);
|
|
468
|
+
const modelInfo = {
|
|
469
|
+
id: data.id,
|
|
470
|
+
name: data.name,
|
|
471
|
+
task: data.task,
|
|
472
|
+
status: data.status,
|
|
473
|
+
accuracy: data.accuracy,
|
|
474
|
+
createdAt: new Date(data.created_at),
|
|
475
|
+
updatedAt: data.updated_at ? new Date(data.updated_at) : void 0,
|
|
476
|
+
config: data.config
|
|
477
|
+
};
|
|
478
|
+
return new AutoMLModel(this, modelInfo);
|
|
479
|
+
}
|
|
480
|
+
async listModels(filters) {
|
|
481
|
+
const { data } = await this.synapCores._getHttpClient().get("/ai/models", {
|
|
482
|
+
params: filters
|
|
483
|
+
});
|
|
484
|
+
return data.models.map((model) => ({
|
|
485
|
+
id: model.id,
|
|
486
|
+
name: model.name,
|
|
487
|
+
task: model.task,
|
|
488
|
+
status: model.status,
|
|
489
|
+
accuracy: model.accuracy,
|
|
490
|
+
createdAt: new Date(model.created_at),
|
|
491
|
+
updatedAt: model.updated_at ? new Date(model.updated_at) : void 0,
|
|
492
|
+
config: model.config
|
|
493
|
+
}));
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Start async training job
|
|
497
|
+
*/
|
|
498
|
+
async trainAsync(options) {
|
|
499
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/train/async", {
|
|
500
|
+
collection: options.collection,
|
|
501
|
+
target: options.target,
|
|
502
|
+
features: options.features,
|
|
503
|
+
task: options.task || "auto",
|
|
504
|
+
name: options.name || `${options.collection}_${options.target}_model`,
|
|
505
|
+
config: options.config || {},
|
|
506
|
+
validation_split: options.validationSplit || 0.2,
|
|
507
|
+
max_trials: options.maxTrials || 10,
|
|
508
|
+
timeout_minutes: options.timeoutMinutes || 60,
|
|
509
|
+
callback_url: options.callback_url,
|
|
510
|
+
webhook_url: options.webhook_url
|
|
511
|
+
});
|
|
512
|
+
return {
|
|
513
|
+
id: data.id || data.job_id,
|
|
514
|
+
name: data.name,
|
|
515
|
+
status: data.status,
|
|
516
|
+
progress: data.progress || 0,
|
|
517
|
+
phase: data.phase,
|
|
518
|
+
task: data.task,
|
|
519
|
+
current_trial: data.current_trial,
|
|
520
|
+
total_trials: data.total_trials || options.maxTrials || 10,
|
|
521
|
+
best_accuracy: data.best_accuracy,
|
|
522
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
523
|
+
error: data.error,
|
|
524
|
+
started_at: new Date(data.started_at || Date.now()),
|
|
525
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
|
|
526
|
+
model_id: data.model_id
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Get training job status
|
|
531
|
+
*/
|
|
532
|
+
async getTrainingJob(jobId) {
|
|
533
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
534
|
+
`/ai/train/jobs/${jobId}`
|
|
535
|
+
);
|
|
536
|
+
return {
|
|
537
|
+
id: data.id || jobId,
|
|
538
|
+
name: data.name,
|
|
539
|
+
status: data.status,
|
|
540
|
+
progress: data.progress || 0,
|
|
541
|
+
phase: data.phase,
|
|
542
|
+
task: data.task,
|
|
543
|
+
current_trial: data.current_trial,
|
|
544
|
+
total_trials: data.total_trials,
|
|
545
|
+
best_accuracy: data.best_accuracy,
|
|
546
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
547
|
+
error: data.error,
|
|
548
|
+
started_at: new Date(data.started_at),
|
|
549
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
|
|
550
|
+
model_id: data.model_id
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* List training jobs
|
|
555
|
+
*/
|
|
556
|
+
async listTrainingJobs(options = {}) {
|
|
557
|
+
const params = new URLSearchParams();
|
|
558
|
+
if (options.status) params.append("status", options.status);
|
|
559
|
+
if (options.page) params.append("page", options.page.toString());
|
|
560
|
+
if (options.page_size) params.append("page_size", options.page_size.toString());
|
|
561
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
562
|
+
`/ai/train/jobs?${params.toString()}`
|
|
563
|
+
);
|
|
564
|
+
return (data.jobs || data).map((job) => ({
|
|
565
|
+
id: job.id,
|
|
566
|
+
name: job.name,
|
|
567
|
+
status: job.status,
|
|
568
|
+
progress: job.progress || 0,
|
|
569
|
+
phase: job.phase,
|
|
570
|
+
task: job.task,
|
|
571
|
+
current_trial: job.current_trial,
|
|
572
|
+
total_trials: job.total_trials,
|
|
573
|
+
best_accuracy: job.best_accuracy,
|
|
574
|
+
eta_ms: job.eta_ms || job.estimated_time_remaining_ms,
|
|
575
|
+
error: job.error,
|
|
576
|
+
started_at: new Date(job.started_at),
|
|
577
|
+
completed_at: job.completed_at ? new Date(job.completed_at) : void 0,
|
|
578
|
+
model_id: job.model_id
|
|
579
|
+
}));
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Cancel a training job
|
|
583
|
+
*/
|
|
584
|
+
async cancelTrainingJob(jobId) {
|
|
585
|
+
await this.synapCores._getHttpClient().post(`/ai/train/jobs/${jobId}/cancel`);
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Get training metrics for a job
|
|
589
|
+
*/
|
|
590
|
+
async getTrainingMetrics(jobId) {
|
|
591
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
592
|
+
`/ai/train/jobs/${jobId}/metrics`
|
|
593
|
+
);
|
|
594
|
+
return (data.metrics || data).map((metric) => ({
|
|
595
|
+
trial: metric.trial,
|
|
596
|
+
accuracy: metric.accuracy,
|
|
597
|
+
loss: metric.loss,
|
|
598
|
+
metrics: metric.metrics,
|
|
599
|
+
timestamp: new Date(metric.timestamp)
|
|
600
|
+
}));
|
|
601
|
+
}
|
|
602
|
+
/**
|
|
603
|
+
* Wait for training job to complete
|
|
604
|
+
*/
|
|
605
|
+
async waitForTrainingJob(jobId, options = {}) {
|
|
606
|
+
const pollInterval = options.pollInterval || 2e3;
|
|
607
|
+
const timeout = options.timeout || 36e5;
|
|
608
|
+
const startTime = Date.now();
|
|
609
|
+
while (true) {
|
|
610
|
+
const job = await this.getTrainingJob(jobId);
|
|
611
|
+
if (options.onProgress) {
|
|
612
|
+
options.onProgress(job);
|
|
613
|
+
}
|
|
614
|
+
if (job.status === "completed") {
|
|
615
|
+
if (!job.model_id) {
|
|
616
|
+
throw new Error("Training completed but no model ID returned");
|
|
617
|
+
}
|
|
618
|
+
return await this.getModel(job.model_id);
|
|
619
|
+
}
|
|
620
|
+
if (job.status === "failed") {
|
|
621
|
+
throw new Error(`Training failed: ${job.error || "Unknown error"}`);
|
|
622
|
+
}
|
|
623
|
+
if (job.status === "cancelled") {
|
|
624
|
+
throw new Error("Training was cancelled");
|
|
625
|
+
}
|
|
626
|
+
if (Date.now() - startTime > timeout) {
|
|
627
|
+
throw new Error("Timeout waiting for training job to complete");
|
|
628
|
+
}
|
|
629
|
+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
|
|
634
|
+
// src/nlp.ts
|
|
635
|
+
var NLPClient = class {
|
|
636
|
+
constructor(synapCores) {
|
|
637
|
+
this.synapCores = synapCores;
|
|
638
|
+
}
|
|
639
|
+
async analyze(options) {
|
|
640
|
+
const isBatch = Array.isArray(options.text);
|
|
641
|
+
const texts = isBatch ? options.text : [options.text];
|
|
642
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/analyze", {
|
|
643
|
+
texts,
|
|
644
|
+
tasks: options.tasks || ["sentiment", "entities", "keywords"],
|
|
645
|
+
language: options.language
|
|
646
|
+
});
|
|
647
|
+
const results = data.results.map((r) => ({
|
|
648
|
+
sentiment: r.sentiment ? {
|
|
649
|
+
label: r.sentiment.label,
|
|
650
|
+
score: r.sentiment.score,
|
|
651
|
+
confidence: r.sentiment.confidence
|
|
652
|
+
} : void 0,
|
|
653
|
+
entities: r.entities ? r.entities.map((e) => ({
|
|
654
|
+
text: e.text,
|
|
655
|
+
type: e.type,
|
|
656
|
+
start: e.start,
|
|
657
|
+
end: e.end,
|
|
658
|
+
score: e.score
|
|
659
|
+
})) : void 0,
|
|
660
|
+
summary: r.summary,
|
|
661
|
+
keywords: r.keywords,
|
|
662
|
+
language: r.language
|
|
663
|
+
}));
|
|
664
|
+
return isBatch ? results : results[0];
|
|
665
|
+
}
|
|
666
|
+
async summarize(options) {
|
|
667
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/summarize", {
|
|
668
|
+
text: options.text,
|
|
669
|
+
max_length: options.maxLength || 150,
|
|
670
|
+
min_length: options.minLength || 30
|
|
671
|
+
});
|
|
672
|
+
return data.summary;
|
|
673
|
+
}
|
|
674
|
+
async extractEntities(text, entityTypes) {
|
|
675
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/entities", {
|
|
676
|
+
text,
|
|
677
|
+
entity_types: entityTypes
|
|
678
|
+
});
|
|
679
|
+
return data.entities.map((e) => ({
|
|
680
|
+
text: e.text,
|
|
681
|
+
type: e.type,
|
|
682
|
+
start: e.start,
|
|
683
|
+
end: e.end,
|
|
684
|
+
score: e.score
|
|
685
|
+
}));
|
|
686
|
+
}
|
|
687
|
+
async sentiment(text) {
|
|
688
|
+
const isBatch = Array.isArray(text);
|
|
689
|
+
const texts = isBatch ? text : [text];
|
|
690
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/sentiment", {
|
|
691
|
+
texts
|
|
692
|
+
});
|
|
693
|
+
const results = data.sentiments.map((s) => ({
|
|
694
|
+
label: s.label,
|
|
695
|
+
score: s.score,
|
|
696
|
+
confidence: s.confidence
|
|
697
|
+
}));
|
|
698
|
+
return isBatch ? results : results[0];
|
|
699
|
+
}
|
|
700
|
+
async classify(options) {
|
|
701
|
+
const isBatch = Array.isArray(options.text);
|
|
702
|
+
const texts = isBatch ? options.text : [options.text];
|
|
703
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/classify", {
|
|
704
|
+
texts,
|
|
705
|
+
categories: options.categories,
|
|
706
|
+
multi_label: options.multiLabel || false
|
|
707
|
+
});
|
|
708
|
+
return isBatch ? data.classifications : data.classifications[0];
|
|
709
|
+
}
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
// src/recipes.ts
|
|
713
|
+
var RecipeClient = class {
|
|
714
|
+
constructor(synapCores) {
|
|
715
|
+
this.synapCores = synapCores;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Create a new recipe
|
|
719
|
+
*/
|
|
720
|
+
async create(options) {
|
|
721
|
+
const { data } = await this.synapCores._getHttpClient().post("/recipes", {
|
|
722
|
+
name: options.name,
|
|
723
|
+
description: options.description,
|
|
724
|
+
category: options.category,
|
|
725
|
+
content: options.content,
|
|
726
|
+
tags: options.tags || [],
|
|
727
|
+
parameters: options.parameters || []
|
|
728
|
+
});
|
|
729
|
+
return {
|
|
730
|
+
id: data.id,
|
|
731
|
+
name: data.name,
|
|
732
|
+
description: data.description,
|
|
733
|
+
category: data.category,
|
|
734
|
+
content: data.content,
|
|
735
|
+
tags: data.tags || [],
|
|
736
|
+
parameters: data.parameters || [],
|
|
737
|
+
created_at: new Date(data.created_at),
|
|
738
|
+
updated_at: new Date(data.updated_at),
|
|
739
|
+
author: data.author,
|
|
740
|
+
execution_count: data.execution_count,
|
|
741
|
+
version: data.version
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* List recipes with optional filters
|
|
746
|
+
*/
|
|
747
|
+
async list(options = {}) {
|
|
748
|
+
const params = new URLSearchParams();
|
|
749
|
+
if (options.category) params.append("category", options.category);
|
|
750
|
+
if (options.search) params.append("search", options.search);
|
|
751
|
+
if (options.page) params.append("page", options.page.toString());
|
|
752
|
+
if (options.page_size) params.append("page_size", options.page_size.toString());
|
|
753
|
+
if (options.tags && options.tags.length > 0) {
|
|
754
|
+
params.append("tags", options.tags.join(","));
|
|
755
|
+
}
|
|
756
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
757
|
+
`/recipes?${params.toString()}`
|
|
758
|
+
);
|
|
759
|
+
return (data.recipes || data).map((recipe) => ({
|
|
760
|
+
id: recipe.id,
|
|
761
|
+
name: recipe.name,
|
|
762
|
+
description: recipe.description,
|
|
763
|
+
category: recipe.category,
|
|
764
|
+
tags: recipe.tags || [],
|
|
765
|
+
created_at: new Date(recipe.created_at),
|
|
766
|
+
updated_at: new Date(recipe.updated_at),
|
|
767
|
+
author: recipe.author,
|
|
768
|
+
execution_count: recipe.execution_count
|
|
769
|
+
}));
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Get a specific recipe by ID
|
|
773
|
+
*/
|
|
774
|
+
async get(id) {
|
|
775
|
+
const { data } = await this.synapCores._getHttpClient().get(`/recipes/${id}`);
|
|
776
|
+
return {
|
|
777
|
+
id: data.id,
|
|
778
|
+
name: data.name,
|
|
779
|
+
description: data.description,
|
|
780
|
+
category: data.category,
|
|
781
|
+
content: data.content,
|
|
782
|
+
tags: data.tags || [],
|
|
783
|
+
parameters: data.parameters || [],
|
|
784
|
+
created_at: new Date(data.created_at),
|
|
785
|
+
updated_at: new Date(data.updated_at),
|
|
786
|
+
author: data.author,
|
|
787
|
+
execution_count: data.execution_count,
|
|
788
|
+
version: data.version
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* Update an existing recipe
|
|
793
|
+
*/
|
|
794
|
+
async update(id, updates) {
|
|
795
|
+
const { data } = await this.synapCores._getHttpClient().put(`/recipes/${id}`, updates);
|
|
796
|
+
return {
|
|
797
|
+
id: data.id,
|
|
798
|
+
name: data.name,
|
|
799
|
+
description: data.description,
|
|
800
|
+
category: data.category,
|
|
801
|
+
content: data.content,
|
|
802
|
+
tags: data.tags || [],
|
|
803
|
+
parameters: data.parameters || [],
|
|
804
|
+
created_at: new Date(data.created_at),
|
|
805
|
+
updated_at: new Date(data.updated_at),
|
|
806
|
+
author: data.author,
|
|
807
|
+
execution_count: data.execution_count,
|
|
808
|
+
version: data.version
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* Delete a recipe
|
|
813
|
+
*/
|
|
814
|
+
async delete(id) {
|
|
815
|
+
await this.synapCores._getHttpClient().delete(`/recipes/${id}`);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Execute a recipe
|
|
819
|
+
*/
|
|
820
|
+
async execute(options) {
|
|
821
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
822
|
+
`/recipes/${options.recipe}/execute`,
|
|
823
|
+
{
|
|
824
|
+
parameters: options.parameters || {},
|
|
825
|
+
dry_run: options.dry_run || false
|
|
826
|
+
}
|
|
827
|
+
);
|
|
828
|
+
return {
|
|
829
|
+
id: data.id || data.execution_id,
|
|
830
|
+
success: data.success,
|
|
831
|
+
results: data.results,
|
|
832
|
+
error: data.error,
|
|
833
|
+
execution_time_ms: data.execution_time_ms || data.took_ms,
|
|
834
|
+
statements_executed: data.statements_executed || 0
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Generate a recipe using AI
|
|
839
|
+
*/
|
|
840
|
+
async generate(options) {
|
|
841
|
+
const { data } = await this.synapCores._getHttpClient().post("/ai/generate-recipe", {
|
|
842
|
+
intent: options.intent,
|
|
843
|
+
category: options.category,
|
|
844
|
+
context: options.context
|
|
845
|
+
});
|
|
846
|
+
return {
|
|
847
|
+
name: data.name,
|
|
848
|
+
description: data.description,
|
|
849
|
+
content: data.content
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* List available recipe categories
|
|
854
|
+
*/
|
|
855
|
+
async listCategories() {
|
|
856
|
+
const { data } = await this.synapCores._getHttpClient().get("/recipes/categories");
|
|
857
|
+
return data.categories || [];
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
// src/schema.ts
|
|
862
|
+
var SchemaClient = class {
|
|
863
|
+
constructor(synapCores) {
|
|
864
|
+
this.synapCores = synapCores;
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* List all tables in the database
|
|
868
|
+
*/
|
|
869
|
+
async listTables(options = {}) {
|
|
870
|
+
const params = new URLSearchParams();
|
|
871
|
+
if (options.includeSystem) {
|
|
872
|
+
params.append("include_system", "true");
|
|
873
|
+
}
|
|
874
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
875
|
+
`/schema/tables?${params.toString()}`
|
|
876
|
+
);
|
|
877
|
+
return (data.tables || data).map((table) => ({
|
|
878
|
+
name: table.name,
|
|
879
|
+
type: table.type || "table",
|
|
880
|
+
column_count: table.column_count || 0,
|
|
881
|
+
row_count: table.row_count,
|
|
882
|
+
size_bytes: table.size_bytes,
|
|
883
|
+
created_at: table.created_at ? new Date(table.created_at) : void 0,
|
|
884
|
+
updated_at: table.updated_at ? new Date(table.updated_at) : void 0,
|
|
885
|
+
comment: table.comment
|
|
886
|
+
}));
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Get complete schema for a specific table
|
|
890
|
+
*/
|
|
891
|
+
async getTable(tableName) {
|
|
892
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
893
|
+
`/schema/tables/${tableName}`
|
|
894
|
+
);
|
|
895
|
+
return {
|
|
896
|
+
table: {
|
|
897
|
+
name: data.name,
|
|
898
|
+
type: data.type || "table",
|
|
899
|
+
column_count: data.columns?.length || 0,
|
|
900
|
+
row_count: data.row_count,
|
|
901
|
+
size_bytes: data.size_bytes,
|
|
902
|
+
created_at: data.created_at ? new Date(data.created_at) : void 0,
|
|
903
|
+
updated_at: data.updated_at ? new Date(data.updated_at) : void 0,
|
|
904
|
+
comment: data.comment
|
|
905
|
+
},
|
|
906
|
+
columns: (data.columns || []).map((col) => ({
|
|
907
|
+
name: col.name,
|
|
908
|
+
data_type: col.data_type || col.type,
|
|
909
|
+
nullable: col.nullable !== false,
|
|
910
|
+
default_value: col.default_value || col.default,
|
|
911
|
+
is_primary_key: col.is_primary_key || col.primary_key,
|
|
912
|
+
is_unique: col.is_unique || col.unique,
|
|
913
|
+
is_indexed: col.is_indexed || col.indexed,
|
|
914
|
+
foreign_key: col.foreign_key,
|
|
915
|
+
comment: col.comment,
|
|
916
|
+
ordinal_position: col.ordinal_position || col.position
|
|
917
|
+
})),
|
|
918
|
+
indexes: (data.indexes || []).map((idx) => ({
|
|
919
|
+
name: idx.name,
|
|
920
|
+
table: idx.table || tableName,
|
|
921
|
+
type: idx.type || "btree",
|
|
922
|
+
columns: idx.columns || [],
|
|
923
|
+
is_unique: idx.is_unique || idx.unique || false,
|
|
924
|
+
is_primary: idx.is_primary || idx.primary || false,
|
|
925
|
+
size_bytes: idx.size_bytes,
|
|
926
|
+
created_at: idx.created_at ? new Date(idx.created_at) : void 0
|
|
927
|
+
})),
|
|
928
|
+
constraints: data.constraints || [],
|
|
929
|
+
relationships: (data.relationships || []).map((rel) => ({
|
|
930
|
+
type: rel.type,
|
|
931
|
+
from_table: rel.from_table || rel.source_table,
|
|
932
|
+
from_column: rel.from_column || rel.source_column,
|
|
933
|
+
to_table: rel.to_table || rel.target_table,
|
|
934
|
+
to_column: rel.to_column || rel.target_column,
|
|
935
|
+
name: rel.name
|
|
936
|
+
}))
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
/**
|
|
940
|
+
* Get columns for a specific table
|
|
941
|
+
*/
|
|
942
|
+
async getColumns(tableName) {
|
|
943
|
+
const schema = await this.getTable(tableName);
|
|
944
|
+
return schema.columns;
|
|
945
|
+
}
|
|
946
|
+
/**
|
|
947
|
+
* Get indexes for a specific table
|
|
948
|
+
*/
|
|
949
|
+
async getIndexes(tableName) {
|
|
950
|
+
const schema = await this.getTable(tableName);
|
|
951
|
+
return schema.indexes;
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* Get all relationships in the database
|
|
955
|
+
*/
|
|
956
|
+
async getRelationships() {
|
|
957
|
+
const { data } = await this.synapCores._getHttpClient().get("/schema/relationships");
|
|
958
|
+
return (data.relationships || data).map((rel) => ({
|
|
959
|
+
type: rel.type,
|
|
960
|
+
from_table: rel.from_table || rel.source_table,
|
|
961
|
+
from_column: rel.from_column || rel.source_column,
|
|
962
|
+
to_table: rel.to_table || rel.target_table,
|
|
963
|
+
to_column: rel.to_column || rel.target_column,
|
|
964
|
+
name: rel.name
|
|
965
|
+
}));
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Get schema statistics
|
|
969
|
+
*/
|
|
970
|
+
async getStatistics() {
|
|
971
|
+
const { data } = await this.synapCores._getHttpClient().get("/schema/statistics");
|
|
972
|
+
return {
|
|
973
|
+
table_count: data.table_count || 0,
|
|
974
|
+
view_count: data.view_count || 0,
|
|
975
|
+
index_count: data.index_count || 0,
|
|
976
|
+
relationship_count: data.relationship_count || 0,
|
|
977
|
+
total_size_bytes: data.total_size_bytes || 0,
|
|
978
|
+
total_rows: data.total_rows || 0,
|
|
979
|
+
version: data.version,
|
|
980
|
+
analyzed_at: data.analyzed_at ? new Date(data.analyzed_at) : void 0
|
|
981
|
+
};
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Validate a schema definition
|
|
985
|
+
*/
|
|
986
|
+
async validateSchema(schema) {
|
|
987
|
+
const { data } = await this.synapCores._getHttpClient().post("/schema/validate", {
|
|
988
|
+
schema
|
|
989
|
+
});
|
|
990
|
+
return {
|
|
991
|
+
is_valid: data.is_valid || data.valid,
|
|
992
|
+
errors: data.errors || [],
|
|
993
|
+
warnings: data.warnings || []
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Compare two schemas
|
|
998
|
+
*/
|
|
999
|
+
async compareSchemas(schema1, schema2) {
|
|
1000
|
+
const { data } = await this.synapCores._getHttpClient().post("/schema/compare", {
|
|
1001
|
+
schema1,
|
|
1002
|
+
schema2
|
|
1003
|
+
});
|
|
1004
|
+
return {
|
|
1005
|
+
differences: data.differences || [],
|
|
1006
|
+
added: data.added || [],
|
|
1007
|
+
removed: data.removed || [],
|
|
1008
|
+
modified: data.modified || []
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Generate SQL DDL for a table
|
|
1013
|
+
*/
|
|
1014
|
+
async generateDDL(tableName) {
|
|
1015
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1016
|
+
`/schema/tables/${tableName}/ddl`
|
|
1017
|
+
);
|
|
1018
|
+
return data.ddl || data.sql;
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Analyze table and update statistics
|
|
1022
|
+
*/
|
|
1023
|
+
async analyzeTable(tableName) {
|
|
1024
|
+
await this.synapCores._getHttpClient().post(`/schema/tables/${tableName}/analyze`);
|
|
1025
|
+
}
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
// src/import.ts
|
|
1029
|
+
var ImportExportClient = class {
|
|
1030
|
+
constructor(synapCores) {
|
|
1031
|
+
this.synapCores = synapCores;
|
|
1032
|
+
}
|
|
1033
|
+
/**
|
|
1034
|
+
* Import data into a table
|
|
1035
|
+
*/
|
|
1036
|
+
async import(options) {
|
|
1037
|
+
const formData = new FormData();
|
|
1038
|
+
formData.append("table", options.table);
|
|
1039
|
+
formData.append("format", options.format);
|
|
1040
|
+
if (options.mode) formData.append("mode", options.mode);
|
|
1041
|
+
if (options.column_mapping) {
|
|
1042
|
+
formData.append("column_mapping", JSON.stringify(options.column_mapping));
|
|
1043
|
+
}
|
|
1044
|
+
if (options.skip_header !== void 0) {
|
|
1045
|
+
formData.append("skip_header", options.skip_header.toString());
|
|
1046
|
+
}
|
|
1047
|
+
if (options.delimiter) formData.append("delimiter", options.delimiter);
|
|
1048
|
+
if (options.batch_size) formData.append("batch_size", options.batch_size.toString());
|
|
1049
|
+
if (options.continue_on_error !== void 0) {
|
|
1050
|
+
formData.append("continue_on_error", options.continue_on_error.toString());
|
|
1051
|
+
}
|
|
1052
|
+
if (options.primary_keys) {
|
|
1053
|
+
formData.append("primary_keys", JSON.stringify(options.primary_keys));
|
|
1054
|
+
}
|
|
1055
|
+
if (Buffer.isBuffer(options.data)) {
|
|
1056
|
+
formData.append("file", new Blob([options.data]), "data");
|
|
1057
|
+
} else {
|
|
1058
|
+
formData.append("data", options.data);
|
|
1059
|
+
}
|
|
1060
|
+
const { data } = await this.synapCores._getHttpClient().post("/import", formData, {
|
|
1061
|
+
headers: {
|
|
1062
|
+
"Content-Type": "multipart/form-data"
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
return {
|
|
1066
|
+
id: data.id || data.job_id,
|
|
1067
|
+
success: data.success,
|
|
1068
|
+
rows_processed: data.rows_processed || 0,
|
|
1069
|
+
rows_imported: data.rows_imported || 0,
|
|
1070
|
+
rows_failed: data.rows_failed || 0,
|
|
1071
|
+
duration_ms: data.duration_ms || data.took_ms || 0,
|
|
1072
|
+
errors: data.errors || [],
|
|
1073
|
+
warnings: data.warnings || []
|
|
1074
|
+
};
|
|
1075
|
+
}
|
|
1076
|
+
/**
|
|
1077
|
+
* Export data from a table or query
|
|
1078
|
+
*/
|
|
1079
|
+
async export(options) {
|
|
1080
|
+
const { data } = await this.synapCores._getHttpClient().post("/export", {
|
|
1081
|
+
source: options.source,
|
|
1082
|
+
format: options.format,
|
|
1083
|
+
destination: options.destination || "response",
|
|
1084
|
+
columns: options.columns,
|
|
1085
|
+
filter: options.filter,
|
|
1086
|
+
order_by: options.order_by,
|
|
1087
|
+
limit: options.limit,
|
|
1088
|
+
include_header: options.include_header,
|
|
1089
|
+
delimiter: options.delimiter,
|
|
1090
|
+
compress: options.compress
|
|
1091
|
+
});
|
|
1092
|
+
return {
|
|
1093
|
+
id: data.id || data.job_id,
|
|
1094
|
+
success: data.success,
|
|
1095
|
+
rows_exported: data.rows_exported || 0,
|
|
1096
|
+
duration_ms: data.duration_ms || data.took_ms || 0,
|
|
1097
|
+
file_path: data.file_path,
|
|
1098
|
+
data: data.data,
|
|
1099
|
+
size_bytes: data.size_bytes,
|
|
1100
|
+
download_url: data.download_url,
|
|
1101
|
+
expires_at: data.expires_at ? new Date(data.expires_at) : void 0
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
/**
|
|
1105
|
+
* Get import job status
|
|
1106
|
+
*/
|
|
1107
|
+
async getImportStatus(jobId) {
|
|
1108
|
+
const { data } = await this.synapCores._getHttpClient().get(`/import/${jobId}/status`);
|
|
1109
|
+
return {
|
|
1110
|
+
id: data.id || jobId,
|
|
1111
|
+
status: data.status,
|
|
1112
|
+
progress: data.progress || 0,
|
|
1113
|
+
phase: data.phase,
|
|
1114
|
+
rows_processed: data.rows_processed,
|
|
1115
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
1116
|
+
error: data.error,
|
|
1117
|
+
started_at: data.started_at ? new Date(data.started_at) : void 0,
|
|
1118
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1119
|
+
};
|
|
1120
|
+
}
|
|
1121
|
+
/**
|
|
1122
|
+
* Get export job status
|
|
1123
|
+
*/
|
|
1124
|
+
async getExportStatus(jobId) {
|
|
1125
|
+
const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/status`);
|
|
1126
|
+
return {
|
|
1127
|
+
id: data.id || jobId,
|
|
1128
|
+
status: data.status,
|
|
1129
|
+
progress: data.progress || 0,
|
|
1130
|
+
phase: data.phase,
|
|
1131
|
+
rows_exported: data.rows_exported,
|
|
1132
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
1133
|
+
error: data.error,
|
|
1134
|
+
started_at: data.started_at ? new Date(data.started_at) : void 0,
|
|
1135
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1136
|
+
};
|
|
1137
|
+
}
|
|
1138
|
+
/**
|
|
1139
|
+
* Cancel an import job
|
|
1140
|
+
*/
|
|
1141
|
+
async cancelImport(jobId) {
|
|
1142
|
+
await this.synapCores._getHttpClient().post(`/import/${jobId}/cancel`);
|
|
1143
|
+
}
|
|
1144
|
+
/**
|
|
1145
|
+
* Cancel an export job
|
|
1146
|
+
*/
|
|
1147
|
+
async cancelExport(jobId) {
|
|
1148
|
+
await this.synapCores._getHttpClient().post(`/export/${jobId}/cancel`);
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Import data from multiple sources in bulk
|
|
1152
|
+
*/
|
|
1153
|
+
async bulkImport(options) {
|
|
1154
|
+
const { data } = await this.synapCores._getHttpClient().post("/import/bulk", {
|
|
1155
|
+
jobs: options.jobs,
|
|
1156
|
+
parallel: options.parallel || false,
|
|
1157
|
+
stop_on_error: options.stop_on_error || false
|
|
1158
|
+
});
|
|
1159
|
+
return {
|
|
1160
|
+
id: data.id || data.bulk_id,
|
|
1161
|
+
success: data.success,
|
|
1162
|
+
results: data.results || [],
|
|
1163
|
+
total_rows_imported: data.total_rows_imported || 0,
|
|
1164
|
+
total_duration_ms: data.total_duration_ms || data.took_ms || 0
|
|
1165
|
+
};
|
|
1166
|
+
}
|
|
1167
|
+
/**
|
|
1168
|
+
* Validate data before import
|
|
1169
|
+
*/
|
|
1170
|
+
async validateData(options) {
|
|
1171
|
+
const { data } = await this.synapCores._getHttpClient().post("/import/validate", {
|
|
1172
|
+
table: options.table,
|
|
1173
|
+
data: options.data,
|
|
1174
|
+
mode: options.mode || "strict",
|
|
1175
|
+
check_foreign_keys: options.check_foreign_keys,
|
|
1176
|
+
check_unique: options.check_unique
|
|
1177
|
+
});
|
|
1178
|
+
return {
|
|
1179
|
+
is_valid: data.is_valid || data.valid,
|
|
1180
|
+
errors: data.errors || [],
|
|
1181
|
+
warnings: data.warnings || [],
|
|
1182
|
+
rows_validated: data.rows_validated || options.data.length
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Get import template for a table
|
|
1187
|
+
*/
|
|
1188
|
+
async getImportTemplate(tableName, format = "csv") {
|
|
1189
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1190
|
+
`/import/template/${tableName}?format=${format}`
|
|
1191
|
+
);
|
|
1192
|
+
return data.template || data.content || data;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* List import/export jobs
|
|
1196
|
+
*/
|
|
1197
|
+
async listJobs(options = {}) {
|
|
1198
|
+
const params = new URLSearchParams();
|
|
1199
|
+
if (options.type) params.append("type", options.type);
|
|
1200
|
+
if (options.status) params.append("status", options.status);
|
|
1201
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1202
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1203
|
+
`/import/jobs?${params.toString()}`
|
|
1204
|
+
);
|
|
1205
|
+
return (data.jobs || data).map((job) => ({
|
|
1206
|
+
id: job.id,
|
|
1207
|
+
status: job.status,
|
|
1208
|
+
progress: job.progress || 0,
|
|
1209
|
+
phase: job.phase,
|
|
1210
|
+
rows_processed: job.rows_processed,
|
|
1211
|
+
rows_exported: job.rows_exported,
|
|
1212
|
+
eta_ms: job.eta_ms,
|
|
1213
|
+
error: job.error,
|
|
1214
|
+
started_at: job.started_at ? new Date(job.started_at) : void 0,
|
|
1215
|
+
completed_at: job.completed_at ? new Date(job.completed_at) : void 0
|
|
1216
|
+
}));
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Download exported data
|
|
1220
|
+
*/
|
|
1221
|
+
async downloadExport(jobId) {
|
|
1222
|
+
const { data } = await this.synapCores._getHttpClient().get(`/export/${jobId}/download`, {
|
|
1223
|
+
responseType: "arraybuffer"
|
|
1224
|
+
});
|
|
1225
|
+
return Buffer.from(data);
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Stream import data (for large files)
|
|
1229
|
+
*/
|
|
1230
|
+
async streamImport(options, onProgress) {
|
|
1231
|
+
const result = await this.import(options);
|
|
1232
|
+
const jobId = result.id;
|
|
1233
|
+
if (onProgress) {
|
|
1234
|
+
const pollInterval = setInterval(async () => {
|
|
1235
|
+
try {
|
|
1236
|
+
const status = await this.getImportStatus(jobId);
|
|
1237
|
+
onProgress(status);
|
|
1238
|
+
if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
|
|
1239
|
+
clearInterval(pollInterval);
|
|
1240
|
+
}
|
|
1241
|
+
} catch (error) {
|
|
1242
|
+
clearInterval(pollInterval);
|
|
1243
|
+
}
|
|
1244
|
+
}, 1e3);
|
|
1245
|
+
}
|
|
1246
|
+
return result;
|
|
1247
|
+
}
|
|
1248
|
+
/**
|
|
1249
|
+
* Stream export data (for large datasets)
|
|
1250
|
+
*/
|
|
1251
|
+
async streamExport(options, onProgress) {
|
|
1252
|
+
const result = await this.export(options);
|
|
1253
|
+
const jobId = result.id;
|
|
1254
|
+
if (onProgress) {
|
|
1255
|
+
const pollInterval = setInterval(async () => {
|
|
1256
|
+
try {
|
|
1257
|
+
const status = await this.getExportStatus(jobId);
|
|
1258
|
+
onProgress(status);
|
|
1259
|
+
if (status.status === "completed" || status.status === "failed" || status.status === "cancelled") {
|
|
1260
|
+
clearInterval(pollInterval);
|
|
1261
|
+
}
|
|
1262
|
+
} catch (error) {
|
|
1263
|
+
clearInterval(pollInterval);
|
|
1264
|
+
}
|
|
1265
|
+
}, 1e3);
|
|
1266
|
+
}
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
1269
|
+
};
|
|
1270
|
+
|
|
1271
|
+
// src/integrations.ts
|
|
1272
|
+
var IntegrationClient = class {
|
|
1273
|
+
constructor(synapCores) {
|
|
1274
|
+
this.synapCores = synapCores;
|
|
1275
|
+
}
|
|
1276
|
+
/**
|
|
1277
|
+
* Create a new integration
|
|
1278
|
+
*/
|
|
1279
|
+
async create(options) {
|
|
1280
|
+
const { data } = await this.synapCores._getHttpClient().post("/integrations", {
|
|
1281
|
+
name: options.name,
|
|
1282
|
+
type: options.type,
|
|
1283
|
+
config: options.config,
|
|
1284
|
+
description: options.description,
|
|
1285
|
+
tags: options.tags || [],
|
|
1286
|
+
activate: options.activate || false
|
|
1287
|
+
});
|
|
1288
|
+
return this.mapIntegration(data);
|
|
1289
|
+
}
|
|
1290
|
+
/**
|
|
1291
|
+
* List integrations with optional filters
|
|
1292
|
+
*/
|
|
1293
|
+
async list(options = {}) {
|
|
1294
|
+
const params = new URLSearchParams();
|
|
1295
|
+
if (options.type) params.append("type", options.type);
|
|
1296
|
+
if (options.status) params.append("status", options.status);
|
|
1297
|
+
if (options.search) params.append("search", options.search);
|
|
1298
|
+
if (options.page) params.append("page", options.page.toString());
|
|
1299
|
+
if (options.page_size) params.append("page_size", options.page_size.toString());
|
|
1300
|
+
if (options.tags && options.tags.length > 0) {
|
|
1301
|
+
params.append("tags", options.tags.join(","));
|
|
1302
|
+
}
|
|
1303
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1304
|
+
`/integrations?${params.toString()}`
|
|
1305
|
+
);
|
|
1306
|
+
return (data.integrations || data).map(
|
|
1307
|
+
(integration) => this.mapIntegration(integration)
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Get a specific integration by ID
|
|
1312
|
+
*/
|
|
1313
|
+
async get(id) {
|
|
1314
|
+
const { data } = await this.synapCores._getHttpClient().get(`/integrations/${id}`);
|
|
1315
|
+
return this.mapIntegration(data);
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Update an existing integration
|
|
1319
|
+
*/
|
|
1320
|
+
async update(id, updates) {
|
|
1321
|
+
const { data } = await this.synapCores._getHttpClient().put(
|
|
1322
|
+
`/integrations/${id}`,
|
|
1323
|
+
updates
|
|
1324
|
+
);
|
|
1325
|
+
return this.mapIntegration(data);
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Delete an integration
|
|
1329
|
+
*/
|
|
1330
|
+
async delete(id) {
|
|
1331
|
+
await this.synapCores._getHttpClient().delete(`/integrations/${id}`);
|
|
1332
|
+
}
|
|
1333
|
+
/**
|
|
1334
|
+
* Activate an integration
|
|
1335
|
+
*/
|
|
1336
|
+
async activate(id) {
|
|
1337
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1338
|
+
`/integrations/${id}/activate`
|
|
1339
|
+
);
|
|
1340
|
+
return this.mapIntegration(data);
|
|
1341
|
+
}
|
|
1342
|
+
/**
|
|
1343
|
+
* Deactivate an integration
|
|
1344
|
+
*/
|
|
1345
|
+
async deactivate(id) {
|
|
1346
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1347
|
+
`/integrations/${id}/deactivate`
|
|
1348
|
+
);
|
|
1349
|
+
return this.mapIntegration(data);
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Execute an integration
|
|
1353
|
+
*/
|
|
1354
|
+
async execute(options) {
|
|
1355
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1356
|
+
`/integrations/${options.integration}/execute`,
|
|
1357
|
+
{
|
|
1358
|
+
payload: options.payload,
|
|
1359
|
+
config_override: options.config_override,
|
|
1360
|
+
sync: options.sync !== false
|
|
1361
|
+
}
|
|
1362
|
+
);
|
|
1363
|
+
return {
|
|
1364
|
+
id: data.id || data.execution_id,
|
|
1365
|
+
success: data.success,
|
|
1366
|
+
response: data.response,
|
|
1367
|
+
status_code: data.status_code,
|
|
1368
|
+
error: data.error,
|
|
1369
|
+
execution_time_ms: data.execution_time_ms || data.took_ms || 0,
|
|
1370
|
+
retry_count: data.retry_count || 0,
|
|
1371
|
+
executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
|
|
1372
|
+
};
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Test an integration without executing
|
|
1376
|
+
*/
|
|
1377
|
+
async test(options) {
|
|
1378
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1379
|
+
`/integrations/${options.integration}/test`,
|
|
1380
|
+
{
|
|
1381
|
+
payload: options.payload,
|
|
1382
|
+
validate_only: options.validate_only || false
|
|
1383
|
+
}
|
|
1384
|
+
);
|
|
1385
|
+
return {
|
|
1386
|
+
success: data.success,
|
|
1387
|
+
validation_errors: data.validation_errors || [],
|
|
1388
|
+
response: data.response,
|
|
1389
|
+
error: data.error,
|
|
1390
|
+
latency_ms: data.latency_ms
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Get integration execution history
|
|
1395
|
+
*/
|
|
1396
|
+
async getExecutionHistory(integrationId, options = {}) {
|
|
1397
|
+
const params = new URLSearchParams();
|
|
1398
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1399
|
+
if (options.offset) params.append("offset", options.offset.toString());
|
|
1400
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1401
|
+
`/integrations/${integrationId}/executions?${params.toString()}`
|
|
1402
|
+
);
|
|
1403
|
+
return (data.executions || data).map((exec) => ({
|
|
1404
|
+
id: exec.id || exec.execution_id,
|
|
1405
|
+
success: exec.success,
|
|
1406
|
+
response: exec.response,
|
|
1407
|
+
status_code: exec.status_code,
|
|
1408
|
+
error: exec.error,
|
|
1409
|
+
execution_time_ms: exec.execution_time_ms || exec.took_ms || 0,
|
|
1410
|
+
retry_count: exec.retry_count || 0,
|
|
1411
|
+
executed_at: exec.executed_at ? new Date(exec.executed_at) : /* @__PURE__ */ new Date()
|
|
1412
|
+
}));
|
|
1413
|
+
}
|
|
1414
|
+
/**
|
|
1415
|
+
* Get integration statistics
|
|
1416
|
+
*/
|
|
1417
|
+
async getStats(integrationId) {
|
|
1418
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1419
|
+
`/integrations/${integrationId}/stats`
|
|
1420
|
+
);
|
|
1421
|
+
return {
|
|
1422
|
+
integration_id: integrationId,
|
|
1423
|
+
total_executions: data.total_executions || 0,
|
|
1424
|
+
successful_executions: data.successful_executions || 0,
|
|
1425
|
+
failed_executions: data.failed_executions || 0,
|
|
1426
|
+
avg_execution_time_ms: data.avg_execution_time_ms || 0,
|
|
1427
|
+
executions_24h: data.executions_24h || 0,
|
|
1428
|
+
uptime_percentage: data.uptime_percentage || 0,
|
|
1429
|
+
last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
|
|
1430
|
+
last_error_at: data.last_error_at ? new Date(data.last_error_at) : void 0
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Create a webhook for an integration
|
|
1435
|
+
*/
|
|
1436
|
+
async createWebhook(options) {
|
|
1437
|
+
const { data } = await this.synapCores._getHttpClient().post("/integrations/webhooks", {
|
|
1438
|
+
integration_id: options.integration_id,
|
|
1439
|
+
event: options.event,
|
|
1440
|
+
url: options.url,
|
|
1441
|
+
secret: options.secret,
|
|
1442
|
+
activate: options.activate !== false
|
|
1443
|
+
});
|
|
1444
|
+
return {
|
|
1445
|
+
id: data.id,
|
|
1446
|
+
integration_id: data.integration_id,
|
|
1447
|
+
event: data.event,
|
|
1448
|
+
url: data.url,
|
|
1449
|
+
active: data.active,
|
|
1450
|
+
secret: data.secret,
|
|
1451
|
+
created_at: new Date(data.created_at)
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
/**
|
|
1455
|
+
* List webhooks for an integration
|
|
1456
|
+
*/
|
|
1457
|
+
async listWebhooks(integrationId) {
|
|
1458
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1459
|
+
`/integrations/${integrationId}/webhooks`
|
|
1460
|
+
);
|
|
1461
|
+
return (data.webhooks || data).map((webhook) => ({
|
|
1462
|
+
id: webhook.id,
|
|
1463
|
+
integration_id: webhook.integration_id,
|
|
1464
|
+
event: webhook.event,
|
|
1465
|
+
url: webhook.url,
|
|
1466
|
+
active: webhook.active,
|
|
1467
|
+
secret: webhook.secret,
|
|
1468
|
+
created_at: new Date(webhook.created_at)
|
|
1469
|
+
}));
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Delete a webhook
|
|
1473
|
+
*/
|
|
1474
|
+
async deleteWebhook(webhookId) {
|
|
1475
|
+
await this.synapCores._getHttpClient().delete(`/integrations/webhooks/${webhookId}`);
|
|
1476
|
+
}
|
|
1477
|
+
/**
|
|
1478
|
+
* Get integration events
|
|
1479
|
+
*/
|
|
1480
|
+
async getEvents(integrationId, options = {}) {
|
|
1481
|
+
const params = new URLSearchParams();
|
|
1482
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1483
|
+
if (options.status) params.append("status", options.status);
|
|
1484
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1485
|
+
`/integrations/${integrationId}/events?${params.toString()}`
|
|
1486
|
+
);
|
|
1487
|
+
return (data.events || data).map((event) => ({
|
|
1488
|
+
id: event.id,
|
|
1489
|
+
integration_id: event.integration_id,
|
|
1490
|
+
event: event.event,
|
|
1491
|
+
data: event.data,
|
|
1492
|
+
timestamp: new Date(event.timestamp),
|
|
1493
|
+
status: event.status,
|
|
1494
|
+
error: event.error
|
|
1495
|
+
}));
|
|
1496
|
+
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Get integration logs
|
|
1499
|
+
*/
|
|
1500
|
+
async getLogs(integrationId, options = {}) {
|
|
1501
|
+
const params = new URLSearchParams();
|
|
1502
|
+
if (options.limit) params.append("limit", options.limit.toString());
|
|
1503
|
+
if (options.level) params.append("level", options.level);
|
|
1504
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1505
|
+
`/integrations/${integrationId}/logs?${params.toString()}`
|
|
1506
|
+
);
|
|
1507
|
+
return (data.logs || data).map((log) => ({
|
|
1508
|
+
id: log.id,
|
|
1509
|
+
integration_id: log.integration_id,
|
|
1510
|
+
level: log.level,
|
|
1511
|
+
message: log.message,
|
|
1512
|
+
data: log.data,
|
|
1513
|
+
timestamp: new Date(log.timestamp)
|
|
1514
|
+
}));
|
|
1515
|
+
}
|
|
1516
|
+
/**
|
|
1517
|
+
* Retry a failed execution
|
|
1518
|
+
*/
|
|
1519
|
+
async retryExecution(executionId) {
|
|
1520
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1521
|
+
`/integrations/executions/${executionId}/retry`
|
|
1522
|
+
);
|
|
1523
|
+
return {
|
|
1524
|
+
id: data.id || data.execution_id,
|
|
1525
|
+
success: data.success,
|
|
1526
|
+
response: data.response,
|
|
1527
|
+
status_code: data.status_code,
|
|
1528
|
+
error: data.error,
|
|
1529
|
+
execution_time_ms: data.execution_time_ms || data.took_ms || 0,
|
|
1530
|
+
retry_count: data.retry_count || 0,
|
|
1531
|
+
executed_at: data.executed_at ? new Date(data.executed_at) : /* @__PURE__ */ new Date()
|
|
1532
|
+
};
|
|
1533
|
+
}
|
|
1534
|
+
/**
|
|
1535
|
+
* Map raw integration data to Integration type
|
|
1536
|
+
*/
|
|
1537
|
+
mapIntegration(data) {
|
|
1538
|
+
return {
|
|
1539
|
+
id: data.id,
|
|
1540
|
+
name: data.name,
|
|
1541
|
+
type: data.type,
|
|
1542
|
+
status: data.status,
|
|
1543
|
+
config: data.config,
|
|
1544
|
+
description: data.description,
|
|
1545
|
+
tags: data.tags || [],
|
|
1546
|
+
created_at: new Date(data.created_at),
|
|
1547
|
+
updated_at: new Date(data.updated_at),
|
|
1548
|
+
last_success_at: data.last_success_at ? new Date(data.last_success_at) : void 0,
|
|
1549
|
+
last_error: data.last_error,
|
|
1550
|
+
execution_count: data.execution_count
|
|
1551
|
+
};
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// src/backup.ts
|
|
1556
|
+
var BackupClient = class {
|
|
1557
|
+
constructor(synapCores) {
|
|
1558
|
+
this.synapCores = synapCores;
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Create a new backup
|
|
1562
|
+
*/
|
|
1563
|
+
async create(options = {}) {
|
|
1564
|
+
const { data } = await this.synapCores._getHttpClient().post("/backups", {
|
|
1565
|
+
name: options.name,
|
|
1566
|
+
description: options.description,
|
|
1567
|
+
type: options.type || "full",
|
|
1568
|
+
tables: options.tables,
|
|
1569
|
+
include_indexes: options.include_indexes !== false,
|
|
1570
|
+
include_procedures: options.include_procedures !== false,
|
|
1571
|
+
compression: options.compression || 6,
|
|
1572
|
+
encrypt: options.encrypt || false,
|
|
1573
|
+
encryption_key: options.encryption_key,
|
|
1574
|
+
storage: options.storage || "local",
|
|
1575
|
+
storage_config: options.storage_config,
|
|
1576
|
+
tags: options.tags || []
|
|
1577
|
+
});
|
|
1578
|
+
return this.mapBackup(data);
|
|
1579
|
+
}
|
|
1580
|
+
/**
|
|
1581
|
+
* List backups with optional filters
|
|
1582
|
+
*/
|
|
1583
|
+
async list(options = {}) {
|
|
1584
|
+
const params = new URLSearchParams();
|
|
1585
|
+
if (options.type) params.append("type", options.type);
|
|
1586
|
+
if (options.status) params.append("status", options.status);
|
|
1587
|
+
if (options.sort) params.append("sort", options.sort);
|
|
1588
|
+
if (options.order) params.append("order", options.order);
|
|
1589
|
+
if (options.page) params.append("page", options.page.toString());
|
|
1590
|
+
if (options.page_size) params.append("page_size", options.page_size.toString());
|
|
1591
|
+
if (options.tags && options.tags.length > 0) {
|
|
1592
|
+
params.append("tags", options.tags.join(","));
|
|
1593
|
+
}
|
|
1594
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1595
|
+
`/backups?${params.toString()}`
|
|
1596
|
+
);
|
|
1597
|
+
return (data.backups || data).map((backup) => this.mapBackup(backup));
|
|
1598
|
+
}
|
|
1599
|
+
/**
|
|
1600
|
+
* Get a specific backup by ID
|
|
1601
|
+
*/
|
|
1602
|
+
async get(id) {
|
|
1603
|
+
const { data } = await this.synapCores._getHttpClient().get(`/backups/${id}`);
|
|
1604
|
+
return this.mapBackup(data);
|
|
1605
|
+
}
|
|
1606
|
+
/**
|
|
1607
|
+
* Delete a backup
|
|
1608
|
+
*/
|
|
1609
|
+
async delete(id) {
|
|
1610
|
+
await this.synapCores._getHttpClient().delete(`/backups/${id}`);
|
|
1611
|
+
}
|
|
1612
|
+
/**
|
|
1613
|
+
* Restore from a backup
|
|
1614
|
+
*/
|
|
1615
|
+
async restore(options) {
|
|
1616
|
+
const { data } = await this.synapCores._getHttpClient().post("/backups/restore", {
|
|
1617
|
+
backup_id: options.backup_id,
|
|
1618
|
+
mode: options.mode || "full",
|
|
1619
|
+
tables: options.tables,
|
|
1620
|
+
target_database: options.target_database,
|
|
1621
|
+
overwrite: options.overwrite || false,
|
|
1622
|
+
skip_indexes: options.skip_indexes || false,
|
|
1623
|
+
skip_procedures: options.skip_procedures || false,
|
|
1624
|
+
decryption_key: options.decryption_key,
|
|
1625
|
+
point_in_time: options.point_in_time?.toISOString(),
|
|
1626
|
+
dry_run: options.dry_run || false
|
|
1627
|
+
});
|
|
1628
|
+
return {
|
|
1629
|
+
id: data.id || data.restore_id,
|
|
1630
|
+
success: data.success,
|
|
1631
|
+
tables_restored: data.tables_restored || [],
|
|
1632
|
+
rows_restored: data.rows_restored || 0,
|
|
1633
|
+
duration_ms: data.duration_ms || data.took_ms || 0,
|
|
1634
|
+
error: data.error,
|
|
1635
|
+
warnings: data.warnings || []
|
|
1636
|
+
};
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Get backup status
|
|
1640
|
+
*/
|
|
1641
|
+
async getBackupStatus(backupId) {
|
|
1642
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1643
|
+
`/backups/${backupId}/status`
|
|
1644
|
+
);
|
|
1645
|
+
return {
|
|
1646
|
+
id: data.id || backupId,
|
|
1647
|
+
status: data.status,
|
|
1648
|
+
progress: data.progress || 0,
|
|
1649
|
+
phase: data.phase,
|
|
1650
|
+
tables_processed: data.tables_processed,
|
|
1651
|
+
total_tables: data.total_tables,
|
|
1652
|
+
bytes_processed: data.bytes_processed,
|
|
1653
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
1654
|
+
error: data.error,
|
|
1655
|
+
started_at: data.started_at ? new Date(data.started_at) : void 0,
|
|
1656
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1657
|
+
};
|
|
1658
|
+
}
|
|
1659
|
+
/**
|
|
1660
|
+
* Get restore status
|
|
1661
|
+
*/
|
|
1662
|
+
async getRestoreStatus(restoreId) {
|
|
1663
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1664
|
+
`/backups/restore/${restoreId}/status`
|
|
1665
|
+
);
|
|
1666
|
+
return {
|
|
1667
|
+
id: data.id || restoreId,
|
|
1668
|
+
status: data.status,
|
|
1669
|
+
progress: data.progress || 0,
|
|
1670
|
+
phase: data.phase,
|
|
1671
|
+
tables_processed: data.tables_processed,
|
|
1672
|
+
total_tables: data.total_tables,
|
|
1673
|
+
rows_processed: data.rows_processed,
|
|
1674
|
+
eta_ms: data.eta_ms || data.estimated_time_remaining_ms,
|
|
1675
|
+
error: data.error,
|
|
1676
|
+
started_at: data.started_at ? new Date(data.started_at) : void 0,
|
|
1677
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0
|
|
1678
|
+
};
|
|
1679
|
+
}
|
|
1680
|
+
/**
|
|
1681
|
+
* Cancel a backup in progress
|
|
1682
|
+
*/
|
|
1683
|
+
async cancelBackup(backupId) {
|
|
1684
|
+
await this.synapCores._getHttpClient().post(`/backups/${backupId}/cancel`);
|
|
1685
|
+
}
|
|
1686
|
+
/**
|
|
1687
|
+
* Cancel a restore in progress
|
|
1688
|
+
*/
|
|
1689
|
+
async cancelRestore(restoreId) {
|
|
1690
|
+
await this.synapCores._getHttpClient().post(`/backups/restore/${restoreId}/cancel`);
|
|
1691
|
+
}
|
|
1692
|
+
/**
|
|
1693
|
+
* Download a backup file
|
|
1694
|
+
*/
|
|
1695
|
+
async download(backupId) {
|
|
1696
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1697
|
+
`/backups/${backupId}/download`,
|
|
1698
|
+
{
|
|
1699
|
+
responseType: "arraybuffer"
|
|
1700
|
+
}
|
|
1701
|
+
);
|
|
1702
|
+
return Buffer.from(data);
|
|
1703
|
+
}
|
|
1704
|
+
/**
|
|
1705
|
+
* Verify backup integrity
|
|
1706
|
+
*/
|
|
1707
|
+
async verify(backupId) {
|
|
1708
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1709
|
+
`/backups/${backupId}/verify`
|
|
1710
|
+
);
|
|
1711
|
+
return {
|
|
1712
|
+
is_valid: data.is_valid || data.valid,
|
|
1713
|
+
integrity_ok: data.integrity_ok || data.integrity,
|
|
1714
|
+
checksum_match: data.checksum_match,
|
|
1715
|
+
tables_verified: data.tables_verified || 0,
|
|
1716
|
+
errors: data.errors || [],
|
|
1717
|
+
warnings: data.warnings || [],
|
|
1718
|
+
verified_at: data.verified_at ? new Date(data.verified_at) : /* @__PURE__ */ new Date()
|
|
1719
|
+
};
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* Create a backup schedule
|
|
1723
|
+
*/
|
|
1724
|
+
async createSchedule(options) {
|
|
1725
|
+
const { data } = await this.synapCores._getHttpClient().post("/backups/schedules", {
|
|
1726
|
+
name: options.name,
|
|
1727
|
+
cron: options.cron,
|
|
1728
|
+
backup_options: options.backup_options,
|
|
1729
|
+
activate: options.activate !== false,
|
|
1730
|
+
tags: options.tags || []
|
|
1731
|
+
});
|
|
1732
|
+
return {
|
|
1733
|
+
id: data.id,
|
|
1734
|
+
name: data.name,
|
|
1735
|
+
cron: data.cron,
|
|
1736
|
+
backup_options: data.backup_options,
|
|
1737
|
+
active: data.active,
|
|
1738
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1739
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1740
|
+
created_at: new Date(data.created_at),
|
|
1741
|
+
tags: data.tags || []
|
|
1742
|
+
};
|
|
1743
|
+
}
|
|
1744
|
+
/**
|
|
1745
|
+
* List backup schedules
|
|
1746
|
+
*/
|
|
1747
|
+
async listSchedules() {
|
|
1748
|
+
const { data } = await this.synapCores._getHttpClient().get("/backups/schedules");
|
|
1749
|
+
return (data.schedules || data).map((schedule) => ({
|
|
1750
|
+
id: schedule.id,
|
|
1751
|
+
name: schedule.name,
|
|
1752
|
+
cron: schedule.cron,
|
|
1753
|
+
backup_options: schedule.backup_options,
|
|
1754
|
+
active: schedule.active,
|
|
1755
|
+
last_run_at: schedule.last_run_at ? new Date(schedule.last_run_at) : void 0,
|
|
1756
|
+
next_run_at: schedule.next_run_at ? new Date(schedule.next_run_at) : void 0,
|
|
1757
|
+
created_at: new Date(schedule.created_at),
|
|
1758
|
+
tags: schedule.tags || []
|
|
1759
|
+
}));
|
|
1760
|
+
}
|
|
1761
|
+
/**
|
|
1762
|
+
* Get a specific schedule
|
|
1763
|
+
*/
|
|
1764
|
+
async getSchedule(scheduleId) {
|
|
1765
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
1766
|
+
`/backups/schedules/${scheduleId}`
|
|
1767
|
+
);
|
|
1768
|
+
return {
|
|
1769
|
+
id: data.id,
|
|
1770
|
+
name: data.name,
|
|
1771
|
+
cron: data.cron,
|
|
1772
|
+
backup_options: data.backup_options,
|
|
1773
|
+
active: data.active,
|
|
1774
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1775
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1776
|
+
created_at: new Date(data.created_at),
|
|
1777
|
+
tags: data.tags || []
|
|
1778
|
+
};
|
|
1779
|
+
}
|
|
1780
|
+
/**
|
|
1781
|
+
* Update a backup schedule
|
|
1782
|
+
*/
|
|
1783
|
+
async updateSchedule(scheduleId, updates) {
|
|
1784
|
+
const { data } = await this.synapCores._getHttpClient().put(
|
|
1785
|
+
`/backups/schedules/${scheduleId}`,
|
|
1786
|
+
updates
|
|
1787
|
+
);
|
|
1788
|
+
return {
|
|
1789
|
+
id: data.id,
|
|
1790
|
+
name: data.name,
|
|
1791
|
+
cron: data.cron,
|
|
1792
|
+
backup_options: data.backup_options,
|
|
1793
|
+
active: data.active,
|
|
1794
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1795
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1796
|
+
created_at: new Date(data.created_at),
|
|
1797
|
+
tags: data.tags || []
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Delete a backup schedule
|
|
1802
|
+
*/
|
|
1803
|
+
async deleteSchedule(scheduleId) {
|
|
1804
|
+
await this.synapCores._getHttpClient().delete(`/backups/schedules/${scheduleId}`);
|
|
1805
|
+
}
|
|
1806
|
+
/**
|
|
1807
|
+
* Activate a schedule
|
|
1808
|
+
*/
|
|
1809
|
+
async activateSchedule(scheduleId) {
|
|
1810
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1811
|
+
`/backups/schedules/${scheduleId}/activate`
|
|
1812
|
+
);
|
|
1813
|
+
return {
|
|
1814
|
+
id: data.id,
|
|
1815
|
+
name: data.name,
|
|
1816
|
+
cron: data.cron,
|
|
1817
|
+
backup_options: data.backup_options,
|
|
1818
|
+
active: data.active,
|
|
1819
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1820
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1821
|
+
created_at: new Date(data.created_at),
|
|
1822
|
+
tags: data.tags || []
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Deactivate a schedule
|
|
1827
|
+
*/
|
|
1828
|
+
async deactivateSchedule(scheduleId) {
|
|
1829
|
+
const { data } = await this.synapCores._getHttpClient().post(
|
|
1830
|
+
`/backups/schedules/${scheduleId}/deactivate`
|
|
1831
|
+
);
|
|
1832
|
+
return {
|
|
1833
|
+
id: data.id,
|
|
1834
|
+
name: data.name,
|
|
1835
|
+
cron: data.cron,
|
|
1836
|
+
backup_options: data.backup_options,
|
|
1837
|
+
active: data.active,
|
|
1838
|
+
last_run_at: data.last_run_at ? new Date(data.last_run_at) : void 0,
|
|
1839
|
+
next_run_at: data.next_run_at ? new Date(data.next_run_at) : void 0,
|
|
1840
|
+
created_at: new Date(data.created_at),
|
|
1841
|
+
tags: data.tags || []
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1844
|
+
/**
|
|
1845
|
+
* Get backup metrics
|
|
1846
|
+
*/
|
|
1847
|
+
async getMetrics() {
|
|
1848
|
+
const { data } = await this.synapCores._getHttpClient().get("/backups/metrics");
|
|
1849
|
+
return {
|
|
1850
|
+
total_backups: data.total_backups || 0,
|
|
1851
|
+
total_size_bytes: data.total_size_bytes || 0,
|
|
1852
|
+
successful_backups: data.successful_backups || 0,
|
|
1853
|
+
failed_backups: data.failed_backups || 0,
|
|
1854
|
+
avg_backup_size_bytes: data.avg_backup_size_bytes || 0,
|
|
1855
|
+
avg_duration_ms: data.avg_duration_ms || 0,
|
|
1856
|
+
last_backup_at: data.last_backup_at ? new Date(data.last_backup_at) : void 0,
|
|
1857
|
+
next_scheduled_at: data.next_scheduled_at ? new Date(data.next_scheduled_at) : void 0
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Map raw backup data to Backup type
|
|
1862
|
+
*/
|
|
1863
|
+
mapBackup(data) {
|
|
1864
|
+
return {
|
|
1865
|
+
id: data.id,
|
|
1866
|
+
name: data.name,
|
|
1867
|
+
description: data.description,
|
|
1868
|
+
type: data.type,
|
|
1869
|
+
status: data.status,
|
|
1870
|
+
size_bytes: data.size_bytes,
|
|
1871
|
+
compressed_size_bytes: data.compressed_size_bytes,
|
|
1872
|
+
table_count: data.table_count,
|
|
1873
|
+
created_at: new Date(data.created_at),
|
|
1874
|
+
completed_at: data.completed_at ? new Date(data.completed_at) : void 0,
|
|
1875
|
+
duration_ms: data.duration_ms || data.took_ms,
|
|
1876
|
+
storage: data.storage,
|
|
1877
|
+
storage_path: data.storage_path,
|
|
1878
|
+
encrypted: data.encrypted || false,
|
|
1879
|
+
tags: data.tags || [],
|
|
1880
|
+
parent_backup_id: data.parent_backup_id,
|
|
1881
|
+
error: data.error
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
};
|
|
1885
|
+
|
|
1886
|
+
// src/errors.ts
|
|
1887
|
+
var SynapCoresError = class _SynapCoresError extends Error {
|
|
1888
|
+
constructor(message, code, details) {
|
|
1889
|
+
super(message);
|
|
1890
|
+
this.name = "SynapCoresError";
|
|
1891
|
+
this.code = code;
|
|
1892
|
+
this.details = details;
|
|
1893
|
+
if (Error.captureStackTrace) {
|
|
1894
|
+
Error.captureStackTrace(this, _SynapCoresError);
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
};
|
|
1898
|
+
var ConnectionError = class extends SynapCoresError {
|
|
1899
|
+
constructor(message, details) {
|
|
1900
|
+
super(message, "CONNECTION_ERROR", details);
|
|
1901
|
+
this.name = "ConnectionError";
|
|
1902
|
+
}
|
|
1903
|
+
};
|
|
1904
|
+
var AuthenticationError = class extends SynapCoresError {
|
|
1905
|
+
constructor(message, details) {
|
|
1906
|
+
super(message, "AUTH_ERROR", details);
|
|
1907
|
+
this.name = "AuthenticationError";
|
|
1908
|
+
}
|
|
1909
|
+
};
|
|
1910
|
+
var ValidationError = class extends SynapCoresError {
|
|
1911
|
+
constructor(message, details) {
|
|
1912
|
+
super(message, "VALIDATION_ERROR", details);
|
|
1913
|
+
this.name = "ValidationError";
|
|
1914
|
+
}
|
|
1915
|
+
};
|
|
1916
|
+
var NotFoundError = class extends SynapCoresError {
|
|
1917
|
+
constructor(message, details) {
|
|
1918
|
+
super(message, "NOT_FOUND", details);
|
|
1919
|
+
this.name = "NotFoundError";
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
var ServerError = class extends SynapCoresError {
|
|
1923
|
+
constructor(message, details) {
|
|
1924
|
+
super(message, "SERVER_ERROR", details);
|
|
1925
|
+
this.name = "ServerError";
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
var TimeoutError = class extends SynapCoresError {
|
|
1929
|
+
constructor(message, details) {
|
|
1930
|
+
super(message, "TIMEOUT_ERROR", details);
|
|
1931
|
+
this.name = "TimeoutError";
|
|
1932
|
+
}
|
|
1933
|
+
};
|
|
1934
|
+
var RateLimitError = class extends SynapCoresError {
|
|
1935
|
+
constructor(message, retryAfter, details) {
|
|
1936
|
+
super(message, "RATE_LIMIT_ERROR", details);
|
|
1937
|
+
this.name = "RateLimitError";
|
|
1938
|
+
this.retryAfter = retryAfter;
|
|
1939
|
+
}
|
|
1940
|
+
};
|
|
1941
|
+
var SQLError = class extends SynapCoresError {
|
|
1942
|
+
constructor(message, code, severity = "ERROR", position, hint, detail, details) {
|
|
1943
|
+
super(message, code, details);
|
|
1944
|
+
this.name = "SQLError";
|
|
1945
|
+
this.severity = severity;
|
|
1946
|
+
this.position = position;
|
|
1947
|
+
this.hint = hint;
|
|
1948
|
+
this.detail = detail;
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
var VectorError = class extends SynapCoresError {
|
|
1952
|
+
constructor(message, code, vectorDimensions, expectedDimensions, operation, details) {
|
|
1953
|
+
super(message, code, details);
|
|
1954
|
+
this.name = "VectorError";
|
|
1955
|
+
this.vectorDimensions = vectorDimensions;
|
|
1956
|
+
this.expectedDimensions = expectedDimensions;
|
|
1957
|
+
this.operation = operation;
|
|
1958
|
+
}
|
|
1959
|
+
};
|
|
1960
|
+
var TransactionError = class extends SynapCoresError {
|
|
1961
|
+
constructor(message, code, transactionId, transactionState, details) {
|
|
1962
|
+
super(message, code, details);
|
|
1963
|
+
this.name = "TransactionError";
|
|
1964
|
+
this.transactionId = transactionId;
|
|
1965
|
+
this.transactionState = transactionState;
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
var BatchOperationError = class extends SynapCoresError {
|
|
1969
|
+
constructor(message, code, failedItems, totalProcessed, successfulCount, details) {
|
|
1970
|
+
super(message, code, details);
|
|
1971
|
+
this.name = "BatchOperationError";
|
|
1972
|
+
this.failedItems = failedItems;
|
|
1973
|
+
this.totalProcessed = totalProcessed;
|
|
1974
|
+
this.successfulCount = successfulCount;
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
|
|
1978
|
+
// src/client.ts
|
|
1979
|
+
var SynapCores = class {
|
|
1980
|
+
constructor(config = {}) {
|
|
1981
|
+
this.collectionsCache = /* @__PURE__ */ new Map();
|
|
1982
|
+
this.currentTransaction = null;
|
|
1983
|
+
this.preparedStatements = /* @__PURE__ */ new Map();
|
|
1984
|
+
this.config = {
|
|
1985
|
+
host: config.host || "localhost",
|
|
1986
|
+
port: config.port || 8080,
|
|
1987
|
+
apiKey: config.apiKey || "",
|
|
1988
|
+
jwtToken: config.jwtToken || "",
|
|
1989
|
+
useHttps: config.useHttps || false,
|
|
1990
|
+
timeout: config.timeout || 3e4,
|
|
1991
|
+
maxRetries: config.maxRetries || 3,
|
|
1992
|
+
rejectUnauthorized: config.rejectUnauthorized !== void 0 ? config.rejectUnauthorized : true
|
|
1993
|
+
};
|
|
1994
|
+
if (this.config.apiKey && !this.config.apiKey.startsWith("ak_") && !this.config.apiKey.startsWith("aidb_")) {
|
|
1995
|
+
throw new Error(
|
|
1996
|
+
"Invalid API key format. API keys should start with 'ak_' or 'aidb_' prefix. Please create a valid API key from your AIDB dashboard."
|
|
1997
|
+
);
|
|
1998
|
+
}
|
|
1999
|
+
const protocol = this.config.useHttps ? "https" : "http";
|
|
2000
|
+
const baseURL = `${protocol}://${this.config.host}:${this.config.port}/v1`;
|
|
2001
|
+
const httpsAgent = this.config.useHttps && !this.config.rejectUnauthorized ? new (require("https")).Agent({ rejectUnauthorized: false }) : void 0;
|
|
2002
|
+
const authHeader = {};
|
|
2003
|
+
if (this.config.jwtToken) {
|
|
2004
|
+
authHeader["Authorization"] = `Bearer ${this.config.jwtToken}`;
|
|
2005
|
+
} else if (this.config.apiKey) {
|
|
2006
|
+
authHeader["X-API-Key"] = this.config.apiKey;
|
|
2007
|
+
}
|
|
2008
|
+
this.httpClient = import_axios.default.create({
|
|
2009
|
+
baseURL,
|
|
2010
|
+
timeout: this.config.timeout,
|
|
2011
|
+
headers: {
|
|
2012
|
+
"Content-Type": "application/json",
|
|
2013
|
+
"User-Agent": "synapcores-nodejs/0.1.0",
|
|
2014
|
+
...authHeader
|
|
2015
|
+
},
|
|
2016
|
+
...httpsAgent && { httpsAgent }
|
|
2017
|
+
});
|
|
2018
|
+
this.httpClient.interceptors.response.use(
|
|
2019
|
+
(response) => response,
|
|
2020
|
+
(error) => this.handleError(error)
|
|
2021
|
+
);
|
|
2022
|
+
this.automl = new AutoMLClient(this);
|
|
2023
|
+
this.nlp = new NLPClient(this);
|
|
2024
|
+
this.recipes = new RecipeClient(this);
|
|
2025
|
+
this.schema = new SchemaClient(this);
|
|
2026
|
+
this.import = new ImportExportClient(this);
|
|
2027
|
+
this.integrations = new IntegrationClient(this);
|
|
2028
|
+
this.backup = new BackupClient(this);
|
|
2029
|
+
}
|
|
2030
|
+
handleError(error) {
|
|
2031
|
+
if (!error.response) {
|
|
2032
|
+
const message = error.code === "ECONNREFUSED" ? `Failed to connect to SynapCores server at ${error.config?.baseURL}. Connection refused.` : `Failed to connect to SynapCores server: ${error.message}`;
|
|
2033
|
+
throw new ConnectionError(message);
|
|
2034
|
+
}
|
|
2035
|
+
const { status, data } = error.response;
|
|
2036
|
+
const errorData = data;
|
|
2037
|
+
const errorInfo = errorData?.error || errorData;
|
|
2038
|
+
const errorCode = errorInfo?.code;
|
|
2039
|
+
const errorMessage = errorInfo?.message || errorData?.message || "An error occurred";
|
|
2040
|
+
const errorDetails = errorInfo?.details || errorData?.details || errorData;
|
|
2041
|
+
switch (status) {
|
|
2042
|
+
case 400:
|
|
2043
|
+
throw new ValidationError(
|
|
2044
|
+
errorMessage,
|
|
2045
|
+
errorDetails
|
|
2046
|
+
);
|
|
2047
|
+
case 401:
|
|
2048
|
+
throw new AuthenticationError(
|
|
2049
|
+
errorMessage,
|
|
2050
|
+
errorDetails
|
|
2051
|
+
);
|
|
2052
|
+
case 403:
|
|
2053
|
+
throw new AuthenticationError(
|
|
2054
|
+
errorMessage,
|
|
2055
|
+
errorDetails
|
|
2056
|
+
);
|
|
2057
|
+
case 404:
|
|
2058
|
+
throw new NotFoundError(
|
|
2059
|
+
errorMessage,
|
|
2060
|
+
errorDetails
|
|
2061
|
+
);
|
|
2062
|
+
case 409:
|
|
2063
|
+
throw new ValidationError(
|
|
2064
|
+
errorMessage,
|
|
2065
|
+
errorDetails
|
|
2066
|
+
);
|
|
2067
|
+
case 413:
|
|
2068
|
+
throw new ValidationError(
|
|
2069
|
+
errorMessage || "Payload too large",
|
|
2070
|
+
errorDetails
|
|
2071
|
+
);
|
|
2072
|
+
case 422:
|
|
2073
|
+
throw new ValidationError(
|
|
2074
|
+
errorMessage,
|
|
2075
|
+
errorDetails?.errors || errorDetails
|
|
2076
|
+
);
|
|
2077
|
+
case 429:
|
|
2078
|
+
const retryAfter = error.response.headers["retry-after"];
|
|
2079
|
+
throw new RateLimitError(
|
|
2080
|
+
errorMessage,
|
|
2081
|
+
retryAfter ? parseInt(retryAfter) : void 0,
|
|
2082
|
+
errorDetails
|
|
2083
|
+
);
|
|
2084
|
+
case 500:
|
|
2085
|
+
throw new ServerError(
|
|
2086
|
+
errorMessage || "Internal server error",
|
|
2087
|
+
errorDetails
|
|
2088
|
+
);
|
|
2089
|
+
case 503:
|
|
2090
|
+
throw new ServerError(
|
|
2091
|
+
errorMessage || "Service unavailable",
|
|
2092
|
+
errorDetails
|
|
2093
|
+
);
|
|
2094
|
+
default:
|
|
2095
|
+
if (status >= 500) {
|
|
2096
|
+
throw new ServerError(
|
|
2097
|
+
errorMessage || `Server error: ${status}`,
|
|
2098
|
+
errorDetails
|
|
2099
|
+
);
|
|
2100
|
+
}
|
|
2101
|
+
throw new SynapCoresError(
|
|
2102
|
+
errorMessage || `Unexpected error: ${status}`,
|
|
2103
|
+
errorCode || "UNEXPECTED_ERROR",
|
|
2104
|
+
errorDetails
|
|
2105
|
+
);
|
|
2106
|
+
}
|
|
2107
|
+
}
|
|
2108
|
+
/**
|
|
2109
|
+
* Create collection (legacy method for backward compatibility)
|
|
2110
|
+
*/
|
|
2111
|
+
async createCollection(options) {
|
|
2112
|
+
const request = {
|
|
2113
|
+
name: options.name,
|
|
2114
|
+
description: options.description,
|
|
2115
|
+
schema: options.schema
|
|
2116
|
+
};
|
|
2117
|
+
return this.createCollectionWithSchema(request);
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* Create collection matching the database integration guide format
|
|
2121
|
+
*/
|
|
2122
|
+
async createCollectionWithSchema(request) {
|
|
2123
|
+
const { data } = await this.httpClient.post("/collections", {
|
|
2124
|
+
name: request.name,
|
|
2125
|
+
description: request.description,
|
|
2126
|
+
schema: request.schema
|
|
2127
|
+
});
|
|
2128
|
+
const collection = new Collection(this, request.name, data.collection.schema);
|
|
2129
|
+
this.collectionsCache.set(request.name, collection);
|
|
2130
|
+
return collection;
|
|
2131
|
+
}
|
|
2132
|
+
async getCollection(name) {
|
|
2133
|
+
if (this.collectionsCache.has(name)) {
|
|
2134
|
+
return this.collectionsCache.get(name);
|
|
2135
|
+
}
|
|
2136
|
+
const { data } = await this.httpClient.get(`/collections/${name}`);
|
|
2137
|
+
const collection = new Collection(this, name, data.schema);
|
|
2138
|
+
this.collectionsCache.set(name, collection);
|
|
2139
|
+
return collection;
|
|
2140
|
+
}
|
|
2141
|
+
/**
|
|
2142
|
+
* List collections (legacy method for backward compatibility)
|
|
2143
|
+
*/
|
|
2144
|
+
async listCollections() {
|
|
2145
|
+
const result = await this.listCollectionsDetailed();
|
|
2146
|
+
return result.collections.map((c) => c.name);
|
|
2147
|
+
}
|
|
2148
|
+
/**
|
|
2149
|
+
* List collections with detailed information matching the database integration guide format
|
|
2150
|
+
*/
|
|
2151
|
+
async listCollectionsDetailed(options) {
|
|
2152
|
+
const params = new URLSearchParams();
|
|
2153
|
+
if (options?.page) params.append("page", options.page.toString());
|
|
2154
|
+
if (options?.pageSize) params.append("pageSize", options.pageSize.toString());
|
|
2155
|
+
if (options?.search) params.append("search", options.search);
|
|
2156
|
+
if (options?.sortBy) params.append("sortBy", options.sortBy);
|
|
2157
|
+
if (options?.sortOrder) params.append("sortOrder", options.sortOrder);
|
|
2158
|
+
const { data } = await this.httpClient.get(
|
|
2159
|
+
`/collections${params.toString() ? `?${params.toString()}` : ""}`
|
|
2160
|
+
);
|
|
2161
|
+
return data;
|
|
2162
|
+
}
|
|
2163
|
+
async getDocuments(collectionName, page, pageSize) {
|
|
2164
|
+
const { data } = await this.httpClient.get(
|
|
2165
|
+
`/collections/${collectionName}/documents?page=${page}&pageSize=${pageSize}`
|
|
2166
|
+
);
|
|
2167
|
+
return data;
|
|
2168
|
+
}
|
|
2169
|
+
async deleteCollection(name) {
|
|
2170
|
+
await this.httpClient.delete(`/collections/${name}`);
|
|
2171
|
+
this.collectionsCache.delete(name);
|
|
2172
|
+
}
|
|
2173
|
+
/**
|
|
2174
|
+
* Execute SQL query (legacy method for backward compatibility)
|
|
2175
|
+
* @deprecated Use executeQuery for new code
|
|
2176
|
+
*/
|
|
2177
|
+
async sql(query, params) {
|
|
2178
|
+
return this.executeQuery({
|
|
2179
|
+
sql: query,
|
|
2180
|
+
parameters: params ? Object.values(params) : []
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
/**
|
|
2184
|
+
* Execute SQL query matching the database integration guide format
|
|
2185
|
+
*/
|
|
2186
|
+
async executeQuery(request) {
|
|
2187
|
+
const { data } = await this.httpClient.post("/query/execute", {
|
|
2188
|
+
sql: request.sql,
|
|
2189
|
+
parameters: request.parameters || [],
|
|
2190
|
+
max_rows: request.max_rows || 1e3,
|
|
2191
|
+
timeout_secs: request.timeout_secs || 300
|
|
2192
|
+
});
|
|
2193
|
+
return {
|
|
2194
|
+
columns: data.columns || [],
|
|
2195
|
+
rows: data.rows || [],
|
|
2196
|
+
rows_affected: data.rows_affected,
|
|
2197
|
+
execution_time_ms: data.execution_time_ms || 0,
|
|
2198
|
+
queryPlan: data.query_plan
|
|
2199
|
+
};
|
|
2200
|
+
}
|
|
2201
|
+
/**
|
|
2202
|
+
* Execute batch queries
|
|
2203
|
+
*/
|
|
2204
|
+
async executeBatchQueries(request) {
|
|
2205
|
+
const { data } = await this.httpClient.post("/query/execute/batch", {
|
|
2206
|
+
queries: request.queries,
|
|
2207
|
+
transactional: request.transactional || false
|
|
2208
|
+
});
|
|
2209
|
+
return {
|
|
2210
|
+
results: data.results || [],
|
|
2211
|
+
total_execution_time_ms: data.total_execution_time_ms || 0
|
|
2212
|
+
};
|
|
2213
|
+
}
|
|
2214
|
+
async embed(text, options = {}) {
|
|
2215
|
+
const isBatch = Array.isArray(text);
|
|
2216
|
+
const texts = isBatch ? text : [text];
|
|
2217
|
+
const { data } = await this.httpClient.post("/ai/embed", {
|
|
2218
|
+
texts,
|
|
2219
|
+
model: options.model || "default"
|
|
2220
|
+
});
|
|
2221
|
+
return isBatch ? data.embeddings : data.embeddings[0];
|
|
2222
|
+
}
|
|
2223
|
+
// Internal method for HTTP client access
|
|
2224
|
+
_getHttpClient() {
|
|
2225
|
+
return this.httpClient;
|
|
2226
|
+
}
|
|
2227
|
+
// =================================================================
|
|
2228
|
+
// TABLE MANAGEMENT OPERATIONS
|
|
2229
|
+
// =================================================================
|
|
2230
|
+
/**
|
|
2231
|
+
* Creates a new table with the specified columns and constraints
|
|
2232
|
+
* @param tableName - Name of the table to create
|
|
2233
|
+
* @param columns - Column definitions for the table
|
|
2234
|
+
* @param options - Additional table creation options
|
|
2235
|
+
* @returns Promise resolving to table creation result
|
|
2236
|
+
*/
|
|
2237
|
+
async createTable(tableName, columns, options = {}) {
|
|
2238
|
+
let sql = `CREATE TABLE ${options.ifNotExists ? "IF NOT EXISTS" : ""} ${tableName} (`;
|
|
2239
|
+
const columnDefs = columns.map((col) => {
|
|
2240
|
+
let def = `${col.name} ${col.dataType}`;
|
|
2241
|
+
if (col.constraints) {
|
|
2242
|
+
for (const constraint of col.constraints) {
|
|
2243
|
+
switch (constraint.type) {
|
|
2244
|
+
case "PRIMARY_KEY":
|
|
2245
|
+
def += " PRIMARY KEY";
|
|
2246
|
+
break;
|
|
2247
|
+
case "UNIQUE":
|
|
2248
|
+
def += " UNIQUE";
|
|
2249
|
+
break;
|
|
2250
|
+
case "NOT_NULL":
|
|
2251
|
+
def += " NOT NULL";
|
|
2252
|
+
break;
|
|
2253
|
+
case "CHECK":
|
|
2254
|
+
def += ` CHECK (${constraint.expression})`;
|
|
2255
|
+
break;
|
|
2256
|
+
case "FOREIGN_KEY":
|
|
2257
|
+
def += ` REFERENCES ${constraint.referencedTable}(${constraint.referencedColumn})`;
|
|
2258
|
+
break;
|
|
2259
|
+
case "DEFAULT":
|
|
2260
|
+
def += ` DEFAULT ${col.defaultValue}`;
|
|
2261
|
+
break;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
}
|
|
2265
|
+
return def;
|
|
2266
|
+
}).join(", ");
|
|
2267
|
+
sql += columnDefs;
|
|
2268
|
+
if (options.constraints) {
|
|
2269
|
+
const constraintDefs = options.constraints.map((constraint) => {
|
|
2270
|
+
switch (constraint.type) {
|
|
2271
|
+
case "PRIMARY_KEY":
|
|
2272
|
+
return `PRIMARY KEY (${constraint.columns.join(", ")})`;
|
|
2273
|
+
case "UNIQUE":
|
|
2274
|
+
return `UNIQUE (${constraint.columns.join(", ")})`;
|
|
2275
|
+
case "CHECK":
|
|
2276
|
+
return `CHECK (${constraint.expression})`;
|
|
2277
|
+
case "FOREIGN_KEY":
|
|
2278
|
+
return `FOREIGN KEY (${constraint.columns.join(", ")}) REFERENCES ${constraint.referencedTable}(${constraint.referencedColumns?.join(", ")})`;
|
|
2279
|
+
default:
|
|
2280
|
+
return "";
|
|
2281
|
+
}
|
|
2282
|
+
}).filter((def) => def);
|
|
2283
|
+
if (constraintDefs.length > 0) {
|
|
2284
|
+
sql += ", " + constraintDefs.join(", ");
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
sql += ")";
|
|
2288
|
+
if (options.partitionBy) {
|
|
2289
|
+
sql += ` PARTITION BY ${options.partitionBy.type} (${options.partitionBy.column})`;
|
|
2290
|
+
}
|
|
2291
|
+
return this.sql(sql);
|
|
2292
|
+
}
|
|
2293
|
+
/**
|
|
2294
|
+
* Alters an existing table structure
|
|
2295
|
+
* @param tableName - Name of the table to alter
|
|
2296
|
+
* @param alterOptions - Alteration options and parameters
|
|
2297
|
+
* @returns Promise resolving to alteration result
|
|
2298
|
+
*/
|
|
2299
|
+
async alterTable(tableName, alterOptions) {
|
|
2300
|
+
let sql = `ALTER TABLE ${tableName} `;
|
|
2301
|
+
switch (alterOptions.action) {
|
|
2302
|
+
case "ADD_COLUMN":
|
|
2303
|
+
if (!alterOptions.columnDefinition) {
|
|
2304
|
+
throw new ValidationError("Column definition required for ADD_COLUMN");
|
|
2305
|
+
}
|
|
2306
|
+
sql += `ADD COLUMN ${alterOptions.columnDefinition.name} ${alterOptions.columnDefinition.dataType}`;
|
|
2307
|
+
break;
|
|
2308
|
+
case "DROP_COLUMN":
|
|
2309
|
+
sql += `DROP COLUMN ${alterOptions.columnName}`;
|
|
2310
|
+
break;
|
|
2311
|
+
case "RENAME_COLUMN":
|
|
2312
|
+
sql += `RENAME COLUMN ${alterOptions.columnName} TO ${alterOptions.newColumnName}`;
|
|
2313
|
+
break;
|
|
2314
|
+
case "ALTER_COLUMN":
|
|
2315
|
+
sql += `ALTER COLUMN ${alterOptions.columnName} TYPE ${alterOptions.newDataType}`;
|
|
2316
|
+
break;
|
|
2317
|
+
case "ADD_CONSTRAINT":
|
|
2318
|
+
if (!alterOptions.constraint) {
|
|
2319
|
+
throw new ValidationError("Constraint required for ADD_CONSTRAINT");
|
|
2320
|
+
}
|
|
2321
|
+
sql += `ADD CONSTRAINT ${alterOptions.constraint.type.toLowerCase()}_constraint`;
|
|
2322
|
+
break;
|
|
2323
|
+
case "DROP_CONSTRAINT":
|
|
2324
|
+
sql += `DROP CONSTRAINT ${alterOptions.constraintName}`;
|
|
2325
|
+
break;
|
|
2326
|
+
}
|
|
2327
|
+
return this.sql(sql);
|
|
2328
|
+
}
|
|
2329
|
+
/**
|
|
2330
|
+
* Drops an existing table
|
|
2331
|
+
* @param tableName - Name of the table to drop
|
|
2332
|
+
* @param options - Drop options
|
|
2333
|
+
* @returns Promise resolving to drop result
|
|
2334
|
+
*/
|
|
2335
|
+
async dropTable(tableName, options = {}) {
|
|
2336
|
+
let sql = `DROP TABLE ${options.ifExists ? "IF EXISTS" : ""} ${tableName}`;
|
|
2337
|
+
if (options.cascade) {
|
|
2338
|
+
sql += " CASCADE";
|
|
2339
|
+
}
|
|
2340
|
+
return this.sql(sql);
|
|
2341
|
+
}
|
|
2342
|
+
/**
|
|
2343
|
+
* Describes a table structure including columns, constraints, and indexes
|
|
2344
|
+
* @param tableName - Name of the table to describe
|
|
2345
|
+
* @returns Promise resolving to table information
|
|
2346
|
+
*/
|
|
2347
|
+
async describeTable(tableName) {
|
|
2348
|
+
const { data } = await this.httpClient.get(`/table/${tableName}/info`);
|
|
2349
|
+
return data;
|
|
2350
|
+
}
|
|
2351
|
+
/**
|
|
2352
|
+
* Lists all tables in the current database
|
|
2353
|
+
* @param pattern - Optional pattern to filter table names
|
|
2354
|
+
* @returns Promise resolving to array of table names
|
|
2355
|
+
*/
|
|
2356
|
+
async showTables(pattern) {
|
|
2357
|
+
const sql = pattern ? `SHOW TABLES LIKE '${pattern}'` : "SHOW TABLES";
|
|
2358
|
+
const result = await this.sql(sql);
|
|
2359
|
+
return result.rows.map((row) => Object.values(row)[0]);
|
|
2360
|
+
}
|
|
2361
|
+
// =================================================================
|
|
2362
|
+
// INDEX MANAGEMENT OPERATIONS
|
|
2363
|
+
// =================================================================
|
|
2364
|
+
/**
|
|
2365
|
+
* Creates an index on a table
|
|
2366
|
+
* @param indexDef - Index definition with name, table, columns, and options
|
|
2367
|
+
* @returns Promise resolving to index creation result
|
|
2368
|
+
*/
|
|
2369
|
+
async createIndex(indexDef) {
|
|
2370
|
+
const columns = indexDef.columns.map((col) => `${col.name} ${col.order || "ASC"}`).join(", ");
|
|
2371
|
+
const sql = `CREATE ${indexDef.unique ? "UNIQUE" : ""} INDEX ${indexDef.ifNotExists ? "IF NOT EXISTS" : ""} ${indexDef.name} ON ${indexDef.tableName} (${columns})`;
|
|
2372
|
+
return this.sql(sql);
|
|
2373
|
+
}
|
|
2374
|
+
/**
|
|
2375
|
+
* Drops an existing index
|
|
2376
|
+
* @param indexName - Name of the index to drop
|
|
2377
|
+
* @param options - Drop options
|
|
2378
|
+
* @returns Promise resolving to drop result
|
|
2379
|
+
*/
|
|
2380
|
+
async dropIndex(indexName, options = {}) {
|
|
2381
|
+
const sql = `DROP INDEX ${options.ifExists ? "IF EXISTS" : ""} ${indexName}`;
|
|
2382
|
+
return this.sql(sql);
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* Lists all indexes, optionally filtered by table name
|
|
2386
|
+
* @param tableName - Optional table name to filter indexes
|
|
2387
|
+
* @returns Promise resolving to array of index information
|
|
2388
|
+
*/
|
|
2389
|
+
async showIndexes(tableName) {
|
|
2390
|
+
const sql = tableName ? `SHOW INDEXES FROM ${tableName}` : "SHOW INDEXES";
|
|
2391
|
+
const result = await this.sql(sql);
|
|
2392
|
+
const indexNameIdx = result.columns.findIndex((c) => c.name === "index_name" || c.name === "name");
|
|
2393
|
+
const tableNameIdx = result.columns.findIndex((c) => c.name === "table_name" || c.name === "table");
|
|
2394
|
+
const columnsIdx = result.columns.findIndex((c) => c.name === "columns" || c.name === "column");
|
|
2395
|
+
const uniqueIdx = result.columns.findIndex((c) => c.name === "is_unique" || c.name === "unique");
|
|
2396
|
+
return result.rows.map((row) => {
|
|
2397
|
+
const indexName = indexNameIdx >= 0 ? row[indexNameIdx] : "";
|
|
2398
|
+
const table = tableNameIdx >= 0 ? row[tableNameIdx] : "";
|
|
2399
|
+
const columnsStr = columnsIdx >= 0 ? row[columnsIdx] : "";
|
|
2400
|
+
const isUnique = uniqueIdx >= 0 ? row[uniqueIdx] : false;
|
|
2401
|
+
return {
|
|
2402
|
+
name: String(indexName),
|
|
2403
|
+
table: String(table),
|
|
2404
|
+
columns: typeof columnsStr === "string" ? columnsStr.split(",") : [],
|
|
2405
|
+
unique: Boolean(isUnique)
|
|
2406
|
+
};
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
// =================================================================
|
|
2410
|
+
// TRANSACTION SUPPORT
|
|
2411
|
+
// =================================================================
|
|
2412
|
+
/**
|
|
2413
|
+
* Begins a new transaction
|
|
2414
|
+
* @param options - Transaction options including isolation level
|
|
2415
|
+
* @returns Promise resolving to transaction context
|
|
2416
|
+
*/
|
|
2417
|
+
async beginTransaction(options = {}) {
|
|
2418
|
+
if (this.currentTransaction) {
|
|
2419
|
+
throw new Error("Transaction already in progress");
|
|
2420
|
+
}
|
|
2421
|
+
let sql = "BEGIN TRANSACTION";
|
|
2422
|
+
if (options.isolationLevel) {
|
|
2423
|
+
sql += ` ISOLATION LEVEL ${options.isolationLevel}`;
|
|
2424
|
+
}
|
|
2425
|
+
if (options.readOnly) {
|
|
2426
|
+
sql += " READ ONLY";
|
|
2427
|
+
}
|
|
2428
|
+
await this.sql(sql);
|
|
2429
|
+
this.currentTransaction = {
|
|
2430
|
+
id: Math.random().toString(36).substring(7),
|
|
2431
|
+
startTime: /* @__PURE__ */ new Date(),
|
|
2432
|
+
isolationLevel: options.isolationLevel || "READ_COMMITTED",
|
|
2433
|
+
readOnly: options.readOnly || false
|
|
2434
|
+
};
|
|
2435
|
+
if (options.timeout) {
|
|
2436
|
+
setTimeout(() => {
|
|
2437
|
+
if (this.currentTransaction) {
|
|
2438
|
+
this.rollbackTransaction().catch(console.error);
|
|
2439
|
+
}
|
|
2440
|
+
}, options.timeout);
|
|
2441
|
+
}
|
|
2442
|
+
return this.currentTransaction;
|
|
2443
|
+
}
|
|
2444
|
+
/**
|
|
2445
|
+
* Commits the current transaction
|
|
2446
|
+
* @returns Promise resolving when transaction is committed
|
|
2447
|
+
*/
|
|
2448
|
+
async commitTransaction() {
|
|
2449
|
+
if (!this.currentTransaction) {
|
|
2450
|
+
throw new Error("No transaction in progress");
|
|
2451
|
+
}
|
|
2452
|
+
await this.sql("COMMIT");
|
|
2453
|
+
this.currentTransaction = null;
|
|
2454
|
+
}
|
|
2455
|
+
/**
|
|
2456
|
+
* Rolls back the current transaction
|
|
2457
|
+
* @returns Promise resolving when transaction is rolled back
|
|
2458
|
+
*/
|
|
2459
|
+
async rollbackTransaction() {
|
|
2460
|
+
if (!this.currentTransaction) {
|
|
2461
|
+
throw new Error("No transaction in progress");
|
|
2462
|
+
}
|
|
2463
|
+
await this.sql("ROLLBACK");
|
|
2464
|
+
this.currentTransaction = null;
|
|
2465
|
+
}
|
|
2466
|
+
/**
|
|
2467
|
+
* Gets the current transaction context
|
|
2468
|
+
* @returns Current transaction context or null if no transaction
|
|
2469
|
+
*/
|
|
2470
|
+
getCurrentTransaction() {
|
|
2471
|
+
return this.currentTransaction;
|
|
2472
|
+
}
|
|
2473
|
+
// =================================================================
|
|
2474
|
+
// BATCH OPERATIONS
|
|
2475
|
+
// =================================================================
|
|
2476
|
+
/**
|
|
2477
|
+
* Performs batch insert operations
|
|
2478
|
+
* @param options - Batch insert options with table, columns, and rows
|
|
2479
|
+
* @returns Promise resolving to batch operation result
|
|
2480
|
+
*/
|
|
2481
|
+
async batchInsert(options) {
|
|
2482
|
+
const { data } = await this.httpClient.post("/batch/insert", {
|
|
2483
|
+
table_name: options.tableName,
|
|
2484
|
+
columns: options.columns,
|
|
2485
|
+
rows: options.rows,
|
|
2486
|
+
on_conflict: options.onConflict,
|
|
2487
|
+
batch_size: options.batchSize || 1e3
|
|
2488
|
+
});
|
|
2489
|
+
return {
|
|
2490
|
+
totalProcessed: data.total_processed,
|
|
2491
|
+
successful: data.successful,
|
|
2492
|
+
failed: data.failed,
|
|
2493
|
+
errors: data.errors,
|
|
2494
|
+
tookMs: data.took_ms
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
/**
|
|
2498
|
+
* Performs batch update operations
|
|
2499
|
+
* @param options - Batch update options with table and update conditions
|
|
2500
|
+
* @returns Promise resolving to batch operation result
|
|
2501
|
+
*/
|
|
2502
|
+
async batchUpdate(options) {
|
|
2503
|
+
const { data } = await this.httpClient.post("/batch/update", {
|
|
2504
|
+
table_name: options.tableName,
|
|
2505
|
+
updates: options.updates,
|
|
2506
|
+
batch_size: options.batchSize || 1e3
|
|
2507
|
+
});
|
|
2508
|
+
return {
|
|
2509
|
+
totalProcessed: data.total_processed,
|
|
2510
|
+
successful: data.successful,
|
|
2511
|
+
failed: data.failed,
|
|
2512
|
+
errors: data.errors,
|
|
2513
|
+
tookMs: data.took_ms
|
|
2514
|
+
};
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* Performs batch delete operations
|
|
2518
|
+
* @param options - Batch delete options with table and where conditions
|
|
2519
|
+
* @returns Promise resolving to batch operation result
|
|
2520
|
+
*/
|
|
2521
|
+
async batchDelete(options) {
|
|
2522
|
+
const { data } = await this.httpClient.post("/batch/delete", {
|
|
2523
|
+
table_name: options.tableName,
|
|
2524
|
+
where_conditions: options.whereConditions,
|
|
2525
|
+
batch_size: options.batchSize || 1e3
|
|
2526
|
+
});
|
|
2527
|
+
return {
|
|
2528
|
+
totalProcessed: data.total_processed,
|
|
2529
|
+
successful: data.successful,
|
|
2530
|
+
failed: data.failed,
|
|
2531
|
+
errors: data.errors,
|
|
2532
|
+
tookMs: data.took_ms
|
|
2533
|
+
};
|
|
2534
|
+
}
|
|
2535
|
+
// =================================================================
|
|
2536
|
+
// ADVANCED SQL FEATURES
|
|
2537
|
+
// =================================================================
|
|
2538
|
+
/**
|
|
2539
|
+
* Prepares a SQL statement for repeated execution
|
|
2540
|
+
* @param sql - SQL statement to prepare
|
|
2541
|
+
* @param options - Preparation options
|
|
2542
|
+
* @returns Promise resolving to prepared statement
|
|
2543
|
+
*/
|
|
2544
|
+
async prepareStatement(sql, options = {}) {
|
|
2545
|
+
const { data } = await this.httpClient.post("/prepare", {
|
|
2546
|
+
sql,
|
|
2547
|
+
name: options.name,
|
|
2548
|
+
parameter_types: options.parameterTypes
|
|
2549
|
+
});
|
|
2550
|
+
const prepared = {
|
|
2551
|
+
id: data.statement_id,
|
|
2552
|
+
sql,
|
|
2553
|
+
parameterCount: data.parameter_count
|
|
2554
|
+
};
|
|
2555
|
+
if (options.name) {
|
|
2556
|
+
this.preparedStatements.set(options.name, prepared);
|
|
2557
|
+
}
|
|
2558
|
+
return prepared;
|
|
2559
|
+
}
|
|
2560
|
+
/**
|
|
2561
|
+
* Executes a prepared statement with parameters
|
|
2562
|
+
* @param statementId - ID of the prepared statement or statement name
|
|
2563
|
+
* @param params - Parameters for the prepared statement
|
|
2564
|
+
* @returns Promise resolving to query result
|
|
2565
|
+
*/
|
|
2566
|
+
async executePrepared(statementId, params = []) {
|
|
2567
|
+
if (this.preparedStatements.has(statementId)) {
|
|
2568
|
+
statementId = this.preparedStatements.get(statementId).id;
|
|
2569
|
+
}
|
|
2570
|
+
const { data } = await this.httpClient.post("/execute-prepared", {
|
|
2571
|
+
statement_id: statementId,
|
|
2572
|
+
parameters: params
|
|
2573
|
+
});
|
|
2574
|
+
return {
|
|
2575
|
+
columns: data.columns || [],
|
|
2576
|
+
rows: data.rows || [],
|
|
2577
|
+
rows_affected: data.rows_affected,
|
|
2578
|
+
execution_time_ms: data.execution_time_ms || data.took_ms || 0,
|
|
2579
|
+
queryPlan: data.query_plan
|
|
2580
|
+
};
|
|
2581
|
+
}
|
|
2582
|
+
/**
|
|
2583
|
+
* Deallocates a prepared statement
|
|
2584
|
+
* @param statementId - ID of the prepared statement or statement name
|
|
2585
|
+
* @returns Promise resolving when statement is deallocated
|
|
2586
|
+
*/
|
|
2587
|
+
async deallocatePrepared(statementId) {
|
|
2588
|
+
if (this.preparedStatements.has(statementId)) {
|
|
2589
|
+
const prepared = this.preparedStatements.get(statementId);
|
|
2590
|
+
await this.httpClient.delete(`/prepare/${prepared.id}`);
|
|
2591
|
+
this.preparedStatements.delete(statementId);
|
|
2592
|
+
} else {
|
|
2593
|
+
await this.httpClient.delete(`/prepare/${statementId}`);
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Executes a query with Common Table Expressions (CTEs)
|
|
2598
|
+
* @param ctes - Array of CTE definitions
|
|
2599
|
+
* @param mainQuery - Main query that uses the CTEs
|
|
2600
|
+
* @param params - Optional parameters for the query
|
|
2601
|
+
* @returns Promise resolving to query result
|
|
2602
|
+
*/
|
|
2603
|
+
async queryWithCTEs(ctes, mainQuery, params) {
|
|
2604
|
+
const cteSQL = ctes.map((cte) => {
|
|
2605
|
+
const columns = cte.columns ? `(${cte.columns.join(", ")})` : "";
|
|
2606
|
+
return `${cte.name}${columns} AS (${cte.query})`;
|
|
2607
|
+
}).join(", ");
|
|
2608
|
+
const sql = `WITH ${cteSQL} ${mainQuery}`;
|
|
2609
|
+
return this.sql(sql, params);
|
|
2610
|
+
}
|
|
2611
|
+
/**
|
|
2612
|
+
* Executes a query with window functions
|
|
2613
|
+
* @param selectQuery - Base SELECT query
|
|
2614
|
+
* @param windowFunctions - Array of window function definitions
|
|
2615
|
+
* @param params - Optional parameters for the query
|
|
2616
|
+
* @returns Promise resolving to query result
|
|
2617
|
+
*/
|
|
2618
|
+
async queryWithWindowFunctions(selectQuery, windowFunctions, params) {
|
|
2619
|
+
const windowClauses = windowFunctions.map((wf) => {
|
|
2620
|
+
let clause = `${wf.function} OVER (`;
|
|
2621
|
+
if (wf.options.partitionBy) {
|
|
2622
|
+
clause += `PARTITION BY ${wf.options.partitionBy.join(", ")}`;
|
|
2623
|
+
}
|
|
2624
|
+
if (wf.options.orderBy) {
|
|
2625
|
+
const orderBy = wf.options.orderBy.map((order) => `${order.column} ${order.direction}`).join(", ");
|
|
2626
|
+
clause += ` ORDER BY ${orderBy}`;
|
|
2627
|
+
}
|
|
2628
|
+
if (wf.options.frame) {
|
|
2629
|
+
clause += ` ${wf.options.frame.type} BETWEEN ${wf.options.frame.start}`;
|
|
2630
|
+
if (wf.options.frame.end) {
|
|
2631
|
+
clause += ` AND ${wf.options.frame.end}`;
|
|
2632
|
+
}
|
|
2633
|
+
}
|
|
2634
|
+
clause += `) AS ${wf.alias}`;
|
|
2635
|
+
return clause;
|
|
2636
|
+
}).join(", ");
|
|
2637
|
+
const sql = `${selectQuery}, ${windowClauses}`;
|
|
2638
|
+
return this.sql(sql, params);
|
|
2639
|
+
}
|
|
2640
|
+
/**
|
|
2641
|
+
* Performs JSON operations on JSON/JSONB columns
|
|
2642
|
+
* @param tableName - Table containing JSON data
|
|
2643
|
+
* @param jsonColumn - Name of the JSON column
|
|
2644
|
+
* @param operation - JSON operation to perform
|
|
2645
|
+
* @param path - JSON path for the operation
|
|
2646
|
+
* @param value - Value for update operations
|
|
2647
|
+
* @param whereClause - Optional WHERE clause
|
|
2648
|
+
* @returns Promise resolving to query result
|
|
2649
|
+
*/
|
|
2650
|
+
async jsonQuery(tableName, jsonColumn, operation, path, value, whereClause) {
|
|
2651
|
+
let sql;
|
|
2652
|
+
switch (operation) {
|
|
2653
|
+
case "extract":
|
|
2654
|
+
sql = `SELECT ${jsonColumn}->>'${path}' as extracted_value FROM ${tableName}`;
|
|
2655
|
+
break;
|
|
2656
|
+
case "update":
|
|
2657
|
+
sql = `UPDATE ${tableName} SET ${jsonColumn} = jsonb_set(${jsonColumn}, '{${path}}', '${JSON.stringify(value)}')`;
|
|
2658
|
+
break;
|
|
2659
|
+
case "delete":
|
|
2660
|
+
sql = `UPDATE ${tableName} SET ${jsonColumn} = ${jsonColumn} - '${path}'`;
|
|
2661
|
+
break;
|
|
2662
|
+
case "contains":
|
|
2663
|
+
sql = `SELECT * FROM ${tableName} WHERE ${jsonColumn} @> '{"${path}": ${JSON.stringify(value)}}'`;
|
|
2664
|
+
break;
|
|
2665
|
+
}
|
|
2666
|
+
if (whereClause && operation !== "contains") {
|
|
2667
|
+
sql += ` WHERE ${whereClause}`;
|
|
2668
|
+
}
|
|
2669
|
+
return this.sql(sql);
|
|
2670
|
+
}
|
|
2671
|
+
// =================================================================
|
|
2672
|
+
// VECTOR OPERATIONS
|
|
2673
|
+
// =================================================================
|
|
2674
|
+
/**
|
|
2675
|
+
* Performs vector addition
|
|
2676
|
+
* @param vector1 - First vector
|
|
2677
|
+
* @param vector2 - Second vector
|
|
2678
|
+
* @returns Promise resolving to vector addition result
|
|
2679
|
+
*/
|
|
2680
|
+
async vectorAdd(vector1, vector2) {
|
|
2681
|
+
if (vector1.length !== vector2.length) {
|
|
2682
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2683
|
+
}
|
|
2684
|
+
const { data } = await this.httpClient.post("/vectors/add", {
|
|
2685
|
+
vector1,
|
|
2686
|
+
vector2
|
|
2687
|
+
});
|
|
2688
|
+
return {
|
|
2689
|
+
result: { values: data.result, dimensions: data.result.length },
|
|
2690
|
+
operation: "addition",
|
|
2691
|
+
tookMs: data.took_ms
|
|
2692
|
+
};
|
|
2693
|
+
}
|
|
2694
|
+
/**
|
|
2695
|
+
* Performs vector subtraction
|
|
2696
|
+
* @param vector1 - First vector (minuend)
|
|
2697
|
+
* @param vector2 - Second vector (subtrahend)
|
|
2698
|
+
* @returns Promise resolving to vector subtraction result
|
|
2699
|
+
*/
|
|
2700
|
+
async vectorSubtract(vector1, vector2) {
|
|
2701
|
+
if (vector1.length !== vector2.length) {
|
|
2702
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2703
|
+
}
|
|
2704
|
+
const { data } = await this.httpClient.post("/vectors/subtract", {
|
|
2705
|
+
vector1,
|
|
2706
|
+
vector2
|
|
2707
|
+
});
|
|
2708
|
+
return {
|
|
2709
|
+
result: { values: data.result, dimensions: data.result.length },
|
|
2710
|
+
operation: "subtraction",
|
|
2711
|
+
tookMs: data.took_ms
|
|
2712
|
+
};
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Performs scalar multiplication on a vector
|
|
2716
|
+
* @param vector - Input vector
|
|
2717
|
+
* @param scalar - Scalar value to multiply by
|
|
2718
|
+
* @returns Promise resolving to scalar multiplication result
|
|
2719
|
+
*/
|
|
2720
|
+
async vectorScalarMultiply(vector, scalar) {
|
|
2721
|
+
const { data } = await this.httpClient.post("/vectors/scalar-multiply", {
|
|
2722
|
+
vector,
|
|
2723
|
+
scalar
|
|
2724
|
+
});
|
|
2725
|
+
return {
|
|
2726
|
+
result: { values: data.result, dimensions: data.result.length },
|
|
2727
|
+
operation: "scalar_multiplication",
|
|
2728
|
+
tookMs: data.took_ms
|
|
2729
|
+
};
|
|
2730
|
+
}
|
|
2731
|
+
/**
|
|
2732
|
+
* Calculates the dot product of two vectors
|
|
2733
|
+
* @param vector1 - First vector
|
|
2734
|
+
* @param vector2 - Second vector
|
|
2735
|
+
* @returns Promise resolving to dot product result
|
|
2736
|
+
*/
|
|
2737
|
+
async vectorDotProduct(vector1, vector2) {
|
|
2738
|
+
if (vector1.length !== vector2.length) {
|
|
2739
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2740
|
+
}
|
|
2741
|
+
const { data } = await this.httpClient.post("/vectors/dot-product", {
|
|
2742
|
+
vector1,
|
|
2743
|
+
vector2
|
|
2744
|
+
});
|
|
2745
|
+
return {
|
|
2746
|
+
dotProduct: data.dot_product,
|
|
2747
|
+
tookMs: data.took_ms
|
|
2748
|
+
};
|
|
2749
|
+
}
|
|
2750
|
+
/**
|
|
2751
|
+
* Calculates cosine similarity between two vectors
|
|
2752
|
+
* @param vector1 - First vector
|
|
2753
|
+
* @param vector2 - Second vector
|
|
2754
|
+
* @returns Promise resolving to cosine similarity result
|
|
2755
|
+
*/
|
|
2756
|
+
async cosineSimilarity(vector1, vector2) {
|
|
2757
|
+
if (vector1.length !== vector2.length) {
|
|
2758
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2759
|
+
}
|
|
2760
|
+
const { data } = await this.httpClient.post("/vectors/cosine-similarity", {
|
|
2761
|
+
vector1,
|
|
2762
|
+
vector2
|
|
2763
|
+
});
|
|
2764
|
+
return {
|
|
2765
|
+
similarity: data.similarity,
|
|
2766
|
+
function: "cosine",
|
|
2767
|
+
tookMs: data.took_ms
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2770
|
+
/**
|
|
2771
|
+
* Calculates L2 (Euclidean) distance between two vectors
|
|
2772
|
+
* @param vector1 - First vector
|
|
2773
|
+
* @param vector2 - Second vector
|
|
2774
|
+
* @returns Promise resolving to L2 distance result
|
|
2775
|
+
*/
|
|
2776
|
+
async l2Distance(vector1, vector2) {
|
|
2777
|
+
if (vector1.length !== vector2.length) {
|
|
2778
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2779
|
+
}
|
|
2780
|
+
const { data } = await this.httpClient.post("/vectors/l2-distance", {
|
|
2781
|
+
vector1,
|
|
2782
|
+
vector2
|
|
2783
|
+
});
|
|
2784
|
+
return {
|
|
2785
|
+
distance: data.distance,
|
|
2786
|
+
similarity: data.distance,
|
|
2787
|
+
// Include similarity for compatibility
|
|
2788
|
+
function: "l2",
|
|
2789
|
+
tookMs: data.took_ms
|
|
2790
|
+
};
|
|
2791
|
+
}
|
|
2792
|
+
/**
|
|
2793
|
+
* Calculates inner product between two vectors
|
|
2794
|
+
* @param vector1 - First vector
|
|
2795
|
+
* @param vector2 - Second vector
|
|
2796
|
+
* @returns Promise resolving to inner product result
|
|
2797
|
+
*/
|
|
2798
|
+
async innerProduct(vector1, vector2) {
|
|
2799
|
+
if (vector1.length !== vector2.length) {
|
|
2800
|
+
throw new VectorError("Vector dimensions must match", "DIMENSION_MISMATCH");
|
|
2801
|
+
}
|
|
2802
|
+
const { data } = await this.httpClient.post("/vectors/inner-product", {
|
|
2803
|
+
vector1,
|
|
2804
|
+
vector2
|
|
2805
|
+
});
|
|
2806
|
+
return {
|
|
2807
|
+
similarity: data.inner_product,
|
|
2808
|
+
function: "inner_product",
|
|
2809
|
+
tookMs: data.took_ms
|
|
2810
|
+
};
|
|
2811
|
+
}
|
|
2812
|
+
/**
|
|
2813
|
+
* Performs K-nearest neighbors vector search
|
|
2814
|
+
* @param options - KNN search options
|
|
2815
|
+
* @returns Promise resolving to KNN search results
|
|
2816
|
+
*/
|
|
2817
|
+
async knnSearch(options) {
|
|
2818
|
+
const { data } = await this.httpClient.post("/vectors/knn-search", {
|
|
2819
|
+
query_vector: options.queryVector,
|
|
2820
|
+
k: options.k,
|
|
2821
|
+
table_name: options.tableName,
|
|
2822
|
+
vector_column: options.vectorColumn,
|
|
2823
|
+
metadata_columns: options.metadataColumns,
|
|
2824
|
+
filter: options.filter
|
|
2825
|
+
});
|
|
2826
|
+
return data.results.map((result) => ({
|
|
2827
|
+
id: result.id,
|
|
2828
|
+
vector: result.vector,
|
|
2829
|
+
similarity: result.similarity,
|
|
2830
|
+
distance: result.distance,
|
|
2831
|
+
metadata: result.metadata
|
|
2832
|
+
}));
|
|
2833
|
+
}
|
|
2834
|
+
/**
|
|
2835
|
+
* Performs range-based vector similarity search
|
|
2836
|
+
* @param options - Range search options
|
|
2837
|
+
* @returns Promise resolving to range search results
|
|
2838
|
+
*/
|
|
2839
|
+
async rangeSearch(options) {
|
|
2840
|
+
const { data } = await this.httpClient.post("/vectors/range-search", {
|
|
2841
|
+
query_vector: options.queryVector,
|
|
2842
|
+
threshold: options.threshold,
|
|
2843
|
+
table_name: options.tableName,
|
|
2844
|
+
vector_column: options.vectorColumn,
|
|
2845
|
+
metadata_columns: options.metadataColumns,
|
|
2846
|
+
filter: options.filter,
|
|
2847
|
+
max_results: options.maxResults
|
|
2848
|
+
});
|
|
2849
|
+
return data.results.map((result) => ({
|
|
2850
|
+
id: result.id,
|
|
2851
|
+
vector: result.vector,
|
|
2852
|
+
similarity: result.similarity,
|
|
2853
|
+
distance: result.distance,
|
|
2854
|
+
metadata: result.metadata
|
|
2855
|
+
}));
|
|
2856
|
+
}
|
|
2857
|
+
/**
|
|
2858
|
+
* Performs hybrid search combining vector similarity and SQL filtering
|
|
2859
|
+
* @param options - Hybrid search options
|
|
2860
|
+
* @returns Promise resolving to hybrid search results
|
|
2861
|
+
*/
|
|
2862
|
+
async hybridSearch(options) {
|
|
2863
|
+
const { data } = await this.httpClient.post("/vectors/hybrid-search", {
|
|
2864
|
+
vector: options.vector,
|
|
2865
|
+
text_query: options.textQuery,
|
|
2866
|
+
sql_filter: options.sqlFilter,
|
|
2867
|
+
k: options.k,
|
|
2868
|
+
threshold: options.threshold,
|
|
2869
|
+
metric: options.metric,
|
|
2870
|
+
filter: options.filter,
|
|
2871
|
+
weights: options.weights
|
|
2872
|
+
});
|
|
2873
|
+
return data.results.map((result) => ({
|
|
2874
|
+
id: result.id,
|
|
2875
|
+
vector: result.vector,
|
|
2876
|
+
similarity: result.similarity,
|
|
2877
|
+
distance: result.distance,
|
|
2878
|
+
metadata: result.metadata
|
|
2879
|
+
}));
|
|
2880
|
+
}
|
|
2881
|
+
/**
|
|
2882
|
+
* Normalizes a vector to unit length
|
|
2883
|
+
* @param vector - Input vector to normalize
|
|
2884
|
+
* @returns Promise resolving to normalized vector
|
|
2885
|
+
*/
|
|
2886
|
+
async normalizeVector(vector) {
|
|
2887
|
+
const { data } = await this.httpClient.post("/vectors/normalize", {
|
|
2888
|
+
vector
|
|
2889
|
+
});
|
|
2890
|
+
return {
|
|
2891
|
+
result: { values: data.result, dimensions: data.result.length },
|
|
2892
|
+
operation: "normalization",
|
|
2893
|
+
tookMs: data.took_ms
|
|
2894
|
+
};
|
|
2895
|
+
}
|
|
2896
|
+
/**
|
|
2897
|
+
* Calculates the magnitude (length) of a vector
|
|
2898
|
+
* @param vector - Input vector
|
|
2899
|
+
* @returns Promise resolving to vector magnitude
|
|
2900
|
+
*/
|
|
2901
|
+
async vectorMagnitude(vector) {
|
|
2902
|
+
const { data } = await this.httpClient.post("/vectors/magnitude", {
|
|
2903
|
+
vector
|
|
2904
|
+
});
|
|
2905
|
+
return {
|
|
2906
|
+
magnitude: data.magnitude,
|
|
2907
|
+
tookMs: data.took_ms
|
|
2908
|
+
};
|
|
2909
|
+
}
|
|
2910
|
+
// =================================================================
|
|
2911
|
+
// AUTHENTICATION & USER MANAGEMENT
|
|
2912
|
+
// =================================================================
|
|
2913
|
+
/**
|
|
2914
|
+
* Register a new user
|
|
2915
|
+
*/
|
|
2916
|
+
async registerUser(request) {
|
|
2917
|
+
const { data } = await this.httpClient.post("/auth/register", {
|
|
2918
|
+
username: request.username,
|
|
2919
|
+
email: request.email,
|
|
2920
|
+
password: request.password
|
|
2921
|
+
});
|
|
2922
|
+
return data;
|
|
2923
|
+
}
|
|
2924
|
+
/**
|
|
2925
|
+
* Login with username and password
|
|
2926
|
+
*/
|
|
2927
|
+
async login(request) {
|
|
2928
|
+
const { data } = await this.httpClient.post("/auth/login", {
|
|
2929
|
+
username: request.username,
|
|
2930
|
+
password: request.password
|
|
2931
|
+
});
|
|
2932
|
+
if (data.access_token) {
|
|
2933
|
+
this.config.jwtToken = data.access_token;
|
|
2934
|
+
this.httpClient.defaults.headers["Authorization"] = `Bearer ${data.access_token}`;
|
|
2935
|
+
delete this.httpClient.defaults.headers["X-API-Key"];
|
|
2936
|
+
}
|
|
2937
|
+
return data;
|
|
2938
|
+
}
|
|
2939
|
+
/**
|
|
2940
|
+
* Refresh JWT token
|
|
2941
|
+
*/
|
|
2942
|
+
async refreshToken() {
|
|
2943
|
+
const { data } = await this.httpClient.post("/auth/refresh");
|
|
2944
|
+
if (data.access_token) {
|
|
2945
|
+
this.config.jwtToken = data.access_token;
|
|
2946
|
+
this.httpClient.defaults.headers["Authorization"] = `Bearer ${data.access_token}`;
|
|
2947
|
+
delete this.httpClient.defaults.headers["X-API-Key"];
|
|
2948
|
+
}
|
|
2949
|
+
return data;
|
|
2950
|
+
}
|
|
2951
|
+
/**
|
|
2952
|
+
* Set JWT token manually (useful after login)
|
|
2953
|
+
*/
|
|
2954
|
+
setJWTToken(token) {
|
|
2955
|
+
this.config.jwtToken = token;
|
|
2956
|
+
this.httpClient.defaults.headers["Authorization"] = `Bearer ${token}`;
|
|
2957
|
+
delete this.httpClient.defaults.headers["X-API-Key"];
|
|
2958
|
+
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Clear authentication (logout)
|
|
2961
|
+
*/
|
|
2962
|
+
logout() {
|
|
2963
|
+
this.config.jwtToken = "";
|
|
2964
|
+
delete this.httpClient.defaults.headers["Authorization"];
|
|
2965
|
+
delete this.httpClient.defaults.headers["X-API-Key"];
|
|
2966
|
+
}
|
|
2967
|
+
// =================================================================
|
|
2968
|
+
// API KEY MANAGEMENT
|
|
2969
|
+
// =================================================================
|
|
2970
|
+
/**
|
|
2971
|
+
* Create a new API key
|
|
2972
|
+
*/
|
|
2973
|
+
async createAPIKey(request) {
|
|
2974
|
+
const { data } = await this.httpClient.post("/api-keys", {
|
|
2975
|
+
name: request.name,
|
|
2976
|
+
permission: request.permission,
|
|
2977
|
+
expires_in_days: request.expires_in_days
|
|
2978
|
+
});
|
|
2979
|
+
return data;
|
|
2980
|
+
}
|
|
2981
|
+
/**
|
|
2982
|
+
* List all API keys
|
|
2983
|
+
*/
|
|
2984
|
+
async listAPIKeys() {
|
|
2985
|
+
const { data } = await this.httpClient.get("/api-keys");
|
|
2986
|
+
return data;
|
|
2987
|
+
}
|
|
2988
|
+
/**
|
|
2989
|
+
* Get API key statistics
|
|
2990
|
+
*/
|
|
2991
|
+
async getAPIKeyStats(keyId) {
|
|
2992
|
+
const { data } = await this.httpClient.get(`/api-keys/${keyId}/stats`);
|
|
2993
|
+
return data;
|
|
2994
|
+
}
|
|
2995
|
+
/**
|
|
2996
|
+
* Revoke (delete) an API key
|
|
2997
|
+
*/
|
|
2998
|
+
async revokeAPIKey(keyId) {
|
|
2999
|
+
await this.httpClient.delete(`/api-keys/${keyId}`);
|
|
3000
|
+
}
|
|
3001
|
+
// =================================================================
|
|
3002
|
+
// MULTIMEDIA MANAGEMENT
|
|
3003
|
+
// =================================================================
|
|
3004
|
+
/**
|
|
3005
|
+
* Upload multimedia file to a document
|
|
3006
|
+
*/
|
|
3007
|
+
async uploadMultimedia(collection, documentId, file, metadata) {
|
|
3008
|
+
let FormDataClass;
|
|
3009
|
+
try {
|
|
3010
|
+
FormDataClass = require("form-data");
|
|
3011
|
+
} catch {
|
|
3012
|
+
FormDataClass = FormData;
|
|
3013
|
+
}
|
|
3014
|
+
const formData = new FormDataClass();
|
|
3015
|
+
if (Buffer.isBuffer(file)) {
|
|
3016
|
+
formData.append("file", file, { filename: "upload" });
|
|
3017
|
+
} else {
|
|
3018
|
+
formData.append("file", file);
|
|
3019
|
+
}
|
|
3020
|
+
if (metadata) {
|
|
3021
|
+
formData.append("metadata", JSON.stringify(metadata));
|
|
3022
|
+
}
|
|
3023
|
+
const headers = {};
|
|
3024
|
+
if (typeof formData.getHeaders === "function") {
|
|
3025
|
+
Object.assign(headers, formData.getHeaders());
|
|
3026
|
+
}
|
|
3027
|
+
const { data } = await this.httpClient.post(
|
|
3028
|
+
`/multimedia/${collection}/documents/${documentId}/multimedia`,
|
|
3029
|
+
formData,
|
|
3030
|
+
{
|
|
3031
|
+
headers
|
|
3032
|
+
}
|
|
3033
|
+
);
|
|
3034
|
+
return data;
|
|
3035
|
+
}
|
|
3036
|
+
/**
|
|
3037
|
+
* Get multimedia file URL (for viewing/downloading)
|
|
3038
|
+
*/
|
|
3039
|
+
getMultimediaUrl(collection, documentId, multimediaId, download = false) {
|
|
3040
|
+
const protocol = this.config.useHttps ? "https" : "http";
|
|
3041
|
+
const baseUrl = `${protocol}://${this.config.host}:${this.config.port}/v1`;
|
|
3042
|
+
return `${baseUrl}/multimedia/${collection}/documents/${documentId}/multimedia/${multimediaId}${download ? "?download=true" : ""}`;
|
|
3043
|
+
}
|
|
3044
|
+
/**
|
|
3045
|
+
* Get multimedia thumbnail URL
|
|
3046
|
+
*/
|
|
3047
|
+
getMultimediaThumbnailUrl(collection, documentId, multimediaId) {
|
|
3048
|
+
const protocol = this.config.useHttps ? "https" : "http";
|
|
3049
|
+
const baseUrl = `${protocol}://${this.config.host}:${this.config.port}/v1`;
|
|
3050
|
+
return `${baseUrl}/multimedia/${collection}/documents/${documentId}/multimedia/${multimediaId}/thumbnail`;
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* List multimedia files in a document
|
|
3054
|
+
*/
|
|
3055
|
+
async listMultimedia(collection, documentId, limit = 50, offset = 0) {
|
|
3056
|
+
const { data } = await this.httpClient.get(
|
|
3057
|
+
`/multimedia/${collection}/documents/${documentId}/multimedia?limit=${limit}&offset=${offset}`
|
|
3058
|
+
);
|
|
3059
|
+
return data;
|
|
3060
|
+
}
|
|
3061
|
+
/**
|
|
3062
|
+
* Get multimedia file information
|
|
3063
|
+
*/
|
|
3064
|
+
async getMultimedia(collection, documentId, multimediaId) {
|
|
3065
|
+
const { data } = await this.httpClient.get(
|
|
3066
|
+
`/multimedia/${collection}/documents/${documentId}/multimedia/${multimediaId}`
|
|
3067
|
+
);
|
|
3068
|
+
return data;
|
|
3069
|
+
}
|
|
3070
|
+
/**
|
|
3071
|
+
* Delete multimedia file
|
|
3072
|
+
*/
|
|
3073
|
+
async deleteMultimedia(collection, documentId, multimediaId) {
|
|
3074
|
+
await this.httpClient.delete(`/multimedia/${collection}/documents/${documentId}/multimedia/${multimediaId}`);
|
|
3075
|
+
}
|
|
3076
|
+
};
|
|
3077
|
+
|
|
3078
|
+
// src/index.ts
|
|
3079
|
+
var import_zod = require("zod");
|
|
3080
|
+
var VERSION = "0.1.0";
|
|
3081
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3082
|
+
0 && (module.exports = {
|
|
3083
|
+
AuthenticationError,
|
|
3084
|
+
AutoMLClient,
|
|
3085
|
+
AutoMLModel,
|
|
3086
|
+
BackupClient,
|
|
3087
|
+
BatchOperationError,
|
|
3088
|
+
Collection,
|
|
3089
|
+
ConnectionError,
|
|
3090
|
+
ImportExportClient,
|
|
3091
|
+
IntegrationClient,
|
|
3092
|
+
NLPClient,
|
|
3093
|
+
NotFoundError,
|
|
3094
|
+
RateLimitError,
|
|
3095
|
+
RecipeClient,
|
|
3096
|
+
SQLError,
|
|
3097
|
+
SchemaClient,
|
|
3098
|
+
ServerError,
|
|
3099
|
+
Subscription,
|
|
3100
|
+
SynapCores,
|
|
3101
|
+
SynapCoresError,
|
|
3102
|
+
TimeoutError,
|
|
3103
|
+
TransactionError,
|
|
3104
|
+
VERSION,
|
|
3105
|
+
ValidationError,
|
|
3106
|
+
VectorError,
|
|
3107
|
+
z
|
|
3108
|
+
});
|
|
3109
|
+
//# sourceMappingURL=index.js.map
|