@hot-updater/supabase 0.35.12 → 0.36.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/edge.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DRxwDPRy.cjs");
2
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DczYIzj_.cjs");
3
3
  exports.supabaseEdgeFunctionDatabase = require_supabaseEdgeFunctionStorage.supabaseEdgeFunctionDatabase;
4
4
  exports.supabaseEdgeFunctionStorage = require_supabaseEdgeFunctionStorage.supabaseEdgeFunctionStorage;
package/dist/edge.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as supabaseEdgeFunctionDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CO70azPw.mjs";
1
+ import { i as supabaseEdgeFunctionDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-B3yJ5yys.mjs";
2
2
  export { supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage };
@@ -6909,7 +6909,7 @@ const SOURCE_TEMPLATE = `// add this to your App.tsx
6909
6909
  import { HotUpdater } from "@hot-updater/react-native";
6910
6910
 
6911
6911
  function App() {
6912
- return ...
6912
+ return null; // Replace with your app root
6913
6913
  }
6914
6914
 
6915
6915
  export default HotUpdater.wrap({
@@ -6904,7 +6904,7 @@ const SOURCE_TEMPLATE = `// add this to your App.tsx
6904
6904
  import { HotUpdater } from "@hot-updater/react-native";
6905
6905
 
6906
6906
  function App() {
6907
- return ...
6907
+ return null; // Replace with your app root
6908
6908
  }
6909
6909
 
6910
6910
  export default HotUpdater.wrap({
package/dist/index.cjs CHANGED
@@ -21,7 +21,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
21
21
  enumerable: true
22
22
  }) : target, mod));
23
23
  //#endregion
24
- const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DRxwDPRy.cjs");
24
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DczYIzj_.cjs");
25
25
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
26
26
  let _supabase_supabase_js = require("@supabase/supabase-js");
27
27
  let fs_promises = require("fs/promises");
@@ -54,16 +54,28 @@ async function verifyObjectCanBeSignedForRuntime({ bucket, key }) {
54
54
  expiresIn: 3600
55
55
  });
56
56
  }
