@hot-updater/firebase 0.29.1 → 0.29.3

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.
@@ -1493,12 +1493,12 @@ function mergeBundleUpdate(baseBundle, patch) {
1493
1493
  */
1494
1494
  function createDatabasePlugin(options) {
1495
1495
  return (config, hooks) => {
1496
+ let cachedMethods = null;
1497
+ const getMethods = () => {
1498
+ if (!cachedMethods) cachedMethods = options.factory(config);
1499
+ return cachedMethods;
1500
+ };
1496
1501
  return () => {
1497
- let cachedMethods = null;
1498
- const getMethods = () => {
1499
- if (!cachedMethods) cachedMethods = options.factory(config);
1500
- return cachedMethods;
1501
- };
1502
1502
  const changedMap = /* @__PURE__ */ new Map();
1503
1503
  const markChanged = (operation, data) => {
1504
1504
  changedMap.set(data.id, {
@@ -1529,8 +1529,8 @@ function createDatabasePlugin(options) {
1529
1529
  const params = { changedSets: Array.from(changedMap.values()) };
1530
1530
  if (context === void 0) await methods.commitBundle(params);
1531
1531
  else await methods.commitBundle(params, context);
1532
- await hooks?.onDatabaseUpdated?.();
1533
1532
  changedMap.clear();
1533
+ await hooks?.onDatabaseUpdated?.();
1534
1534
  },
1535
1535
  async updateBundle(targetBundleId, newBundle, context) {
1536
1536
  const pendingChange = changedMap.get(targetBundleId);
@@ -1673,6 +1673,23 @@ const sortBundles = (bundles, orderBy) => {
1673
1673
  return direction === "asc" ? result : -result;
1674
1674
  });
1675
1675
  };
1676
+ const applyFirestoreQueryableFilters = (query, where) => {
1677
+ let nextQuery = query;
1678
+ if (where?.channel) nextQuery = nextQuery.where("channel", "==", where.channel);
1679
+ if (where?.platform) nextQuery = nextQuery.where("platform", "==", where.platform);
1680
+ if (where?.enabled !== void 0) nextQuery = nextQuery.where("enabled", "==", where.enabled);
1681
+ if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) nextQuery = nextQuery.where("fingerprint_hash", "==", where.fingerprintHash);
1682
+ if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) nextQuery = nextQuery.where("target_app_version", "==", where.targetAppVersion);
1683
+ if (where?.id?.eq) nextQuery = nextQuery.where("id", "==", where.id.eq);
1684
+ if (where?.id?.gt) nextQuery = nextQuery.where("id", ">", where.id.gt);
1685
+ if (where?.id?.gte) nextQuery = nextQuery.where("id", ">=", where.id.gte);
1686
+ if (where?.id?.lt) nextQuery = nextQuery.where("id", "<", where.id.lt);
1687
+ if (where?.id?.lte) nextQuery = nextQuery.where("id", "<=", where.id.lte);
1688
+ return nextQuery;
1689
+ };
1690
+ const requiresInMemoryFiltering = (where) => {
1691
+ return Boolean(where?.id?.in || where?.targetAppVersionIn || where?.targetAppVersionNotNull || where?.targetAppVersion === null || where?.fingerprintHash === null);
1692
+ };
1676
1693
  const convertToBundle = (firestoreData) => ({
1677
1694
  channel: firestoreData.channel,
1678
1695
  enabled: Boolean(firestoreData.enabled),
@@ -1692,7 +1709,6 @@ const convertToBundle = (firestoreData) => ({
1692
1709
  const firebaseDatabase = createDatabasePlugin({
1693
1710
  name: "firebaseDatabase",
1694
1711
  factory: (config) => {
1695
- let bundles = [];
1696
1712
  let app;
1697
1713
  try {
1698
1714
  app = firebase_admin.default.app();
@@ -1703,32 +1719,30 @@ const firebaseDatabase = createDatabasePlugin({
1703
1719
  const bundlesCollection = db.collection("bundles");
1704
1720
  return {
1705
1721
  async getBundleById(bundleId) {
1706
- const found = bundles.find((b) => b.id === bundleId);
1707
- if (found) return found;
1708
1722
  const bundleSnap = await bundlesCollection.doc(bundleId).get();
1709
1723
  if (!bundleSnap.exists) return null;
1710
1724
  return convertToBundle(bundleSnap.data());
1711
1725
  },
1712
1726
  async getBundles(options) {
1713
1727
  const { where, limit, offset, orderBy } = options;
1714
- let query = bundlesCollection;
1715
- if (where?.channel) query = query.where("channel", "==", where.channel);
1716
- if (where?.platform) query = query.where("platform", "==", where.platform);
1717
- if (where?.enabled !== void 0) query = query.where("enabled", "==", where.enabled);
1718
- if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) query = query.where("fingerprint_hash", "==", where.fingerprintHash);
1719
- if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) query = query.where("target_app_version", "==", where.targetAppVersion);
1720
- if (where?.id?.eq) query = query.where("id", "==", where.id.eq);
1721
- if (where?.id?.gt) query = query.where("id", ">", where.id.gt);
1722
- if (where?.id?.gte) query = query.where("id", ">=", where.id.gte);
1723
- if (where?.id?.lt) query = query.where("id", "<", where.id.lt);
1724
- if (where?.id?.lte) query = query.where("id", "<=", where.id.lte);
1728
+ let query = applyFirestoreQueryableFilters(bundlesCollection, where);
1725
1729
  query = query.orderBy("id", orderBy?.direction === "asc" ? "asc" : "desc");
1730
+ if (requiresInMemoryFiltering(where)) {
1731
+ const filteredBundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
1732
+ const total = filteredBundles.length;
1733
+ return {
1734
+ data: filteredBundles.slice(offset, offset + limit),
1735
+ pagination: calculatePagination(total, {
1736
+ limit,
1737
+ offset
1738
+ })
1739
+ };
1740
+ }
1726
1741
  const total = (await query.get()).size;
1727
1742
  if (offset > 0) query = query.offset(offset);
1728
1743
  if (limit) query = query.limit(limit);
1729
- bundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
1730
1744
  return {
1731
- data: bundles,
1745
+ data: sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())), orderBy),
1732
1746
  pagination: calculatePagination(total, {
1733
1747
  limit,
1734
1748
  offset
@@ -1748,7 +1762,6 @@ const firebaseDatabase = createDatabasePlugin({
1748
1762
  async commitBundle({ changedSets }) {
1749
1763
  if (changedSets.length === 0) return;
1750
1764
  let isTargetAppVersionChanged = false;
1751
- const deletedBundleIds = /* @__PURE__ */ new Set();
1752
1765
  await db.runTransaction(async (transaction) => {
1753
1766
  const bundlesSnapshot = await transaction.get(bundlesCollection);
1754
1767
  const targetVersionsSnapshot = await transaction.get(db.collection("target_app_versions"));
@@ -1779,7 +1792,6 @@ const firebaseDatabase = createDatabasePlugin({
1779
1792
  } else if (operation === "delete") {
1780
1793
  if (!bundlesMap[data.id]) throw new Error(`Bundle with id ${data.id} not found`);
1781
1794
  delete bundlesMap[data.id];
1782
- deletedBundleIds.add(data.id);
1783
1795
  isTargetAppVersionChanged = true;
1784
1796
  }
1785
1797
  }
@@ -1827,7 +1839,6 @@ const firebaseDatabase = createDatabasePlugin({
1827
1839
  }
1828
1840
  for (const channelDoc of channelsSnapshot.docs) if (!requiredChannels.has(channelDoc.id)) transaction.delete(channelDoc.ref);
1829
1841
  });
1830
- for (const bundleId of deletedBundleIds) bundles = bundles.filter((b) => b.id !== bundleId);
1831
1842
  }
1832
1843
  };
1833
1844
  }
package/dist/index.cjs CHANGED
@@ -54,6 +54,23 @@ const sortBundles = (bundles, orderBy) => {
54
54
  return direction === "asc" ? result : -result;
55
55
  });
56
56
  };
57
+ const applyFirestoreQueryableFilters = (query, where) => {
58
+ let nextQuery = query;
59
+ if (where?.channel) nextQuery = nextQuery.where("channel", "==", where.channel);
60
+ if (where?.platform) nextQuery = nextQuery.where("platform", "==", where.platform);
61
+ if (where?.enabled !== void 0) nextQuery = nextQuery.where("enabled", "==", where.enabled);
62
+ if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) nextQuery = nextQuery.where("fingerprint_hash", "==", where.fingerprintHash);
63
+ if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) nextQuery = nextQuery.where("target_app_version", "==", where.targetAppVersion);
64
+ if (where?.id?.eq) nextQuery = nextQuery.where("id", "==", where.id.eq);
65
+ if (where?.id?.gt) nextQuery = nextQuery.where("id", ">", where.id.gt);
66
+ if (where?.id?.gte) nextQuery = nextQuery.where("id", ">=", where.id.gte);
67
+ if (where?.id?.lt) nextQuery = nextQuery.where("id", "<", where.id.lt);
68
+ if (where?.id?.lte) nextQuery = nextQuery.where("id", "<=", where.id.lte);
69
+ return nextQuery;
70
+ };
71
+ const requiresInMemoryFiltering = (where) => {
72
+ return Boolean(where?.id?.in || where?.targetAppVersionIn || where?.targetAppVersionNotNull || where?.targetAppVersion === null || where?.fingerprintHash === null);
73
+ };
57
74
  const convertToBundle = (firestoreData) => ({
58
75
  channel: firestoreData.channel,
59
76
  enabled: Boolean(firestoreData.enabled),
@@ -73,7 +90,6 @@ const convertToBundle = (firestoreData) => ({
73
90
  const firebaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
74
91
  name: "firebaseDatabase",
75
92
  factory: (config) => {
76
- let bundles = [];
77
93
  let app;
78
94
  try {
79
95
  app = firebase_admin.default.app();
@@ -84,32 +100,30 @@ const firebaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
84
100
  const bundlesCollection = db.collection("bundles");
85
101
  return {
86
102
  async getBundleById(bundleId) {
87
- const found = bundles.find((b) => b.id === bundleId);
88
- if (found) return found;
89
103
  const bundleSnap = await bundlesCollection.doc(bundleId).get();
90
104
  if (!bundleSnap.exists) return null;
91
105
  return convertToBundle(bundleSnap.data());
92
106
  },
93
107
  async getBundles(options) {
94
108
  const { where, limit, offset, orderBy } = options;
95
- let query = bundlesCollection;
96
- if (where?.channel) query = query.where("channel", "==", where.channel);
97
- if (where?.platform) query = query.where("platform", "==", where.platform);
98
- if (where?.enabled !== void 0) query = query.where("enabled", "==", where.enabled);
99
- if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) query = query.where("fingerprint_hash", "==", where.fingerprintHash);
100
- if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) query = query.where("target_app_version", "==", where.targetAppVersion);
101
- if (where?.id?.eq) query = query.where("id", "==", where.id.eq);
102
- if (where?.id?.gt) query = query.where("id", ">", where.id.gt);
103
- if (where?.id?.gte) query = query.where("id", ">=", where.id.gte);
104
- if (where?.id?.lt) query = query.where("id", "<", where.id.lt);
105
- if (where?.id?.lte) query = query.where("id", "<=", where.id.lte);
109
+ let query = applyFirestoreQueryableFilters(bundlesCollection, where);
106
110
  query = query.orderBy("id", orderBy?.direction === "asc" ? "asc" : "desc");
111
+ if (requiresInMemoryFiltering(where)) {
112
+ const filteredBundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
113
+ const total = filteredBundles.length;
114
+ return {
115
+ data: filteredBundles.slice(offset, offset + limit),
116
+ pagination: (0, _hot_updater_plugin_core.calculatePagination)(total, {
117
+ limit,
118
+ offset
119
+ })
120
+ };
121
+ }
107
122
  const total = (await query.get()).size;
108
123
  if (offset > 0) query = query.offset(offset);
109
124
  if (limit) query = query.limit(limit);
110
- bundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
111
125
  return {
112
- data: bundles,
126
+ data: sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())), orderBy),
113
127
  pagination: (0, _hot_updater_plugin_core.calculatePagination)(total, {
114
128
  limit,
115
129
  offset
@@ -129,7 +143,6 @@ const firebaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
129
143
  async commitBundle({ changedSets }) {
130
144
  if (changedSets.length === 0) return;
131
145
  let isTargetAppVersionChanged = false;
132
- const deletedBundleIds = /* @__PURE__ */ new Set();
133
146
  await db.runTransaction(async (transaction) => {
134
147
  const bundlesSnapshot = await transaction.get(bundlesCollection);
135
148
  const targetVersionsSnapshot = await transaction.get(db.collection("target_app_versions"));
@@ -160,7 +173,6 @@ const firebaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
160
173
  } else if (operation === "delete") {
161
174
  if (!bundlesMap[data.id]) throw new Error(`Bundle with id ${data.id} not found`);
162
175
  delete bundlesMap[data.id];
163
- deletedBundleIds.add(data.id);
164
176
  isTargetAppVersionChanged = true;
165
177
  }
166
178
  }
@@ -208,7 +220,6 @@ const firebaseDatabase = (0, _hot_updater_plugin_core.createDatabasePlugin)({
208
220
  }
209
221
  for (const channelDoc of channelsSnapshot.docs) if (!requiredChannels.has(channelDoc.id)) transaction.delete(channelDoc.ref);
210
222
  });
211
- for (const bundleId of deletedBundleIds) bundles = bundles.filter((b) => b.id !== bundleId);
212
223
  }
213
224
  };
214
225
  }
package/dist/index.mjs CHANGED
@@ -28,6 +28,23 @@ const sortBundles = (bundles, orderBy) => {
28
28
  return direction === "asc" ? result : -result;
29
29
  });
30
30
  };
31
+ const applyFirestoreQueryableFilters = (query, where) => {
32
+ let nextQuery = query;
33
+ if (where?.channel) nextQuery = nextQuery.where("channel", "==", where.channel);
34
+ if (where?.platform) nextQuery = nextQuery.where("platform", "==", where.platform);
35
+ if (where?.enabled !== void 0) nextQuery = nextQuery.where("enabled", "==", where.enabled);
36
+ if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) nextQuery = nextQuery.where("fingerprint_hash", "==", where.fingerprintHash);
37
+ if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) nextQuery = nextQuery.where("target_app_version", "==", where.targetAppVersion);
38
+ if (where?.id?.eq) nextQuery = nextQuery.where("id", "==", where.id.eq);
39
+ if (where?.id?.gt) nextQuery = nextQuery.where("id", ">", where.id.gt);
40
+ if (where?.id?.gte) nextQuery = nextQuery.where("id", ">=", where.id.gte);
41
+ if (where?.id?.lt) nextQuery = nextQuery.where("id", "<", where.id.lt);
42
+ if (where?.id?.lte) nextQuery = nextQuery.where("id", "<=", where.id.lte);
43
+ return nextQuery;
44
+ };
45
+ const requiresInMemoryFiltering = (where) => {
46
+ return Boolean(where?.id?.in || where?.targetAppVersionIn || where?.targetAppVersionNotNull || where?.targetAppVersion === null || where?.fingerprintHash === null);
47
+ };
31
48
  const convertToBundle = (firestoreData) => ({
32
49
  channel: firestoreData.channel,
33
50
  enabled: Boolean(firestoreData.enabled),
@@ -47,7 +64,6 @@ const convertToBundle = (firestoreData) => ({
47
64
  const firebaseDatabase = createDatabasePlugin({
48
65
  name: "firebaseDatabase",
49
66
  factory: (config) => {
50
- let bundles = [];
51
67
  let app;
52
68
  try {
53
69
  app = admin.app();
@@ -58,32 +74,30 @@ const firebaseDatabase = createDatabasePlugin({
58
74
  const bundlesCollection = db.collection("bundles");
59
75
  return {
60
76
  async getBundleById(bundleId) {
61
- const found = bundles.find((b) => b.id === bundleId);
62
- if (found) return found;
63
77
  const bundleSnap = await bundlesCollection.doc(bundleId).get();
64
78
  if (!bundleSnap.exists) return null;
65
79
  return convertToBundle(bundleSnap.data());
66
80
  },
67
81
  async getBundles(options) {
68
82
  const { where, limit, offset, orderBy } = options;
69
- let query = bundlesCollection;
70
- if (where?.channel) query = query.where("channel", "==", where.channel);
71
- if (where?.platform) query = query.where("platform", "==", where.platform);
72
- if (where?.enabled !== void 0) query = query.where("enabled", "==", where.enabled);
73
- if (where?.fingerprintHash !== void 0 && where.fingerprintHash !== null) query = query.where("fingerprint_hash", "==", where.fingerprintHash);
74
- if (where?.targetAppVersion !== void 0 && where.targetAppVersion !== null) query = query.where("target_app_version", "==", where.targetAppVersion);
75
- if (where?.id?.eq) query = query.where("id", "==", where.id.eq);
76
- if (where?.id?.gt) query = query.where("id", ">", where.id.gt);
77
- if (where?.id?.gte) query = query.where("id", ">=", where.id.gte);
78
- if (where?.id?.lt) query = query.where("id", "<", where.id.lt);
79
- if (where?.id?.lte) query = query.where("id", "<=", where.id.lte);
83
+ let query = applyFirestoreQueryableFilters(bundlesCollection, where);
80
84
  query = query.orderBy("id", orderBy?.direction === "asc" ? "asc" : "desc");
85
+ if (requiresInMemoryFiltering(where)) {
86
+ const filteredBundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
87
+ const total = filteredBundles.length;
88
+ return {
89
+ data: filteredBundles.slice(offset, offset + limit),
90
+ pagination: calculatePagination(total, {
91
+ limit,
92
+ offset
93
+ })
94
+ };
95
+ }
81
96
  const total = (await query.get()).size;
82
97
  if (offset > 0) query = query.offset(offset);
83
98
  if (limit) query = query.limit(limit);
84
- bundles = sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())).filter((bundle) => bundleMatchesQueryWhere(bundle, where)), orderBy);
85
99
  return {
86
- data: bundles,
100
+ data: sortBundles((await query.get()).docs.map((doc) => convertToBundle(doc.data())), orderBy),
87
101
  pagination: calculatePagination(total, {
88
102
  limit,
89
103
  offset
@@ -103,7 +117,6 @@ const firebaseDatabase = createDatabasePlugin({
103
117
  async commitBundle({ changedSets }) {
104
118
  if (changedSets.length === 0) return;
105
119
  let isTargetAppVersionChanged = false;
106
- const deletedBundleIds = /* @__PURE__ */ new Set();
107
120
  await db.runTransaction(async (transaction) => {
108
121
  const bundlesSnapshot = await transaction.get(bundlesCollection);
109
122
  const targetVersionsSnapshot = await transaction.get(db.collection("target_app_versions"));
@@ -134,7 +147,6 @@ const firebaseDatabase = createDatabasePlugin({
134
147
  } else if (operation === "delete") {
135
148
  if (!bundlesMap[data.id]) throw new Error(`Bundle with id ${data.id} not found`);
136
149
  delete bundlesMap[data.id];
137
- deletedBundleIds.add(data.id);
138
150
  isTargetAppVersionChanged = true;
139
151
  }
140
152
  }
@@ -182,7 +194,6 @@ const firebaseDatabase = createDatabasePlugin({
182
194
  }
183
195
  for (const channelDoc of channelsSnapshot.docs) if (!requiredChannels.has(channelDoc.id)) transaction.delete(channelDoc.ref);
184
196
  });
185
- for (const bundleId of deletedBundleIds) bundles = bundles.filter((b) => b.id !== bundleId);
186
197
  }
187
198
  };
188
199
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/firebase",
3
3
  "type": "module",
4
- "version": "0.29.1",
4
+ "version": "0.29.3",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "types": "dist/index.d.cts",
@@ -36,10 +36,10 @@
36
36
  "dependencies": {
37
37
  "firebase": "^11.3.1",
38
38
  "hono": "4.12.9",
39
- "@hot-updater/cli-tools": "0.29.1",
40
- "@hot-updater/core": "0.29.1",
41
- "@hot-updater/plugin-core": "0.29.1",
42
- "@hot-updater/server": "0.29.1"
39
+ "@hot-updater/cli-tools": "0.29.3",
40
+ "@hot-updater/core": "0.29.3",
41
+ "@hot-updater/plugin-core": "0.29.3",
42
+ "@hot-updater/server": "0.29.3"
43
43
  },
44
44
  "publishConfig": {
45
45
  "access": "public"
@@ -54,9 +54,9 @@
54
54
  "firebase-tools": "^13.32.0",
55
55
  "fkill": "^9.0.0",
56
56
  "mime": "^4.0.4",
57
- "@hot-updater/js": "0.29.1",
58
- "@hot-updater/mock": "0.29.1",
59
- "@hot-updater/test-utils": "0.29.1"
57
+ "@hot-updater/js": "0.29.3",
58
+ "@hot-updater/test-utils": "0.29.3",
59
+ "@hot-updater/mock": "0.29.3"
60
60
  },
61
61
  "peerDependencies": {
62
62
  "firebase-admin": "*",