@hot-updater/plugin-core 0.32.0 → 0.33.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/bundleUnitOfWork.cjs +158 -0
- package/dist/bundleUnitOfWork.mjs +158 -0
- package/dist/bundleUnitOfWorkStore.cjs +15 -0
- package/dist/bundleUnitOfWorkStore.mjs +15 -0
- package/dist/createBlobDatabasePlugin.cjs +149 -493
- package/dist/createBlobDatabasePlugin.d.cts +2 -4
- package/dist/createBlobDatabasePlugin.d.mts +2 -4
- package/dist/createBlobDatabasePlugin.mjs +149 -493
- package/dist/createDatabasePlugin.cjs +71 -32
- package/dist/createDatabasePlugin.mjs +71 -32
- package/dist/createDatabasePluginGetUpdateInfo.cjs +11 -3
- package/dist/createDatabasePluginGetUpdateInfo.mjs +11 -3
- package/dist/index.cjs +6 -1
- package/dist/index.d.cts +4 -2
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +4 -2
- package/dist/requestUpdateBundleState.cjs +26 -0
- package/dist/requestUpdateBundleState.d.cts +12 -0
- package/dist/requestUpdateBundleState.d.mts +12 -0
- package/dist/requestUpdateBundleState.mjs +24 -0
- package/dist/resolveUpdateInfoFromBundles.cjs +14 -0
- package/dist/resolveUpdateInfoFromBundles.d.cts +16 -0
- package/dist/resolveUpdateInfoFromBundles.d.mts +16 -0
- package/dist/resolveUpdateInfoFromBundles.mjs +13 -0
- package/package.json +8 -5
|
@@ -1,14 +1,31 @@
|
|
|
1
1
|
const require_runtime = require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
-
const
|
|
2
|
+
const require_queryBundles = require("./queryBundles.cjs");
|
|
3
3
|
const require_createDatabasePlugin = require("./createDatabasePlugin.cjs");
|
|
4
4
|
const require_filterCompatibleAppVersions = require("./filterCompatibleAppVersions.cjs");
|
|
5
|
-
const require_queryBundles = require("./queryBundles.cjs");
|
|
6
5
|
const require_paginateBundles = require("./paginateBundles.cjs");
|
|
7
|
-
|
|
6
|
+
const require_resolveUpdateInfoFromBundles = require("./resolveUpdateInfoFromBundles.cjs");
|
|
8
7
|
let es_toolkit = require("es-toolkit");
|
|
9
8
|
let semver = require("semver");
|
|
10
9
|
semver = require_runtime.__toESM(semver);
|
|
11
10
|
//#region src/createBlobDatabasePlugin.ts
|
|
11
|
+
const STORAGE_OPERATION_CONCURRENCY = 8;
|
|
12
|
+
async function mapWithConcurrency(items, concurrency, mapper) {
|
|
13
|
+
const results = [];
|
|
14
|
+
let nextIndex = 0;
|
|
15
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
16
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
17
|
+
while (true) {
|
|
18
|
+
const index = nextIndex;
|
|
19
|
+
nextIndex += 1;
|
|
20
|
+
if (index >= items.length) break;
|
|
21
|
+
results[index] = await mapper(items[index], index);
|
|
22
|
+
}
|
|
23
|
+
}));
|
|
24
|
+
return results;
|
|
25
|
+
}
|
|
26
|
+
async function forEachWithConcurrency(items, concurrency, mapper) {
|
|
27
|
+
await mapWithConcurrency(items, concurrency, mapper);
|
|
28
|
+
}
|
|
12
29
|
function removeBundleInternalKeys(bundle) {
|
|
13
30
|
const { _updateJsonKey, _oldUpdateJsonKey, ...pureBundle } = bundle;
|
|
14
31
|
return pureBundle;
|
|
@@ -49,134 +66,43 @@ function resolveStorageTarget({ targetAppVersion, fingerprintHash }) {
|
|
|
49
66
|
if (!target) throw new Error("target not found");
|
|
50
67
|
return target;
|
|
51
68
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
direction: "desc"
|
|
55
|
-
};
|
|
56
|
-
const MANAGEMENT_INDEX_PREFIX = "_index";
|
|
57
|
-
const MANAGEMENT_INDEX_VERSION = 1;
|
|
58
|
-
const DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE = 128;
|
|
59
|
-
const ALL_SCOPE_CACHE_KEY = "*|*";
|
|
60
|
-
function resolveManagementIndexPageSize(config) {
|
|
61
|
-
const pageSize = config.managementIndexPageSize ?? DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE;
|
|
62
|
-
if (!Number.isInteger(pageSize) || pageSize < 1) throw new Error("managementIndexPageSize must be a positive integer.");
|
|
63
|
-
return pageSize;
|
|
64
|
-
}
|
|
65
|
-
function sortManagedBundles(bundles, orderBy = DEFAULT_DESC_ORDER) {
|
|
66
|
-
return require_queryBundles.sortBundles(bundles, orderBy);
|
|
67
|
-
}
|
|
68
|
-
function isDefaultManagementOrder(orderBy) {
|
|
69
|
-
return orderBy === void 0 || orderBy.field === DEFAULT_DESC_ORDER.field && orderBy.direction === DEFAULT_DESC_ORDER.direction;
|
|
70
|
-
}
|
|
71
|
-
function hasUnsupportedManagementFilters(where) {
|
|
72
|
-
if (!where) return false;
|
|
73
|
-
return Boolean(where.enabled !== void 0 || where.id !== void 0 || where.targetAppVersion !== void 0 || where.targetAppVersionIn !== void 0 || where.targetAppVersionNotNull !== void 0 || where.fingerprintHash !== void 0);
|
|
69
|
+
function targetVersionMutationKey(bundle) {
|
|
70
|
+
return `${bundle.channel}/${bundle.platform}`;
|
|
74
71
|
}
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
function getTargetVersionMutation(mutations, bundle) {
|
|
73
|
+
const key = targetVersionMutationKey(bundle);
|
|
74
|
+
const existingMutation = mutations.get(key);
|
|
75
|
+
if (existingMutation) return existingMutation;
|
|
76
|
+
const mutation = {
|
|
77
|
+
additions: /* @__PURE__ */ new Set(),
|
|
78
|
+
channel: bundle.channel,
|
|
79
|
+
platform: bundle.platform,
|
|
80
|
+
removals: /* @__PURE__ */ new Set()
|
|
80
81
|
};
|
|
82
|
+
mutations.set(key, mutation);
|
|
83
|
+
return mutation;
|
|
81
84
|
}
|
|
82
|
-
function
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return `${channel ?? "*"}|${platform ?? "*"}`;
|
|
87
|
-
}
|
|
88
|
-
function getManagementScopePrefix({ channel, platform }) {
|
|
89
|
-
if (channel && platform) return `${MANAGEMENT_INDEX_PREFIX}/channel/${encodeScopePart(channel)}/platform/${platform}`;
|
|
90
|
-
if (channel) return `${MANAGEMENT_INDEX_PREFIX}/channel/${encodeScopePart(channel)}`;
|
|
91
|
-
if (platform) return `${MANAGEMENT_INDEX_PREFIX}/platform/${platform}`;
|
|
92
|
-
return `${MANAGEMENT_INDEX_PREFIX}/all`;
|
|
93
|
-
}
|
|
94
|
-
function getManagementRootKey(scope) {
|
|
95
|
-
return `${getManagementScopePrefix(scope)}/root.json`;
|
|
96
|
-
}
|
|
97
|
-
function getManagementPageKey(scope, pageIndex) {
|
|
98
|
-
return `${getManagementScopePrefix(scope)}/pages/${String(pageIndex).padStart(4, "0")}.json`;
|
|
85
|
+
function addTargetVersionAddition(mutations, bundle) {
|
|
86
|
+
const targetAppVersion = normalizeTargetAppVersion(bundle.targetAppVersion);
|
|
87
|
+
if (targetAppVersion == null) return;
|
|
88
|
+
getTargetVersionMutation(mutations, bundle).additions.add(targetAppVersion);
|
|
99
89
|
}
|
|
100
|
-
function
|
|
101
|
-
const
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
_updateJsonKey: `${bundle.channel}/${bundle.platform}/${target}/update.json`
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
function getPageStartOffsets(pages) {
|
|
108
|
-
const startOffsets = [];
|
|
109
|
-
let offset = 0;
|
|
110
|
-
for (const page of pages) {
|
|
111
|
-
startOffsets.push(offset);
|
|
112
|
-
offset += page.count;
|
|
113
|
-
}
|
|
114
|
-
return startOffsets;
|
|
90
|
+
function addTargetVersionRemoval(mutations, bundle) {
|
|
91
|
+
const targetAppVersion = normalizeTargetAppVersion(bundle.targetAppVersion);
|
|
92
|
+
if (targetAppVersion == null) return;
|
|
93
|
+
getTargetVersionMutation(mutations, bundle).removals.add(targetAppVersion);
|
|
115
94
|
}
|
|
116
|
-
function
|
|
117
|
-
return {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
limit,
|
|
121
|
-
offset: 0
|
|
122
|
-
})
|
|
123
|
-
};
|
|
95
|
+
function getManagementListPrefixes(where) {
|
|
96
|
+
if (where?.channel && where.platform) return [`${where.channel}/${where.platform}/`];
|
|
97
|
+
if (where?.channel) return [`${where.channel}/`];
|
|
98
|
+
return [""];
|
|
124
99
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (!options?.includeChannels && scopeBundles.length === 0) return;
|
|
132
|
-
const pageKeys = [];
|
|
133
|
-
const pageDescriptors = [];
|
|
134
|
-
for (let pageIndex = 0; pageIndex * pageSize < scopeBundles.length; pageIndex++) {
|
|
135
|
-
const page = scopeBundles.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize);
|
|
136
|
-
const key = getManagementPageKey(scope, pageIndex);
|
|
137
|
-
pages.set(key, page);
|
|
138
|
-
pageKeys.push(key);
|
|
139
|
-
pageDescriptors.push({
|
|
140
|
-
key,
|
|
141
|
-
count: page.length,
|
|
142
|
-
firstId: page[0].id,
|
|
143
|
-
lastId: page.at(-1).id
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
const root = {
|
|
147
|
-
version: MANAGEMENT_INDEX_VERSION,
|
|
148
|
-
pageSize,
|
|
149
|
-
total: scopeBundles.length,
|
|
150
|
-
pages: pageDescriptors,
|
|
151
|
-
...options?.includeChannels ? { channels } : {}
|
|
152
|
-
};
|
|
153
|
-
scopes.push({
|
|
154
|
-
cacheKey: getManagementScopeCacheKey(scope),
|
|
155
|
-
rootKey: getManagementRootKey(scope),
|
|
156
|
-
root,
|
|
157
|
-
pageKeys
|
|
158
|
-
});
|
|
159
|
-
};
|
|
160
|
-
addScope({}, sortedAllBundles, { includeChannels: true });
|
|
161
|
-
for (const channel of channels) {
|
|
162
|
-
const channelBundles = sortedAllBundles.filter((bundle) => bundle.channel === channel);
|
|
163
|
-
addScope({ channel }, channelBundles);
|
|
164
|
-
for (const platform of ["ios", "android"]) {
|
|
165
|
-
const scopedBundles = channelBundles.filter((bundle) => bundle.platform === platform);
|
|
166
|
-
addScope({
|
|
167
|
-
channel,
|
|
168
|
-
platform
|
|
169
|
-
}, scopedBundles);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
for (const platform of ["ios", "android"]) {
|
|
173
|
-
const platformBundles = sortedAllBundles.filter((bundle) => bundle.platform === platform);
|
|
174
|
-
addScope({ platform }, platformBundles);
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
pages,
|
|
178
|
-
scopes
|
|
179
|
-
};
|
|
100
|
+
const DEFAULT_DESC_ORDER = {
|
|
101
|
+
field: "id",
|
|
102
|
+
direction: "desc"
|
|
103
|
+
};
|
|
104
|
+
function sortManagedBundles(bundles, orderBy = DEFAULT_DESC_ORDER) {
|
|
105
|
+
return require_queryBundles.sortBundles(bundles, orderBy);
|
|
180
106
|
}
|
|
181
107
|
/**
|
|
182
108
|
* Creates a blob storage-based database plugin with lazy initialization.
|
|
@@ -187,339 +113,90 @@ function buildManagementIndexArtifacts(allBundles, pageSize) {
|
|
|
187
113
|
*/
|
|
188
114
|
const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
189
115
|
return (config, hooks) => {
|
|
190
|
-
const
|
|
191
|
-
const { listObjects, loadObject, uploadObject, deleteObject, invalidatePaths, apiBasePath } = factory(config);
|
|
116
|
+
const { listObjects, loadObject, uploadObject, deleteObject, shouldSkipLoadObjectError, invalidatePaths, apiBasePath } = factory(config);
|
|
192
117
|
const bundlesMap = /* @__PURE__ */ new Map();
|
|
193
118
|
const pendingBundlesMap = /* @__PURE__ */ new Map();
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
const replaceManagementRootCache = (artifacts) => {
|
|
202
|
-
managementRootCache.clear();
|
|
203
|
-
for (const scope of artifacts.scopes) managementRootCache.set(scope.cacheKey, scope.root);
|
|
204
|
-
};
|
|
205
|
-
const createHydratedBundle = (bundle) => {
|
|
206
|
-
const hydratedBundle = createBundleWithUpdateJsonKey(bundle);
|
|
207
|
-
bundlesMap.set(hydratedBundle.id, hydratedBundle);
|
|
208
|
-
return hydratedBundle;
|
|
209
|
-
};
|
|
210
|
-
const loadStoredManagementRoot = async (scope) => {
|
|
211
|
-
const cacheKey = getManagementScopeCacheKey(scope);
|
|
212
|
-
const storedRoot = await loadObject(getManagementRootKey(scope));
|
|
213
|
-
if (storedRoot) {
|
|
214
|
-
managementRootCache.set(cacheKey, storedRoot);
|
|
215
|
-
return storedRoot;
|
|
216
|
-
}
|
|
217
|
-
managementRootCache.delete(cacheKey);
|
|
218
|
-
return null;
|
|
219
|
-
};
|
|
220
|
-
const loadManagementPage = async (descriptor, pageCache) => {
|
|
221
|
-
if (pageCache?.has(descriptor.key)) return pageCache.get(descriptor.key) ?? null;
|
|
222
|
-
const page = await loadObject(descriptor.key);
|
|
223
|
-
pageCache?.set(descriptor.key, page);
|
|
224
|
-
return page;
|
|
225
|
-
};
|
|
226
|
-
const loadBundleFromManagementRoot = async (root, bundleId) => {
|
|
227
|
-
const pageIndex = findPageIndexContainingId(root.pages, bundleId);
|
|
228
|
-
if (pageIndex < 0) return null;
|
|
229
|
-
const descriptor = root.pages[pageIndex];
|
|
230
|
-
const page = await loadManagementPage(descriptor);
|
|
231
|
-
if (!page) return null;
|
|
232
|
-
return page.find((item) => item.id === bundleId) ?? null;
|
|
233
|
-
};
|
|
234
|
-
const loadAllBundlesFromRoot = async (root) => {
|
|
235
|
-
const allBundles = [];
|
|
236
|
-
const pageCache = /* @__PURE__ */ new Map();
|
|
237
|
-
for (const descriptor of root.pages) {
|
|
238
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
239
|
-
if (!page) return null;
|
|
240
|
-
allBundles.push(...page);
|
|
119
|
+
const locallyDeletedBundleIds = /* @__PURE__ */ new Set();
|
|
120
|
+
const loadOptionalObject = async (key) => {
|
|
121
|
+
try {
|
|
122
|
+
return await loadObject(key);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
if (shouldSkipLoadObjectError?.(error, key)) return null;
|
|
125
|
+
throw error;
|
|
241
126
|
}
|
|
242
|
-
return allBundles;
|
|
243
|
-
};
|
|
244
|
-
const persistManagementIndexArtifacts = async (nextArtifacts, previousArtifacts) => {
|
|
245
|
-
for (const [key, page] of nextArtifacts.pages.entries()) await uploadObject(key, page);
|
|
246
|
-
for (const scope of nextArtifacts.scopes) await uploadObject(scope.rootKey, scope.root);
|
|
247
|
-
if (!previousArtifacts) return;
|
|
248
|
-
const nextPageKeys = new Set(nextArtifacts.pages.keys());
|
|
249
|
-
const nextRootKeys = new Set(nextArtifacts.scopes.map((scope) => scope.rootKey));
|
|
250
|
-
for (const [key] of previousArtifacts.pages.entries()) if (!nextPageKeys.has(key)) await deleteObject(key).catch(() => {});
|
|
251
|
-
for (const scope of previousArtifacts.scopes) if (!nextRootKeys.has(scope.rootKey)) await deleteObject(scope.rootKey).catch(() => {});
|
|
252
|
-
};
|
|
253
|
-
const ensureAllManagementRoot = async () => {
|
|
254
|
-
const storedAllRoot = await loadStoredManagementRoot({});
|
|
255
|
-
if (storedAllRoot && storedAllRoot.pageSize === managementIndexPageSize) return storedAllRoot;
|
|
256
|
-
const rebuiltBundles = sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
257
|
-
const nextArtifacts = buildManagementIndexArtifacts(rebuiltBundles, managementIndexPageSize);
|
|
258
|
-
await persistManagementIndexArtifacts(nextArtifacts, storedAllRoot ? buildManagementIndexArtifacts(rebuiltBundles, storedAllRoot.pageSize) : void 0);
|
|
259
|
-
replaceManagementRootCache(nextArtifacts);
|
|
260
|
-
return getAllManagementArtifact(nextArtifacts).root;
|
|
261
|
-
};
|
|
262
|
-
const loadManagementScopeRoot = async (scope) => {
|
|
263
|
-
const cacheKey = getManagementScopeCacheKey(scope);
|
|
264
|
-
if (cacheKey === ALL_SCOPE_CACHE_KEY) return ensureAllManagementRoot();
|
|
265
|
-
const storedRoot = await loadStoredManagementRoot(scope);
|
|
266
|
-
if (storedRoot) return storedRoot;
|
|
267
|
-
await ensureAllManagementRoot();
|
|
268
|
-
const storedScopedRoot = await loadStoredManagementRoot(scope);
|
|
269
|
-
if (storedScopedRoot) return storedScopedRoot;
|
|
270
|
-
managementRootCache.set(cacheKey, null);
|
|
271
|
-
return null;
|
|
272
|
-
};
|
|
273
|
-
const loadAllBundlesForManagementFallback = async () => {
|
|
274
|
-
const allRoot = await loadManagementScopeRoot({});
|
|
275
|
-
if (allRoot) {
|
|
276
|
-
const pagedBundles = await loadAllBundlesFromRoot(allRoot);
|
|
277
|
-
if (pagedBundles) return pagedBundles;
|
|
278
|
-
}
|
|
279
|
-
return sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
280
|
-
};
|
|
281
|
-
const loadCurrentBundlesForIndexRebuild = async () => {
|
|
282
|
-
return loadAllBundlesForManagementFallback();
|
|
283
127
|
};
|
|
284
|
-
const
|
|
285
|
-
return
|
|
128
|
+
const loadAllBundlesForManagementFallback = async (where) => {
|
|
129
|
+
return sortManagedBundles((await reloadBundles(getManagementListPrefixes(where))).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
286
130
|
};
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
if (normalizedOffset >= root.total) return {
|
|
294
|
-
data: [],
|
|
295
|
-
pagination: require_calculatePagination.calculatePagination(root.total, {
|
|
296
|
-
limit,
|
|
297
|
-
offset: normalizedOffset
|
|
298
|
-
})
|
|
299
|
-
};
|
|
300
|
-
let pageIndex = 0;
|
|
301
|
-
for (let index = pageStartOffsets.length - 1; index >= 0; index--) if ((pageStartOffsets[index] ?? 0) <= normalizedOffset) {
|
|
302
|
-
pageIndex = index;
|
|
303
|
-
break;
|
|
304
|
-
}
|
|
305
|
-
const startInPage = normalizedOffset - (pageStartOffsets[pageIndex] ?? 0);
|
|
306
|
-
const data = [];
|
|
307
|
-
for (let currentPageIndex = pageIndex; currentPageIndex < root.pages.length && (limit <= 0 || data.length < limit); currentPageIndex++) {
|
|
308
|
-
const descriptor = root.pages[currentPageIndex];
|
|
309
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
310
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
311
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
312
|
-
limit,
|
|
313
|
-
offset: normalizedOffset
|
|
314
|
-
});
|
|
315
|
-
data.push(...currentPageIndex === pageIndex ? page.slice(startInPage) : page);
|
|
316
|
-
}
|
|
317
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
318
|
-
return {
|
|
319
|
-
data: paginatedData,
|
|
320
|
-
pagination: {
|
|
321
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
322
|
-
limit,
|
|
323
|
-
offset: normalizedOffset
|
|
324
|
-
}),
|
|
325
|
-
...paginatedData.length > 0 && normalizedOffset + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
326
|
-
...paginatedData.length > 0 && normalizedOffset > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
if (cursor?.after) {
|
|
331
|
-
let pageIndex = root.pages.findIndex((page) => {
|
|
332
|
-
const containsCursor = cursor.after.localeCompare(page.firstId) <= 0 && cursor.after.localeCompare(page.lastId) >= 0;
|
|
333
|
-
const wholePageEligible = cursor.after.localeCompare(page.firstId) > 0;
|
|
334
|
-
return containsCursor || wholePageEligible;
|
|
335
|
-
});
|
|
336
|
-
if (pageIndex < 0) return {
|
|
337
|
-
data: [],
|
|
338
|
-
pagination: {
|
|
339
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
340
|
-
limit,
|
|
341
|
-
offset: root.total
|
|
342
|
-
}),
|
|
343
|
-
previousCursor: cursor.after
|
|
344
|
-
}
|
|
345
|
-
};
|
|
346
|
-
const data = [];
|
|
347
|
-
let startIndex = null;
|
|
348
|
-
while (pageIndex < root.pages.length && (limit <= 0 || data.length < limit)) {
|
|
349
|
-
const descriptor = root.pages[pageIndex];
|
|
350
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
351
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
352
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
353
|
-
limit,
|
|
354
|
-
cursor
|
|
355
|
-
});
|
|
356
|
-
const containsCursor = cursor.after.localeCompare(descriptor.firstId) <= 0 && cursor.after.localeCompare(descriptor.lastId) >= 0;
|
|
357
|
-
let eligiblePageBundles = page;
|
|
358
|
-
if (containsCursor) {
|
|
359
|
-
const startInPage = page.findIndex((bundle) => bundle.id.localeCompare(cursor.after) < 0);
|
|
360
|
-
if (startInPage < 0) eligiblePageBundles = [];
|
|
361
|
-
else {
|
|
362
|
-
eligiblePageBundles = page.slice(startInPage);
|
|
363
|
-
startIndex ??= (pageStartOffsets[pageIndex] ?? 0) + startInPage;
|
|
364
|
-
}
|
|
365
|
-
} else if (eligiblePageBundles.length > 0) startIndex ??= pageStartOffsets[pageIndex] ?? 0;
|
|
366
|
-
data.push(...eligiblePageBundles);
|
|
367
|
-
if (limit > 0 && data.length >= limit) break;
|
|
368
|
-
pageIndex += 1;
|
|
369
|
-
}
|
|
370
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
371
|
-
const resolvedStartIndex = startIndex ?? root.total;
|
|
372
|
-
return {
|
|
373
|
-
data: paginatedData,
|
|
374
|
-
pagination: {
|
|
375
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
376
|
-
limit,
|
|
377
|
-
offset: resolvedStartIndex
|
|
378
|
-
}),
|
|
379
|
-
...paginatedData.length > 0 && resolvedStartIndex + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
380
|
-
...paginatedData.length > 0 && resolvedStartIndex > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
381
|
-
}
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
if (cursor?.before) {
|
|
385
|
-
let pageIndex = -1;
|
|
386
|
-
for (let index = root.pages.length - 1; index >= 0; index--) {
|
|
387
|
-
const page = root.pages[index];
|
|
388
|
-
const containsCursor = cursor.before.localeCompare(page.firstId) <= 0 && cursor.before.localeCompare(page.lastId) >= 0;
|
|
389
|
-
const wholePageEligible = cursor.before.localeCompare(page.lastId) < 0;
|
|
390
|
-
if (containsCursor || wholePageEligible) {
|
|
391
|
-
pageIndex = index;
|
|
392
|
-
break;
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
if (pageIndex < 0) return createEmptyManagementResult(limit);
|
|
396
|
-
let startIndex = null;
|
|
397
|
-
let collected = [];
|
|
398
|
-
while (pageIndex >= 0 && (limit <= 0 || collected.length < limit)) {
|
|
399
|
-
const descriptor = root.pages[pageIndex];
|
|
400
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
401
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
402
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
403
|
-
limit,
|
|
404
|
-
cursor
|
|
405
|
-
});
|
|
406
|
-
const eligiblePageBundles = cursor.before.localeCompare(descriptor.firstId) <= 0 && cursor.before.localeCompare(descriptor.lastId) >= 0 ? page.filter((bundle) => bundle.id.localeCompare(cursor.before) > 0) : page;
|
|
407
|
-
collected = [...eligiblePageBundles, ...collected];
|
|
408
|
-
if (eligiblePageBundles.length > 0) startIndex = pageStartOffsets[pageIndex] ?? 0;
|
|
409
|
-
if (limit > 0 && collected.length >= limit) break;
|
|
410
|
-
pageIndex -= 1;
|
|
411
|
-
}
|
|
412
|
-
if (startIndex === null || collected.length === 0) return createEmptyManagementResult(limit);
|
|
413
|
-
let paginatedData = collected;
|
|
414
|
-
if (limit > 0 && collected.length > limit) {
|
|
415
|
-
const dropCount = collected.length - limit;
|
|
416
|
-
paginatedData = collected.slice(dropCount);
|
|
417
|
-
startIndex += dropCount;
|
|
418
|
-
}
|
|
419
|
-
const pagination = require_calculatePagination.calculatePagination(root.total, {
|
|
420
|
-
limit,
|
|
421
|
-
offset: startIndex
|
|
422
|
-
});
|
|
423
|
-
return {
|
|
424
|
-
data: paginatedData,
|
|
425
|
-
pagination: {
|
|
426
|
-
...pagination,
|
|
427
|
-
...paginatedData.length > 0 && startIndex + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
428
|
-
...paginatedData.length > 0 && startIndex > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
429
|
-
}
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
const pageIndex = 0;
|
|
433
|
-
const startInPage = 0;
|
|
434
|
-
const data = [];
|
|
435
|
-
for (let currentPageIndex = pageIndex; currentPageIndex < root.pages.length && (limit <= 0 || data.length < limit); currentPageIndex++) {
|
|
436
|
-
const descriptor = root.pages[currentPageIndex];
|
|
437
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
438
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
439
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
440
|
-
limit,
|
|
441
|
-
cursor
|
|
131
|
+
const cacheBundlesFromObject = (key, bundles) => {
|
|
132
|
+
for (const bundle of bundles) {
|
|
133
|
+
if (locallyDeletedBundleIds.has(bundle.id) || pendingBundlesMap.has(bundle.id)) continue;
|
|
134
|
+
bundlesMap.set(bundle.id, {
|
|
135
|
+
...bundle,
|
|
136
|
+
_updateJsonKey: key
|
|
442
137
|
});
|
|
443
|
-
data.push(...currentPageIndex === pageIndex ? page.slice(startInPage) : page);
|
|
444
138
|
}
|
|
445
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
446
|
-
return {
|
|
447
|
-
data: paginatedData,
|
|
448
|
-
pagination: {
|
|
449
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
450
|
-
limit,
|
|
451
|
-
offset: 0
|
|
452
|
-
}),
|
|
453
|
-
...paginatedData.length > 0 && paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {}
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
139
|
};
|
|
457
|
-
async
|
|
140
|
+
const loadBundleObject = async (key) => {
|
|
141
|
+
const bundles = await loadOptionalObject(key) ?? [];
|
|
142
|
+
cacheBundlesFromObject(key, bundles);
|
|
143
|
+
return bundles;
|
|
144
|
+
};
|
|
145
|
+
async function reloadBundles(prefixes = [""]) {
|
|
458
146
|
bundlesMap.clear();
|
|
459
|
-
|
|
460
|
-
|
|
147
|
+
pendingBundlesMap.clear();
|
|
148
|
+
locallyDeletedBundleIds.clear();
|
|
149
|
+
const allBundles = (await mapWithConcurrency((await mapWithConcurrency(prefixes, STORAGE_OPERATION_CONCURRENCY, (prefix) => listObjects(prefix))).flat().filter((key) => /^[^/]+\/(?:ios|android)\/[^/]+\/update\.json$/.test(key)), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
150
|
+
return (await loadBundleObject(key)).map((bundle) => ({
|
|
461
151
|
...bundle,
|
|
462
152
|
_updateJsonKey: key
|
|
463
153
|
}));
|
|
464
|
-
});
|
|
465
|
-
const allBundles = (await Promise.all(filePromises)).flat();
|
|
154
|
+
})).flat();
|
|
466
155
|
for (const bundle of allBundles) bundlesMap.set(bundle.id, bundle);
|
|
467
156
|
for (const [id, bundle] of pendingBundlesMap.entries()) bundlesMap.set(id, bundle);
|
|
468
|
-
return (0, es_toolkit.orderBy)(
|
|
157
|
+
return (0, es_toolkit.orderBy)(Array.from(bundlesMap.values()), [(v) => v.id], ["desc"]);
|
|
469
158
|
}
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
* Returns true if the file was updated, false if no changes were made.
|
|
473
|
-
*/
|
|
474
|
-
async function updateTargetVersionsForPlatform(platform) {
|
|
475
|
-
const updateJsonPattern = new RegExp(`^[^/]+/${platform}/[^/]+/update\\.json$`);
|
|
476
|
-
const targetVersionsPattern = new RegExp(`^[^/]+/${platform}/target-app-versions\\.json$`);
|
|
477
|
-
const allKeys = await listObjects("");
|
|
478
|
-
const updateJsonKeys = allKeys.filter((key) => updateJsonPattern.test(key));
|
|
479
|
-
const targetVersionsKeys = allKeys.filter((key) => targetVersionsPattern.test(key));
|
|
480
|
-
const keysByChannel = updateJsonKeys.reduce((acc, key) => {
|
|
481
|
-
const channel = key.split("/")[0];
|
|
482
|
-
acc[channel] = acc[channel] || [];
|
|
483
|
-
acc[channel].push(key);
|
|
484
|
-
return acc;
|
|
485
|
-
}, {});
|
|
486
|
-
for (const key of targetVersionsKeys) {
|
|
487
|
-
const channel = key.split("/")[0];
|
|
488
|
-
if (!keysByChannel[channel]) keysByChannel[channel] = [];
|
|
489
|
-
}
|
|
490
|
-
for (const channel of Object.keys(keysByChannel)) {
|
|
491
|
-
const updateKeys = keysByChannel[channel];
|
|
159
|
+
async function applyTargetVersionMutations(mutations) {
|
|
160
|
+
await Promise.all(Array.from(mutations.values()).map(async ({ additions, channel, platform, removals }) => {
|
|
492
161
|
const targetKey = `${channel}/${platform}/target-app-versions.json`;
|
|
493
|
-
const
|
|
494
|
-
const
|
|
495
|
-
const
|
|
496
|
-
for (const v of currentVersions) if (!newTargetVersions.includes(v)) newTargetVersions.push(v);
|
|
162
|
+
const oldTargetVersions = await loadOptionalObject(targetKey) ?? [];
|
|
163
|
+
const newTargetVersions = oldTargetVersions.filter((version) => !removals.has(version) || additions.has(version));
|
|
164
|
+
for (const version of additions) if (!newTargetVersions.includes(version)) newTargetVersions.push(version);
|
|
497
165
|
if (JSON.stringify(oldTargetVersions) !== JSON.stringify(newTargetVersions)) await uploadObject(targetKey, newTargetVersions);
|
|
498
|
-
}
|
|
166
|
+
}));
|
|
499
167
|
}
|
|
500
|
-
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }) => {
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
168
|
+
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }, context) => {
|
|
169
|
+
const bundles = (await mapWithConcurrency(require_filterCompatibleAppVersions.filterCompatibleAppVersions(await loadOptionalObject(`${channel}/${platform}/target-app-versions.json`) ?? [], appVersion), STORAGE_OPERATION_CONCURRENCY, async (targetAppVersion) => {
|
|
170
|
+
return loadBundleObject(`${channel}/${platform}/${normalizeTargetAppVersion(targetAppVersion) ?? targetAppVersion}/update.json`);
|
|
171
|
+
})).flat();
|
|
172
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
173
|
+
args: {
|
|
174
|
+
_updateStrategy: "appVersion",
|
|
175
|
+
appVersion,
|
|
176
|
+
bundleId,
|
|
177
|
+
channel,
|
|
178
|
+
cohort,
|
|
179
|
+
minBundleId,
|
|
180
|
+
platform
|
|
181
|
+
},
|
|
182
|
+
bundles,
|
|
183
|
+
context
|
|
512
184
|
});
|
|
513
185
|
};
|
|
514
|
-
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }) => {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
186
|
+
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }, context) => {
|
|
187
|
+
const bundles = await loadBundleObject(`${channel}/${platform}/${fingerprintHash}/update.json`);
|
|
188
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
189
|
+
args: {
|
|
190
|
+
_updateStrategy: "fingerprint",
|
|
191
|
+
bundleId,
|
|
192
|
+
channel,
|
|
193
|
+
cohort,
|
|
194
|
+
fingerprintHash,
|
|
195
|
+
minBundleId,
|
|
196
|
+
platform
|
|
197
|
+
},
|
|
198
|
+
bundles,
|
|
199
|
+
context
|
|
523
200
|
});
|
|
524
201
|
};
|
|
525
202
|
const addAppVersionInvalidationPaths = (pathsToInvalidate, { platform, channel, targetAppVersion }) => {
|
|
@@ -541,48 +218,27 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
541
218
|
targetAppVersion
|
|
542
219
|
});
|
|
543
220
|
};
|
|
544
|
-
|
|
221
|
+
const createPlugin = require_createDatabasePlugin.createDatabasePlugin({
|
|
545
222
|
name,
|
|
546
223
|
factory: () => ({
|
|
547
224
|
supportsCursorPagination: true,
|
|
548
225
|
async getBundleById(bundleId) {
|
|
226
|
+
if (locallyDeletedBundleIds.has(bundleId)) return null;
|
|
549
227
|
const pendingBundle = pendingBundlesMap.get(bundleId);
|
|
550
228
|
if (pendingBundle) return removeBundleInternalKeys(pendingBundle);
|
|
551
229
|
const bundle = bundlesMap.get(bundleId);
|
|
552
230
|
if (bundle) return removeBundleInternalKeys(bundle);
|
|
553
|
-
const allRoot = await loadManagementScopeRoot({});
|
|
554
|
-
if (allRoot) {
|
|
555
|
-
const matchedBundle = await loadBundleFromManagementRoot(allRoot, bundleId);
|
|
556
|
-
if (matchedBundle) return removeBundleInternalKeys(createHydratedBundle(matchedBundle));
|
|
557
|
-
managementRootCache.delete(ALL_SCOPE_CACHE_KEY);
|
|
558
|
-
const refreshedAllRoot = await loadStoredManagementRoot({});
|
|
559
|
-
if (refreshedAllRoot) {
|
|
560
|
-
const refreshedBundle = await loadBundleFromManagementRoot(refreshedAllRoot, bundleId);
|
|
561
|
-
if (refreshedBundle) return removeBundleInternalKeys(createHydratedBundle(refreshedBundle));
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
231
|
const matchedBundle = (await reloadBundles()).find((item) => item.id === bundleId);
|
|
565
232
|
if (!matchedBundle) return null;
|
|
566
233
|
return removeBundleInternalKeys(matchedBundle);
|
|
567
234
|
},
|
|
568
|
-
async getUpdateInfo(args) {
|
|
569
|
-
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args);
|
|
570
|
-
return getFingerprintUpdateInfo(args);
|
|
235
|
+
async getUpdateInfo(args, context) {
|
|
236
|
+
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args, context);
|
|
237
|
+
return getFingerprintUpdateInfo(args, context);
|
|
571
238
|
},
|
|
572
239
|
async getBundles(options) {
|
|
573
240
|
const { where, limit, offset, orderBy, cursor } = options;
|
|
574
|
-
|
|
575
|
-
if (scope) {
|
|
576
|
-
const root = await loadManagementScopeRoot(scope);
|
|
577
|
-
if (!root) return createEmptyManagementResult(limit);
|
|
578
|
-
return readPagedBundles({
|
|
579
|
-
root,
|
|
580
|
-
limit,
|
|
581
|
-
offset,
|
|
582
|
-
cursor
|
|
583
|
-
});
|
|
584
|
-
}
|
|
585
|
-
let allBundles = await loadAllBundlesForManagementFallback();
|
|
241
|
+
let allBundles = await loadAllBundlesForManagementFallback(where);
|
|
586
242
|
if (where) allBundles = allBundles.filter((bundle) => require_queryBundles.bundleMatchesQueryWhere(bundle, where));
|
|
587
243
|
return require_paginateBundles.paginateBundles({
|
|
588
244
|
bundles: allBundles,
|
|
@@ -593,18 +249,16 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
593
249
|
});
|
|
594
250
|
},
|
|
595
251
|
async getChannels() {
|
|
596
|
-
return (await
|
|
252
|
+
return [...new Set((await loadAllBundlesForManagementFallback()).map((bundle) => bundle.channel))].sort();
|
|
597
253
|
},
|
|
598
254
|
async commitBundle({ changedSets }) {
|
|
599
255
|
if (changedSets.length === 0) return;
|
|
600
256
|
const changedBundlesByKey = {};
|
|
601
257
|
const removalsByKey = {};
|
|
258
|
+
const targetVersionRemovalsByKey = {};
|
|
602
259
|
const pathsToInvalidate = /* @__PURE__ */ new Set();
|
|
603
|
-
|
|
604
|
-
let isChannelChanged = false;
|
|
260
|
+
const targetVersionMutations = /* @__PURE__ */ new Map();
|
|
605
261
|
for (const { operation, data } of changedSets) {
|
|
606
|
-
if (data.targetAppVersion !== void 0) isTargetAppVersionChanged = true;
|
|
607
|
-
if (operation === "update" && data.channel !== void 0) isChannelChanged = true;
|
|
608
262
|
if (operation === "insert") {
|
|
609
263
|
const target = resolveStorageTarget(data);
|
|
610
264
|
const key = `${data.channel}/${data.platform}/${target}/update.json`;
|
|
@@ -612,10 +266,12 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
612
266
|
...data,
|
|
613
267
|
_updateJsonKey: key
|
|
614
268
|
};
|
|
269
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
615
270
|
bundlesMap.set(data.id, bundleWithKey);
|
|
616
271
|
pendingBundlesMap.set(data.id, bundleWithKey);
|
|
617
272
|
changedBundlesByKey[key] = changedBundlesByKey[key] || [];
|
|
618
273
|
changedBundlesByKey[key].push(removeBundleInternalKeys(bundleWithKey));
|
|
274
|
+
addTargetVersionAddition(targetVersionMutations, data);
|
|
619
275
|
addLookupInvalidationPaths(pathsToInvalidate, data);
|
|
620
276
|
continue;
|
|
621
277
|
}
|
|
@@ -625,9 +281,12 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
625
281
|
if (!bundle) throw new Error("Bundle to delete not found");
|
|
626
282
|
bundlesMap.delete(data.id);
|
|
627
283
|
pendingBundlesMap.delete(data.id);
|
|
284
|
+
locallyDeletedBundleIds.add(data.id);
|
|
628
285
|
const key = bundle._updateJsonKey;
|
|
629
286
|
removalsByKey[key] = removalsByKey[key] || [];
|
|
630
287
|
removalsByKey[key].push(bundle.id);
|
|
288
|
+
targetVersionRemovalsByKey[key] = targetVersionRemovalsByKey[key] || [];
|
|
289
|
+
targetVersionRemovalsByKey[key].push(bundle);
|
|
631
290
|
addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
632
291
|
continue;
|
|
633
292
|
}
|
|
@@ -644,11 +303,14 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
644
303
|
const oldKey = bundle._updateJsonKey;
|
|
645
304
|
removalsByKey[oldKey] = removalsByKey[oldKey] || [];
|
|
646
305
|
removalsByKey[oldKey].push(bundle.id);
|
|
306
|
+
targetVersionRemovalsByKey[oldKey] = targetVersionRemovalsByKey[oldKey] || [];
|
|
307
|
+
targetVersionRemovalsByKey[oldKey].push(bundle);
|
|
647
308
|
changedBundlesByKey[newKey] = changedBundlesByKey[newKey] || [];
|
|
648
309
|
updatedBundle._oldUpdateJsonKey = oldKey;
|
|
649
310
|
updatedBundle._updateJsonKey = newKey;
|
|
650
311
|
bundlesMap.set(data.id, updatedBundle);
|
|
651
312
|
pendingBundlesMap.set(data.id, updatedBundle);
|
|
313
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
652
314
|
changedBundlesByKey[newKey].push(removeBundleInternalKeys(updatedBundle));
|
|
653
315
|
const oldChannel = bundle.channel;
|
|
654
316
|
const nextChannel = updatedBundle.channel;
|
|
@@ -659,6 +321,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
659
321
|
channel: nextChannel
|
|
660
322
|
});
|
|
661
323
|
}
|
|
324
|
+
addTargetVersionAddition(targetVersionMutations, updatedBundle);
|
|
662
325
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
663
326
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
664
327
|
continue;
|
|
@@ -666,20 +329,24 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
666
329
|
const currentKey = bundle._updateJsonKey;
|
|
667
330
|
bundlesMap.set(data.id, updatedBundle);
|
|
668
331
|
pendingBundlesMap.set(data.id, updatedBundle);
|
|
332
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
669
333
|
changedBundlesByKey[currentKey] = changedBundlesByKey[currentKey] || [];
|
|
670
334
|
changedBundlesByKey[currentKey].push(removeBundleInternalKeys(updatedBundle));
|
|
671
335
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
336
|
+
addTargetVersionAddition(targetVersionMutations, updatedBundle);
|
|
672
337
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
673
338
|
}
|
|
674
339
|
}
|
|
675
|
-
|
|
676
|
-
const updatedBundles = (await
|
|
340
|
+
await forEachWithConcurrency(Object.keys(removalsByKey), STORAGE_OPERATION_CONCURRENCY, async (oldKey) => {
|
|
341
|
+
const updatedBundles = (await loadOptionalObject(oldKey) ?? []).filter((b) => !removalsByKey[oldKey].includes(b.id));
|
|
677
342
|
updatedBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
678
|
-
if (updatedBundles.length === 0)
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
343
|
+
if (updatedBundles.length === 0) {
|
|
344
|
+
await deleteObject(oldKey);
|
|
345
|
+
for (const removedBundle of targetVersionRemovalsByKey[oldKey] ?? []) addTargetVersionRemoval(targetVersionMutations, removedBundle);
|
|
346
|
+
} else await uploadObject(oldKey, updatedBundles);
|
|
347
|
+
});
|
|
348
|
+
await forEachWithConcurrency(Object.keys(changedBundlesByKey), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
349
|
+
const currentBundles = await loadOptionalObject(key) ?? [];
|
|
683
350
|
const pureBundles = changedBundlesByKey[key].map((bundle) => bundle);
|
|
684
351
|
for (const changedBundle of pureBundles) {
|
|
685
352
|
const index = currentBundles.findIndex((b) => b.id === changedBundle.id);
|
|
@@ -688,22 +355,8 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
688
355
|
}
|
|
689
356
|
currentBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
690
357
|
await uploadObject(key, currentBundles);
|
|
691
|
-
})
|
|
692
|
-
if (
|
|
693
|
-
const currentIndexBundles = await loadCurrentBundlesForIndexRebuild();
|
|
694
|
-
const nextIndexMap = new Map(currentIndexBundles.map((bundle) => [bundle.id, bundle]));
|
|
695
|
-
for (const { operation, data } of changedSets) {
|
|
696
|
-
if (operation === "delete") {
|
|
697
|
-
nextIndexMap.delete(data.id);
|
|
698
|
-
continue;
|
|
699
|
-
}
|
|
700
|
-
nextIndexMap.set(data.id, data);
|
|
701
|
-
}
|
|
702
|
-
const nextIndexBundles = sortManagedBundles(Array.from(nextIndexMap.values()));
|
|
703
|
-
const previousArtifacts = buildManagementIndexArtifacts(currentIndexBundles, managementIndexPageSize);
|
|
704
|
-
const nextArtifacts = buildManagementIndexArtifacts(nextIndexBundles, managementIndexPageSize);
|
|
705
|
-
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
706
|
-
replaceManagementRootCache(nextArtifacts);
|
|
358
|
+
});
|
|
359
|
+
if (targetVersionMutations.size > 0) await applyTargetVersionMutations(targetVersionMutations);
|
|
707
360
|
const encondedPaths = /* @__PURE__ */ new Set();
|
|
708
361
|
for (const path of pathsToInvalidate) encondedPaths.add(encodeURI(path));
|
|
709
362
|
await invalidatePaths(Array.from(encondedPaths));
|
|
@@ -711,6 +364,9 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
711
364
|
}
|
|
712
365
|
})
|
|
713
366
|
})({}, hooks);
|
|
367
|
+
return () => {
|
|
368
|
+
return createPlugin();
|
|
369
|
+
};
|
|
714
370
|
};
|
|
715
371
|
};
|
|
716
372
|
//#endregion
|