@hot-updater/supabase 0.30.12 → 0.31.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-Dd8ytWP1.cjs");
2
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-BZC0Z0XP.cjs");
3
3
  exports.supabaseEdgeFunctionDatabase = require_supabaseEdgeFunctionStorage.supabaseEdgeFunctionDatabase;
4
4
  exports.supabaseEdgeFunctionStorage = require_supabaseEdgeFunctionStorage.supabaseEdgeFunctionStorage;
package/dist/edge.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CSPi2UB8.cjs";
1
+ import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CU396KO3.cjs";
2
2
  export { supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage };
package/dist/edge.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-ByPGforO.mjs";
1
+ import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-BRxGvt-r.mjs";
2
2
  export { supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage };
package/dist/edge.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as supabaseEdgeFunctionDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-DnnViEfo.mjs";
1
+ import { n as supabaseEdgeFunctionDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-BKU_mLzA.mjs";
2
2
  export { supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage };
@@ -6258,7 +6258,8 @@ const supabaseApi = (supabaseUrl, supabaseAnonKey) => {
6258
6258
  const require$1 = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href);
6259
6259
  const EDGE_VENDOR_DIR = "_hot-updater";
6260
6260
  const WORKSPACE_PACKAGE_PREFIX = "@hot-updater/";
6261
- const IMPORT_SPECIFIER_PATTERN = /from\s+["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)/g;
6261
+ const STATIC_IMPORT_SPECIFIER_PATTERN = /^\s*(?:import|export)\s+(?:type\s+)?(?:[^"'`]+?\s+from\s+)?["']([^"']+)["'];?/gm;
6262
+ const DYNAMIC_IMPORT_SPECIFIER_PATTERN = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
6262
6263
  const getConfigScaffold = (build) => {
6263
6264
  return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setStorage({
6264
6265
  imports: [{
@@ -6291,7 +6292,6 @@ function App() {
6291
6292
  export default HotUpdater.wrap({
6292
6293
  baseURL: "%%source%%",
6293
6294
  updateStrategy: "appVersion", // or "fingerprint"
6294
- updateMode: "auto",
6295
6295
  })(App);`;
6296
6296
  const SUPABASE_CONFIG_TEMPLATE = `
6297
6297
  project_id = "%%projectId%%"
@@ -6339,8 +6339,9 @@ const collectBareImportSpecifiers = async (entryPath) => {
6339
6339
  if (!currentFile || visitedFiles.has(currentFile)) continue;
6340
6340
  visitedFiles.add(currentFile);
6341
6341
  const source = await fs_promises.default.readFile(currentFile, "utf8");
6342
- for (const match of source.matchAll(IMPORT_SPECIFIER_PATTERN)) {
6343
- const specifier = match[1] ?? match[2];
6342
+ const matches = [...source.matchAll(STATIC_IMPORT_SPECIFIER_PATTERN), ...source.matchAll(DYNAMIC_IMPORT_SPECIFIER_PATTERN)];
6343
+ for (const match of matches) {
6344
+ const specifier = match[1];
6344
6345
  if (!specifier) continue;
6345
6346
  if (specifier.startsWith("./") || specifier.startsWith("../")) {
6346
6347
  const resolvedPath = await resolveLocalModulePath(currentFile, specifier);
@@ -6253,7 +6253,8 @@ const supabaseApi = (supabaseUrl, supabaseAnonKey) => {
6253
6253
  const require$1 = createRequire(import.meta.url);
6254
6254
  const EDGE_VENDOR_DIR = "_hot-updater";
6255
6255
  const WORKSPACE_PACKAGE_PREFIX = "@hot-updater/";
6256
- const IMPORT_SPECIFIER_PATTERN = /from\s+["']([^"']+)["']|import\s*\(\s*["']([^"']+)["']\s*\)/g;
6256
+ const STATIC_IMPORT_SPECIFIER_PATTERN = /^\s*(?:import|export)\s+(?:type\s+)?(?:[^"'`]+?\s+from\s+)?["']([^"']+)["'];?/gm;
6257
+ const DYNAMIC_IMPORT_SPECIFIER_PATTERN = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
6257
6258
  const getConfigScaffold = (build) => {
6258
6259
  return createHotUpdaterConfigScaffoldFromBuilder(new ConfigBuilder().setBuildType(build).setStorage({
6259
6260
  imports: [{
@@ -6286,7 +6287,6 @@ function App() {
6286
6287
  export default HotUpdater.wrap({
6287
6288
  baseURL: "%%source%%",
6288
6289
  updateStrategy: "appVersion", // or "fingerprint"
6289
- updateMode: "auto",
6290
6290
  })(App);`;
6291
6291
  const SUPABASE_CONFIG_TEMPLATE = `
6292
6292
  project_id = "%%projectId%%"
@@ -6334,8 +6334,9 @@ const collectBareImportSpecifiers = async (entryPath) => {
6334
6334
  if (!currentFile || visitedFiles.has(currentFile)) continue;
6335
6335
  visitedFiles.add(currentFile);
6336
6336
  const source = await fs.readFile(currentFile, "utf8");
6337
- for (const match of source.matchAll(IMPORT_SPECIFIER_PATTERN)) {
6338
- const specifier = match[1] ?? match[2];
6337
+ const matches = [...source.matchAll(STATIC_IMPORT_SPECIFIER_PATTERN), ...source.matchAll(DYNAMIC_IMPORT_SPECIFIER_PATTERN)];
6338
+ for (const match of matches) {
6339
+ const specifier = match[1];
6339
6340
  if (!specifier) continue;
6340
6341
  if (specifier.startsWith("./") || specifier.startsWith("../")) {
6341
6342
  const resolvedPath = await resolveLocalModulePath(currentFile, specifier);
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-Dd8ytWP1.cjs");
24
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-BZC0Z0XP.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");
@@ -29,44 +29,68 @@ fs_promises = __toESM(fs_promises);
29
29
  let path = require("path");
30
30
  path = __toESM(path);
31
31
  //#region src/supabaseStorage.ts
32
- const supabaseStorage = (0, _hot_updater_plugin_core.createStoragePlugin)({
32
+ const supabaseStorage = (0, _hot_updater_plugin_core.createUniversalStoragePlugin)({
33
33
  name: "supabaseStorage",
34
34
  supportedProtocol: "supabase-storage",
35
35
  factory: (config) => {
36
36
  const bucket = (0, _supabase_supabase_js.createClient)(config.supabaseUrl, config.supabaseAnonKey).storage.from(config.bucketName);
37
37
  const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
38
38
  return {
39
- async delete(storageUri) {
40
- const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
41
- if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
42
- const { error } = await bucket.remove([key]);
43
- if (error) {
44
- if (error.message?.includes("not found")) throw new Error(`Bundle not found`);
45
- throw new Error(`Failed to delete bundle: ${error.message}`);
39
+ node: {
40
+ async delete(storageUri) {
41
+ const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
42
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
43
+ const { error } = await bucket.remove([key]);
44
+ if (error) {
45
+ if (error.message?.includes("not found")) throw new Error(`Bundle not found`);
46
+ throw new Error(`Failed to delete bundle: ${error.message}`);
47
+ }
48
+ },
49
+ async upload(key, filePath) {
50
+ const Body = await fs_promises.default.readFile(filePath);
51
+ const ContentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
52
+ const Key = getStorageKey(key, path.default.basename(filePath));
53
+ const upload = await bucket.upload(Key, Body, {
54
+ contentType: ContentType,
55
+ cacheControl: "max-age=31536000",
56
+ headers: {}
57
+ });
58
+ if (upload.error) throw upload.error;
59
+ return { storageUri: `supabase-storage://${upload.data.fullPath}` };
60
+ },
61
+ async downloadFile(storageUri, filePath) {
62
+ const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
63
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
64
+ const { data, error } = await bucket.download(key);
65
+ if (error) throw new Error(`Failed to download bundle: ${error.message}`);
66
+ if (!data) throw new Error("Failed to download bundle");
67
+ await fs_promises.default.mkdir(path.default.dirname(filePath), { recursive: true });
68
+ await fs_promises.default.writeFile(filePath, new Uint8Array(await data.arrayBuffer()));
46
69
  }
47
70
  },
48
- async upload(key, filePath) {
49
- const Body = await fs_promises.default.readFile(filePath);
50
- const ContentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
51
- const Key = getStorageKey(key, path.default.basename(filePath));
52
- const upload = await bucket.upload(Key, Body, {
53
- contentType: ContentType,
54
- cacheControl: "max-age=31536000",
55
- headers: {}
56
- });
57
- if (upload.error) throw upload.error;
58
- return { storageUri: `supabase-storage://${upload.data.fullPath}` };
59
- },
60
- async getDownloadUrl(storageUri) {
61
- const u = new URL(storageUri);
62
- if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
63
- let key = `${u.host}${u.pathname}`.replace(/^\//, "");
64
- if (!key) throw new Error("Invalid Supabase storage URI: missing key");
65
- if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
66
- const { data, error } = await bucket.createSignedUrl(key, 3600);
67
- if (error) throw new Error(`Failed to generate download URL: ${error.message}`);
68
- if (!data?.signedUrl) throw new Error("Failed to generate download URL");
69
- return { fileUrl: data.signedUrl };
71
+ runtime: {
72
+ async readText(storageUri) {
73
+ const { key, bucket: bucketName } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "supabase-storage");
74
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
75
+ const { data, error } = await bucket.download(key);
76
+ if (error) {
77
+ if (error.message?.includes("not found")) return null;
78
+ throw new Error(`Failed to read storage text: ${error.message}`);
79
+ }
80
+ if (!data) return null;
81
+ return data.text();
82
+ },
83
+ async getDownloadUrl(storageUri) {
84
+ const u = new URL(storageUri);
85
+ if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
86
+ let key = `${u.host}${u.pathname}`.replace(/^\//, "");
87
+ if (!key) throw new Error("Invalid Supabase storage URI: missing key");
88
+ if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
89
+ const { data, error } = await bucket.createSignedUrl(key, 3600);
90
+ if (error) throw new Error(`Failed to generate download URL: ${error.message}`);
91
+ if (!data?.signedUrl) throw new Error("Failed to generate download URL");
92
+ return { fileUrl: data.signedUrl };
93
+ }
70
94
  }
71
95
  };
72
96
  }
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage, r as SupabaseEdgeFunctionDatabaseConfig, t as SupabaseEdgeFunctionStorageConfig } from "./supabaseEdgeFunctionStorage-CSPi2UB8.cjs";
1
+ import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage, r as SupabaseEdgeFunctionDatabaseConfig, t as SupabaseEdgeFunctionStorageConfig } from "./supabaseEdgeFunctionStorage-CU396KO3.cjs";
2
2
  import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
3
3
 
4
4
  //#region src/supabaseDatabase.d.ts
@@ -18,6 +18,6 @@ interface SupabaseStorageConfig {
18
18
  */
19
19
  basePath?: string;
20
20
  }
21
- declare const supabaseStorage: (config: SupabaseStorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
21
+ declare const supabaseStorage: (config: SupabaseStorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.UniversalStoragePlugin<unknown>;
22
22
  //#endregion
23
23
  export { SupabaseDatabaseConfig, SupabaseEdgeFunctionDatabaseConfig, SupabaseEdgeFunctionStorageConfig, SupabaseStorageConfig, supabaseDatabase, supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage, supabaseStorage };
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage, r as SupabaseEdgeFunctionDatabaseConfig, t as SupabaseEdgeFunctionStorageConfig } from "./supabaseEdgeFunctionStorage-ByPGforO.mjs";
1
+ import { i as supabaseEdgeFunctionDatabase, n as supabaseEdgeFunctionStorage, r as SupabaseEdgeFunctionDatabaseConfig, t as SupabaseEdgeFunctionStorageConfig } from "./supabaseEdgeFunctionStorage-BRxGvt-r.mjs";
2
2
  import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
3
3
 
4
4
  //#region src/supabaseDatabase.d.ts
@@ -18,6 +18,6 @@ interface SupabaseStorageConfig {
18
18
  */
19
19
  basePath?: string;
20
20
  }
21
- declare const supabaseStorage: (config: SupabaseStorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.StoragePlugin<unknown>;
21
+ declare const supabaseStorage: (config: SupabaseStorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.UniversalStoragePlugin<unknown>;
22
22
  //#endregion
23
23
  export { SupabaseDatabaseConfig, SupabaseEdgeFunctionDatabaseConfig, SupabaseEdgeFunctionStorageConfig, SupabaseStorageConfig, supabaseDatabase, supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage, supabaseStorage };
package/dist/index.mjs CHANGED
@@ -1,47 +1,71 @@
1
- import { n as supabaseEdgeFunctionDatabase, r as supabaseDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-DnnViEfo.mjs";
2
- import { createStorageKeyBuilder, createStoragePlugin, getContentType, parseStorageUri } from "@hot-updater/plugin-core";
1
+ import { n as supabaseEdgeFunctionDatabase, r as supabaseDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-BKU_mLzA.mjs";
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";
5
5
  import path from "path";
6
6
  //#region src/supabaseStorage.ts
7
- const supabaseStorage = createStoragePlugin({
7
+ const supabaseStorage = createUniversalStoragePlugin({
8
8
  name: "supabaseStorage",
9
9
  supportedProtocol: "supabase-storage",
10
10
  factory: (config) => {
11
11
  const bucket = createClient(config.supabaseUrl, config.supabaseAnonKey).storage.from(config.bucketName);
12
12
  const getStorageKey = createStorageKeyBuilder(config.basePath);
13
13
  return {
14
- async delete(storageUri) {
15
- const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
16
- if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
17
- const { error } = await bucket.remove([key]);
18
- if (error) {
19
- if (error.message?.includes("not found")) throw new Error(`Bundle not found`);
20
- throw new Error(`Failed to delete bundle: ${error.message}`);
14
+ node: {
15
+ async delete(storageUri) {
16
+ const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
17
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
18
+ const { error } = await bucket.remove([key]);
19
+ if (error) {
20
+ if (error.message?.includes("not found")) throw new Error(`Bundle not found`);
21
+ throw new Error(`Failed to delete bundle: ${error.message}`);
22
+ }
23
+ },
24
+ async upload(key, filePath) {
25
+ const Body = await fs.readFile(filePath);
26
+ const ContentType = getContentType(filePath);
27
+ const Key = getStorageKey(key, path.basename(filePath));
28
+ const upload = await bucket.upload(Key, Body, {
29
+ contentType: ContentType,
30
+ cacheControl: "max-age=31536000",
31
+ headers: {}
32
+ });
33
+ if (upload.error) throw upload.error;
34
+ return { storageUri: `supabase-storage://${upload.data.fullPath}` };
35
+ },
36
+ async downloadFile(storageUri, filePath) {
37
+ const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
38
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
39
+ const { data, error } = await bucket.download(key);
40
+ if (error) throw new Error(`Failed to download bundle: ${error.message}`);
41
+ if (!data) throw new Error("Failed to download bundle");
42
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
43
+ await fs.writeFile(filePath, new Uint8Array(await data.arrayBuffer()));
21
44
  }
22
45
  },
23
- async upload(key, filePath) {
24
- const Body = await fs.readFile(filePath);
25
- const ContentType = getContentType(filePath);
26
- const Key = getStorageKey(key, path.basename(filePath));
27
- const upload = await bucket.upload(Key, Body, {
28
- contentType: ContentType,
29
- cacheControl: "max-age=31536000",
30
- headers: {}
31
- });
32
- if (upload.error) throw upload.error;
33
- return { storageUri: `supabase-storage://${upload.data.fullPath}` };
34
- },
35
- async getDownloadUrl(storageUri) {
36
- const u = new URL(storageUri);
37
- if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
38
- let key = `${u.host}${u.pathname}`.replace(/^\//, "");
39
- if (!key) throw new Error("Invalid Supabase storage URI: missing key");
40
- if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
41
- const { data, error } = await bucket.createSignedUrl(key, 3600);
42
- if (error) throw new Error(`Failed to generate download URL: ${error.message}`);
43
- if (!data?.signedUrl) throw new Error("Failed to generate download URL");
44
- return { fileUrl: data.signedUrl };
46
+ runtime: {
47
+ async readText(storageUri) {
48
+ const { key, bucket: bucketName } = parseStorageUri(storageUri, "supabase-storage");
49
+ if (bucketName !== config.bucketName) throw new Error(`Bucket name mismatch: expected "${config.bucketName}", but found "${bucketName}".`);
50
+ const { data, error } = await bucket.download(key);
51
+ if (error) {
52
+ if (error.message?.includes("not found")) return null;
53
+ throw new Error(`Failed to read storage text: ${error.message}`);
54
+ }
55
+ if (!data) return null;
56
+ return data.text();
57
+ },
58
+ async getDownloadUrl(storageUri) {
59
+ const u = new URL(storageUri);
60
+ if (u.protocol.replace(":", "") !== "supabase-storage") throw new Error("Invalid Supabase storage URI protocol");
61
+ let key = `${u.host}${u.pathname}`.replace(/^\//, "");
62
+ if (!key) throw new Error("Invalid Supabase storage URI: missing key");
63
+ if (key.startsWith(`${config.bucketName}/`)) key = key.substring(`${config.bucketName}/`.length);
64
+ const { data, error } = await bucket.createSignedUrl(key, 3600);
65
+ if (error) throw new Error(`Failed to generate download URL: ${error.message}`);
66
+ if (!data?.signedUrl) throw new Error("Failed to generate download URL");
67
+ return { fileUrl: data.signedUrl };
68
+ }
45
69
  }
46
70
  };
47
71
  }
@@ -0,0 +1,274 @@
1
+ import { DEFAULT_ROLLOUT_COHORT_COUNT, getAssetBaseStorageUri, getBundlePatches, getManifestFileHash, getManifestStorageUri, stripBundleArtifactMetadata } from "@hot-updater/core";
2
+ import { calculatePagination, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createRuntimeStoragePlugin } from "@hot-updater/plugin-core";
3
+ import { createClient } from "@supabase/supabase-js";
4
+ //#region src/supabaseDatabase.ts
5
+ const normalizeMetadata = (value) => {
6
+ if (!value) return {};
7
+ if (typeof value === "string") try {
8
+ return normalizeMetadata(JSON.parse(value));
9
+ } catch {
10
+ return {};
11
+ }
12
+ if (typeof value === "object" && !Array.isArray(value)) return value;
13
+ return {};
14
+ };
15
+ const BUNDLE_SELECT_COLUMNS = "id, channel, enabled, platform, should_force_update, file_hash, git_commit_hash, message, fingerprint_hash, target_app_version, storage_uri, metadata, manifest_storage_uri, manifest_file_hash, asset_base_storage_uri, rollout_cohort_count, target_cohorts";
16
+ const createSupabaseError = (error) => {
17
+ if (error instanceof Error) return error;
18
+ if (error && typeof error === "object") {
19
+ const properties = {};
20
+ let target = error;
21
+ while (target && target !== Object.prototype) {
22
+ for (const key of Object.getOwnPropertyNames(target)) properties[key] = error[key];
23
+ target = Object.getPrototypeOf(target);
24
+ }
25
+ return new Error(JSON.stringify({
26
+ name: error.constructor.name,
27
+ ...properties
28
+ }));
29
+ }
30
+ try {
31
+ return new Error(JSON.stringify(error));
32
+ } catch {
33
+ return new Error(String(error));
34
+ }
35
+ };
36
+ const buildBundlePatchId = (bundleId, baseBundleId) => `${bundleId}:${baseBundleId}`;
37
+ const mapRowToBundle = (row, patchRows = []) => {
38
+ const rawMetadata = normalizeMetadata(row.metadata);
39
+ const patches = patchRows.slice().sort((left, right) => left.order_index - right.order_index || left.base_bundle_id.localeCompare(right.base_bundle_id)).map((patch) => ({
40
+ baseBundleId: patch.base_bundle_id,
41
+ baseFileHash: patch.base_file_hash,
42
+ patchFileHash: patch.patch_file_hash,
43
+ patchStorageUri: patch.patch_storage_uri
44
+ }));
45
+ const primaryPatch = patches[0] ?? null;
46
+ return {
47
+ channel: row.channel,
48
+ enabled: Boolean(row.enabled),
49
+ shouldForceUpdate: Boolean(row.should_force_update),
50
+ fileHash: row.file_hash,
51
+ gitCommitHash: row.git_commit_hash,
52
+ id: row.id,
53
+ message: row.message,
54
+ platform: row.platform,
55
+ targetAppVersion: row.target_app_version,
56
+ fingerprintHash: row.fingerprint_hash,
57
+ storageUri: row.storage_uri,
58
+ metadata: stripBundleArtifactMetadata(rawMetadata),
59
+ manifestStorageUri: row.manifest_storage_uri ?? null,
60
+ manifestFileHash: row.manifest_file_hash ?? null,
61
+ assetBaseStorageUri: row.asset_base_storage_uri ?? null,
62
+ patches,
63
+ patchBaseBundleId: primaryPatch?.baseBundleId ?? null,
64
+ patchBaseFileHash: primaryPatch?.baseFileHash ?? null,
65
+ patchFileHash: primaryPatch?.patchFileHash ?? null,
66
+ patchStorageUri: primaryPatch?.patchStorageUri ?? null,
67
+ rolloutCohortCount: row.rollout_cohort_count ?? DEFAULT_ROLLOUT_COHORT_COUNT,
68
+ targetCohorts: row.target_cohorts ?? null
69
+ };
70
+ };
71
+ const bundleToRow = (bundle) => ({
72
+ id: bundle.id,
73
+ channel: bundle.channel,
74
+ enabled: bundle.enabled,
75
+ should_force_update: bundle.shouldForceUpdate,
76
+ file_hash: bundle.fileHash,
77
+ git_commit_hash: bundle.gitCommitHash,
78
+ message: bundle.message,
79
+ platform: bundle.platform,
80
+ target_app_version: bundle.targetAppVersion,
81
+ fingerprint_hash: bundle.fingerprintHash,
82
+ storage_uri: bundle.storageUri,
83
+ metadata: stripBundleArtifactMetadata(bundle.metadata) ?? {},
84
+ manifest_storage_uri: getManifestStorageUri(bundle),
85
+ manifest_file_hash: getManifestFileHash(bundle),
86
+ asset_base_storage_uri: getAssetBaseStorageUri(bundle),
87
+ rollout_cohort_count: bundle.rolloutCohortCount ?? DEFAULT_ROLLOUT_COHORT_COUNT,
88
+ target_cohorts: bundle.targetCohorts ?? null
89
+ });
90
+ const bundleToPatchRows = (bundle) => getBundlePatches(bundle).map((patch, index) => ({
91
+ id: buildBundlePatchId(bundle.id, patch.baseBundleId),
92
+ bundle_id: bundle.id,
93
+ base_bundle_id: patch.baseBundleId,
94
+ base_file_hash: patch.baseFileHash,
95
+ patch_file_hash: patch.patchFileHash,
96
+ patch_storage_uri: patch.patchStorageUri,
97
+ order_index: index
98
+ }));
99
+ const supabaseDatabase = createDatabasePlugin({
100
+ name: "supabaseDatabase",
101
+ factory: (config) => {
102
+ const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey);
103
+ const fetchPatchMap = async (bundleIds) => {
104
+ const patchMap = /* @__PURE__ */ new Map();
105
+ if (bundleIds.length === 0) return patchMap;
106
+ const { data, error } = await supabase.from("bundle_patches").select("*").in("bundle_id", bundleIds).order("order_index", { ascending: true });
107
+ if (error) throw createSupabaseError(error);
108
+ for (const row of data ?? []) {
109
+ const current = patchMap.get(row.bundle_id) ?? [];
110
+ current.push(row);
111
+ patchMap.set(row.bundle_id, current);
112
+ }
113
+ return patchMap;
114
+ };
115
+ const mapRowsToBundles = async (rows) => {
116
+ const patchMap = await fetchPatchMap(rows.map((row) => row.id));
117
+ return rows.map((row) => mapRowToBundle(row, patchMap.get(row.id)));
118
+ };
119
+ return {
120
+ getUpdateInfo: createDatabasePluginGetUpdateInfo({
121
+ async listTargetAppVersions({ platform, channel, minBundleId }) {
122
+ const { data, error } = await supabase.from("bundles").select("target_app_version").eq("platform", platform).eq("channel", channel).eq("enabled", true).gte("id", minBundleId).not("target_app_version", "is", null);
123
+ if (error) throw createSupabaseError(error);
124
+ return Array.from(new Set((data ?? []).map((row) => row.target_app_version).filter((version) => Boolean(version))));
125
+ },
126
+ async getBundlesByTargetAppVersions({ platform, channel, minBundleId }, targetAppVersions) {
127
+ const { data, error } = await supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).eq("platform", platform).eq("channel", channel).eq("enabled", true).gte("id", minBundleId).in("target_app_version", targetAppVersions);
128
+ if (error) throw createSupabaseError(error);
129
+ return mapRowsToBundles(data ?? []);
130
+ },
131
+ async getBundlesByFingerprint({ platform, channel, minBundleId, fingerprintHash }) {
132
+ const { data, error } = await supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).eq("platform", platform).eq("channel", channel).eq("enabled", true).gte("id", minBundleId).eq("fingerprint_hash", fingerprintHash);
133
+ if (error) throw createSupabaseError(error);
134
+ return mapRowsToBundles(data ?? []);
135
+ }
136
+ }),
137
+ async getBundleById(bundleId) {
138
+ const [{ data, error }, patchMap] = await Promise.all([supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).eq("id", bundleId).single(), fetchPatchMap([bundleId])]);
139
+ if (!data || error) return null;
140
+ return mapRowToBundle(data, patchMap.get(bundleId) ?? []);
141
+ },
142
+ async getBundles(options) {
143
+ const { where, limit, orderBy } = options ?? {};
144
+ const offset = (options && "offset" in options ? options.offset : void 0) ?? 0;
145
+ if (where?.targetAppVersionIn && where.targetAppVersionIn.length === 0 || where?.id?.in && where.id.in.length === 0) return {
146
+ data: [],
147
+ pagination: calculatePagination(0, {
148
+ limit,
149
+ offset
150
+ })
151
+ };
152
+ let countQuery = supabase.from("bundles").select("*", {
153
+ count: "exact",
154
+ head: true
155
+ });
156
+ if (where?.channel) countQuery = countQuery.eq("channel", where.channel);
157
+ if (where?.platform) countQuery = countQuery.eq("platform", where.platform);
158
+ if (where?.enabled !== void 0) countQuery = countQuery.eq("enabled", where.enabled);
159
+ if (where?.fingerprintHash !== void 0) countQuery = where.fingerprintHash === null ? countQuery.is("fingerprint_hash", null) : countQuery.eq("fingerprint_hash", where.fingerprintHash);
160
+ if (where?.targetAppVersion !== void 0) countQuery = where.targetAppVersion === null ? countQuery.is("target_app_version", null) : countQuery.eq("target_app_version", where.targetAppVersion);
161
+ if (where?.targetAppVersionIn) countQuery = countQuery.in("target_app_version", where.targetAppVersionIn);
162
+ if (where?.targetAppVersionNotNull) countQuery = countQuery.not("target_app_version", "is", null);
163
+ if (where?.id?.eq) countQuery = countQuery.eq("id", where.id.eq);
164
+ if (where?.id?.gt) countQuery = countQuery.gt("id", where.id.gt);
165
+ if (where?.id?.gte) countQuery = countQuery.gte("id", where.id.gte);
166
+ if (where?.id?.lt) countQuery = countQuery.lt("id", where.id.lt);
167
+ if (where?.id?.lte) countQuery = countQuery.lte("id", where.id.lte);
168
+ if (where?.id?.in) countQuery = countQuery.in("id", where.id.in);
169
+ const { count: total = 0 } = await countQuery;
170
+ let query = supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).order("id", { ascending: orderBy?.direction === "asc" });
171
+ if (where?.channel) query = query.eq("channel", where.channel);
172
+ if (where?.platform) query = query.eq("platform", where.platform);
173
+ if (where?.enabled !== void 0) query = query.eq("enabled", where.enabled);
174
+ if (where?.fingerprintHash !== void 0) query = where.fingerprintHash === null ? query.is("fingerprint_hash", null) : query.eq("fingerprint_hash", where.fingerprintHash);
175
+ if (where?.targetAppVersion !== void 0) query = where.targetAppVersion === null ? query.is("target_app_version", null) : query.eq("target_app_version", where.targetAppVersion);
176
+ if (where?.targetAppVersionIn) query = query.in("target_app_version", where.targetAppVersionIn);
177
+ if (where?.targetAppVersionNotNull) query = query.not("target_app_version", "is", null);
178
+ if (where?.id?.eq) query = query.eq("id", where.id.eq);
179
+ if (where?.id?.gt) query = query.gt("id", where.id.gt);
180
+ if (where?.id?.gte) query = query.gte("id", where.id.gte);
181
+ if (where?.id?.lt) query = query.lt("id", where.id.lt);
182
+ if (where?.id?.lte) query = query.lte("id", where.id.lte);
183
+ if (where?.id?.in) query = query.in("id", where.id.in);
184
+ if (limit) query = query.limit(limit);
185
+ if (offset) query = query.range(offset, offset + (limit || 20) - 1);
186
+ const { data } = await query;
187
+ const patchMap = await fetchPatchMap((data ?? []).map((bundle) => bundle.id));
188
+ return {
189
+ data: (data ?? []).map((bundle) => mapRowToBundle(bundle, patchMap.get(bundle.id) ?? [])),
190
+ pagination: calculatePagination(total ?? 0, {
191
+ limit,
192
+ offset
193
+ })
194
+ };
195
+ },
196
+ async getChannels() {
197
+ const { data, error } = await supabase.rpc("get_channels");
198
+ if (error) throw error;
199
+ return data.map((bundle) => bundle.channel);
200
+ },
201
+ async commitBundle({ changedSets }) {
202
+ if (changedSets.length === 0) return;
203
+ for (const op of changedSets) if (op.operation === "delete") {
204
+ const { error: patchDeleteError } = await supabase.from("bundle_patches").delete().eq("bundle_id", op.data.id);
205
+ if (patchDeleteError) throw new Error(`Failed to delete bundle patches: ${patchDeleteError.message}`);
206
+ const { error: basePatchDeleteError } = await supabase.from("bundle_patches").delete().eq("base_bundle_id", op.data.id);
207
+ if (basePatchDeleteError) throw new Error(`Failed to delete base bundle patches: ${basePatchDeleteError.message}`);
208
+ const { error } = await supabase.from("bundles").delete().eq("id", op.data.id);
209
+ if (error) throw new Error(`Failed to delete bundle: ${error.message}`);
210
+ } else if (op.operation === "insert" || op.operation === "update") {
211
+ const bundle = op.data;
212
+ const patchRows = bundleToPatchRows(bundle);
213
+ const { error } = await supabase.from("bundles").upsert(bundleToRow(bundle), { onConflict: "id" });
214
+ if (error) throw error;
215
+ const { error: patchDeleteError } = await supabase.from("bundle_patches").delete().eq("bundle_id", bundle.id);
216
+ if (patchDeleteError) throw patchDeleteError;
217
+ if (patchRows.length > 0) {
218
+ const { error: patchInsertError } = await supabase.from("bundle_patches").upsert(patchRows, { onConflict: "id" });
219
+ if (patchInsertError) throw patchInsertError;
220
+ }
221
+ }
222
+ }
223
+ };
224
+ }
225
+ });
226
+ //#endregion
227
+ //#region src/supabaseEdgeFunctionDatabase.ts
228
+ const supabaseEdgeFunctionDatabase = (config, hooks) => {
229
+ return supabaseDatabase({
230
+ supabaseUrl: config.supabaseUrl,
231
+ supabaseAnonKey: config.supabaseServiceRoleKey
232
+ }, hooks);
233
+ };
234
+ //#endregion
235
+ //#region src/supabaseEdgeFunctionStorage.ts
236
+ const parseSupabaseStorageUri = (storageUri) => {
237
+ const storageUrl = new URL(storageUri);
238
+ if (storageUrl.protocol !== "supabase-storage:") throw new Error("Invalid Supabase storage URI protocol");
239
+ const bucketName = storageUrl.host;
240
+ const key = storageUrl.pathname.replace(/^\/+/, "");
241
+ if (!bucketName || !key) throw new Error("Invalid Supabase storage URI");
242
+ return {
243
+ bucketName,
244
+ key
245
+ };
246
+ };
247
+ const supabaseEdgeFunctionStorage = createRuntimeStoragePlugin({
248
+ name: "supabaseEdgeFunctionStorage",
249
+ supportedProtocol: "supabase-storage",
250
+ factory: (config) => {
251
+ const supabase = createClient(config.supabaseUrl, config.supabaseServiceRoleKey);
252
+ return {
253
+ async readText(storageUri) {
254
+ const { bucketName, key } = parseSupabaseStorageUri(storageUri);
255
+ const { data, error } = await supabase.storage.from(bucketName).download(key);
256
+ if (error) {
257
+ if (error.message?.includes("not found")) return null;
258
+ throw new Error(`Failed to read storage text: ${error.message}`);
259
+ }
260
+ if (!data) return null;
261
+ return data.text();
262
+ },
263
+ async getDownloadUrl(storageUri) {
264
+ const { bucketName, key } = parseSupabaseStorageUri(storageUri);
265
+ const { data, error } = await supabase.storage.from(bucketName).createSignedUrl(key, config.signedUrlExpiresIn ?? 3600);
266
+ if (error) throw new Error(`Failed to generate download URL: ${error.message}`);
267
+ if (!data?.signedUrl) throw new Error("Failed to generate download URL");
268
+ return { fileUrl: data.signedUrl };
269
+ }
270
+ };
271
+ }
272
+ });
273
+ //#endregion
274
+ export { supabaseEdgeFunctionDatabase as n, supabaseDatabase as r, supabaseEdgeFunctionStorage as t };
@@ -1,5 +1,5 @@
1
1
  import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
2
- import { DatabasePluginHooks, StoragePlugin } from "@hot-updater/plugin-core";
2
+ import { DatabasePluginHooks } from "@hot-updater/plugin-core";
3
3
 
4
4
  //#region src/supabaseEdgeFunctionDatabase.d.ts
5
5
  interface SupabaseEdgeFunctionDatabaseConfig {
@@ -14,6 +14,6 @@ interface SupabaseEdgeFunctionStorageConfig {
14
14
  supabaseServiceRoleKey: string;
15
15
  signedUrlExpiresIn?: number;
16
16
  }
17
- declare const supabaseEdgeFunctionStorage: (config: SupabaseEdgeFunctionStorageConfig) => () => StoragePlugin;
17
+ declare const supabaseEdgeFunctionStorage: (config: SupabaseEdgeFunctionStorageConfig, hooks?: _$_hot_updater_plugin_core0.StoragePluginHooks) => () => _$_hot_updater_plugin_core0.RuntimeStoragePlugin<unknown>;
18
18
  //#endregion
19
19
  export { supabaseEdgeFunctionDatabase as i, supabaseEdgeFunctionStorage as n, SupabaseEdgeFunctionDatabaseConfig as r, SupabaseEdgeFunctionStorageConfig as t };