@nimbleflux/fluxbase-sdk 2026.3.6 → 2026.3.7-rc.10

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/dist/index.cjs CHANGED
@@ -7,6 +7,7 @@ var FluxbaseFetch = class {
7
7
  this.isRefreshing = false;
8
8
  this.refreshPromise = null;
9
9
  this.anonKey = null;
10
+ this.beforeRequestCallback = null;
10
11
  this.baseUrl = baseUrl.replace(/\/$/, "");
11
12
  this.defaultHeaders = {
12
13
  "Content-Type": "application/json",
@@ -22,6 +23,14 @@ var FluxbaseFetch = class {
22
23
  setRefreshTokenCallback(callback) {
23
24
  this.refreshTokenCallback = callback;
24
25
  }
26
+ /**
27
+ * Register a callback to be called before every request.
28
+ * The callback receives the headers object and can modify it in place.
29
+ * This is useful for dynamically injecting headers at request time.
30
+ */
31
+ setBeforeRequestCallback(callback) {
32
+ this.beforeRequestCallback = callback;
33
+ }
25
34
  /**
26
35
  * Set the anon key for fallback authentication
27
36
  * When setAuthToken(null) is called, the Authorization header will be
@@ -43,6 +52,18 @@ var FluxbaseFetch = class {
43
52
  delete this.defaultHeaders["Authorization"];
44
53
  }
45
54
  }
55
+ /**
56
+ * Set a custom header on all requests
57
+ */
58
+ setHeader(name, value) {
59
+ this.defaultHeaders[name] = value;
60
+ }
61
+ /**
62
+ * Remove a custom header
63
+ */
64
+ removeHeader(name) {
65
+ delete this.defaultHeaders[name];
66
+ }
46
67
  /**
47
68
  * Make an HTTP request
48
69
  */
@@ -55,15 +76,23 @@ var FluxbaseFetch = class {
55
76
  async requestInternal(path, options, isRetry) {
56
77
  const url = `${this.baseUrl}${path}`;
57
78
  const headers = { ...this.defaultHeaders, ...options.headers };
79
+ if (this.beforeRequestCallback) {
80
+ this.beforeRequestCallback(headers);
81
+ }
58
82
  const controller = new AbortController();
59
- const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.timeout);
83
+ const timeoutId = setTimeout(
84
+ () => controller.abort(),
85
+ options.timeout ?? this.timeout
86
+ );
60
87
  if (this.debug) {
61
88
  console.log(`[Fluxbase SDK] ${options.method} ${url}`, options.body);
62
89
  }
63
90
  try {
64
91
  const isFormData = options.body && (options.body.constructor?.name === "FormData" || options.body instanceof FormData);
65
92
  const requestHeaders = isFormData ? Object.fromEntries(
66
- Object.entries(headers).filter(([key]) => key.toLowerCase() !== "content-type")
93
+ Object.entries(headers).filter(
94
+ ([key]) => key.toLowerCase() !== "content-type"
95
+ )
67
96
  ) : headers;
68
97
  const response = await fetch(url, {
69
98
  method: options.method,
@@ -159,7 +188,11 @@ var FluxbaseFetch = class {
159
188
  * POST request that returns response with headers (for POST-based queries with count)
160
189
  */
161
190
  async postWithHeaders(path, body, options = {}) {
162
- return this.requestWithHeaders(path, { ...options, method: "POST", body });
191
+ return this.requestWithHeaders(path, {
192
+ ...options,
193
+ method: "POST",
194
+ body
195
+ });
163
196
  }
164
197
  /**
165
198
  * Make an HTTP request and return response with headers
@@ -173,15 +206,23 @@ var FluxbaseFetch = class {
173
206
  async requestWithHeadersInternal(path, options, isRetry) {
174
207
  const url = `${this.baseUrl}${path}`;
175
208
  const headers = { ...this.defaultHeaders, ...options.headers };
209
+ if (this.beforeRequestCallback) {
210
+ this.beforeRequestCallback(headers);
211
+ }
176
212
  const controller = new AbortController();
177
- const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.timeout);
213
+ const timeoutId = setTimeout(
214
+ () => controller.abort(),
215
+ options.timeout ?? this.timeout
216
+ );
178
217
  if (this.debug) {
179
218
  console.log(`[Fluxbase SDK] ${options.method} ${url}`, options.body);
180
219
  }
181
220
  try {
182
221
  const isFormData = options.body && (options.body.constructor?.name === "FormData" || options.body instanceof FormData);
183
222
  const requestHeaders = isFormData ? Object.fromEntries(
184
- Object.entries(headers).filter(([key]) => key.toLowerCase() !== "content-type")
223
+ Object.entries(headers).filter(
224
+ ([key]) => key.toLowerCase() !== "content-type"
225
+ )
185
226
  ) : headers;
186
227
  const response = await fetch(url, {
187
228
  method: options.method,
@@ -262,6 +303,9 @@ var FluxbaseFetch = class {
262
303
  async head(path, options = {}) {
263
304
  const url = `${this.baseUrl}${path}`;
264
305
  const headers = { ...this.defaultHeaders, ...options.headers };
306
+ if (this.beforeRequestCallback) {
307
+ this.beforeRequestCallback(headers);
308
+ }
265
309
  const response = await fetch(url, {
266
310
  method: "HEAD",
267
311
  headers
@@ -274,9 +318,15 @@ var FluxbaseFetch = class {
274
318
  async getBlob(path, options = {}) {
275
319
  const url = `${this.baseUrl}${path}`;
276
320
  const headers = { ...this.defaultHeaders, ...options.headers };
321
+ if (this.beforeRequestCallback) {
322
+ this.beforeRequestCallback(headers);
323
+ }
277
324
  delete headers["Content-Type"];
278
325
  const controller = new AbortController();
279
- const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.timeout);
326
+ const timeoutId = setTimeout(
327
+ () => controller.abort(),
328
+ options.timeout ?? this.timeout
329
+ );
280
330
  if (this.debug) {
281
331
  console.log(`[Fluxbase SDK] GET (blob) ${url}`);
282
332
  }
@@ -2510,7 +2560,11 @@ var StorageBucket = class {
2510
2560
  }
2511
2561
  let response;
2512
2562
  if (options?.onUploadProgress) {
2513
- response = await this.uploadWithProgress(path, formData, options.onUploadProgress);
2563
+ response = await this.uploadWithProgress(
2564
+ path,
2565
+ formData,
2566
+ options.onUploadProgress
2567
+ );
2514
2568
  } else {
2515
2569
  response = await this.fetch.request(
2516
2570
  `/api/v1/storage/${this.bucketName}/${path}`,
@@ -2618,7 +2672,10 @@ var StorageBucket = class {
2618
2672
  async uploadStream(path, stream, size, options) {
2619
2673
  try {
2620
2674
  if (size <= 0) {
2621
- return { data: null, error: new Error("size must be a positive number") };
2675
+ return {
2676
+ data: null,
2677
+ error: new Error("size must be a positive number")
2678
+ };
2622
2679
  }
2623
2680
  const headers = {
2624
2681
  ...this.fetch["defaultHeaders"],
@@ -2665,7 +2722,9 @@ var StorageBucket = class {
2665
2722
  );
2666
2723
  if (!response.ok) {
2667
2724
  const errorData = await response.json().catch(() => ({ error: response.statusText }));
2668
- throw new Error(errorData.error || `Upload failed: ${response.statusText}`);
2725
+ throw new Error(
2726
+ errorData.error || `Upload failed: ${response.statusText}`
2727
+ );
2669
2728
  }
2670
2729
  const result = await response.json();
2671
2730
  return {
@@ -3064,7 +3123,10 @@ var StorageBucket = class {
3064
3123
  return { data: null, error: new Error("Upload aborted") };
3065
3124
  }
3066
3125
  const chunkController = new AbortController();
3067
- const timeoutId = setTimeout(() => chunkController.abort(), chunkTimeout);
3126
+ const timeoutId = setTimeout(
3127
+ () => chunkController.abort(),
3128
+ chunkTimeout
3129
+ );
3068
3130
  if (options?.signal) {
3069
3131
  options.signal.addEventListener(
3070
3132
  "abort",
@@ -3271,6 +3333,42 @@ var StorageBucket = class {
3271
3333
  return { data: null, error };
3272
3334
  }
3273
3335
  }
3336
+ /**
3337
+ * Copy a file to a new path
3338
+ *
3339
+ * @param fromPath - Source file path
3340
+ * @param toPath - Destination file path
3341
+ * @returns Promise resolving to { data, error } tuple
3342
+ */
3343
+ async copy(fromPath, toPath) {
3344
+ try {
3345
+ const data = await this.fetch.post(
3346
+ `/api/v1/storage/${this.bucketName}/copy`,
3347
+ { from_path: fromPath, to_path: toPath }
3348
+ );
3349
+ return { data, error: null };
3350
+ } catch (error) {
3351
+ return { data: null, error };
3352
+ }
3353
+ }
3354
+ /**
3355
+ * Move a file to a new path
3356
+ *
3357
+ * @param fromPath - Source file path
3358
+ * @param toPath - Destination file path
3359
+ * @returns Promise resolving to { data, error } tuple
3360
+ */
3361
+ async move(fromPath, toPath) {
3362
+ try {
3363
+ const data = await this.fetch.post(
3364
+ `/api/v1/storage/${this.bucketName}/move`,
3365
+ { from_path: fromPath, to_path: toPath }
3366
+ );
3367
+ return { data, error: null };
3368
+ } catch (error) {
3369
+ return { data: null, error };
3370
+ }
3371
+ }
3274
3372
  /**
3275
3373
  * Get a public URL for a file
3276
3374
  * @param path - The file path
@@ -3393,50 +3491,6 @@ var StorageBucket = class {
3393
3491
  return { data: null, error };
3394
3492
  }
3395
3493
  }
3396
- /**
3397
- * Move a file to a new location
3398
- * @param fromPath - Current file path
3399
- * @param toPath - New file path
3400
- */
3401
- async move(fromPath, toPath) {
3402
- try {
3403
- await this.fetch.post(
3404
- `/api/v1/storage/${this.bucketName}/move`,
3405
- {
3406
- from_path: fromPath,
3407
- to_path: toPath
3408
- }
3409
- );
3410
- return {
3411
- data: { message: "Successfully moved" },
3412
- error: null
3413
- };
3414
- } catch (error) {
3415
- return { data: null, error };
3416
- }
3417
- }
3418
- /**
3419
- * Copy a file to a new location
3420
- * @param fromPath - Source file path
3421
- * @param toPath - Destination file path
3422
- */
3423
- async copy(fromPath, toPath) {
3424
- try {
3425
- await this.fetch.post(
3426
- `/api/v1/storage/${this.bucketName}/copy`,
3427
- {
3428
- from_path: fromPath,
3429
- to_path: toPath
3430
- }
3431
- );
3432
- return {
3433
- data: { path: toPath },
3434
- error: null
3435
- };
3436
- } catch (error) {
3437
- return { data: null, error };
3438
- }
3439
- }
3440
3494
  /**
3441
3495
  * Share a file with another user (RLS)
3442
3496
  * @param path - The file path
@@ -4263,25 +4317,6 @@ var AppSettingsManager = class {
4263
4317
  request
4264
4318
  );
4265
4319
  }
4266
- /**
4267
- * Reset all application settings to defaults
4268
- *
4269
- * This will delete all custom settings and return to default values.
4270
- *
4271
- * @returns Promise resolving to AppSettings - Default settings
4272
- *
4273
- * @example
4274
- * ```typescript
4275
- * const defaults = await client.admin.settings.app.reset()
4276
- * console.log('Settings reset to defaults:', defaults)
4277
- * ```
4278
- */
4279
- async reset() {
4280
- return await this.fetch.post(
4281
- "/api/v1/admin/app/settings/reset",
4282
- {}
4283
- );
4284
- }
4285
4320
  /**
4286
4321
  * Enable user signup
4287
4322
  *
@@ -4877,6 +4912,14 @@ var AppSettingsManager = class {
4877
4912
  );
4878
4913
  return response.value;
4879
4914
  }
4915
+ /**
4916
+ * Reset all application settings to their default values
4917
+ *
4918
+ * @returns Promise resolving to the default app settings
4919
+ */
4920
+ async reset() {
4921
+ return this.fetch.post("/api/v1/admin/app/settings/reset", {});
4922
+ }
4880
4923
  };
4881
4924
  var EmailTemplateManager = class {
4882
4925
  constructor(fetch2) {
@@ -5130,6 +5173,59 @@ var EmailSettingsManager = class {
5130
5173
  async setProvider(provider) {
5131
5174
  return await this.update({ provider });
5132
5175
  }
5176
+ // Tenant-scoped methods
5177
+ /**
5178
+ * Get tenant-level email settings (resolved through cascade)
5179
+ *
5180
+ * Returns email settings resolved for the current tenant context,
5181
+ * including source information for each field.
5182
+ *
5183
+ * @returns Promise resolving to TenantEmailProviderSettings
5184
+ */
5185
+ async getForTenant() {
5186
+ return await this.fetch.get(
5187
+ "/api/v1/admin/email/settings/tenant"
5188
+ );
5189
+ }
5190
+ /**
5191
+ * Update tenant-level email settings
5192
+ *
5193
+ * Only provided fields are updated. These override instance-level defaults.
5194
+ *
5195
+ * @param request - Settings to update
5196
+ * @returns Promise resolving to TenantEmailProviderSettings
5197
+ */
5198
+ async updateForTenant(request) {
5199
+ return await this.fetch.put(
5200
+ "/api/v1/admin/email/settings/tenant",
5201
+ request
5202
+ );
5203
+ }
5204
+ /**
5205
+ * Delete a tenant-level email setting override
5206
+ *
5207
+ * Removes the tenant override for a specific field, reverting to the instance default.
5208
+ *
5209
+ * @param field - The field name to remove the override for
5210
+ * @returns Promise resolving to TenantEmailProviderSettings
5211
+ */
5212
+ async deleteTenantOverride(field) {
5213
+ return await this.fetch.delete(
5214
+ `/api/v1/admin/email/settings/tenant/${field}`
5215
+ );
5216
+ }
5217
+ /**
5218
+ * Test tenant-level email configuration
5219
+ *
5220
+ * @param recipientEmail - Email address to send the test email to
5221
+ * @returns Promise resolving to TestEmailSettingsResponse
5222
+ */
5223
+ async testForTenant(recipientEmail) {
5224
+ return await this.fetch.post(
5225
+ "/api/v1/admin/email/settings/tenant/test",
5226
+ { recipient_email: recipientEmail }
5227
+ );
5228
+ }
5133
5229
  };
5134
5230
  var FluxbaseSettings = class {
5135
5231
  constructor(fetch2) {
@@ -6130,7 +6226,10 @@ var ClientKeysManager = class {
6130
6226
  * ```
6131
6227
  */
6132
6228
  async create(request) {
6133
- return await this.fetch.post("/api/v1/client-keys", request);
6229
+ return await this.fetch.post(
6230
+ "/api/v1/client-keys",
6231
+ request
6232
+ );
6134
6233
  }
6135
6234
  /**
6136
6235
  * List all client keys for the authenticated user
@@ -6180,7 +6279,10 @@ var ClientKeysManager = class {
6180
6279
  * ```
6181
6280
  */
6182
6281
  async update(keyId, updates) {
6183
- return await this.fetch.patch(`/api/v1/client-keys/${keyId}`, updates);
6282
+ return await this.fetch.patch(
6283
+ `/api/v1/client-keys/${keyId}`,
6284
+ updates
6285
+ );
6184
6286
  }
6185
6287
  /**
6186
6288
  * Revoke a client key
@@ -6197,7 +6299,10 @@ var ClientKeysManager = class {
6197
6299
  * ```
6198
6300
  */
6199
6301
  async revoke(keyId) {
6200
- return await this.fetch.post(`/api/v1/client-keys/${keyId}/revoke`, {});
6302
+ return await this.fetch.post(
6303
+ `/api/v1/client-keys/${keyId}/revoke`,
6304
+ {}
6305
+ );
6201
6306
  }
6202
6307
  /**
6203
6308
  * Delete a client key
@@ -6214,7 +6319,9 @@ var ClientKeysManager = class {
6214
6319
  * ```
6215
6320
  */
6216
6321
  async delete(keyId) {
6217
- return await this.fetch.delete(`/api/v1/client-keys/${keyId}`);
6322
+ return await this.fetch.delete(
6323
+ `/api/v1/client-keys/${keyId}`
6324
+ );
6218
6325
  }
6219
6326
  };
6220
6327
  var APIKeysManager = ClientKeysManager;
@@ -6289,7 +6396,10 @@ var WebhooksManager = class {
6289
6396
  * ```
6290
6397
  */
6291
6398
  async update(webhookId, updates) {
6292
- return await this.fetch.patch(`/api/v1/webhooks/${webhookId}`, updates);
6399
+ return await this.fetch.patch(
6400
+ `/api/v1/webhooks/${webhookId}`,
6401
+ updates
6402
+ );
6293
6403
  }
6294
6404
  /**
6295
6405
  * Delete a webhook
@@ -6304,7 +6414,9 @@ var WebhooksManager = class {
6304
6414
  * ```
6305
6415
  */
6306
6416
  async delete(webhookId) {
6307
- return await this.fetch.delete(`/api/v1/webhooks/${webhookId}`);
6417
+ return await this.fetch.delete(
6418
+ `/api/v1/webhooks/${webhookId}`
6419
+ );
6308
6420
  }
6309
6421
  /**
6310
6422
  * Test a webhook by sending a test payload
@@ -6324,7 +6436,10 @@ var WebhooksManager = class {
6324
6436
  * ```
6325
6437
  */
6326
6438
  async test(webhookId) {
6327
- return await this.fetch.post(`/api/v1/webhooks/${webhookId}/test`, {});
6439
+ return await this.fetch.post(
6440
+ `/api/v1/webhooks/${webhookId}/test`,
6441
+ {}
6442
+ );
6328
6443
  }
6329
6444
  /**
6330
6445
  * List webhook delivery history
@@ -6371,7 +6486,10 @@ var InvitationsManager = class {
6371
6486
  * ```
6372
6487
  */
6373
6488
  async create(request) {
6374
- return await this.fetch.post("/api/v1/admin/invitations", request);
6489
+ return await this.fetch.post(
6490
+ "/api/v1/admin/invitations",
6491
+ request
6492
+ );
6375
6493
  }
6376
6494
  /**
6377
6495
  * List all invitations (admin only)
@@ -6424,7 +6542,9 @@ var InvitationsManager = class {
6424
6542
  * ```
6425
6543
  */
6426
6544
  async validate(token) {
6427
- return await this.fetch.get(`/api/v1/invitations/${token}/validate`);
6545
+ return await this.fetch.get(
6546
+ `/api/v1/invitations/${token}/validate`
6547
+ );
6428
6548
  }
6429
6549
  /**
6430
6550
  * Accept an invitation and create a new user (public endpoint)
@@ -6446,7 +6566,10 @@ var InvitationsManager = class {
6446
6566
  * ```
6447
6567
  */
6448
6568
  async accept(token, request) {
6449
- return await this.fetch.post(`/api/v1/invitations/${token}/accept`, request);
6569
+ return await this.fetch.post(
6570
+ `/api/v1/invitations/${token}/accept`,
6571
+ request
6572
+ );
6450
6573
  }
6451
6574
  /**
6452
6575
  * Revoke an invitation (admin only)
@@ -6461,7 +6584,9 @@ var InvitationsManager = class {
6461
6584
  * ```
6462
6585
  */
6463
6586
  async revoke(token) {
6464
- return await this.fetch.delete(`/api/v1/admin/invitations/${token}`);
6587
+ return await this.fetch.delete(
6588
+ `/api/v1/admin/invitations/${token}`
6589
+ );
6465
6590
  }
6466
6591
  };
6467
6592
  var FluxbaseManagement = class {
@@ -7383,24 +7508,14 @@ var FluxbaseAdminJobs = class _FluxbaseAdminJobs {
7383
7508
  /**
7384
7509
  * Create a new job function
7385
7510
  *
7386
- * @param request - Job function configuration and code
7387
- * @returns Promise resolving to { data, error } tuple with created job function metadata
7388
- *
7389
- * @example
7390
- * ```typescript
7391
- * const { data, error } = await client.admin.jobs.create({
7392
- * name: 'process-data',
7393
- * code: 'export async function handler(req) { return { success: true } }',
7394
- * enabled: true,
7395
- * timeout_seconds: 300
7396
- * })
7397
- * ```
7511
+ * @param params - Job function configuration
7512
+ * @returns Promise resolving to { data, error } tuple with created job function
7398
7513
  */
7399
- async create(request) {
7514
+ async create(params) {
7400
7515
  try {
7401
7516
  const data = await this.fetch.post(
7402
7517
  "/api/v1/admin/jobs/functions",
7403
- request
7518
+ params
7404
7519
  );
7405
7520
  return { data, error: null };
7406
7521
  } catch (error) {
@@ -7481,50 +7596,42 @@ var FluxbaseAdminJobs = class _FluxbaseAdminJobs {
7481
7596
  }
7482
7597
  }
7483
7598
  /**
7484
- * Update an existing job function
7599
+ * Delete a job function
7485
7600
  *
7486
7601
  * @param namespace - Namespace
7487
7602
  * @param name - Job function name
7488
- * @param updates - Fields to update
7489
- * @returns Promise resolving to { data, error } tuple with updated job function metadata
7603
+ * @returns Promise resolving to { data, error } tuple
7490
7604
  *
7491
7605
  * @example
7492
7606
  * ```typescript
7493
- * const { data, error } = await client.admin.jobs.update('default', 'process-data', {
7494
- * enabled: false,
7495
- * timeout_seconds: 600
7496
- * })
7607
+ * const { data, error } = await client.admin.jobs.delete('default', 'process-data')
7497
7608
  * ```
7498
7609
  */
7499
- async update(namespace, name, updates) {
7610
+ async delete(namespace, name) {
7500
7611
  try {
7501
- const data = await this.fetch.put(
7502
- `/api/v1/admin/jobs/functions/${namespace}/${name}`,
7503
- updates
7612
+ await this.fetch.delete(
7613
+ `/api/v1/admin/jobs/functions/${namespace}/${name}`
7504
7614
  );
7505
- return { data, error: null };
7615
+ return { data: null, error: null };
7506
7616
  } catch (error) {
7507
7617
  return { data: null, error };
7508
7618
  }
7509
7619
  }
7510
7620
  /**
7511
- * Delete a job function
7621
+ * Update an existing job function
7512
7622
  *
7513
7623
  * @param namespace - Namespace
7514
7624
  * @param name - Job function name
7515
- * @returns Promise resolving to { data, error } tuple
7516
- *
7517
- * @example
7518
- * ```typescript
7519
- * const { data, error } = await client.admin.jobs.delete('default', 'process-data')
7520
- * ```
7625
+ * @param updates - Fields to update
7626
+ * @returns Promise resolving to { data, error } tuple with updated job function
7521
7627
  */
7522
- async delete(namespace, name) {
7628
+ async update(namespace, name, updates) {
7523
7629
  try {
7524
- await this.fetch.delete(
7525
- `/api/v1/admin/jobs/functions/${namespace}/${name}`
7630
+ const data = await this.fetch.put(
7631
+ `/api/v1/admin/jobs/functions/${namespace}/${name}`,
7632
+ updates
7526
7633
  );
7527
- return { data: null, error: null };
7634
+ return { data, error: null };
7528
7635
  } catch (error) {
7529
7636
  return { data: null, error };
7530
7637
  }
@@ -8039,18 +8146,10 @@ var FluxbaseAdminAI = class {
8039
8146
  }
8040
8147
  }
8041
8148
  /**
8042
- * Get details of a specific provider
8149
+ * Get details of a specific AI provider
8043
8150
  *
8044
8151
  * @param id - Provider ID
8045
8152
  * @returns Promise resolving to { data, error } tuple with provider details
8046
- *
8047
- * @example
8048
- * ```typescript
8049
- * const { data, error } = await client.admin.ai.getProvider('uuid')
8050
- * if (data) {
8051
- * console.log('Provider:', data.display_name)
8052
- * }
8053
- * ```
8054
8153
  */
8055
8154
  async getProvider(id) {
8056
8155
  try {
@@ -8065,39 +8164,24 @@ var FluxbaseAdminAI = class {
8065
8164
  /**
8066
8165
  * Create a new AI provider
8067
8166
  *
8068
- * @param request - Provider configuration
8167
+ * @param params - Provider configuration including name, provider_type, and optional config
8069
8168
  * @returns Promise resolving to { data, error } tuple with created provider
8070
- *
8071
- * @example
8072
- * ```typescript
8073
- * const { data, error } = await client.admin.ai.createProvider({
8074
- * name: 'openai-main',
8075
- * display_name: 'OpenAI (Main)',
8076
- * provider_type: 'openai',
8077
- * is_default: true,
8078
- * config: {
8079
- * api_key: 'sk-...',
8080
- * model: 'gpt-4-turbo',
8081
- * }
8082
- * })
8083
- * ```
8084
8169
  */
8085
- async createProvider(request) {
8170
+ async createProvider(params) {
8086
8171
  try {
8087
- const normalizedConfig = {};
8088
- if (request.config) {
8089
- for (const [key, value] of Object.entries(request.config)) {
8090
- if (value !== void 0 && value !== null) {
8091
- normalizedConfig[key] = String(value);
8092
- }
8093
- }
8172
+ const body = {
8173
+ name: params.name,
8174
+ provider_type: params.provider_type
8175
+ };
8176
+ if (params.display_name !== void 0)
8177
+ body.display_name = params.display_name;
8178
+ if (params.is_default !== void 0) body.is_default = params.is_default;
8179
+ if (params.config) {
8180
+ body.config = normalizeConfig(params.config);
8094
8181
  }
8095
8182
  const data = await this.fetch.post(
8096
8183
  "/api/v1/admin/ai/providers",
8097
- {
8098
- ...request,
8099
- config: normalizedConfig
8100
- }
8184
+ body
8101
8185
  );
8102
8186
  return { data, error: null };
8103
8187
  } catch (error) {
@@ -8110,34 +8194,16 @@ var FluxbaseAdminAI = class {
8110
8194
  * @param id - Provider ID
8111
8195
  * @param updates - Fields to update
8112
8196
  * @returns Promise resolving to { data, error } tuple with updated provider
8113
- *
8114
- * @example
8115
- * ```typescript
8116
- * const { data, error } = await client.admin.ai.updateProvider('uuid', {
8117
- * display_name: 'Updated Name',
8118
- * config: {
8119
- * api_key: 'new-key',
8120
- * model: 'gpt-4-turbo',
8121
- * },
8122
- * enabled: true,
8123
- * })
8124
- * ```
8125
8197
  */
8126
8198
  async updateProvider(id, updates) {
8127
8199
  try {
8128
- let normalizedUpdates = updates;
8200
+ const body = { ...updates };
8129
8201
  if (updates.config) {
8130
- const normalizedConfig = {};
8131
- for (const [key, value] of Object.entries(updates.config)) {
8132
- if (value !== void 0 && value !== null) {
8133
- normalizedConfig[key] = String(value);
8134
- }
8135
- }
8136
- normalizedUpdates = { ...updates, config: normalizedConfig };
8202
+ body.config = normalizeConfig(updates.config);
8137
8203
  }
8138
8204
  const data = await this.fetch.put(
8139
8205
  `/api/v1/admin/ai/providers/${id}`,
8140
- normalizedUpdates
8206
+ body
8141
8207
  );
8142
8208
  return { data, error: null };
8143
8209
  } catch (error) {
@@ -8145,15 +8211,10 @@ var FluxbaseAdminAI = class {
8145
8211
  }
8146
8212
  }
8147
8213
  /**
8148
- * Set a provider as the default
8214
+ * Set a provider as the default provider
8149
8215
  *
8150
8216
  * @param id - Provider ID
8151
8217
  * @returns Promise resolving to { data, error } tuple with updated provider
8152
- *
8153
- * @example
8154
- * ```typescript
8155
- * const { data, error } = await client.admin.ai.setDefaultProvider('uuid')
8156
- * ```
8157
8218
  */
8158
8219
  async setDefaultProvider(id) {
8159
8220
  try {
@@ -8167,15 +8228,10 @@ var FluxbaseAdminAI = class {
8167
8228
  }
8168
8229
  }
8169
8230
  /**
8170
- * Delete a provider
8231
+ * Delete an AI provider
8171
8232
  *
8172
8233
  * @param id - Provider ID
8173
8234
  * @returns Promise resolving to { data, error } tuple
8174
- *
8175
- * @example
8176
- * ```typescript
8177
- * const { data, error } = await client.admin.ai.deleteProvider('uuid')
8178
- * ```
8179
8235
  */
8180
8236
  async deleteProvider(id) {
8181
8237
  try {
@@ -8189,31 +8245,24 @@ var FluxbaseAdminAI = class {
8189
8245
  * Set a provider as the embedding provider
8190
8246
  *
8191
8247
  * @param id - Provider ID
8192
- * @returns Promise resolving to { data, error } tuple
8193
- *
8194
- * @example
8195
- * ```typescript
8196
- * const { data, error } = await client.admin.ai.setEmbeddingProvider('uuid')
8197
- * ```
8248
+ * @returns Promise resolving to { data, error } tuple with updated provider
8198
8249
  */
8199
8250
  async setEmbeddingProvider(id) {
8200
8251
  try {
8201
- const data = await this.fetch.put(`/api/v1/admin/ai/providers/${id}/embedding`, {});
8252
+ const data = await this.fetch.put(
8253
+ `/api/v1/admin/ai/providers/${id}/embedding`,
8254
+ {}
8255
+ );
8202
8256
  return { data, error: null };
8203
8257
  } catch (error) {
8204
8258
  return { data: null, error };
8205
8259
  }
8206
8260
  }
8207
8261
  /**
8208
- * Clear explicit embedding provider preference (revert to default)
8262
+ * Clear the embedding provider assignment for a provider
8209
8263
  *
8210
- * @param id - Provider ID to clear
8264
+ * @param id - Provider ID
8211
8265
  * @returns Promise resolving to { data, error } tuple
8212
- *
8213
- * @example
8214
- * ```typescript
8215
- * const { data, error } = await client.admin.ai.clearEmbeddingProvider('uuid')
8216
- * ```
8217
8266
  */
8218
8267
  async clearEmbeddingProvider(id) {
8219
8268
  try {
@@ -8226,308 +8275,6 @@ var FluxbaseAdminAI = class {
8226
8275
  }
8227
8276
  }
8228
8277
  // ============================================================================
8229
- // KNOWLEDGE BASE MANAGEMENT (RAG)
8230
- // ============================================================================
8231
- /**
8232
- * List all knowledge bases
8233
- *
8234
- * @returns Promise resolving to { data, error } tuple with array of knowledge base summaries
8235
- *
8236
- * @example
8237
- * ```typescript
8238
- * const { data, error } = await client.admin.ai.listKnowledgeBases()
8239
- * if (data) {
8240
- * console.log('Knowledge bases:', data.map(kb => kb.name))
8241
- * }
8242
- * ```
8243
- */
8244
- async listKnowledgeBases() {
8245
- try {
8246
- const response = await this.fetch.get("/api/v1/admin/ai/knowledge-bases");
8247
- return { data: response.knowledge_bases || [], error: null };
8248
- } catch (error) {
8249
- return { data: null, error };
8250
- }
8251
- }
8252
- /**
8253
- * Get a specific knowledge base
8254
- *
8255
- * @param id - Knowledge base ID
8256
- * @returns Promise resolving to { data, error } tuple with knowledge base details
8257
- *
8258
- * @example
8259
- * ```typescript
8260
- * const { data, error } = await client.admin.ai.getKnowledgeBase('uuid')
8261
- * if (data) {
8262
- * console.log('Knowledge base:', data.name)
8263
- * }
8264
- * ```
8265
- */
8266
- async getKnowledgeBase(id) {
8267
- try {
8268
- const data = await this.fetch.get(
8269
- `/api/v1/admin/ai/knowledge-bases/${id}`
8270
- );
8271
- return { data, error: null };
8272
- } catch (error) {
8273
- return { data: null, error };
8274
- }
8275
- }
8276
- /**
8277
- * Create a new knowledge base
8278
- *
8279
- * @param request - Knowledge base configuration
8280
- * @returns Promise resolving to { data, error } tuple with created knowledge base
8281
- *
8282
- * @example
8283
- * ```typescript
8284
- * const { data, error } = await client.admin.ai.createKnowledgeBase({
8285
- * name: 'product-docs',
8286
- * description: 'Product documentation',
8287
- * chunk_size: 512,
8288
- * chunk_overlap: 50,
8289
- * })
8290
- * ```
8291
- */
8292
- async createKnowledgeBase(request) {
8293
- try {
8294
- const data = await this.fetch.post(
8295
- "/api/v1/admin/ai/knowledge-bases",
8296
- request
8297
- );
8298
- return { data, error: null };
8299
- } catch (error) {
8300
- return { data: null, error };
8301
- }
8302
- }
8303
- /**
8304
- * Update an existing knowledge base
8305
- *
8306
- * @param id - Knowledge base ID
8307
- * @param updates - Fields to update
8308
- * @returns Promise resolving to { data, error } tuple with updated knowledge base
8309
- *
8310
- * @example
8311
- * ```typescript
8312
- * const { data, error } = await client.admin.ai.updateKnowledgeBase('uuid', {
8313
- * description: 'Updated description',
8314
- * enabled: true,
8315
- * })
8316
- * ```
8317
- */
8318
- async updateKnowledgeBase(id, updates) {
8319
- try {
8320
- const data = await this.fetch.put(
8321
- `/api/v1/admin/ai/knowledge-bases/${id}`,
8322
- updates
8323
- );
8324
- return { data, error: null };
8325
- } catch (error) {
8326
- return { data: null, error };
8327
- }
8328
- }
8329
- /**
8330
- * Delete a knowledge base
8331
- *
8332
- * @param id - Knowledge base ID
8333
- * @returns Promise resolving to { data, error } tuple
8334
- *
8335
- * @example
8336
- * ```typescript
8337
- * const { data, error } = await client.admin.ai.deleteKnowledgeBase('uuid')
8338
- * ```
8339
- */
8340
- async deleteKnowledgeBase(id) {
8341
- try {
8342
- await this.fetch.delete(`/api/v1/admin/ai/knowledge-bases/${id}`);
8343
- return { data: null, error: null };
8344
- } catch (error) {
8345
- return { data: null, error };
8346
- }
8347
- }
8348
- // ============================================================================
8349
- // DOCUMENT MANAGEMENT
8350
- // ============================================================================
8351
- /**
8352
- * List documents in a knowledge base
8353
- *
8354
- * @param knowledgeBaseId - Knowledge base ID
8355
- * @returns Promise resolving to { data, error } tuple with array of documents
8356
- *
8357
- * @example
8358
- * ```typescript
8359
- * const { data, error } = await client.admin.ai.listDocuments('kb-uuid')
8360
- * if (data) {
8361
- * console.log('Documents:', data.map(d => d.title))
8362
- * }
8363
- * ```
8364
- */
8365
- async listDocuments(knowledgeBaseId) {
8366
- try {
8367
- const response = await this.fetch.get(`/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents`);
8368
- return { data: response.documents || [], error: null };
8369
- } catch (error) {
8370
- return { data: null, error };
8371
- }
8372
- }
8373
- /**
8374
- * Get a specific document
8375
- *
8376
- * @param knowledgeBaseId - Knowledge base ID
8377
- * @param documentId - Document ID
8378
- * @returns Promise resolving to { data, error } tuple with document details
8379
- *
8380
- * @example
8381
- * ```typescript
8382
- * const { data, error } = await client.admin.ai.getDocument('kb-uuid', 'doc-uuid')
8383
- * ```
8384
- */
8385
- async getDocument(knowledgeBaseId, documentId) {
8386
- try {
8387
- const data = await this.fetch.get(
8388
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents/${documentId}`
8389
- );
8390
- return { data, error: null };
8391
- } catch (error) {
8392
- return { data: null, error };
8393
- }
8394
- }
8395
- /**
8396
- * Add a document to a knowledge base
8397
- *
8398
- * Document will be chunked and embedded asynchronously.
8399
- *
8400
- * @param knowledgeBaseId - Knowledge base ID
8401
- * @param request - Document content and metadata
8402
- * @returns Promise resolving to { data, error } tuple with document ID
8403
- *
8404
- * @example
8405
- * ```typescript
8406
- * const { data, error } = await client.admin.ai.addDocument('kb-uuid', {
8407
- * title: 'Getting Started Guide',
8408
- * content: 'This is the content of the document...',
8409
- * metadata: { category: 'guides' },
8410
- * })
8411
- * if (data) {
8412
- * console.log('Document ID:', data.document_id)
8413
- * }
8414
- * ```
8415
- */
8416
- async addDocument(knowledgeBaseId, request) {
8417
- try {
8418
- const data = await this.fetch.post(
8419
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents`,
8420
- request
8421
- );
8422
- return { data, error: null };
8423
- } catch (error) {
8424
- return { data: null, error };
8425
- }
8426
- }
8427
- /**
8428
- * Upload a document file to a knowledge base
8429
- *
8430
- * Supported file types: PDF, TXT, MD, HTML, CSV, DOCX, XLSX, RTF, EPUB, JSON
8431
- * Maximum file size: 50MB
8432
- *
8433
- * @param knowledgeBaseId - Knowledge base ID
8434
- * @param file - File to upload (File or Blob)
8435
- * @param title - Optional document title (defaults to filename without extension)
8436
- * @returns Promise resolving to { data, error } tuple with upload result
8437
- *
8438
- * @example
8439
- * ```typescript
8440
- * // Browser
8441
- * const fileInput = document.getElementById('file') as HTMLInputElement
8442
- * const file = fileInput.files?.[0]
8443
- * if (file) {
8444
- * const { data, error } = await client.admin.ai.uploadDocument('kb-uuid', file)
8445
- * if (data) {
8446
- * console.log('Document ID:', data.document_id)
8447
- * console.log('Extracted length:', data.extracted_length)
8448
- * }
8449
- * }
8450
- *
8451
- * // Node.js (with node-fetch or similar)
8452
- * import { Blob } from 'buffer'
8453
- * const content = await fs.readFile('document.pdf')
8454
- * const blob = new Blob([content], { type: 'application/pdf' })
8455
- * const { data, error } = await client.admin.ai.uploadDocument('kb-uuid', blob, 'My Document')
8456
- * ```
8457
- */
8458
- async uploadDocument(knowledgeBaseId, file, title) {
8459
- try {
8460
- const formData = new FormData();
8461
- formData.append("file", file);
8462
- if (title) {
8463
- formData.append("title", title);
8464
- }
8465
- const data = await this.fetch.post(
8466
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents/upload`,
8467
- formData
8468
- );
8469
- return { data, error: null };
8470
- } catch (error) {
8471
- return { data: null, error };
8472
- }
8473
- }
8474
- /**
8475
- * Delete a document from a knowledge base
8476
- *
8477
- * @param knowledgeBaseId - Knowledge base ID
8478
- * @param documentId - Document ID
8479
- * @returns Promise resolving to { data, error } tuple
8480
- *
8481
- * @example
8482
- * ```typescript
8483
- * const { data, error } = await client.admin.ai.deleteDocument('kb-uuid', 'doc-uuid')
8484
- * ```
8485
- */
8486
- async deleteDocument(knowledgeBaseId, documentId) {
8487
- try {
8488
- await this.fetch.delete(
8489
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents/${documentId}`
8490
- );
8491
- return { data: null, error: null };
8492
- } catch (error) {
8493
- return { data: null, error };
8494
- }
8495
- }
8496
- /**
8497
- * Search a knowledge base
8498
- *
8499
- * @param knowledgeBaseId - Knowledge base ID
8500
- * @param query - Search query
8501
- * @param options - Search options
8502
- * @returns Promise resolving to { data, error } tuple with search results
8503
- *
8504
- * @example
8505
- * ```typescript
8506
- * const { data, error } = await client.admin.ai.searchKnowledgeBase('kb-uuid', 'how to reset password', {
8507
- * max_chunks: 5,
8508
- * threshold: 0.7,
8509
- * })
8510
- * if (data) {
8511
- * console.log('Results:', data.results.map(r => r.content))
8512
- * }
8513
- * ```
8514
- */
8515
- async searchKnowledgeBase(knowledgeBaseId, query, options) {
8516
- try {
8517
- const data = await this.fetch.post(
8518
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/search`,
8519
- {
8520
- query,
8521
- max_chunks: options?.max_chunks,
8522
- threshold: options?.threshold
8523
- }
8524
- );
8525
- return { data, error: null };
8526
- } catch (error) {
8527
- return { data: null, error };
8528
- }
8529
- }
8530
- // ============================================================================
8531
8278
  // CHATBOT KNOWLEDGE BASE LINKING
8532
8279
  // ============================================================================
8533
8280
  /**
@@ -8544,482 +8291,63 @@ var FluxbaseAdminAI = class {
8544
8291
  * }
8545
8292
  * ```
8546
8293
  */
8547
- async listChatbotKnowledgeBases(chatbotId) {
8548
- try {
8549
- const response = await this.fetch.get(`/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases`);
8550
- return { data: response.knowledge_bases || [], error: null };
8551
- } catch (error) {
8552
- return { data: null, error };
8553
- }
8554
- }
8555
- /**
8556
- * Link a knowledge base to a chatbot
8557
- *
8558
- * @param chatbotId - Chatbot ID
8559
- * @param request - Link configuration
8560
- * @returns Promise resolving to { data, error } tuple with link details
8561
- *
8562
- * @example
8563
- * ```typescript
8564
- * const { data, error } = await client.admin.ai.linkKnowledgeBase('chatbot-uuid', {
8565
- * knowledge_base_id: 'kb-uuid',
8566
- * priority: 1,
8567
- * max_chunks: 5,
8568
- * similarity_threshold: 0.7,
8569
- * })
8570
- * ```
8571
- */
8572
- async linkKnowledgeBase(chatbotId, request) {
8573
- try {
8574
- const data = await this.fetch.post(
8575
- `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases`,
8576
- request
8577
- );
8578
- return { data, error: null };
8579
- } catch (error) {
8580
- return { data: null, error };
8581
- }
8582
- }
8583
- /**
8584
- * Update a chatbot-knowledge base link
8585
- *
8586
- * @param chatbotId - Chatbot ID
8587
- * @param knowledgeBaseId - Knowledge base ID
8588
- * @param updates - Fields to update
8589
- * @returns Promise resolving to { data, error } tuple with updated link
8590
- *
8591
- * @example
8592
- * ```typescript
8593
- * const { data, error } = await client.admin.ai.updateChatbotKnowledgeBase(
8594
- * 'chatbot-uuid',
8595
- * 'kb-uuid',
8596
- * { max_chunks: 10, enabled: true }
8597
- * )
8598
- * ```
8599
- */
8600
- async updateChatbotKnowledgeBase(chatbotId, knowledgeBaseId, updates) {
8601
- try {
8602
- const data = await this.fetch.put(
8603
- `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases/${knowledgeBaseId}`,
8604
- updates
8605
- );
8606
- return { data, error: null };
8607
- } catch (error) {
8608
- return { data: null, error };
8609
- }
8610
- }
8611
- /**
8612
- * Unlink a knowledge base from a chatbot
8613
- *
8614
- * @param chatbotId - Chatbot ID
8615
- * @param knowledgeBaseId - Knowledge base ID
8616
- * @returns Promise resolving to { data, error } tuple
8617
- *
8618
- * @example
8619
- * ```typescript
8620
- * const { data, error } = await client.admin.ai.unlinkKnowledgeBase('chatbot-uuid', 'kb-uuid')
8621
- * ```
8622
- */
8623
- async unlinkKnowledgeBase(chatbotId, knowledgeBaseId) {
8624
- try {
8625
- await this.fetch.delete(
8626
- `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases/${knowledgeBaseId}`
8627
- );
8628
- return { data: null, error: null };
8629
- } catch (error) {
8630
- return { data: null, error };
8631
- }
8632
- }
8633
- // ============================================================================
8634
- // DOCUMENT UPDATE AND BULK DELETE
8635
- // ============================================================================
8636
- /**
8637
- * Update a document in a knowledge base
8638
- *
8639
- * @param knowledgeBaseId - Knowledge base ID
8640
- * @param documentId - Document ID
8641
- * @param updates - Fields to update
8642
- * @returns Promise resolving to { data, error } tuple with updated document
8643
- *
8644
- * @example
8645
- * ```typescript
8646
- * const { data, error } = await client.admin.ai.updateDocument('kb-uuid', 'doc-uuid', {
8647
- * title: 'Updated Title',
8648
- * tags: ['updated', 'tag'],
8649
- * metadata: { category: 'updated' },
8650
- * })
8651
- * ```
8652
- */
8653
- async updateDocument(knowledgeBaseId, documentId, updates) {
8654
- try {
8655
- const data = await this.fetch.patch(
8656
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents/${documentId}`,
8657
- updates
8658
- );
8659
- return { data, error: null };
8660
- } catch (error) {
8661
- return { data: null, error };
8662
- }
8663
- }
8664
- /**
8665
- * Delete documents from a knowledge base by filter
8666
- *
8667
- * @param knowledgeBaseId - Knowledge base ID
8668
- * @param filter - Filter criteria for deletion
8669
- * @returns Promise resolving to { data, error } tuple with deletion count
8670
- *
8671
- * @example
8672
- * ```typescript
8673
- * // Delete by tags
8674
- * const { data, error } = await client.admin.ai.deleteDocumentsByFilter('kb-uuid', {
8675
- * tags: ['deprecated', 'archive'],
8676
- * })
8677
- *
8678
- * // Delete by metadata
8679
- * const { data, error } = await client.admin.ai.deleteDocumentsByFilter('kb-uuid', {
8680
- * metadata: { source: 'legacy-system' },
8681
- * })
8682
- *
8683
- * if (data) {
8684
- * console.log(`Deleted ${data.deleted_count} documents`)
8685
- * }
8686
- * ```
8687
- */
8688
- async deleteDocumentsByFilter(knowledgeBaseId, filter) {
8689
- try {
8690
- const data = await this.fetch.post(
8691
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/documents/delete-by-filter`,
8692
- filter
8693
- );
8694
- return { data, error: null };
8695
- } catch (error) {
8696
- return { data: null, error };
8697
- }
8698
- }
8699
- // ============================================================================
8700
- // KNOWLEDGE BASE CAPABILITIES
8701
- // ============================================================================
8702
- /**
8703
- * Get knowledge base system capabilities
8704
- *
8705
- * Returns information about OCR support, supported file types, etc.
8706
- *
8707
- * @returns Promise resolving to { data, error } tuple with capabilities
8708
- *
8709
- * @example
8710
- * ```typescript
8711
- * const { data, error } = await client.admin.ai.getCapabilities()
8712
- * if (data) {
8713
- * console.log('OCR available:', data.ocr_available)
8714
- * console.log('Supported types:', data.supported_file_types)
8715
- * }
8716
- * ```
8717
- */
8718
- async getCapabilities() {
8719
- try {
8720
- const data = await this.fetch.get(
8721
- "/api/v1/admin/ai/knowledge-bases/capabilities"
8722
- );
8723
- return { data, error: null };
8724
- } catch (error) {
8725
- return { data: null, error };
8726
- }
8727
- }
8728
- // ============================================================================
8729
- // KNOWLEDGE GRAPH / ENTITIES
8730
- // ============================================================================
8731
- /**
8732
- * List entities in a knowledge base
8733
- *
8734
- * @param knowledgeBaseId - Knowledge base ID
8735
- * @param entityType - Optional entity type filter
8736
- * @returns Promise resolving to { data, error } tuple with array of entities
8737
- *
8738
- * @example
8739
- * ```typescript
8740
- * // List all entities
8741
- * const { data, error } = await client.admin.ai.listEntities('kb-uuid')
8742
- *
8743
- * // Filter by type
8744
- * const { data, error } = await client.admin.ai.listEntities('kb-uuid', 'person')
8745
- *
8746
- * if (data) {
8747
- * console.log('Entities:', data.map(e => e.name))
8748
- * }
8749
- * ```
8750
- */
8751
- async listEntities(knowledgeBaseId, entityType) {
8752
- try {
8753
- const params = entityType ? `?entity_type=${entityType}` : "";
8754
- const response = await this.fetch.get(
8755
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/entities${params}`
8756
- );
8757
- return { data: response.entities || [], error: null };
8758
- } catch (error) {
8759
- return { data: null, error };
8760
- }
8761
- }
8762
- /**
8763
- * Search for entities in a knowledge base
8764
- *
8765
- * @param knowledgeBaseId - Knowledge base ID
8766
- * @param query - Search query
8767
- * @param types - Optional entity type filters
8768
- * @returns Promise resolving to { data, error } tuple with matching entities
8769
- *
8770
- * @example
8771
- * ```typescript
8772
- * // Search all entity types
8773
- * const { data, error } = await client.admin.ai.searchEntities('kb-uuid', 'John')
8774
- *
8775
- * // Search specific types
8776
- * const { data, error } = await client.admin.ai.searchEntities('kb-uuid', 'Apple', ['organization', 'product'])
8777
- *
8778
- * if (data) {
8779
- * console.log('Found entities:', data.map(e => `${e.name} (${e.entity_type})`))
8780
- * }
8781
- * ```
8782
- */
8783
- async searchEntities(knowledgeBaseId, query, types) {
8784
- try {
8785
- const params = new URLSearchParams({ query });
8786
- if (types && types.length > 0) {
8787
- params.append("types", types.join(","));
8788
- }
8789
- const response = await this.fetch.get(
8790
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/entities/search?${params.toString()}`
8791
- );
8792
- return { data: response.entities || [], error: null };
8793
- } catch (error) {
8794
- return { data: null, error };
8795
- }
8796
- }
8797
- /**
8798
- * Get relationships for a specific entity
8799
- *
8800
- * @param knowledgeBaseId - Knowledge base ID
8801
- * @param entityId - Entity ID
8802
- * @returns Promise resolving to { data, error } tuple with entity relationships
8803
- *
8804
- * @example
8805
- * ```typescript
8806
- * const { data, error } = await client.admin.ai.getEntityRelationships('kb-uuid', 'entity-uuid')
8807
- * if (data) {
8808
- * console.log('Relationships:', data.map(r => `${r.relationship_type} -> ${r.target_entity?.name}`))
8809
- * }
8810
- * ```
8811
- */
8812
- async getEntityRelationships(knowledgeBaseId, entityId) {
8813
- try {
8814
- const response = await this.fetch.get(
8815
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/entities/${entityId}/relationships`
8816
- );
8817
- return { data: response.relationships || [], error: null };
8818
- } catch (error) {
8819
- return { data: null, error };
8820
- }
8821
- }
8822
- /**
8823
- * Get the knowledge graph for a knowledge base
8824
- *
8825
- * Returns all entities and relationships for visualization.
8826
- *
8827
- * @param knowledgeBaseId - Knowledge base ID
8828
- * @returns Promise resolving to { data, error } tuple with graph data
8829
- *
8830
- * @example
8831
- * ```typescript
8832
- * const { data, error } = await client.admin.ai.getKnowledgeGraph('kb-uuid')
8833
- * if (data) {
8834
- * console.log('Graph:', data.entity_count, 'entities,', data.relationship_count, 'relationships')
8835
- * // Use with visualization libraries like D3.js, Cytoscape.js, etc.
8836
- * }
8837
- * ```
8838
- */
8839
- async getKnowledgeGraph(knowledgeBaseId) {
8840
- try {
8841
- const data = await this.fetch.get(
8842
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/graph`
8843
- );
8844
- return { data, error: null };
8845
- } catch (error) {
8846
- return { data: null, error };
8847
- }
8848
- }
8849
- // ============================================================================
8850
- // KNOWLEDGE BASE REVERSE LOOKUP
8851
- // ============================================================================
8852
- /**
8853
- * List all chatbots that use a specific knowledge base
8854
- *
8855
- * Reverse lookup to find which chatbots are linked to a knowledge base.
8856
- *
8857
- * @param knowledgeBaseId - Knowledge base ID
8858
- * @returns Promise resolving to { data, error } tuple with array of chatbot summaries
8859
- *
8860
- * @example
8861
- * ```typescript
8862
- * const { data, error } = await client.admin.ai.listChatbotsUsingKB('kb-uuid')
8863
- * if (data) {
8864
- * console.log('Used by chatbots:', data.map(c => c.name))
8865
- * }
8866
- * ```
8867
- */
8868
- async listChatbotsUsingKB(knowledgeBaseId) {
8869
- try {
8870
- const response = await this.fetch.get(`/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/chatbots`);
8871
- return { data: response.chatbots || [], error: null };
8872
- } catch (error) {
8873
- return { data: null, error };
8874
- }
8875
- }
8876
- // ============================================================================
8877
- // TABLE EXPORT
8878
- // ============================================================================
8879
- /**
8880
- * Export a database table to a knowledge base
8881
- *
8882
- * The table schema will be exported as a markdown document and indexed.
8883
- * Optionally filter which columns to export for security or relevance.
8884
- *
8885
- * @param knowledgeBaseId - Knowledge base ID
8886
- * @param options - Export options including column selection
8887
- * @returns Promise resolving to { data, error } tuple with export result
8888
- *
8889
- * @example
8890
- * ```typescript
8891
- * // Export all columns
8892
- * const { data, error } = await client.admin.ai.exportTable('kb-uuid', {
8893
- * schema: 'public',
8894
- * table: 'users',
8895
- * include_foreign_keys: true,
8896
- * })
8897
- *
8898
- * // Export specific columns (recommended for sensitive data)
8899
- * const { data, error } = await client.admin.ai.exportTable('kb-uuid', {
8900
- * schema: 'public',
8901
- * table: 'users',
8902
- * columns: ['id', 'name', 'email', 'created_at'],
8903
- * })
8904
- * ```
8905
- */
8906
- async exportTable(knowledgeBaseId, options) {
8907
- try {
8908
- const data = await this.fetch.post(
8909
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/tables/export`,
8910
- options
8911
- );
8912
- return { data, error: null };
8913
- } catch (error) {
8914
- return { data: null, error };
8915
- }
8916
- }
8917
- /**
8918
- * Get detailed table information including columns
8919
- *
8920
- * Use this to discover available columns before exporting.
8921
- *
8922
- * @param schema - Schema name (e.g., 'public')
8923
- * @param table - Table name
8924
- * @returns Promise resolving to { data, error } tuple with table details
8925
- *
8926
- * @example
8927
- * ```typescript
8928
- * const { data, error } = await client.admin.ai.getTableDetails('public', 'users')
8929
- * if (data) {
8930
- * console.log('Columns:', data.columns.map(c => c.name))
8931
- * console.log('Primary key:', data.primary_key)
8932
- * }
8933
- * ```
8934
- */
8935
- async getTableDetails(schema, table) {
8936
- try {
8937
- const data = await this.fetch.get(
8938
- `/api/v1/admin/ai/tables/${schema}/${table}`
8939
- );
8940
- return { data, error: null };
8941
- } catch (error) {
8942
- return { data: null, error };
8943
- }
8944
- }
8945
- // ============================================================================
8946
- // TABLE EXPORT PRESETS
8947
- // ============================================================================
8948
- /**
8949
- * Create a table export preset
8950
- *
8951
- * Saves a table export configuration for easy re-export. Use triggerTableExportSync
8952
- * to re-export when the schema changes.
8953
- *
8954
- * @param knowledgeBaseId - Knowledge base ID
8955
- * @param config - Export preset configuration
8956
- * @returns Promise resolving to { data, error } tuple with created preset
8957
- *
8958
- * @example
8959
- * ```typescript
8960
- * const { data, error } = await client.admin.ai.createTableExportSync('kb-uuid', {
8961
- * schema_name: 'public',
8962
- * table_name: 'products',
8963
- * columns: ['id', 'name', 'description', 'price'],
8964
- * include_foreign_keys: true,
8965
- * export_now: true, // Trigger initial export
8966
- * })
8967
- * ```
8968
- */
8969
- async createTableExportSync(knowledgeBaseId, config) {
8970
- try {
8971
- const data = await this.fetch.post(
8972
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/sync-configs`,
8973
- config
8974
- );
8975
- return { data, error: null };
8294
+ async listChatbotKnowledgeBases(chatbotId) {
8295
+ try {
8296
+ const response = await this.fetch.get(`/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases`);
8297
+ return { data: response.knowledge_bases || [], error: null };
8976
8298
  } catch (error) {
8977
8299
  return { data: null, error };
8978
8300
  }
8979
8301
  }
8980
8302
  /**
8981
- * List table export presets for a knowledge base
8303
+ * Link a knowledge base to a chatbot
8982
8304
  *
8983
- * @param knowledgeBaseId - Knowledge base ID
8984
- * @returns Promise resolving to { data, error } tuple with array of presets
8305
+ * @param chatbotId - Chatbot ID
8306
+ * @param request - Link configuration
8307
+ * @returns Promise resolving to { data, error } tuple with link details
8985
8308
  *
8986
8309
  * @example
8987
8310
  * ```typescript
8988
- * const { data, error } = await client.admin.ai.listTableExportSyncs('kb-uuid')
8989
- * if (data) {
8990
- * data.forEach(config => {
8991
- * console.log(`${config.schema_name}.${config.table_name}`)
8992
- * })
8993
- * }
8311
+ * const { data, error } = await client.admin.ai.linkKnowledgeBase('chatbot-uuid', {
8312
+ * knowledge_base_id: 'kb-uuid',
8313
+ * priority: 1,
8314
+ * max_chunks: 5,
8315
+ * similarity_threshold: 0.7,
8316
+ * })
8994
8317
  * ```
8995
8318
  */
8996
- async listTableExportSyncs(knowledgeBaseId) {
8319
+ async linkKnowledgeBase(chatbotId, request) {
8997
8320
  try {
8998
- const response = await this.fetch.get(`/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/sync-configs`);
8999
- return { data: response.sync_configs || [], error: null };
8321
+ const data = await this.fetch.post(
8322
+ `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases`,
8323
+ request
8324
+ );
8325
+ return { data, error: null };
9000
8326
  } catch (error) {
9001
8327
  return { data: null, error };
9002
8328
  }
9003
8329
  }
9004
8330
  /**
9005
- * Update a table export preset
8331
+ * Update a chatbot-knowledge base link
9006
8332
  *
8333
+ * @param chatbotId - Chatbot ID
9007
8334
  * @param knowledgeBaseId - Knowledge base ID
9008
- * @param syncId - Preset ID
9009
8335
  * @param updates - Fields to update
9010
- * @returns Promise resolving to { data, error } tuple with updated preset
8336
+ * @returns Promise resolving to { data, error } tuple with updated link
9011
8337
  *
9012
8338
  * @example
9013
8339
  * ```typescript
9014
- * const { data, error } = await client.admin.ai.updateTableExportSync('kb-uuid', 'sync-id', {
9015
- * columns: ['id', 'name', 'email', 'updated_at'],
9016
- * })
8340
+ * const { data, error } = await client.admin.ai.updateChatbotKnowledgeBase(
8341
+ * 'chatbot-uuid',
8342
+ * 'kb-uuid',
8343
+ * { max_chunks: 10, enabled: true }
8344
+ * )
9017
8345
  * ```
9018
8346
  */
9019
- async updateTableExportSync(knowledgeBaseId, syncId, updates) {
8347
+ async updateChatbotKnowledgeBase(chatbotId, knowledgeBaseId, updates) {
9020
8348
  try {
9021
- const data = await this.fetch.patch(
9022
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/sync-configs/${syncId}`,
8349
+ const data = await this.fetch.put(
8350
+ `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases/${knowledgeBaseId}`,
9023
8351
  updates
9024
8352
  );
9025
8353
  return { data, error: null };
@@ -9028,50 +8356,52 @@ var FluxbaseAdminAI = class {
9028
8356
  }
9029
8357
  }
9030
8358
  /**
9031
- * Delete a table export sync configuration
8359
+ * Unlink a knowledge base from a chatbot
9032
8360
  *
8361
+ * @param chatbotId - Chatbot ID
9033
8362
  * @param knowledgeBaseId - Knowledge base ID
9034
- * @param syncId - Sync config ID
9035
8363
  * @returns Promise resolving to { data, error } tuple
9036
8364
  *
9037
8365
  * @example
9038
8366
  * ```typescript
9039
- * const { data, error } = await client.admin.ai.deleteTableExportSync('kb-uuid', 'sync-id')
8367
+ * const { data, error } = await client.admin.ai.unlinkKnowledgeBase('chatbot-uuid', 'kb-uuid')
9040
8368
  * ```
9041
8369
  */
9042
- async deleteTableExportSync(knowledgeBaseId, syncId) {
8370
+ async unlinkKnowledgeBase(chatbotId, knowledgeBaseId) {
9043
8371
  try {
9044
8372
  await this.fetch.delete(
9045
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/sync-configs/${syncId}`
8373
+ `/api/v1/admin/ai/chatbots/${chatbotId}/knowledge-bases/${knowledgeBaseId}`
9046
8374
  );
9047
8375
  return { data: null, error: null };
9048
8376
  } catch (error) {
9049
8377
  return { data: null, error };
9050
8378
  }
9051
8379
  }
8380
+ // ============================================================================
8381
+ // TABLE DETAILS
8382
+ // ============================================================================
9052
8383
  /**
9053
- * Manually trigger a table export sync
8384
+ * Get detailed table information including columns
9054
8385
  *
9055
- * Immediately re-exports the table to the knowledge base,
9056
- * regardless of the sync mode.
8386
+ * Use this to discover available columns before exporting.
9057
8387
  *
9058
- * @param knowledgeBaseId - Knowledge base ID
9059
- * @param syncId - Sync config ID
9060
- * @returns Promise resolving to { data, error } tuple with export result
8388
+ * @param schema - Schema name (e.g., 'public')
8389
+ * @param table - Table name
8390
+ * @returns Promise resolving to { data, error } tuple with table details
9061
8391
  *
9062
8392
  * @example
9063
8393
  * ```typescript
9064
- * const { data, error } = await client.admin.ai.triggerTableExportSync('kb-uuid', 'sync-id')
8394
+ * const { data, error } = await client.admin.ai.getTableDetails('public', 'users')
9065
8395
  * if (data) {
9066
- * console.log('Exported document:', data.document_id)
8396
+ * console.log('Columns:', data.columns.map(c => c.name))
8397
+ * console.log('Primary key:', data.primary_key)
9067
8398
  * }
9068
8399
  * ```
9069
8400
  */
9070
- async triggerTableExportSync(knowledgeBaseId, syncId) {
8401
+ async getTableDetails(schema, table) {
9071
8402
  try {
9072
- const data = await this.fetch.post(
9073
- `/api/v1/admin/ai/knowledge-bases/${knowledgeBaseId}/sync-configs/${syncId}/trigger`,
9074
- {}
8403
+ const data = await this.fetch.get(
8404
+ `/api/v1/admin/ai/tables/${schema}/${table}`
9075
8405
  );
9076
8406
  return { data, error: null };
9077
8407
  } catch (error) {
@@ -9079,6 +8409,14 @@ var FluxbaseAdminAI = class {
9079
8409
  }
9080
8410
  }
9081
8411
  };
8412
+ function normalizeConfig(config) {
8413
+ const result = {};
8414
+ for (const [key, value] of Object.entries(config)) {
8415
+ if (value === void 0 || value === null) continue;
8416
+ result[key] = String(value);
8417
+ }
8418
+ return result;
8419
+ }
9082
8420
 
9083
8421
  // src/admin-rpc.ts
9084
8422
  var FluxbaseAdminRPC = class {
@@ -9593,19 +8931,18 @@ var FluxbaseAdminStorage = class {
9593
8931
  });
9594
8932
  }
9595
8933
  /**
9596
- * Generate a signed URL for temporary access
8934
+ * Generate a signed URL for a private object
9597
8935
  *
9598
8936
  * @param bucket - Bucket name
9599
8937
  * @param key - Object key (path)
9600
- * @param expiresIn - Expiration time in seconds
8938
+ * @param expiresIn - URL expiration time in seconds
9601
8939
  * @returns Signed URL and expiration info
9602
8940
  *
9603
8941
  * @example
9604
8942
  * ```typescript
9605
8943
  * const { data } = await admin.storage.generateSignedUrl('my-bucket', 'file.pdf', 3600);
9606
8944
  * if (data) {
9607
- * console.log(`Download at: ${data.url}`);
9608
- * console.log(`Expires in: ${data.expires_in} seconds`);
8945
+ * window.open(data.url);
9609
8946
  * }
9610
8947
  * ```
9611
8948
  */
@@ -9613,7 +8950,7 @@ var FluxbaseAdminStorage = class {
9613
8950
  return wrapAsync(async () => {
9614
8951
  const encodedKey = key.split("/").map((s) => encodeURIComponent(s)).join("/");
9615
8952
  return await this.fetch.post(
9616
- `/api/v1/storage/${encodeURIComponent(bucket)}/${encodedKey}/signed-url`,
8953
+ `/api/v1/storage/${encodeURIComponent(bucket)}/sign/${encodedKey}`,
9617
8954
  { expires_in: expiresIn }
9618
8955
  );
9619
8956
  });
@@ -9732,53 +9069,318 @@ var FluxbaseAdminRealtime = class {
9732
9069
  * ```typescript
9733
9070
  * const status = await client.admin.realtime.getStatus('public', 'products')
9734
9071
  *
9735
- * if (status.realtime_enabled) {
9736
- * console.log('Events:', status.events.join(', '))
9737
- * console.log('Excluded:', status.excluded_columns?.join(', ') || 'none')
9738
- * } else {
9739
- * console.log('Realtime not enabled')
9072
+ * if (status.realtime_enabled) {
9073
+ * console.log('Events:', status.events.join(', '))
9074
+ * console.log('Excluded:', status.excluded_columns?.join(', ') || 'none')
9075
+ * } else {
9076
+ * console.log('Realtime not enabled')
9077
+ * }
9078
+ * ```
9079
+ */
9080
+ async getStatus(schema, table) {
9081
+ return await this.fetch.get(
9082
+ `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`
9083
+ );
9084
+ }
9085
+ /**
9086
+ * Update realtime configuration for a table
9087
+ *
9088
+ * Modifies the events or excluded columns for a realtime-enabled table
9089
+ * without recreating the trigger.
9090
+ *
9091
+ * @param schema - Schema name
9092
+ * @param table - Table name
9093
+ * @param config - New configuration
9094
+ * @returns Promise resolving to success message
9095
+ *
9096
+ * @example
9097
+ * ```typescript
9098
+ * // Change which events are tracked
9099
+ * await client.admin.realtime.updateConfig('public', 'products', {
9100
+ * events: ['INSERT', 'UPDATE'] // Stop tracking deletes
9101
+ * })
9102
+ *
9103
+ * // Update excluded columns
9104
+ * await client.admin.realtime.updateConfig('public', 'posts', {
9105
+ * exclude: ['raw_content', 'search_vector']
9106
+ * })
9107
+ *
9108
+ * // Clear excluded columns
9109
+ * await client.admin.realtime.updateConfig('public', 'posts', {
9110
+ * exclude: [] // Include all columns again
9111
+ * })
9112
+ * ```
9113
+ */
9114
+ async updateConfig(schema, table, config) {
9115
+ return await this.fetch.patch(
9116
+ `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`,
9117
+ config
9118
+ );
9119
+ }
9120
+ };
9121
+
9122
+ // src/admin-service-keys.ts
9123
+ var ServiceKeysManager = class {
9124
+ constructor(fetch2) {
9125
+ this.fetch = fetch2;
9126
+ }
9127
+ /**
9128
+ * List all service keys
9129
+ *
9130
+ * @returns List of service keys
9131
+ *
9132
+ * @example
9133
+ * ```typescript
9134
+ * const { data, error } = await client.admin.serviceKeys.list()
9135
+ * ```
9136
+ */
9137
+ async list() {
9138
+ try {
9139
+ const data = await this.fetch.get("/api/v1/admin/service-keys");
9140
+ return { data, error: null };
9141
+ } catch (error) {
9142
+ return { data: null, error };
9143
+ }
9144
+ }
9145
+ /**
9146
+ * Get a service key by ID
9147
+ *
9148
+ * @param id - Service key ID
9149
+ * @returns Service key details
9150
+ *
9151
+ * @example
9152
+ * ```typescript
9153
+ * const { data, error } = await client.admin.serviceKeys.get('key-id')
9154
+ * ```
9155
+ */
9156
+ async get(id) {
9157
+ try {
9158
+ const data = await this.fetch.get(`/api/v1/admin/service-keys/${id}`);
9159
+ return { data, error: null };
9160
+ } catch (error) {
9161
+ return { data: null, error };
9162
+ }
9163
+ }
9164
+ /**
9165
+ * Create a new service key
9166
+ *
9167
+ * The full key value is only returned once - store it securely!
9168
+ *
9169
+ * @param request - Key creation options
9170
+ * @returns Created key with full key value
9171
+ *
9172
+ * @example
9173
+ * ```typescript
9174
+ * const { data, error } = await client.admin.serviceKeys.create({
9175
+ * name: 'Production API Key',
9176
+ * key_type: 'service',
9177
+ * scopes: ['*'],
9178
+ * rate_limit_per_minute: 1000
9179
+ * })
9180
+ *
9181
+ * if (data) {
9182
+ * // Store data.key securely - it won't be shown again!
9183
+ * console.log('Key created:', data.key)
9184
+ * }
9185
+ * ```
9186
+ */
9187
+ async create(request) {
9188
+ try {
9189
+ const data = await this.fetch.post(
9190
+ "/api/v1/admin/service-keys",
9191
+ request
9192
+ );
9193
+ return { data, error: null };
9194
+ } catch (error) {
9195
+ return { data: null, error };
9196
+ }
9197
+ }
9198
+ /**
9199
+ * Update a service key
9200
+ *
9201
+ * @param id - Service key ID
9202
+ * @param request - Update options
9203
+ * @returns Updated key
9204
+ *
9205
+ * @example
9206
+ * ```typescript
9207
+ * const { data, error } = await client.admin.serviceKeys.update('key-id', {
9208
+ * name: 'New Name',
9209
+ * rate_limit_per_minute: 2000
9210
+ * })
9211
+ * ```
9212
+ */
9213
+ async update(id, request) {
9214
+ try {
9215
+ const data = await this.fetch.put(
9216
+ `/api/v1/admin/service-keys/${id}`,
9217
+ request
9218
+ );
9219
+ return { data, error: null };
9220
+ } catch (error) {
9221
+ return { data: null, error };
9222
+ }
9223
+ }
9224
+ /**
9225
+ * Delete a service key permanently
9226
+ *
9227
+ * @param id - Service key ID
9228
+ * @returns Success or error
9229
+ *
9230
+ * @example
9231
+ * ```typescript
9232
+ * const { error } = await client.admin.serviceKeys.delete('key-id')
9233
+ * ```
9234
+ */
9235
+ async delete(id) {
9236
+ try {
9237
+ await this.fetch.delete(`/api/v1/admin/service-keys/${id}`);
9238
+ return { error: null };
9239
+ } catch (error) {
9240
+ return { error };
9241
+ }
9242
+ }
9243
+ /**
9244
+ * Disable a service key (temporarily)
9245
+ *
9246
+ * @param id - Service key ID
9247
+ * @returns Success or error
9248
+ *
9249
+ * @example
9250
+ * ```typescript
9251
+ * const { error } = await client.admin.serviceKeys.disable('key-id')
9252
+ * ```
9253
+ */
9254
+ async disable(id) {
9255
+ try {
9256
+ await this.fetch.post(`/api/v1/admin/service-keys/${id}/disable`, {});
9257
+ return { error: null };
9258
+ } catch (error) {
9259
+ return { error };
9260
+ }
9261
+ }
9262
+ /**
9263
+ * Enable a disabled service key
9264
+ *
9265
+ * @param id - Service key ID
9266
+ * @returns Success or error
9267
+ *
9268
+ * @example
9269
+ * ```typescript
9270
+ * const { error } = await client.admin.serviceKeys.enable('key-id')
9271
+ * ```
9272
+ */
9273
+ async enable(id) {
9274
+ try {
9275
+ await this.fetch.post(`/api/v1/admin/service-keys/${id}/enable`, {});
9276
+ return { error: null };
9277
+ } catch (error) {
9278
+ return { error };
9279
+ }
9280
+ }
9281
+ /**
9282
+ * Revoke a service key permanently (emergency)
9283
+ *
9284
+ * Use for immediate revocation when a key is compromised.
9285
+ *
9286
+ * @param id - Service key ID
9287
+ * @param request - Revocation options
9288
+ * @returns Success or error
9289
+ *
9290
+ * @example
9291
+ * ```typescript
9292
+ * const { error } = await client.admin.serviceKeys.revoke('key-id', {
9293
+ * reason: 'Key was compromised'
9294
+ * })
9295
+ * ```
9296
+ */
9297
+ async revoke(id, request) {
9298
+ try {
9299
+ const body = request?.reason ? new URLSearchParams({ reason: request.reason }) : {};
9300
+ await this.fetch.post(`/api/v1/admin/service-keys/${id}/revoke`, body);
9301
+ return { error: null };
9302
+ } catch (error) {
9303
+ return { error };
9304
+ }
9305
+ }
9306
+ /**
9307
+ * Deprecate a service key (graceful rotation)
9308
+ *
9309
+ * Marks the key for removal but keeps it active during grace period.
9310
+ *
9311
+ * @param id - Service key ID
9312
+ * @param request - Deprecation options
9313
+ * @returns Deprecation details
9314
+ *
9315
+ * @example
9316
+ * ```typescript
9317
+ * const { data, error } = await client.admin.serviceKeys.deprecate('key-id', {
9318
+ * reason: 'Rotating to new key',
9319
+ * grace_period_hours: 48
9320
+ * })
9321
+ * ```
9322
+ */
9323
+ async deprecate(id, request) {
9324
+ try {
9325
+ const params = new URLSearchParams();
9326
+ if (request?.grace_period_hours) {
9327
+ params.set("grace_period_hours", String(request.grace_period_hours));
9328
+ }
9329
+ const body = request?.grace_period_hours ? Object.fromEntries(params) : {};
9330
+ const data = await this.fetch.post(`/api/v1/admin/service-keys/${id}/deprecate`, body);
9331
+ return { data, error: null };
9332
+ } catch (error) {
9333
+ return { data: null, error };
9334
+ }
9335
+ }
9336
+ /**
9337
+ * Rotate a service key (create replacement)
9338
+ *
9339
+ * Creates a new key with the same settings and deprecates the old one.
9340
+ * The new key is returned with its full value.
9341
+ *
9342
+ * @param id - Service key ID to rotate
9343
+ * @returns New key with full key value
9344
+ *
9345
+ * @example
9346
+ * ```typescript
9347
+ * const { data, error } = await client.admin.serviceKeys.rotate('old-key-id')
9348
+ *
9349
+ * if (data) {
9350
+ * console.log('New key:', data.key)
9351
+ * console.log('Old key deprecated at:', data.deprecated_at)
9740
9352
  * }
9741
9353
  * ```
9742
9354
  */
9743
- async getStatus(schema, table) {
9744
- return await this.fetch.get(
9745
- `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`
9746
- );
9355
+ async rotate(id) {
9356
+ try {
9357
+ const data = await this.fetch.post(
9358
+ `/api/v1/admin/service-keys/${id}/rotate`,
9359
+ {}
9360
+ );
9361
+ return { data, error: null };
9362
+ } catch (error) {
9363
+ return { data: null, error };
9364
+ }
9747
9365
  }
9748
9366
  /**
9749
- * Update realtime configuration for a table
9750
- *
9751
- * Modifies the events or excluded columns for a realtime-enabled table
9752
- * without recreating the trigger.
9367
+ * Get revocation history for a service key
9753
9368
  *
9754
- * @param schema - Schema name
9755
- * @param table - Table name
9756
- * @param config - New configuration
9757
- * @returns Promise resolving to success message
9369
+ * @param id - Service key ID
9370
+ * @returns Revocation history
9758
9371
  *
9759
9372
  * @example
9760
9373
  * ```typescript
9761
- * // Change which events are tracked
9762
- * await client.admin.realtime.updateConfig('public', 'products', {
9763
- * events: ['INSERT', 'UPDATE'] // Stop tracking deletes
9764
- * })
9765
- *
9766
- * // Update excluded columns
9767
- * await client.admin.realtime.updateConfig('public', 'posts', {
9768
- * exclude: ['raw_content', 'search_vector']
9769
- * })
9770
- *
9771
- * // Clear excluded columns
9772
- * await client.admin.realtime.updateConfig('public', 'posts', {
9773
- * exclude: [] // Include all columns again
9774
- * })
9374
+ * const { data, error } = await client.admin.serviceKeys.getRevocationHistory('key-id')
9775
9375
  * ```
9776
9376
  */
9777
- async updateConfig(schema, table, config) {
9778
- return await this.fetch.patch(
9779
- `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`,
9780
- config
9781
- );
9377
+ async getRevocationHistory(id) {
9378
+ try {
9379
+ const data = await this.fetch.get(`/api/v1/admin/service-keys/${id}/revocations`);
9380
+ return { data, error: null };
9381
+ } catch (error) {
9382
+ return { data: null, error };
9383
+ }
9782
9384
  }
9783
9385
  };
9784
9386
 
@@ -9800,6 +9402,7 @@ var FluxbaseAdmin = class {
9800
9402
  this.rpc = new FluxbaseAdminRPC(fetch2);
9801
9403
  this.storage = new FluxbaseAdminStorage(fetch2);
9802
9404
  this.realtime = new FluxbaseAdminRealtime(fetch2);
9405
+ this.serviceKeys = new ServiceKeysManager(fetch2);
9803
9406
  }
9804
9407
  /**
9805
9408
  * Set admin authentication token
@@ -9845,31 +9448,6 @@ var FluxbaseAdmin = class {
9845
9448
  });
9846
9449
  }
9847
9450
  // ============================================================================
9848
- // Email
9849
- // ============================================================================
9850
- /**
9851
- * Send an email
9852
- *
9853
- * @param request - Email details (to, subject, html/text)
9854
- *
9855
- * @example
9856
- * ```typescript
9857
- * const { error } = await admin.sendEmail({
9858
- * to: 'user@example.com',
9859
- * subject: 'Hello',
9860
- * html: '<p>Your message here</p>'
9861
- * });
9862
- * if (!error) {
9863
- * console.log('Email sent');
9864
- * }
9865
- * ```
9866
- */
9867
- async sendEmail(request) {
9868
- return wrapAsyncVoid(async () => {
9869
- await this.fetch.post("/api/v1/admin/email/send", request);
9870
- });
9871
- }
9872
- // ============================================================================
9873
9451
  // Admin Authentication
9874
9452
  // ============================================================================
9875
9453
  /**
@@ -11624,6 +11202,228 @@ var FluxbaseBranching = class {
11624
11202
  }
11625
11203
  };
11626
11204
 
11205
+ // src/tenant.ts
11206
+ var FluxbaseTenant = class {
11207
+ constructor(fetch2) {
11208
+ this.fetch = fetch2;
11209
+ }
11210
+ /**
11211
+ * List all tenants (instance admin only)
11212
+ *
11213
+ * @returns Promise with tenants list or error
11214
+ *
11215
+ * @example
11216
+ * ```typescript
11217
+ * const { data, error } = await client.tenant.list()
11218
+ * ```
11219
+ */
11220
+ async list() {
11221
+ try {
11222
+ const data = await this.fetch.get("/api/v1/admin/tenants");
11223
+ return { data, error: null };
11224
+ } catch (error) {
11225
+ return { data: null, error };
11226
+ }
11227
+ }
11228
+ /**
11229
+ * List tenants the current user has access to
11230
+ *
11231
+ * @returns Promise with tenants and user's role in each
11232
+ *
11233
+ * @example
11234
+ * ```typescript
11235
+ * const { data, error } = await client.tenant.listMine()
11236
+ * // data: [{ id: '...', slug: 'acme', name: 'Acme', my_role: 'tenant_admin', status: 'active' }]
11237
+ * ```
11238
+ */
11239
+ async listMine() {
11240
+ try {
11241
+ const data = await this.fetch.get("/api/v1/admin/tenants/mine");
11242
+ return { data, error: null };
11243
+ } catch (error) {
11244
+ return { data: null, error };
11245
+ }
11246
+ }
11247
+ /**
11248
+ * Get a tenant by ID
11249
+ *
11250
+ * @param id - Tenant ID
11251
+ * @returns Promise with tenant details or error
11252
+ *
11253
+ * @example
11254
+ * ```typescript
11255
+ * const { data, error } = await client.tenant.get('tenant-id')
11256
+ * ```
11257
+ */
11258
+ async get(id) {
11259
+ try {
11260
+ const data = await this.fetch.get(`/api/v1/admin/tenants/${id}`);
11261
+ return { data, error: null };
11262
+ } catch (error) {
11263
+ return { data: null, error };
11264
+ }
11265
+ }
11266
+ /**
11267
+ * Create a new tenant (instance admin only)
11268
+ *
11269
+ * This creates a new isolated database for the tenant.
11270
+ *
11271
+ * @param options - Tenant creation options
11272
+ * @returns Promise with created tenant or error
11273
+ *
11274
+ * @example
11275
+ * ```typescript
11276
+ * const { data, error } = await client.tenant.create({
11277
+ * slug: 'acme-corp',
11278
+ * name: 'Acme Corporation',
11279
+ * metadata: { plan: 'enterprise' }
11280
+ * })
11281
+ * ```
11282
+ */
11283
+ async create(options) {
11284
+ try {
11285
+ const data = await this.fetch.post("/api/v1/admin/tenants", options);
11286
+ return { data, error: null };
11287
+ } catch (error) {
11288
+ return { data: null, error };
11289
+ }
11290
+ }
11291
+ /**
11292
+ * Update a tenant (tenant admin only)
11293
+ *
11294
+ * @param id - Tenant ID
11295
+ * @param options - Update options
11296
+ * @returns Promise with updated tenant or error
11297
+ *
11298
+ * @example
11299
+ * ```typescript
11300
+ * const { data, error } = await client.tenant.update('tenant-id', {
11301
+ * name: 'New Name'
11302
+ * })
11303
+ * ```
11304
+ */
11305
+ async update(id, options) {
11306
+ try {
11307
+ const data = await this.fetch.patch(`/api/v1/admin/tenants/${id}`, options);
11308
+ return { data, error: null };
11309
+ } catch (error) {
11310
+ return { data: null, error };
11311
+ }
11312
+ }
11313
+ /**
11314
+ * Delete a tenant (instance admin only)
11315
+ *
11316
+ * This permanently deletes the tenant's database and all its data.
11317
+ * Cannot delete the default tenant.
11318
+ *
11319
+ * @param id - Tenant ID
11320
+ * @returns Promise that resolves when deleted
11321
+ *
11322
+ * @example
11323
+ * ```typescript
11324
+ * const { error } = await client.tenant.delete('tenant-id')
11325
+ * ```
11326
+ */
11327
+ async delete(id) {
11328
+ try {
11329
+ await this.fetch.delete(`/api/v1/admin/tenants/${id}`);
11330
+ return { data: void 0, error: null };
11331
+ } catch (error) {
11332
+ return { data: null, error };
11333
+ }
11334
+ }
11335
+ /**
11336
+ * Migrate a tenant database to the latest schema (instance admin only)
11337
+ *
11338
+ * @param id - Tenant ID
11339
+ * @returns Promise with migration status or error
11340
+ *
11341
+ * @example
11342
+ * ```typescript
11343
+ * const { data, error } = await client.tenant.migrate('tenant-id')
11344
+ * // data: { status: 'migrated' }
11345
+ * ```
11346
+ */
11347
+ async migrate(id) {
11348
+ try {
11349
+ const data = await this.fetch.post(
11350
+ `/api/v1/admin/tenants/${id}/migrate`,
11351
+ {}
11352
+ );
11353
+ return { data, error: null };
11354
+ } catch (error) {
11355
+ return { data: null, error };
11356
+ }
11357
+ }
11358
+ /**
11359
+ * List admins of a tenant
11360
+ *
11361
+ * @param tenantId - Tenant ID
11362
+ * @returns Promise with admin list or error
11363
+ *
11364
+ * @example
11365
+ * ```typescript
11366
+ * const { data, error } = await client.tenant.listAdmins('tenant-id')
11367
+ * // data: [{ id: '...', tenant_id: '...', user_id: '...', email: 'admin@example.com' }]
11368
+ * ```
11369
+ */
11370
+ async listAdmins(tenantId) {
11371
+ try {
11372
+ const data = await this.fetch.get(
11373
+ `/api/v1/admin/tenants/${tenantId}/admins`
11374
+ );
11375
+ return { data, error: null };
11376
+ } catch (error) {
11377
+ return { data: null, error };
11378
+ }
11379
+ }
11380
+ /**
11381
+ * Assign an admin to a tenant (tenant admin only)
11382
+ *
11383
+ * @param tenantId - Tenant ID
11384
+ * @param options - Admin assignment options
11385
+ * @returns Promise with created assignment or error
11386
+ *
11387
+ * @example
11388
+ * ```typescript
11389
+ * const { data, error } = await client.tenant.assignAdmin('tenant-id', {
11390
+ * user_id: 'user-id'
11391
+ * })
11392
+ * ```
11393
+ */
11394
+ async assignAdmin(tenantId, options) {
11395
+ try {
11396
+ const data = await this.fetch.post(
11397
+ `/api/v1/admin/tenants/${tenantId}/admins`,
11398
+ options
11399
+ );
11400
+ return { data, error: null };
11401
+ } catch (error) {
11402
+ return { data: null, error };
11403
+ }
11404
+ }
11405
+ /**
11406
+ * Remove an admin from a tenant (tenant admin only)
11407
+ *
11408
+ * @param tenantId - Tenant ID
11409
+ * @param userId - User ID
11410
+ * @returns Promise that resolves when removed
11411
+ *
11412
+ * @example
11413
+ * ```typescript
11414
+ * const { error } = await client.tenant.removeAdmin('tenant-id', 'user-id')
11415
+ * ```
11416
+ */
11417
+ async removeAdmin(tenantId, userId) {
11418
+ try {
11419
+ await this.fetch.delete(`/api/v1/admin/tenants/${tenantId}/admins/${userId}`);
11420
+ return { data: void 0, error: null };
11421
+ } catch (error) {
11422
+ return { data: null, error };
11423
+ }
11424
+ }
11425
+ };
11426
+
11627
11427
  // src/query-builder.ts
11628
11428
  var URL_LENGTH_THRESHOLD = 4096;
11629
11429
  var QueryBuilder = class {
@@ -12915,7 +12715,7 @@ var SchemaQueryBuilder = class {
12915
12715
  };
12916
12716
 
12917
12717
  // src/client.ts
12918
- var FluxbaseClient = class {
12718
+ var FluxbaseClient = class _FluxbaseClient {
12919
12719
  /**
12920
12720
  * Create a new Fluxbase client instance
12921
12721
  *
@@ -12935,6 +12735,7 @@ var FluxbaseClient = class {
12935
12735
  constructor(fluxbaseUrl, fluxbaseKey, options) {
12936
12736
  this.fluxbaseUrl = fluxbaseUrl;
12937
12737
  this.fluxbaseKey = fluxbaseKey;
12738
+ this.options = options;
12938
12739
  const headers = {
12939
12740
  apikey: fluxbaseKey,
12940
12741
  Authorization: `Bearer ${fluxbaseKey}`,
@@ -12987,6 +12788,7 @@ var FluxbaseClient = class {
12987
12788
  waitForCompletion: rpcInstance.waitForCompletion.bind(rpcInstance)
12988
12789
  });
12989
12790
  this.rpc = rpcCallable;
12791
+ this.tenant = new FluxbaseTenant(this.fetch);
12990
12792
  this.setupAuthSync();
12991
12793
  }
12992
12794
  /**
@@ -13092,6 +12894,96 @@ var FluxbaseClient = class {
13092
12894
  this.fetch.setAuthToken(token);
13093
12895
  this.realtime.setAuth(token);
13094
12896
  }
12897
+ /**
12898
+ * Get the current tenant ID
12899
+ *
12900
+ * Returns the tenant ID from X-FB-Tenant header or JWT claim, or default tenant.
12901
+ *
12902
+ * @returns The current tenant ID, or undefined if not set
12903
+ *
12904
+ * @category Multi-Tenancy
12905
+ */
12906
+ getTenantId() {
12907
+ return this._tenantId;
12908
+ }
12909
+ /**
12910
+ * Set the tenant context for all subsequent requests
12911
+ *
12912
+ * This adds the X-FB-Tenant header to all HTTP requests and updates
12913
+ * the realtime connection to filter by tenant.
12914
+ *
12915
+ * @param tenantId - The tenant ID to use for scoping
12916
+ *
12917
+ * @example
12918
+ * ```typescript
12919
+ * // Switch to a specific tenant
12920
+ * client.setTenant('tenant-uuid-here')
12921
+ *
12922
+ * // All subsequent requests will be scoped to this tenant
12923
+ * const { data } = await client.from('users').select('*').execute()
12924
+ * ```
12925
+ *
12926
+ * @category Multi-Tenancy
12927
+ */
12928
+ setTenant(tenantId) {
12929
+ this._tenantId = tenantId;
12930
+ if (tenantId) {
12931
+ this.fetch.setHeader("X-FB-Tenant", tenantId);
12932
+ } else {
12933
+ this.fetch.removeHeader("X-FB-Tenant");
12934
+ }
12935
+ }
12936
+ /**
12937
+ * Register a callback that is called before every request.
12938
+ * The callback receives the headers object and can modify it in place.
12939
+ * This is useful for dynamically injecting headers at request time
12940
+ * (e.g., reading tenant context from an external store).
12941
+ *
12942
+ * The callback runs after static headers are merged, so it can override them.
12943
+ *
12944
+ * @param callback - A function that receives the headers object, or null to remove
12945
+ *
12946
+ * @category Advanced
12947
+ */
12948
+ setBeforeRequestCallback(callback) {
12949
+ this.fetch.setBeforeRequestCallback(callback);
12950
+ }
12951
+ /**
12952
+ * Create a new client scoped to a specific tenant
12953
+ *
12954
+ * This returns a new client instance with the tenant context set.
12955
+ * The original client is not modified.
12956
+ *
12957
+ * @param tenantId - The tenant ID to scope to
12958
+ * @returns A new FluxbaseClient instance scoped to the tenant
12959
+ *
12960
+ * @example
12961
+ * ```typescript
12962
+ * // Create a tenant-scoped client
12963
+ * const tenantClient = client.forTenant('tenant-uuid')
12964
+ *
12965
+ * // Use the scoped client for tenant-specific operations
12966
+ * const { data } = await tenantClient.from('users').select('*').execute()
12967
+ * ```
12968
+ *
12969
+ * @category Multi-Tenancy
12970
+ */
12971
+ forTenant(tenantId) {
12972
+ const options = {
12973
+ ...this.options,
12974
+ headers: {
12975
+ ...this.options?.headers,
12976
+ "X-FB-Tenant": tenantId
12977
+ }
12978
+ };
12979
+ const scopedClient = new _FluxbaseClient(
12980
+ this.fluxbaseUrl,
12981
+ this.fluxbaseKey,
12982
+ options
12983
+ );
12984
+ scopedClient._tenantId = tenantId;
12985
+ return scopedClient;
12986
+ }
13095
12987
  /**
13096
12988
  * Create or get a realtime channel (Supabase-compatible)
13097
12989
  *
@@ -13258,6 +13150,7 @@ exports.FluxbaseRPC = FluxbaseRPC;
13258
13150
  exports.FluxbaseRealtime = FluxbaseRealtime;
13259
13151
  exports.FluxbaseSettings = FluxbaseSettings;
13260
13152
  exports.FluxbaseStorage = FluxbaseStorage;
13153
+ exports.FluxbaseTenant = FluxbaseTenant;
13261
13154
  exports.FluxbaseVector = FluxbaseVector;
13262
13155
  exports.ImpersonationManager = ImpersonationManager;
13263
13156
  exports.InvitationsManager = InvitationsManager;
@@ -13266,6 +13159,7 @@ exports.QueryBuilder = QueryBuilder;
13266
13159
  exports.RealtimeChannel = RealtimeChannel;
13267
13160
  exports.SchemaQueryBuilder = SchemaQueryBuilder;
13268
13161
  exports.SecretsManager = SecretsManager;
13162
+ exports.ServiceKeysManager = ServiceKeysManager;
13269
13163
  exports.SettingsClient = SettingsClient;
13270
13164
  exports.StorageBucket = StorageBucket;
13271
13165
  exports.SystemSettingsManager = SystemSettingsManager;