@hot-updater/supabase 0.32.0 → 0.33.0

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-D933mGy9.cjs");
2
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DRxwDPRy.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-B4KN0khj.mjs";
1
+ import { n as supabaseEdgeFunctionDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CO70azPw.mjs";
2
2
  export { supabaseEdgeFunctionDatabase, supabaseEdgeFunctionStorage };
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-D933mGy9.cjs");
24
+ const require_supabaseEdgeFunctionStorage = require("./supabaseEdgeFunctionStorage-DRxwDPRy.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");
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-B4KN0khj.mjs";
1
+ import { i as resolveSupabaseServiceRoleKey, n as supabaseEdgeFunctionDatabase, r as supabaseDatabase, t as supabaseEdgeFunctionStorage } from "./supabaseEdgeFunctionStorage-CO70azPw.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";
@@ -1,14 +1,8 @@
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";
1
+ import { DEFAULT_ROLLOUT_COHORT_COUNT, NIL_UUID, getAssetBaseStorageUri, getBundlePatches, getManifestFileHash, getManifestStorageUri, stripBundleArtifactMetadata } from "@hot-updater/core";
2
+ import { calculatePagination, createDatabasePlugin, createRuntimeStoragePlugin, filterCompatibleAppVersions } from "@hot-updater/plugin-core";
3
3
  import { createClient } from "@supabase/supabase-js";
4
- //#region src/supabaseConfig.ts
5
- const resolveSupabaseServiceRoleKey = (config) => {
6
- const key = config.supabaseServiceRoleKey ?? config.supabaseAnonKey;
7
- if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
8
- return key;
9
- };
10
- //#endregion
11
- //#region src/supabaseDatabase.ts
4
+ //#region src/supabaseBundleMapper.ts
5
+ 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";
12
6
  const normalizeMetadata = (value) => {
13
7
  if (!value) return {};
14
8
  if (typeof value === "string") try {
@@ -19,27 +13,6 @@ const normalizeMetadata = (value) => {
19
13
  if (typeof value === "object" && !Array.isArray(value)) return value;
20
14
  return {};
21
15
  };
22
- 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";
23
- const createSupabaseError = (error) => {
24
- if (error instanceof Error) return error;
25
- if (error && typeof error === "object") {
26
- const properties = {};
27
- let target = error;
28
- while (target && target !== Object.prototype) {
29
- for (const key of Object.getOwnPropertyNames(target)) properties[key] = error[key];
30
- target = Object.getPrototypeOf(target);
31
- }
32
- return new Error(JSON.stringify({
33
- name: error.constructor.name,
34
- ...properties
35
- }));
36
- }
37
- try {
38
- return new Error(JSON.stringify(error));
39
- } catch {
40
- return new Error(String(error));
41
- }
42
- };
43
16
  const buildBundlePatchId = (bundleId, baseBundleId) => `${bundleId}:${baseBundleId}`;
44
17
  const mapRowToBundle = (row, patchRows = []) => {
45
18
  const rawMetadata = normalizeMetadata(row.metadata);
@@ -103,6 +76,43 @@ const bundleToPatchRows = (bundle) => getBundlePatches(bundle).map((patch, index
103
76
  patch_storage_uri: patch.patchStorageUri,
104
77
  order_index: index
105
78
  }));
79
+ //#endregion
80
+ //#region src/supabaseConfig.ts
81
+ const resolveSupabaseServiceRoleKey = (config) => {
82
+ const key = config.supabaseServiceRoleKey ?? config.supabaseAnonKey;
83
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
84
+ return key;
85
+ };
86
+ //#endregion
87
+ //#region src/supabaseDatabase.ts
88
+ const createSupabaseError = (error) => {
89
+ if (error instanceof Error) return error;
90
+ if (error && typeof error === "object") {
91
+ const properties = {};
92
+ let target = error;
93
+ while (target && target !== Object.prototype) {
94
+ for (const key of Object.getOwnPropertyNames(target)) properties[key] = error[key];
95
+ target = Object.getPrototypeOf(target);
96
+ }
97
+ return new Error(JSON.stringify({
98
+ name: error.constructor.name,
99
+ ...properties
100
+ }));
101
+ }
102
+ try {
103
+ return new Error(JSON.stringify(error));
104
+ } catch {
105
+ return new Error(String(error));
106
+ }
107
+ };
108
+ const mapUpdateInfoRow = (row) => ({
109
+ id: row.id,
110
+ shouldForceUpdate: row.should_force_update,
111
+ message: row.message,
112
+ status: row.status,
113
+ storageUri: row.storage_uri,
114
+ fileHash: row.file_hash
115
+ });
106
116
  const supabaseDatabase = createDatabasePlugin({
107
117
  name: "supabaseDatabase",
108
118
  factory: (config) => {
@@ -119,28 +129,42 @@ const supabaseDatabase = createDatabasePlugin({
119
129
  }
120
130
  return patchMap;
121
131
  };
122
- const mapRowsToBundles = async (rows) => {
123
- const patchMap = await fetchPatchMap(rows.map((row) => row.id));
124
- return rows.map((row) => mapRowToBundle(row, patchMap.get(row.id)));
125
- };
126
132
  return {
127
- getUpdateInfo: createDatabasePluginGetUpdateInfo({
128
- async listTargetAppVersions({ platform, channel, minBundleId }) {
129
- 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);
133
+ async getUpdateInfo(args) {
134
+ const channel = args.channel ?? "production";
135
+ const minBundleId = args.minBundleId ?? NIL_UUID;
136
+ if (args._updateStrategy === "appVersion") {
137
+ const { data: targetAppVersionRows, error: targetAppVersionError } = await supabase.rpc("get_target_app_version_list", {
138
+ app_platform: args.platform,
139
+ min_bundle_id: minBundleId
140
+ });
141
+ if (targetAppVersionError) throw createSupabaseError(targetAppVersionError);
142
+ const targetAppVersionList = filterCompatibleAppVersions((targetAppVersionRows ?? []).map((row) => row.target_app_version).filter((version) => Boolean(version)), args.appVersion);
143
+ const { data, error } = await supabase.rpc("get_update_info_by_app_version", {
144
+ app_platform: args.platform,
145
+ app_version: args.appVersion,
146
+ bundle_id: args.bundleId,
147
+ min_bundle_id: minBundleId,
148
+ target_channel: channel,
149
+ target_app_version_list: targetAppVersionList,
150
+ cohort: args.cohort ?? null
151
+ });
130
152
  if (error) throw createSupabaseError(error);
131
- return Array.from(new Set((data ?? []).map((row) => row.target_app_version).filter((version) => Boolean(version))));
132
- },
133
- async getBundlesByTargetAppVersions({ platform, channel, minBundleId }, targetAppVersions) {
134
- 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);
135
- if (error) throw createSupabaseError(error);
136
- return mapRowsToBundles(data ?? []);
137
- },
138
- async getBundlesByFingerprint({ platform, channel, minBundleId, fingerprintHash }) {
139
- 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);
140
- if (error) throw createSupabaseError(error);
141
- return mapRowsToBundles(data ?? []);
153
+ const updateInfo = data?.[0] ?? null;
154
+ return updateInfo ? mapUpdateInfoRow(updateInfo) : null;
142
155
  }
143
- }),
156
+ const { data, error } = await supabase.rpc("get_update_info_by_fingerprint_hash", {
157
+ app_platform: args.platform,
158
+ bundle_id: args.bundleId,
159
+ min_bundle_id: minBundleId,
160
+ target_channel: channel,
161
+ target_fingerprint_hash: args.fingerprintHash,
162
+ cohort: args.cohort ?? null
163
+ });
164
+ if (error) throw createSupabaseError(error);
165
+ const updateInfo = data?.[0] ?? null;
166
+ return updateInfo ? mapUpdateInfoRow(updateInfo) : null;
167
+ },
144
168
  async getBundleById(bundleId) {
145
169
  const [{ data, error }, patchMap] = await Promise.all([supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).eq("id", bundleId).single(), fetchPatchMap([bundleId])]);
146
170
  if (!data || error) return null;
@@ -2,14 +2,8 @@ require("./index.cjs");
2
2
  let _hot_updater_core = require("@hot-updater/core");
3
3
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
4
4
  let _supabase_supabase_js = require("@supabase/supabase-js");
5
- //#region src/supabaseConfig.ts
6
- const resolveSupabaseServiceRoleKey = (config) => {
7
- const key = config.supabaseServiceRoleKey ?? config.supabaseAnonKey;
8
- if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
9
- return key;
10
- };
11
- //#endregion
12
- //#region src/supabaseDatabase.ts
5
+ //#region src/supabaseBundleMapper.ts
6
+ 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";
13
7
  const normalizeMetadata = (value) => {
14
8
  if (!value) return {};
15
9
  if (typeof value === "string") try {
@@ -20,27 +14,6 @@ const normalizeMetadata = (value) => {
20
14
  if (typeof value === "object" && !Array.isArray(value)) return value;
21
15
  return {};
22
16
  };
23
- 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";
24
- const createSupabaseError = (error) => {
25
- if (error instanceof Error) return error;
26
- if (error && typeof error === "object") {
27
- const properties = {};
28
- let target = error;
29
- while (target && target !== Object.prototype) {
30
- for (const key of Object.getOwnPropertyNames(target)) properties[key] = error[key];
31
- target = Object.getPrototypeOf(target);
32
- }
33
- return new Error(JSON.stringify({
34
- name: error.constructor.name,
35
- ...properties
36
- }));
37
- }
38
- try {
39
- return new Error(JSON.stringify(error));
40
- } catch {
41
- return new Error(String(error));
42
- }
43
- };
44
17
  const buildBundlePatchId = (bundleId, baseBundleId) => `${bundleId}:${baseBundleId}`;
45
18
  const mapRowToBundle = (row, patchRows = []) => {
46
19
  const rawMetadata = normalizeMetadata(row.metadata);
@@ -104,6 +77,43 @@ const bundleToPatchRows = (bundle) => (0, _hot_updater_core.getBundlePatches)(bu
104
77
  patch_storage_uri: patch.patchStorageUri,
105
78
  order_index: index
106
79
  }));
80
+ //#endregion
81
+ //#region src/supabaseConfig.ts
82
+ const resolveSupabaseServiceRoleKey = (config) => {
83
+ const key = config.supabaseServiceRoleKey ?? config.supabaseAnonKey;
84
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
85
+ return key;
86
+ };
87
+ //#endregion
88
+ //#region src/supabaseDatabase.ts
89
+ const createSupabaseError = (error) => {
90
+ if (error instanceof Error) return error;
91
+ if (error && typeof error === "object") {
92
+ const properties = {};
93
+ let target = error;
94
+ while (target && target !== Object.prototype) {
95
+ for (const key of Object.getOwnPropertyNames(target)) properties[key] = error[key];
96
+ target = Object.getPrototypeOf(target);
97
+ }
98
+ return new Error(JSON.stringify({
99
+ name: error.constructor.name,
100
+ ...properties
101
+ }));
102
+ }
103
+ try {
104
+ return new Error(JSON.stringify(error));
105
+ } catch {
106
+ return new Error(String(error));
107
+ }
108
+ };
109
+ const mapUpdateInfoRow = (row) => ({
110
+ id: row.id,
111
+ shouldForceUpdate: row.should_force_update,
112
+ message: row.message,
113
+ status: row.status,
114
+ storageUri: row.storage_uri,
115
+ fileHash: row.file_hash
116
+ });
107
117
  const supabaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
108
118
  name: "supabaseDatabase",
109
119
  factory: (config) => {
@@ -120,28 +130,42 @@ const supabaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
120
130
  }
121
131
  return patchMap;
122
132
  };
123
- const mapRowsToBundles = async (rows) => {
124
- const patchMap = await fetchPatchMap(rows.map((row) => row.id));
125
- return rows.map((row) => mapRowToBundle(row, patchMap.get(row.id)));
126
- };
127
133
  return {
128
- getUpdateInfo: (0, _hot_updater_plugin_core.createDatabasePluginGetUpdateInfo)({
129
- async listTargetAppVersions({ platform, channel, minBundleId }) {
130
- 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);
134
+ async getUpdateInfo(args) {
135
+ const channel = args.channel ?? "production";
136
+ const minBundleId = args.minBundleId ?? _hot_updater_core.NIL_UUID;
137
+ if (args._updateStrategy === "appVersion") {
138
+ const { data: targetAppVersionRows, error: targetAppVersionError } = await supabase.rpc("get_target_app_version_list", {
139
+ app_platform: args.platform,
140
+ min_bundle_id: minBundleId
141
+ });
142
+ if (targetAppVersionError) throw createSupabaseError(targetAppVersionError);
143
+ const targetAppVersionList = (0, _hot_updater_plugin_core.filterCompatibleAppVersions)((targetAppVersionRows ?? []).map((row) => row.target_app_version).filter((version) => Boolean(version)), args.appVersion);
144
+ const { data, error } = await supabase.rpc("get_update_info_by_app_version", {
145
+ app_platform: args.platform,
146
+ app_version: args.appVersion,
147
+ bundle_id: args.bundleId,
148
+ min_bundle_id: minBundleId,
149
+ target_channel: channel,
150
+ target_app_version_list: targetAppVersionList,
151
+ cohort: args.cohort ?? null
152
+ });
131
153
  if (error) throw createSupabaseError(error);
132
- return Array.from(new Set((data ?? []).map((row) => row.target_app_version).filter((version) => Boolean(version))));
133
- },
134
- async getBundlesByTargetAppVersions({ platform, channel, minBundleId }, targetAppVersions) {
135
- 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);
136
- if (error) throw createSupabaseError(error);
137
- return mapRowsToBundles(data ?? []);
138
- },
139
- async getBundlesByFingerprint({ platform, channel, minBundleId, fingerprintHash }) {
140
- 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);
141
- if (error) throw createSupabaseError(error);
142
- return mapRowsToBundles(data ?? []);
154
+ const updateInfo = data?.[0] ?? null;
155
+ return updateInfo ? mapUpdateInfoRow(updateInfo) : null;
143
156
  }
144
- }),
157
+ const { data, error } = await supabase.rpc("get_update_info_by_fingerprint_hash", {
158
+ app_platform: args.platform,
159
+ bundle_id: args.bundleId,
160
+ min_bundle_id: minBundleId,
161
+ target_channel: channel,
162
+ target_fingerprint_hash: args.fingerprintHash,
163
+ cohort: args.cohort ?? null
164
+ });
165
+ if (error) throw createSupabaseError(error);
166
+ const updateInfo = data?.[0] ?? null;
167
+ return updateInfo ? mapUpdateInfoRow(updateInfo) : null;
168
+ },
145
169
  async getBundleById(bundleId) {
146
170
  const [{ data, error }, patchMap] = await Promise.all([supabase.from("bundles").select(BUNDLE_SELECT_COLUMNS).eq("id", bundleId).single(), fetchPatchMap([bundleId])]);
147
171
  if (!data || error) return null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/supabase",
3
3
  "type": "module",
4
- "version": "0.32.0",
4
+ "version": "0.33.0",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -47,10 +47,10 @@
47
47
  "@supabase/supabase-js": "2.76.1",
48
48
  "hono": "4.12.9",
49
49
  "uuidv7": "^1.0.2",
50
- "@hot-updater/core": "0.32.0",
51
- "@hot-updater/plugin-core": "0.32.0",
52
- "@hot-updater/cli-tools": "0.32.0",
53
- "@hot-updater/server": "0.32.0"
50
+ "@hot-updater/core": "0.33.0",
51
+ "@hot-updater/plugin-core": "0.33.0",
52
+ "@hot-updater/server": "0.33.0",
53
+ "@hot-updater/cli-tools": "0.33.0"
54
54
  },
55
55
  "devDependencies": {
56
56
  "@electric-sql/pglite": "0.2.17",
@@ -60,10 +60,10 @@
60
60
  "execa": "9.5.2",
61
61
  "@types/node": "^20",
62
62
  "mime": "^4.0.4",
63
- "@hot-updater/js": "0.32.0",
64
- "@hot-updater/mock": "0.32.0",
65
- "@hot-updater/test-utils": "0.32.0",
66
- "@hot-updater/postgres": "0.32.0"
63
+ "@hot-updater/js": "0.33.0",
64
+ "@hot-updater/mock": "0.33.0",
65
+ "@hot-updater/postgres": "0.33.0",
66
+ "@hot-updater/test-utils": "0.33.0"
67
67
  },
68
68
  "scripts": {
69
69
  "build": "tsdown",