@fluxbase/sdk 2026.1.8 → 2026.1.9-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.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));
@@ -8888,6 +8932,168 @@ var FluxbaseAdminStorage = class {
8888
8932
  }
8889
8933
  };
8890
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
+
8891
9097
  // src/admin.ts
8892
9098
  var FluxbaseAdmin = class {
8893
9099
  constructor(fetch2) {
@@ -8905,6 +9111,7 @@ var FluxbaseAdmin = class {
8905
9111
  this.ai = new FluxbaseAdminAI(fetch2);
8906
9112
  this.rpc = new FluxbaseAdminRPC(fetch2);
8907
9113
  this.storage = new FluxbaseAdminStorage(fetch2);
9114
+ this.realtime = new FluxbaseAdminRealtime(fetch2);
8908
9115
  }
8909
9116
  /**
8910
9117
  * Set admin authentication token
@@ -11917,6 +12124,6 @@ function assertType(value, validator, errorMessage = "Type assertion failed") {
11917
12124
  }
11918
12125
  }
11919
12126
 
11920
- 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 };
11921
12128
  //# sourceMappingURL=index.js.map
11922
12129
  //# sourceMappingURL=index.js.map