@fluxbase/sdk 2026.1.7 → 2026.1.9-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1426,8 +1426,9 @@ var RealtimeChannel = class {
1426
1426
  this.presenceCallbacks = /* @__PURE__ */ new Map();
1427
1427
  this.broadcastCallbacks = /* @__PURE__ */ new Map();
1428
1428
  this.executionLogCallbacks = /* @__PURE__ */ new Set();
1429
- this.subscriptionConfig = null;
1430
- this.subscriptionId = null;
1429
+ this.subscriptionConfigs = [];
1430
+ this.subscriptionIds = /* @__PURE__ */ new Map();
1431
+ // "schema.table" -> subscription_id
1431
1432
  this.executionLogConfig = null;
1432
1433
  this._presenceState = {};
1433
1434
  this.myPresenceKey = null;
@@ -1456,13 +1457,15 @@ var RealtimeChannel = class {
1456
1457
  on(event, configOrCallback, callback) {
1457
1458
  if (event === "postgres_changes" && typeof configOrCallback !== "function") {
1458
1459
  const config = configOrCallback;
1459
- this.subscriptionConfig = config;
1460
1460
  const actualCallback = callback;
1461
- const eventType = config.event;
1462
- if (!this.callbacks.has(eventType)) {
1463
- this.callbacks.set(eventType, /* @__PURE__ */ new Set());
1461
+ let entry = this.subscriptionConfigs.find(
1462
+ (e) => e.config.schema === config.schema && e.config.table === config.table && e.config.event === config.event && e.config.filter === config.filter
1463
+ );
1464
+ if (!entry) {
1465
+ entry = { config, callbacks: /* @__PURE__ */ new Set() };
1466
+ this.subscriptionConfigs.push(entry);
1464
1467
  }
1465
- this.callbacks.get(eventType).add(actualCallback);
1468
+ entry.callbacks.add(actualCallback);
1466
1469
  } else if (event === "broadcast" && typeof configOrCallback !== "function") {
1467
1470
  const config = configOrCallback;
1468
1471
  const actualCallback = callback;
@@ -1533,11 +1536,20 @@ var RealtimeChannel = class {
1533
1536
  this.shouldReconnect = false;
1534
1537
  return new Promise((resolve) => {
1535
1538
  if (this.ws) {
1536
- this.sendMessage({
1537
- type: "unsubscribe",
1538
- channel: this.channelName,
1539
- subscription_id: this.subscriptionId || void 0
1540
- });
1539
+ if (this.subscriptionIds.size > 0) {
1540
+ for (const subId of this.subscriptionIds.values()) {
1541
+ this.sendMessage({
1542
+ type: "unsubscribe",
1543
+ channel: this.channelName,
1544
+ subscription_id: subId
1545
+ });
1546
+ }
1547
+ } else {
1548
+ this.sendMessage({
1549
+ type: "unsubscribe",
1550
+ channel: this.channelName
1551
+ });
1552
+ }
1541
1553
  const startTime = Date.now();
1542
1554
  const maxWait = timeout || 5e3;
1543
1555
  const checkDisconnect = () => {
@@ -1772,14 +1784,20 @@ var RealtimeChannel = class {
1772
1784
  }
1773
1785
  };
1774
1786
  this.sendMessage(logSubscribeMessage);
1787
+ } else if (this.subscriptionConfigs.length > 0) {
1788
+ for (const entry of this.subscriptionConfigs) {
1789
+ const subscribeMessage = {
1790
+ type: "subscribe",
1791
+ channel: this.channelName,
1792
+ config: entry.config
1793
+ };
1794
+ this.sendMessage(subscribeMessage);
1795
+ }
1775
1796
  } else {
1776
1797
  const subscribeMessage = {
1777
1798
  type: "subscribe",
1778
1799
  channel: this.channelName
1779
1800
  };
1780
- if (this.subscriptionConfig) {
1781
- subscribeMessage.config = this.subscriptionConfig;
1782
- }
1783
1801
  this.sendMessage(subscribeMessage);
1784
1802
  }
1785
1803
  this.startHeartbeat();
@@ -1859,18 +1877,29 @@ var RealtimeChannel = class {
1859
1877
  this.pendingAcks.delete("access_token");
1860
1878
  }
1861
1879
  console.log("[Fluxbase Realtime] Token updated successfully");
1862
- } else {
1863
- if (payload.subscription_id) {
1864
- this.subscriptionId = payload.subscription_id;
1865
- console.log("[Fluxbase Realtime] Subscription ID received:", this.subscriptionId);
1880
+ } else if (payload.subscription_id) {
1881
+ const schema = payload.schema || "public";
1882
+ const table = payload.table || "";
1883
+ if (table) {
1884
+ this.subscriptionIds.set(`${schema}.${table}`, payload.subscription_id);
1885
+ console.log("[Fluxbase Realtime] Subscription ID received for", `${schema}.${table}:`, payload.subscription_id);
1866
1886
  } else {
1867
- console.log("[Fluxbase Realtime] Acknowledged:", message);
1887
+ console.log("[Fluxbase Realtime] Subscription ID received:", payload.subscription_id);
1868
1888
  }
1889
+ } else {
1890
+ console.log("[Fluxbase Realtime] Acknowledged:", message);
1869
1891
  }
1870
1892
  } else {
1871
1893
  if (message.payload && typeof message.payload === "object" && "subscription_id" in message.payload) {
1872
- this.subscriptionId = message.payload.subscription_id;
1873
- console.log("[Fluxbase Realtime] Subscription ID received:", this.subscriptionId);
1894
+ const payload = message.payload;
1895
+ const schema = payload.schema || "public";
1896
+ const table = payload.table || "";
1897
+ if (table) {
1898
+ this.subscriptionIds.set(`${schema}.${table}`, payload.subscription_id);
1899
+ console.log("[Fluxbase Realtime] Subscription ID received for", `${schema}.${table}:`, payload.subscription_id);
1900
+ } else {
1901
+ console.log("[Fluxbase Realtime] Subscription ID received:", payload.subscription_id);
1902
+ }
1874
1903
  } else {
1875
1904
  console.log("[Fluxbase Realtime] Acknowledged:", message);
1876
1905
  }
@@ -1964,6 +1993,21 @@ var RealtimeChannel = class {
1964
1993
  old: payload.old_record || payload.old || {},
1965
1994
  errors: payload.errors || null
1966
1995
  };
1996
+ for (const entry of this.subscriptionConfigs) {
1997
+ const c = entry.config;
1998
+ const schemaMatch = !c.schema || c.schema === supabasePayload.schema;
1999
+ const tableMatch = !c.table || c.table === supabasePayload.table;
2000
+ const eventMatch = c.event === "*" || c.event === supabasePayload.eventType;
2001
+ if (schemaMatch && tableMatch && eventMatch) {
2002
+ entry.callbacks.forEach((cb) => {
2003
+ try {
2004
+ cb(supabasePayload);
2005
+ } catch (err) {
2006
+ console.error("[Fluxbase Realtime] Error in postgres_changes callback:", err);
2007
+ }
2008
+ });
2009
+ }
2010
+ }
1967
2011
  const callbacks = this.callbacks.get(supabasePayload.eventType);
1968
2012
  if (callbacks) {
1969
2013
  callbacks.forEach((callback) => callback(supabasePayload));
@@ -3714,9 +3758,7 @@ var FluxbaseRPC = class {
3714
3758
  async list(namespace) {
3715
3759
  try {
3716
3760
  const params = namespace ? `?namespace=${encodeURIComponent(namespace)}` : "";
3717
- const response = await this.fetch.get(
3718
- `/api/v1/rpc/procedures${params}`
3719
- );
3761
+ const response = await this.fetch.get(`/api/v1/rpc/procedures${params}`);
3720
3762
  return { data: response.procedures || [], error: null };
3721
3763
  } catch (error) {
3722
3764
  return { data: null, error };
@@ -3754,7 +3796,8 @@ var FluxbaseRPC = class {
3754
3796
  {
3755
3797
  params,
3756
3798
  async: options?.async
3757
- }
3799
+ },
3800
+ { timeout: options?.timeout }
3758
3801
  );
3759
3802
  return { data: response, error: null };
3760
3803
  } catch (error) {
@@ -3853,7 +3896,10 @@ var FluxbaseRPC = class {
3853
3896
  await new Promise((resolve) => setTimeout(resolve, interval));
3854
3897
  interval = Math.min(interval * 1.5, maxInterval);
3855
3898
  }
3856
- return { data: null, error: new Error("Timeout waiting for execution to complete") };
3899
+ return {
3900
+ data: null,
3901
+ error: new Error("Timeout waiting for execution to complete")
3902
+ };
3857
3903
  }
3858
3904
  };
3859
3905
 
@@ -8886,6 +8932,168 @@ var FluxbaseAdminStorage = class {
8886
8932
  }
8887
8933
  };
8888
8934
 
8935
+ // src/admin-realtime.ts
8936
+ var FluxbaseAdminRealtime = class {
8937
+ constructor(fetch2) {
8938
+ this.fetch = fetch2;
8939
+ }
8940
+ /**
8941
+ * Enable realtime on a table
8942
+ *
8943
+ * Creates the necessary database triggers to broadcast changes to WebSocket subscribers.
8944
+ * Also sets REPLICA IDENTITY FULL to include old values in UPDATE/DELETE events.
8945
+ *
8946
+ * @param table - Table name to enable realtime on
8947
+ * @param options - Optional configuration
8948
+ * @returns Promise resolving to EnableRealtimeResponse
8949
+ *
8950
+ * @example
8951
+ * ```typescript
8952
+ * // Enable realtime on products table (all events)
8953
+ * await client.admin.realtime.enableRealtime('products')
8954
+ *
8955
+ * // Enable on a specific schema
8956
+ * await client.admin.realtime.enableRealtime('orders', {
8957
+ * schema: 'sales'
8958
+ * })
8959
+ *
8960
+ * // Enable specific events only
8961
+ * await client.admin.realtime.enableRealtime('audit_log', {
8962
+ * events: ['INSERT'] // Only broadcast inserts
8963
+ * })
8964
+ *
8965
+ * // Exclude large columns from notifications
8966
+ * await client.admin.realtime.enableRealtime('posts', {
8967
+ * exclude: ['content', 'raw_html'] // Skip these in payload
8968
+ * })
8969
+ * ```
8970
+ */
8971
+ async enableRealtime(table, options) {
8972
+ const request = {
8973
+ schema: options?.schema ?? "public",
8974
+ table,
8975
+ events: options?.events,
8976
+ exclude: options?.exclude
8977
+ };
8978
+ return await this.fetch.post(
8979
+ "/api/v1/admin/realtime/tables",
8980
+ request
8981
+ );
8982
+ }
8983
+ /**
8984
+ * Disable realtime on a table
8985
+ *
8986
+ * Removes the realtime trigger from a table. Existing subscribers will stop
8987
+ * receiving updates for this table.
8988
+ *
8989
+ * @param schema - Schema name
8990
+ * @param table - Table name
8991
+ * @returns Promise resolving to success message
8992
+ *
8993
+ * @example
8994
+ * ```typescript
8995
+ * await client.admin.realtime.disableRealtime('public', 'products')
8996
+ * console.log('Realtime disabled')
8997
+ * ```
8998
+ */
8999
+ async disableRealtime(schema, table) {
9000
+ return await this.fetch.delete(
9001
+ `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`
9002
+ );
9003
+ }
9004
+ /**
9005
+ * List all realtime-enabled tables
9006
+ *
9007
+ * Returns a list of all tables that have realtime enabled, along with their
9008
+ * configuration (events, excluded columns, etc.).
9009
+ *
9010
+ * @param options - Optional filter options
9011
+ * @returns Promise resolving to ListRealtimeTablesResponse
9012
+ *
9013
+ * @example
9014
+ * ```typescript
9015
+ * // List all enabled tables
9016
+ * const { tables, count } = await client.admin.realtime.listTables()
9017
+ * console.log(`${count} tables have realtime enabled`)
9018
+ *
9019
+ * tables.forEach(t => {
9020
+ * console.log(`${t.schema}.${t.table}: ${t.events.join(', ')}`)
9021
+ * })
9022
+ *
9023
+ * // Include disabled tables
9024
+ * const all = await client.admin.realtime.listTables({ includeDisabled: true })
9025
+ * ```
9026
+ */
9027
+ async listTables(options) {
9028
+ const params = options?.includeDisabled ? "?enabled=false" : "";
9029
+ return await this.fetch.get(
9030
+ `/api/v1/admin/realtime/tables${params}`
9031
+ );
9032
+ }
9033
+ /**
9034
+ * Get realtime status for a specific table
9035
+ *
9036
+ * Returns the realtime configuration for a table, including whether it's enabled,
9037
+ * which events are tracked, and which columns are excluded.
9038
+ *
9039
+ * @param schema - Schema name
9040
+ * @param table - Table name
9041
+ * @returns Promise resolving to RealtimeTableStatus
9042
+ *
9043
+ * @example
9044
+ * ```typescript
9045
+ * const status = await client.admin.realtime.getStatus('public', 'products')
9046
+ *
9047
+ * if (status.realtime_enabled) {
9048
+ * console.log('Events:', status.events.join(', '))
9049
+ * console.log('Excluded:', status.excluded_columns?.join(', ') || 'none')
9050
+ * } else {
9051
+ * console.log('Realtime not enabled')
9052
+ * }
9053
+ * ```
9054
+ */
9055
+ async getStatus(schema, table) {
9056
+ return await this.fetch.get(
9057
+ `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`
9058
+ );
9059
+ }
9060
+ /**
9061
+ * Update realtime configuration for a table
9062
+ *
9063
+ * Modifies the events or excluded columns for a realtime-enabled table
9064
+ * without recreating the trigger.
9065
+ *
9066
+ * @param schema - Schema name
9067
+ * @param table - Table name
9068
+ * @param config - New configuration
9069
+ * @returns Promise resolving to success message
9070
+ *
9071
+ * @example
9072
+ * ```typescript
9073
+ * // Change which events are tracked
9074
+ * await client.admin.realtime.updateConfig('public', 'products', {
9075
+ * events: ['INSERT', 'UPDATE'] // Stop tracking deletes
9076
+ * })
9077
+ *
9078
+ * // Update excluded columns
9079
+ * await client.admin.realtime.updateConfig('public', 'posts', {
9080
+ * exclude: ['raw_content', 'search_vector']
9081
+ * })
9082
+ *
9083
+ * // Clear excluded columns
9084
+ * await client.admin.realtime.updateConfig('public', 'posts', {
9085
+ * exclude: [] // Include all columns again
9086
+ * })
9087
+ * ```
9088
+ */
9089
+ async updateConfig(schema, table, config) {
9090
+ return await this.fetch.patch(
9091
+ `/api/v1/admin/realtime/tables/${encodeURIComponent(schema)}/${encodeURIComponent(table)}`,
9092
+ config
9093
+ );
9094
+ }
9095
+ };
9096
+
8889
9097
  // src/admin.ts
8890
9098
  var FluxbaseAdmin = class {
8891
9099
  constructor(fetch2) {
@@ -8903,6 +9111,7 @@ var FluxbaseAdmin = class {
8903
9111
  this.ai = new FluxbaseAdminAI(fetch2);
8904
9112
  this.rpc = new FluxbaseAdminRPC(fetch2);
8905
9113
  this.storage = new FluxbaseAdminStorage(fetch2);
9114
+ this.realtime = new FluxbaseAdminRealtime(fetch2);
8906
9115
  }
8907
9116
  /**
8908
9117
  * Set admin authentication token
@@ -11915,6 +12124,6 @@ function assertType(value, validator, errorMessage = "Type assertion failed") {
11915
12124
  }
11916
12125
  }
11917
12126
 
11918
- export { APIKeysManager, AppSettingsManager, AuthSettingsManager, ClientKeysManager, DDLManager, EmailSettingsManager, EmailTemplateManager, ExecutionLogsChannel, FluxbaseAI, FluxbaseAIChat, FluxbaseAdmin, FluxbaseAdminAI, FluxbaseAdminFunctions, FluxbaseAdminJobs, FluxbaseAdminMigrations, FluxbaseAdminRPC, FluxbaseAdminStorage, FluxbaseAuth, FluxbaseBranching, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseGraphQL, FluxbaseJobs, FluxbaseManagement, FluxbaseOAuth, FluxbaseRPC, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, FluxbaseVector, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, SchemaQueryBuilder, SettingsClient, StorageBucket, SystemSettingsManager, WebhooksManager, assertType, bundleCode, createClient, denoExternalPlugin, hasPostgrestError, isArray, isAuthError, isAuthSuccess, isBoolean, isFluxbaseError, isFluxbaseSuccess, isNumber, isObject, isPostgrestSuccess, isString, loadImportMap };
12127
+ export { APIKeysManager, AppSettingsManager, AuthSettingsManager, ClientKeysManager, DDLManager, EmailSettingsManager, EmailTemplateManager, ExecutionLogsChannel, FluxbaseAI, FluxbaseAIChat, FluxbaseAdmin, FluxbaseAdminAI, FluxbaseAdminFunctions, FluxbaseAdminJobs, FluxbaseAdminMigrations, FluxbaseAdminRPC, FluxbaseAdminRealtime, FluxbaseAdminStorage, FluxbaseAuth, FluxbaseBranching, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseGraphQL, FluxbaseJobs, FluxbaseManagement, FluxbaseOAuth, FluxbaseRPC, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, FluxbaseVector, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, SchemaQueryBuilder, SettingsClient, StorageBucket, SystemSettingsManager, WebhooksManager, assertType, bundleCode, createClient, denoExternalPlugin, hasPostgrestError, isArray, isAuthError, isAuthSuccess, isBoolean, isFluxbaseError, isFluxbaseSuccess, isNumber, isObject, isPostgrestSuccess, isString, loadImportMap };
11919
12128
  //# sourceMappingURL=index.js.map
11920
12129
  //# sourceMappingURL=index.js.map