@fluxbase/sdk 0.0.1-rc.14 → 0.0.1-rc.16

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
@@ -602,22 +602,55 @@ var RealtimeChannel = class {
602
602
  }
603
603
  /**
604
604
  * Subscribe to the channel
605
+ * @param callback - Optional status callback (Supabase-compatible)
606
+ * @param _timeout - Optional timeout in milliseconds (currently unused)
605
607
  */
606
- subscribe() {
608
+ subscribe(callback, _timeout) {
607
609
  this.connect();
610
+ if (callback) {
611
+ const checkConnection = () => {
612
+ if (this.ws && this.ws.readyState === WebSocket.OPEN) {
613
+ callback("SUBSCRIBED");
614
+ } else if (this.ws && this.ws.readyState === WebSocket.CLOSED) {
615
+ callback("CHANNEL_ERROR", new Error("Failed to connect"));
616
+ } else {
617
+ setTimeout(checkConnection, 100);
618
+ }
619
+ };
620
+ setTimeout(checkConnection, 100);
621
+ }
608
622
  return this;
609
623
  }
610
624
  /**
611
625
  * Unsubscribe from the channel
612
- */
613
- unsubscribe() {
614
- if (this.ws) {
615
- this.send({
616
- type: "unsubscribe",
617
- channel: this.channelName
618
- });
619
- this.disconnect();
620
- }
626
+ * @param timeout - Optional timeout in milliseconds
627
+ * @returns Promise resolving to status string (Supabase-compatible)
628
+ */
629
+ async unsubscribe(timeout) {
630
+ return new Promise((resolve) => {
631
+ if (this.ws) {
632
+ this.send({
633
+ type: "unsubscribe",
634
+ channel: this.channelName
635
+ });
636
+ const startTime = Date.now();
637
+ const maxWait = timeout || 5e3;
638
+ const checkDisconnect = () => {
639
+ if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
640
+ this.disconnect();
641
+ resolve("ok");
642
+ } else if (Date.now() - startTime > maxWait) {
643
+ this.disconnect();
644
+ resolve("timed out");
645
+ } else {
646
+ setTimeout(checkDisconnect, 100);
647
+ }
648
+ };
649
+ setTimeout(checkDisconnect, 100);
650
+ } else {
651
+ resolve("ok");
652
+ }
653
+ });
621
654
  }
622
655
  /**
623
656
  * Internal: Connect to WebSocket
@@ -706,13 +739,22 @@ var RealtimeChannel = class {
706
739
  * Internal: Handle broadcast message
707
740
  */
708
741
  handleBroadcast(payload) {
709
- const callbacks = this.callbacks.get(payload.type);
742
+ const supabasePayload = {
743
+ eventType: payload.type || payload.eventType,
744
+ schema: payload.schema,
745
+ table: payload.table,
746
+ commit_timestamp: payload.timestamp || payload.commit_timestamp || (/* @__PURE__ */ new Date()).toISOString(),
747
+ new: payload.new_record || payload.new || {},
748
+ old: payload.old_record || payload.old || {},
749
+ errors: payload.errors || null
750
+ };
751
+ const callbacks = this.callbacks.get(supabasePayload.eventType);
710
752
  if (callbacks) {
711
- callbacks.forEach((callback) => callback(payload));
753
+ callbacks.forEach((callback) => callback(supabasePayload));
712
754
  }
713
755
  const wildcardCallbacks = this.callbacks.get("*");
714
756
  if (wildcardCallbacks) {
715
- wildcardCallbacks.forEach((callback) => callback(payload));
757
+ wildcardCallbacks.forEach((callback) => callback(supabasePayload));
716
758
  }
717
759
  }
718
760
  /**
@@ -742,7 +784,9 @@ var RealtimeChannel = class {
742
784
  }
743
785
  this.reconnectAttempts++;
744
786
  const delay = this.reconnectDelay * Math.pow(2, this.reconnectAttempts - 1);
745
- console.log(`[Fluxbase Realtime] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`);
787
+ console.log(
788
+ `[Fluxbase Realtime] Reconnecting in ${delay}ms (attempt ${this.reconnectAttempts})`
789
+ );
746
790
  setTimeout(() => {
747
791
  this.connect();
748
792
  }, delay);
@@ -810,7 +854,7 @@ var StorageBucket = class {
810
854
  if (options?.upsert !== void 0) {
811
855
  formData.append("upsert", String(options.upsert));
812
856
  }
813
- const data = await this.fetch.request(
857
+ const response = await this.fetch.request(
814
858
  `/api/v1/storage/${this.bucketName}/${path}`,
815
859
  {
816
860
  method: "POST",
@@ -819,7 +863,14 @@ var StorageBucket = class {
819
863
  // Let browser set Content-Type for FormData
820
864
  }
821
865
  );
822
- return { data, error: null };
866
+ return {
867
+ data: {
868
+ id: response.id || response.key || path,
869
+ path,
870
+ fullPath: `${this.bucketName}/${path}`
871
+ },
872
+ error: null
873
+ };
823
874
  } catch (error) {
824
875
  return { data: null, error };
825
876
  }
@@ -847,13 +898,24 @@ var StorageBucket = class {
847
898
  }
848
899
  /**
849
900
  * List files in the bucket
850
- * @param options - List options (prefix, limit, offset)
901
+ * Supports both Supabase-style list(path, options) and Fluxbase-style list(options)
902
+ * @param pathOrOptions - The folder path or list options
903
+ * @param maybeOptions - List options when first param is a path
851
904
  */
852
- async list(options) {
905
+ async list(pathOrOptions, maybeOptions) {
853
906
  try {
854
907
  const params = new URLSearchParams();
855
- if (options?.prefix) {
856
- params.set("prefix", options.prefix);
908
+ let prefix;
909
+ let options;
910
+ if (typeof pathOrOptions === "string") {
911
+ prefix = pathOrOptions;
912
+ options = maybeOptions;
913
+ } else {
914
+ options = pathOrOptions;
915
+ prefix = options?.prefix;
916
+ }
917
+ if (prefix) {
918
+ params.set("prefix", prefix);
857
919
  }
858
920
  if (options?.limit) {
859
921
  params.set("limit", String(options.limit));
@@ -863,8 +925,17 @@ var StorageBucket = class {
863
925
  }
864
926
  const queryString = params.toString();
865
927
  const path = `/api/v1/storage/${this.bucketName}${queryString ? `?${queryString}` : ""}`;
866
- const data = await this.fetch.get(path);
867
- return { data: data.files || [], error: null };
928
+ const response = await this.fetch.get(path);
929
+ const files = (response.files || []).map((file) => ({
930
+ name: file.key || file.name,
931
+ id: file.id,
932
+ bucket_id: file.bucket || this.bucketName,
933
+ created_at: file.last_modified || file.created_at,
934
+ updated_at: file.updated_at,
935
+ last_accessed_at: file.last_accessed_at,
936
+ metadata: file.metadata
937
+ }));
938
+ return { data: files, error: null };
868
939
  } catch (error) {
869
940
  return { data: null, error };
870
941
  }
@@ -875,10 +946,15 @@ var StorageBucket = class {
875
946
  */
876
947
  async remove(paths) {
877
948
  try {
949
+ const removedFiles = [];
878
950
  for (const path of paths) {
879
951
  await this.fetch.delete(`/api/v1/storage/${this.bucketName}/${path}`);
952
+ removedFiles.push({
953
+ name: path,
954
+ bucket_id: this.bucketName
955
+ });
880
956
  }
881
- return { data: null, error: null };
957
+ return { data: removedFiles, error: null };
882
958
  } catch (error) {
883
959
  return { data: null, error };
884
960
  }
@@ -915,14 +991,17 @@ var StorageBucket = class {
915
991
  */
916
992
  async move(fromPath, toPath) {
917
993
  try {
918
- const data = await this.fetch.post(
994
+ await this.fetch.post(
919
995
  `/api/v1/storage/${this.bucketName}/move`,
920
996
  {
921
997
  from_path: fromPath,
922
998
  to_path: toPath
923
999
  }
924
1000
  );
925
- return { data, error: null };
1001
+ return {
1002
+ data: { message: "Successfully moved" },
1003
+ error: null
1004
+ };
926
1005
  } catch (error) {
927
1006
  return { data: null, error };
928
1007
  }
@@ -934,14 +1013,17 @@ var StorageBucket = class {
934
1013
  */
935
1014
  async copy(fromPath, toPath) {
936
1015
  try {
937
- const data = await this.fetch.post(
1016
+ await this.fetch.post(
938
1017
  `/api/v1/storage/${this.bucketName}/copy`,
939
1018
  {
940
1019
  from_path: fromPath,
941
1020
  to_path: toPath
942
1021
  }
943
1022
  );
944
- return { data, error: null };
1023
+ return {
1024
+ data: { path: toPath },
1025
+ error: null
1026
+ };
945
1027
  } catch (error) {
946
1028
  return { data: null, error };
947
1029
  }
@@ -1024,7 +1106,7 @@ var FluxbaseStorage = class {
1024
1106
  async createBucket(bucketName) {
1025
1107
  try {
1026
1108
  await this.fetch.post(`/api/v1/storage/buckets/${bucketName}`);
1027
- return { data: null, error: null };
1109
+ return { data: { name: bucketName }, error: null };
1028
1110
  } catch (error) {
1029
1111
  return { data: null, error };
1030
1112
  }
@@ -1036,7 +1118,7 @@ var FluxbaseStorage = class {
1036
1118
  async deleteBucket(bucketName) {
1037
1119
  try {
1038
1120
  await this.fetch.delete(`/api/v1/storage/buckets/${bucketName}`);
1039
- return { data: null, error: null };
1121
+ return { data: { message: "Successfully deleted" }, error: null };
1040
1122
  } catch (error) {
1041
1123
  return { data: null, error };
1042
1124
  }
@@ -1053,13 +1135,13 @@ var FluxbaseStorage = class {
1053
1135
  return { data: null, error: listError };
1054
1136
  }
1055
1137
  if (objects && objects.length > 0) {
1056
- const paths = objects.map((obj) => obj.key);
1138
+ const paths = objects.map((obj) => obj.name);
1057
1139
  const { error: removeError } = await bucket.remove(paths);
1058
1140
  if (removeError) {
1059
1141
  return { data: null, error: removeError };
1060
1142
  }
1061
1143
  }
1062
- return { data: null, error: null };
1144
+ return { data: { message: "Successfully emptied" }, error: null };
1063
1145
  } catch (error) {
1064
1146
  return { data: null, error };
1065
1147
  }
@@ -1093,6 +1175,208 @@ var FluxbaseStorage = class {
1093
1175
  }
1094
1176
  };
1095
1177
 
1178
+ // src/functions.ts
1179
+ var FluxbaseFunctions = class {
1180
+ constructor(fetch2) {
1181
+ this.fetch = fetch2;
1182
+ }
1183
+ /**
1184
+ * Invoke an edge function
1185
+ *
1186
+ * This method is fully compatible with Supabase's functions.invoke() API.
1187
+ *
1188
+ * @param functionName - The name of the function to invoke
1189
+ * @param options - Invocation options including body, headers, and HTTP method
1190
+ * @returns Promise resolving to { data, error } tuple
1191
+ *
1192
+ * @example
1193
+ * ```typescript
1194
+ * // Simple invocation
1195
+ * const { data, error } = await client.functions.invoke('hello', {
1196
+ * body: { name: 'World' }
1197
+ * })
1198
+ *
1199
+ * // With GET method
1200
+ * const { data, error } = await client.functions.invoke('get-data', {
1201
+ * method: 'GET'
1202
+ * })
1203
+ *
1204
+ * // With custom headers
1205
+ * const { data, error } = await client.functions.invoke('api-proxy', {
1206
+ * body: { query: 'search' },
1207
+ * headers: { 'Authorization': 'Bearer token' },
1208
+ * method: 'POST'
1209
+ * })
1210
+ * ```
1211
+ */
1212
+ async invoke(functionName, options) {
1213
+ try {
1214
+ const method = options?.method || "POST";
1215
+ const headers = options?.headers || {};
1216
+ const body = options?.body;
1217
+ const endpoint = `/api/v1/functions/${functionName}/invoke`;
1218
+ let response;
1219
+ switch (method) {
1220
+ case "GET":
1221
+ response = await this.fetch.get(endpoint, { headers });
1222
+ break;
1223
+ case "DELETE":
1224
+ response = await this.fetch.delete(endpoint, { headers });
1225
+ break;
1226
+ case "PUT":
1227
+ response = await this.fetch.put(endpoint, body, { headers });
1228
+ break;
1229
+ case "PATCH":
1230
+ response = await this.fetch.patch(endpoint, body, { headers });
1231
+ break;
1232
+ case "POST":
1233
+ default:
1234
+ response = await this.fetch.post(endpoint, body, { headers });
1235
+ break;
1236
+ }
1237
+ return { data: response, error: null };
1238
+ } catch (error) {
1239
+ return { data: null, error };
1240
+ }
1241
+ }
1242
+ /**
1243
+ * Create a new edge function
1244
+ *
1245
+ * @param request - Function configuration and code
1246
+ * @returns Promise resolving to { data, error } tuple with created function metadata
1247
+ *
1248
+ * @example
1249
+ * ```typescript
1250
+ * const { data, error } = await client.functions.create({
1251
+ * name: 'my-function',
1252
+ * code: 'export default async function handler(req) { return { hello: "world" } }',
1253
+ * enabled: true
1254
+ * })
1255
+ * ```
1256
+ */
1257
+ async create(request) {
1258
+ try {
1259
+ const data = await this.fetch.post("/api/v1/functions", request);
1260
+ return { data, error: null };
1261
+ } catch (error) {
1262
+ return { data: null, error };
1263
+ }
1264
+ }
1265
+ /**
1266
+ * List all edge functions
1267
+ *
1268
+ * @returns Promise resolving to { data, error } tuple with array of functions
1269
+ *
1270
+ * @example
1271
+ * ```typescript
1272
+ * const { data, error } = await client.functions.list()
1273
+ * if (data) {
1274
+ * console.log('Functions:', data.map(f => f.name))
1275
+ * }
1276
+ * ```
1277
+ */
1278
+ async list() {
1279
+ try {
1280
+ const data = await this.fetch.get("/api/v1/functions");
1281
+ return { data, error: null };
1282
+ } catch (error) {
1283
+ return { data: null, error };
1284
+ }
1285
+ }
1286
+ /**
1287
+ * Get details of a specific edge function
1288
+ *
1289
+ * @param name - Function name
1290
+ * @returns Promise resolving to { data, error } tuple with function metadata
1291
+ *
1292
+ * @example
1293
+ * ```typescript
1294
+ * const { data, error } = await client.functions.get('my-function')
1295
+ * if (data) {
1296
+ * console.log('Function version:', data.version)
1297
+ * }
1298
+ * ```
1299
+ */
1300
+ async get(name) {
1301
+ try {
1302
+ const data = await this.fetch.get(`/api/v1/functions/${name}`);
1303
+ return { data, error: null };
1304
+ } catch (error) {
1305
+ return { data: null, error };
1306
+ }
1307
+ }
1308
+ /**
1309
+ * Update an existing edge function
1310
+ *
1311
+ * @param name - Function name
1312
+ * @param updates - Fields to update
1313
+ * @returns Promise resolving to { data, error } tuple with updated function metadata
1314
+ *
1315
+ * @example
1316
+ * ```typescript
1317
+ * const { data, error } = await client.functions.update('my-function', {
1318
+ * enabled: false,
1319
+ * description: 'Updated description'
1320
+ * })
1321
+ * ```
1322
+ */
1323
+ async update(name, updates) {
1324
+ try {
1325
+ const data = await this.fetch.put(`/api/v1/functions/${name}`, updates);
1326
+ return { data, error: null };
1327
+ } catch (error) {
1328
+ return { data: null, error };
1329
+ }
1330
+ }
1331
+ /**
1332
+ * Delete an edge function
1333
+ *
1334
+ * @param name - Function name
1335
+ * @returns Promise resolving to { data, error } tuple
1336
+ *
1337
+ * @example
1338
+ * ```typescript
1339
+ * const { data, error } = await client.functions.delete('my-function')
1340
+ * ```
1341
+ */
1342
+ async delete(name) {
1343
+ try {
1344
+ await this.fetch.delete(`/api/v1/functions/${name}`);
1345
+ return { data: null, error: null };
1346
+ } catch (error) {
1347
+ return { data: null, error };
1348
+ }
1349
+ }
1350
+ /**
1351
+ * Get execution history for an edge function
1352
+ *
1353
+ * @param name - Function name
1354
+ * @param limit - Maximum number of executions to return (optional)
1355
+ * @returns Promise resolving to { data, error } tuple with execution records
1356
+ *
1357
+ * @example
1358
+ * ```typescript
1359
+ * const { data, error } = await client.functions.getExecutions('my-function', 10)
1360
+ * if (data) {
1361
+ * data.forEach(exec => {
1362
+ * console.log(`${exec.executed_at}: ${exec.status} (${exec.duration_ms}ms)`)
1363
+ * })
1364
+ * }
1365
+ * ```
1366
+ */
1367
+ async getExecutions(name, limit) {
1368
+ try {
1369
+ const params = limit ? `?limit=${limit}` : "";
1370
+ const data = await this.fetch.get(
1371
+ `/api/v1/functions/${name}/executions${params}`
1372
+ );
1373
+ return { data, error: null };
1374
+ } catch (error) {
1375
+ return { data: null, error };
1376
+ }
1377
+ }
1378
+ };
1379
+
1096
1380
  // src/settings.ts
1097
1381
  var SystemSettingsManager = class {
1098
1382
  constructor(fetch2) {
@@ -3682,8 +3966,12 @@ var FluxbaseClient = class {
3682
3966
  if (options.auth?.token) {
3683
3967
  this.fetch.setAuthToken(options.auth.token);
3684
3968
  }
3685
- this.realtime = new FluxbaseRealtime(options.url, options.auth?.token || null);
3969
+ this.realtime = new FluxbaseRealtime(
3970
+ options.url,
3971
+ options.auth?.token || null
3972
+ );
3686
3973
  this.storage = new FluxbaseStorage(this.fetch);
3974
+ this.functions = new FluxbaseFunctions(this.fetch);
3687
3975
  this.admin = new FluxbaseAdmin(this.fetch);
3688
3976
  this.management = new FluxbaseManagement(this.fetch);
3689
3977
  this.setupAuthSync();
@@ -3738,7 +4026,10 @@ var FluxbaseClient = class {
3738
4026
  */
3739
4027
  async rpc(functionName, params) {
3740
4028
  try {
3741
- const data = await this.fetch.post(`/api/v1/rpc/${functionName}`, params || {});
4029
+ const data = await this.fetch.post(
4030
+ `/api/v1/rpc/${functionName}`,
4031
+ params || {}
4032
+ );
3742
4033
  return { data, error: null };
3743
4034
  } catch (error) {
3744
4035
  return { data: null, error };
@@ -3778,6 +4069,36 @@ var FluxbaseClient = class {
3778
4069
  this.fetch.setAuthToken(token);
3779
4070
  this.realtime.setToken(token);
3780
4071
  }
4072
+ /**
4073
+ * Create or get a realtime channel (Supabase-compatible alias)
4074
+ *
4075
+ * This is a convenience method that delegates to client.realtime.channel().
4076
+ * Both patterns work identically:
4077
+ * - client.channel('room-1') - Supabase-style
4078
+ * - client.realtime.channel('room-1') - Fluxbase-style
4079
+ *
4080
+ * @param name - Channel name
4081
+ * @returns RealtimeChannel instance
4082
+ *
4083
+ * @example
4084
+ * ```typescript
4085
+ * // Supabase-compatible usage
4086
+ * const channel = client.channel('room-1')
4087
+ * .on('postgres_changes', {
4088
+ * event: '*',
4089
+ * schema: 'public',
4090
+ * table: 'messages'
4091
+ * }, (payload) => {
4092
+ * console.log('Change:', payload)
4093
+ * })
4094
+ * .subscribe()
4095
+ * ```
4096
+ *
4097
+ * @category Realtime
4098
+ */
4099
+ channel(name) {
4100
+ return this.realtime.channel(name);
4101
+ }
3781
4102
  /**
3782
4103
  * Get the internal HTTP client
3783
4104
  *
@@ -3801,6 +4122,6 @@ function createClient(options) {
3801
4122
  return new FluxbaseClient(options);
3802
4123
  }
3803
4124
 
3804
- export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, EmailTemplateManager, FluxbaseAdmin, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
4125
+ export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, EmailTemplateManager, FluxbaseAdmin, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
3805
4126
  //# sourceMappingURL=index.js.map
3806
4127
  //# sourceMappingURL=index.js.map