57
+ const parseSupabaseStorageUri = (storageUri) => {
58
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
59
+ return {
60
+ bucket,
61
+ key: require_supabaseEdgeFunctionStorage.decodeStorageObjectKey(key)
62
+ };
63
+ };
57
64
  const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugin)({
58
65
  name: "supabaseStorage",
59
66
  supportedProtocol: "supabase-storage",
60
67
  factory: (config) => {
61
68
  const bucket = (0, _supabase_supabase_js.createClient)(config.supabaseUrl, require_supabaseEdgeFunctionStorage.resolveSupabaseServiceRoleKey(config)).storage.from(config.bucketName);
62
69
  const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
70
+ const resolveSignedUrl = require_supabaseEdgeFunctionStorage.createSupabaseSignedUrlBatcher({
71
+ createSignedUrls: (_bucketName, keys, expiresIn) => bucket.createSignedUrls(keys, expiresIn),
72
+ expiresIn: 3600,
73
+ formatObjectPath: (_bucketName, key) => key
74
+ });
63
75
  return {
64
76
  node: {
65
77
  async delete(storageUri) {
66
- const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
78
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
67
79
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
68
80
  const { error } = await bucket.remove([key]);
69
81
  if (error) {
@@ -88,7 +100,7 @@ const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugi
88
100
  return { storageUri: `supabase-storage://${upload.data.fullPath}` };
89
101
  },
90
102
  async exists(storageUri) {
91
- const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
103
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
92
104
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
93
105
  const { data, error } = await bucket.exists(key);
94
106
  if (data === false) return false;
@@ -100,7 +112,7 @@ const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugi
100
112
  return data;
101
113
  },
102
114
  async downloadFile(storageUri, filePath) {
103
- const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
115
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
104
116
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
105
117
  const { data, error } = await bucket.download(key);
106
118
  if (error) throw new Error(`Failed to download bundle: ${error.message}`);
@@ -111,7 +123,7 @@ const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugi
111
123
  },
112
124
  runtime: {
113
125
  async readText(storageUri) {
114
- const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
126
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
115
127
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
116
128
  const { data, error } = await bucket.download(key);
117
129
  if (error) {
@@ -124,14 +136,10 @@ const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugi
124
136
  async getDownloadUrl(storageUri) {
125
137
  const u = new URL(storageUri);
126
138
  if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
127
- let key = `${u.host}${u.pathname}`.replace(/^\//, "");
139
+ let key = require_supabaseEdgeFunctionStorage.decodeStorageObjectKey(`${u.host}${u.pathname}`.replace(/^\//, ""));
128
140
  if (!key) throw new Error("Invalid Supabase storage URI: missing key");
129
141
  if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
130
- return { fileUrl: await createSignedUrlOrThrow({
131
- bucket,
132
- key,
133
- expiresIn: 3600
134
- }) };
142
+ return { fileUrl: await resolveSignedUrl(config.bucketName, key) };
135
143
  }
136
144
  }
137
145
  };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as resolveSupabaseServiceRoleKey, n as supabaseEdgeFunctionDatabase, r as supabaseDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CO70azPw.mjs";
1
+ import { a as supabaseDatabase, i as supabaseEdgeFunctionDatabase, n as decodeStorageObjectKey, o as resolveSupabaseServiceRoleKey, r as createSupabaseSignedUrlBatcher, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-B3yJ5yys.mjs";
2
2
  import { createStorageKeyBuilder, createUniversalStoragePlugin, getContentType, parseStorageUri } from "@hot-updater/plugin-core";
3
3
  import { createClient } from "@supabase/supabase-js";
4
4
  import fs from "fs/promises";
@@ -29,16 +29,28 @@ async function verifyObjectCanBeSignedForRuntime({ bucket, key }) {
29
29
  expiresIn: 3600
30
30
  });
31
31
  }
32
+ const parseSupabaseStorageUri = (storageUri) => {
33
+ const { bucket, key } = parseStorageUri(storageUri, "supabase-storage");
34
+ return {
35
+ bucket,
36
+ key: decodeStorageObjectKey(key)
37
+ };
38
+ };
32
39
  const supabaseStorage = createUniversalStoragePlugin({
33
40
  name: "supabaseStorage",
34
41
  supportedProtocol: "supabase-storage",
35
42
  factory: (config) => {
36
43
  const bucket = createClient(config.supabaseUrl, resolveSupabaseServiceRoleKey(config)).storage.from(config.bucketName);
37
44
  const getStorageKey = createStorageKeyBuilder(config.basePath);
45
+ const resolveSignedUrl = createSupabaseSignedUrlBatcher({
46
+ createSignedUrls: (_bucketName, keys, expiresIn) => bucket.createSignedUrls(keys, expiresIn),
47
+ expiresIn: 3600,
48
+ formatObjectPath: (_bucketName, key) => key
49
+ });
38
50
  return {
39
51
  node: {
40
52
  async delete(storageUri) {
41
- const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
53
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
42
54
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
43
55
  const { error } = await bucket.remove([key]);
44
56
  if (error) {
@@ -63,7 +75,7 @@ const supabaseStorage = createUniversalStoragePlugin({
63
75
  return { storageUri: `supabase-storage://${upload.data.fullPath}` };
64
76
  },
65
77
  async exists(storageUri) {
66
- const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
78
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
67
79
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
68
80
  const { data, error } = await bucket.exists(key);
69
81
  if (data === false) return false;
@@ -75,7 +87,7 @@ const supabaseStorage = createUniversalStoragePlugin({
75
87
  return data;
76
88
  },
77
89
  async downloadFile(storageUri, filePath) {
78
- const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
90
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
79
91
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
80
92
  const { data, error } = await bucket.download(key);
81
93
  if (error) throw new Error(`Failed to download bundle: ${error.message}`);
@@ -86,7 +98,7 @@ const supabaseStorage = createUniversalStoragePlugin({
86
98
  },
87
99
  runtime: {
88
100
  async readText(storageUri) {
89
- const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
101
+ const { key, bucket: bucketName } = parseSupabaseStorageUri(storageUri);
90
102
  if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
91
103
  const { data, error } = await bucket.download(key);
92
104
  if (error) {
@@ -99,14 +111,10 @@ const supabaseStorage = createUniversalStoragePlugin({
99
111
  async getDownloadUrl(storageUri) {
100
112
  const u = new URL(storageUri);
101
113
  if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
102
- let key = `${u.host}${u.pathname}`.replace(/^\//, "");
114
+ let key = decodeStorageObjectKey(`${u.host}${u.pathname}`.replace(/^\//, ""));
103
115
  if (!key) throw new Error("Invalid Supabase storage URI: missing key");
104
116
  if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
105
- return { fileUrl: await createSignedUrlOrThrow({
106
- bucket,
107
- key,
108
- expiresIn: 3600
109
- }) };
117
+ return { fileUrl: await resolveSignedUrl(config.bucketName, key) };
110
118
  }
111
119
  }
112
120
  };
@@ -263,17 +263,86 @@ const supabaseEdgeFunctionDatabase = (config, hooks) => {
263
263
  }, hooks);
264
264
  };
265
265
  //#endregion
266
- //#region src/supabaseEdgeFunctionStorage.ts
266
+ //#region src/supabaseSignedUrlBatcher.ts
267
267
  function getErrorMessage(error) {
268
268
  if (error instanceof Error) return error.message;
269
269
  if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
270
270
  return String(error);
271
271
  }
272
+ const createSupabaseSignedUrlBatcher = ({ createSignedUrls, expiresIn, formatObjectPath }) => {
273
+ let pendingByBucket = /* @__PURE__ */ new Map();
274
+ let flushScheduled = false;
275
+ const createSignedUrlError = (bucketName, key, error) => /* @__PURE__ */ new Error(`Failed to generate download URL for "${formatObjectPath(bucketName, key)}": ${getErrorMessage(error)}`);
276
+ const flush = async () => {
277
+ const batches = pendingByBucket;
278
+ pendingByBucket = /* @__PURE__ */ new Map();
279
+ flushScheduled = false;
280
+ await Promise.all([...batches.entries()].map(async ([bucketName, pending]) => {
281
+ try {
282
+ const { data, error } = await createSignedUrls(bucketName, pending.map(({ key }) => key), expiresIn);
283
+ if (error || !data) {
284
+ const batchError = error ?? /* @__PURE__ */ new Error("missing signed URL response");
285
+ for (const request of pending) request.reject(createSignedUrlError(bucketName, request.key, batchError));
286
+ return;
287
+ }
288
+ pending.forEach((request, index) => {
289
+ const result = data[index];
290
+ if (!result?.error && result?.signedUrl) {
291
+ request.resolve(result.signedUrl);
292
+ return;
293
+ }
294
+ request.reject(createSignedUrlError(bucketName, request.key, result?.error ?? /* @__PURE__ */ new Error("missing signed URL")));
295
+ });
296
+ } catch (error) {
297
+ for (const request of pending) request.reject(createSignedUrlError(bucketName, request.key, error));
298
+ }
299
+ }));
300
+ };
301
+ return (bucketName, key) => new Promise((resolve, reject) => {
302
+ const pending = pendingByBucket.get(bucketName) ?? [];
303
+ pending.push({
304
+ key,
305
+ reject,
306
+ resolve
307
+ });
308
+ pendingByBucket.set(bucketName, pending);
309
+ if (!flushScheduled) {
310
+ flushScheduled = true;
311
+ queueMicrotask(() => {
312
+ flush();
313
+ });
314
+ }
315
+ });
316
+ };
317
+ //#endregion
318
+ //#region src/supabaseStorageKey.ts
319
+ /**
320
+ * Supabase upload responses echo a percent-encoded object key (`data.Key`),
321
+ * so the `supabase-storage://` URIs built from them keep that encoding.
322
+ *
323
+ * Storage API endpoints that carry the key in the request path
324
+ * (`createSignedUrl`, `download`, `exists`) decode it server side, but the
325
+ * ones that carry keys in the JSON body (`createSignedUrls`, `remove`) do
326
+ * not, and look up an object whose name literally contains `%40`.
327
+ *
328
+ * Decoding when the URI is parsed keeps both request shapes pointing at the
329
+ * same object. Keys that are not valid percent-encoded sequences are left
330
+ * untouched.
331
+ */
332
+ const decodeStorageObjectKey = (key) => {
333
+ try {
334
+ return decodeURIComponent(key);
335
+ } catch {
336
+ return key;
337
+ }
338
+ };
339
+ //#endregion
340
+ //#region src/supabaseEdgeFunctionStorage.ts
272
341
  const parseSupabaseStorageUri = (storageUri) => {
273
342
  const storageUrl = new URL(storageUri);
274
343
  if (storageUrl.protocol !== "supabase-storage:") throw new Error("Invalid Supabase storage URI protocol");
275
344
  const bucketName = storageUrl.host;
276
- const key = storageUrl.pathname.replace(/^\/+/, "");
345
+ const key = decodeStorageObjectKey(storageUrl.pathname.replace(/^\/+/, ""));
277
346
  if (!bucketName || !key) throw new Error("Invalid Supabase storage URI");
278
347
  return {
279
348
  bucketName,
@@ -285,6 +354,11 @@ const supabaseEdgeFunctionStorage = createRuntimeStoragePlugin({
285
354
  supportedProtocol: "supabase-storage",
286
355
  factory: (config) => {
287
356
  const supabase = createClient(config.supabaseUrl, config.supabaseServiceRoleKey);
357
+ const resolveSignedUrl = createSupabaseSignedUrlBatcher({
358
+ createSignedUrls: (bucketName, keys, expiresIn) => supabase.storage.from(bucketName).createSignedUrls(keys, expiresIn),
359
+ expiresIn: config.signedUrlExpiresIn ?? 3600,
360
+ formatObjectPath: (bucketName, key) => `${bucketName}/${key}`
361
+ });
288
362
  return {
289
363
  async readText(storageUri) {
290
364
  const { bucketName, key } = parseSupabaseStorageUri(storageUri);
@@ -298,22 +372,10 @@ const supabaseEdgeFunctionStorage = createRuntimeStoragePlugin({
298
372
  },
299
373
  async getDownloadUrl(storageUri) {
300
374
  const { bucketName, key } = parseSupabaseStorageUri(storageUri);
301
- const bucket = supabase.storage.from(bucketName);
302
- const expiresIn = config.signedUrlExpiresIn ?? 3600;
303
- let data = null;
304
- let error = null;
305
- try {
306
- const response = await bucket.createSignedUrl(key, expiresIn);
307
- data = response.data;
308
- error = response.error;
309
- } catch (thrownError) {
310
- error = thrownError;
311
- }
312
- if (!error && data?.signedUrl) return { fileUrl: data.signedUrl };
313
- throw new Error(`Failed to generate download URL for "${bucketName}/${key}": ${getErrorMessage(error ?? /* @__PURE__ */ new Error("missing signed URL"))}`);
375
+ return { fileUrl: await resolveSignedUrl(bucketName, key) };
314
376
  }
315
377
  };
316
378
  }
317
379
  });
318
380
  //#endregion
319
- export { resolveSupabaseServiceRoleKey as i, supabaseEdgeFunctionDatabase as n, supabaseDatabase as r, supabaseEdgeFunctionStorage as t };
381
+ export { supabaseDatabase as a, supabaseEdgeFunctionDatabase as i, decodeStorageObjectKey as n, resolveSupabaseServiceRoleKey as o, createSupabaseSignedUrlBatcher as r, supabaseEdgeFunctionStorage as t };
@@ -264,17 +264,86 @@ const supabaseEdgeFunctionDatabase = (config, hooks) => {
264
264
  }, hooks);
265
265
  };
266
266
  //#endregion
267
- //#region src/supabaseEdgeFunctionStorage.ts
267
+ //#region src/supabaseSignedUrlBatcher.ts
268
268
  function getErrorMessage(error) {
269
269
  if (error instanceof Error) return error.message;
270
270
  if (error && typeof error === "object" && "message" in error && typeof error.message === "string") return error.message;
271
271
  return String(error);
272
272
  }
273
+ const createSupabaseSignedUrlBatcher = ({ createSignedUrls, expiresIn, formatObjectPath }) => {
274
+ let pendingByBucket = /* @__PURE__ */ new Map();
275
+ let flushScheduled = false;
276
+ const createSignedUrlError = (bucketName, key, error) => /* @__PURE__ */ new Error(`Failed to generate download URL for "${formatObjectPath(bucketName, key)}": ${getErrorMessage(error)}`);
277
+ const flush = async () => {
278
+ const batches = pendingByBucket;
279
+ pendingByBucket = /* @__PURE__ */ new Map();
280
+ flushScheduled = false;
281
+ await Promise.all([...batches.entries()].map(async ([bucketName, pending]) => {
282
+ try {
283
+ const { data, error } = await createSignedUrls(bucketName, pending.map(({ key }) => key), expiresIn);
284
+ if (error || !data) {
285
+ const batchError = error ?? /* @__PURE__ */ new Error("missing signed URL response");
286
+ for (const request of pending) request.reject(createSignedUrlError(bucketName, request.key, batchError));
287
+ return;
288
+ }
289
+ pending.forEach((request, index) => {
290
+ const result = data[index];
291
+ if (!result?.error && result?.signedUrl) {
292
+ request.resolve(result.signedUrl);
293
+ return;
294
+ }
295
+ request.reject(createSignedUrlError(bucketName, request.key, result?.error ?? /* @__PURE__ */ new Error("missing signed URL")));
296
+ });
297
+ } catch (error) {
298
+ for (const request of pending) request.reject(createSignedUrlError(bucketName, request.key, error));
299
+ }
300
+ }));
301
+ };
302
+ return (bucketName, key) => new Promise((resolve, reject) => {
303
+ const pending = pendingByBucket.get(bucketName) ?? [];
304
+ pending.push({
305
+ key,
306
+ reject,
307
+ resolve
308
+ });
309
+ pendingByBucket.set(bucketName, pending);
310
+ if (!flushScheduled) {
311
+ flushScheduled = true;
312
+ queueMicrotask(() => {
313
+ flush();
314
+ });
315
+ }
316
+ });
317
+ };
318
+ //#endregion
319
+ //#region src/supabaseStorageKey.ts
320
+ /**
321
+ * Supabase upload responses echo a percent-encoded object key (`data.Key`),
322
+ * so the `supabase-storage://` URIs built from them keep that encoding.
323
+ *
324
+ * Storage API endpoints that carry the key in the request path
325
+ * (`createSignedUrl`, `download`, `exists`) decode it server side, but the
326
+ * ones that carry keys in the JSON body (`createSignedUrls`, `remove`) do
327
+ * not, and look up an object whose name literally contains `%40`.
328
+ *
329
+ * Decoding when the URI is parsed keeps both request shapes pointing at the
330
+ * same object. Keys that are not valid percent-encoded sequences are left
331
+ * untouched.
332
+ */
333
+ const decodeStorageObjectKey = (key) => {
334
+ try {
335
+ return decodeURIComponent(key);
336
+ } catch {
337
+ return key;
338
+ }
339
+ };
340
+ //#endregion
341
+ //#region src/supabaseEdgeFunctionStorage.ts
273
342
  const parseSupabaseStorageUri = (storageUri) => {
274
343
  const storageUrl = new URL(storageUri);
275
344
  if (storageUrl.protocol !== "supabase-storage:") throw new Error("Invalid Supabase storage URI protocol");
276
345
  const bucketName = storageUrl.host;
277
- const key = storageUrl.pathname.replace(/^\/+/, "");
346
+ const key = decodeStorageObjectKey(storageUrl.pathname.replace(/^\/+/, ""));
278
347
  if (!bucketName || !key) throw new Error("Invalid Supabase storage URI");
279
348
  return {
280
349
  bucketName,
@@ -286,6 +355,11 @@ const supabaseEdgeFunctionStorage = (0, _hot_updater_plugin_core.createRuntimeSt
286
355
  supportedProtocol: "supabase-storage",
287
356
  factory: (config) => {
288
357
  const supabase = (0, _supabase_supabase_js.createClient)(config.supabaseUrl, config.supabaseServiceRoleKey);
358
+ const resolveSignedUrl = createSupabaseSignedUrlBatcher({
359
+ createSignedUrls: (bucketName, keys, expiresIn) => supabase.storage.from(bucketName).createSignedUrls(keys, expiresIn),
360
+ expiresIn: config.signedUrlExpiresIn ?? 3600,
361
+ formatObjectPath: (bucketName, key) => `${bucketName}/${key}`
362
+ });
289
363
  return {
290
364
  async readText(storageUri) {
291
365
  const { bucketName, key } = parseSupabaseStorageUri(storageUri);
@@ -299,24 +373,24 @@ const supabaseEdgeFunctionStorage = (0, _hot_updater_plugin_core.createRuntimeSt
299
373
  },
300
374
  async getDownloadUrl(storageUri) {
301
375
  const { bucketName, key } = parseSupabaseStorageUri(storageUri);
302
- const bucket = supabase.storage.from(bucketName);
303
- const expiresIn = config.signedUrlExpiresIn ?? 3600;
304
- let data = null;
305
- let error = null;
306
- try {
307
- const response = await bucket.createSignedUrl(key, expiresIn);
308
- data = response.data;
309
- error = response.error;
310
- } catch (thrownError) {
311
- error = thrownError;
312
- }
313
- if (!error && data?.signedUrl) return { fileUrl: data.signedUrl };
314
- throw new Error(`Failed to generate download URL for "${bucketName}/${key}": ${getErrorMessage(error ?? /* @__PURE__ */ new Error("missing signed URL"))}`);
376
+ return { fileUrl: await resolveSignedUrl(bucketName, key) };
315
377
  }
316
378
  };
317
379
  }
318
380
  });
319
381
  //#endregion
382
+ Object.defineProperty(exports, "createSupabaseSignedUrlBatcher", {
383
+ enumerable: true,
384
+ get: function() {
385
+ return createSupabaseSignedUrlBatcher;
386
+ }
387
+ });
388
+ Object.defineProperty(exports, "decodeStorageObjectKey", {
389
+ enumerable: true,
390
+ get: function() {
391
+ return decodeStorageObjectKey;
392
+ }
393
+ });
320
394
  Object.defineProperty(exports, "resolveSupabaseServiceRoleKey", {
321
395
  enumerable: true,
322
396
  get: function() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/supabase",
3
3
  "type": "module",
4
- "version": "0.35.12",
4
+ "version": "0.36.1",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -55,10 +55,10 @@
55
55
  "@supabase/supabase-js": "2.76.1",
56
56
  "hono": "4.12.9",
57
57
  "uuidv7": "^1.0.2",
58
- "@hot-updater/core": "0.35.12",
59
- "@hot-updater/plugin-core": "0.35.12",
60
- "@hot-updater/cli-tools": "0.35.12",
61
- "@hot-updater/server": "0.35.12"
58
+ "@hot-updater/core": "0.36.1",
59
+ "@hot-updater/plugin-core": "0.36.1",
60
+ "@hot-updater/cli-tools": "0.36.1",
61
+ "@hot-updater/server": "0.36.1"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@electric-sql/pglite": "0.4.1",
@@ -68,10 +68,10 @@
68
68
  "execa": "9.5.2",
69
69
  "@types/node": "^20",
70
70
  "mime": "^4.0.4",
71
- "@hot-updater/js": "0.35.12",
72
- "@hot-updater/mock": "0.35.12",
73
- "@hot-updater/test-utils": "0.35.12",
74
- "@hot-updater/postgres": "0.35.12"
71
+ "@hot-updater/js": "0.36.1",
72
+ "@hot-updater/test-utils": "0.36.1",
73
+ "@hot-updater/postgres": "0.36.1",
74
+ "@hot-updater/mock": "0.36.1"
75
75
  },
76
76
  "scripts": {
77
77
  "build": "tsdown",