@hot-updater/plugin-core 0.33.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 +80 -524
- package/dist/createBlobDatabasePlugin.d.cts +1 -4
- package/dist/createBlobDatabasePlugin.d.mts +1 -4
- package/dist/createBlobDatabasePlugin.mjs +80 -524
- package/dist/createDatabasePlugin.cjs +71 -32
- package/dist/createDatabasePlugin.mjs +71 -32
- package/dist/index.cjs +2 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +3 -3
- package/dist/requestUpdateBundleState.cjs +15 -9
- package/dist/requestUpdateBundleState.d.cts +7 -1
- package/dist/requestUpdateBundleState.d.mts +7 -1
- package/dist/requestUpdateBundleState.mjs +15 -10
- package/dist/types/index.d.cts +1 -24
- package/dist/types/index.d.mts +1 -24
- package/package.json +8 -5
|
@@ -1,8 +1,7 @@
|
|
|
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");
|
|
@@ -67,140 +66,43 @@ function resolveStorageTarget({ targetAppVersion, fingerprintHash }) {
|
|
|
67
66
|
if (!target) throw new Error("target not found");
|
|
68
67
|
return target;
|
|
69
68
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
direction: "desc"
|
|
73
|
-
};
|
|
74
|
-
const MANAGEMENT_INDEX_PREFIX = "_index";
|
|
75
|
-
const MANAGEMENT_INDEX_VERSION = 1;
|
|
76
|
-
const DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE = 128;
|
|
77
|
-
const ALL_SCOPE_CACHE_KEY = "*|*";
|
|
78
|
-
function summarizeManagementIndexArtifacts(artifacts) {
|
|
79
|
-
return {
|
|
80
|
-
pagesWritten: artifacts.pages.size,
|
|
81
|
-
scopesWritten: artifacts.scopes.length
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function resolveManagementIndexPageSize(config) {
|
|
85
|
-
const pageSize = config.managementIndexPageSize ?? DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE;
|
|
86
|
-
if (!Number.isInteger(pageSize) || pageSize < 1) throw new Error("managementIndexPageSize must be a positive integer.");
|
|
87
|
-
return pageSize;
|
|
88
|
-
}
|
|
89
|
-
function sortManagedBundles(bundles, orderBy = DEFAULT_DESC_ORDER) {
|
|
90
|
-
return require_queryBundles.sortBundles(bundles, orderBy);
|
|
91
|
-
}
|
|
92
|
-
function isDefaultManagementOrder(orderBy) {
|
|
93
|
-
return orderBy === void 0 || orderBy.field === DEFAULT_DESC_ORDER.field && orderBy.direction === DEFAULT_DESC_ORDER.direction;
|
|
69
|
+
function targetVersionMutationKey(bundle) {
|
|
70
|
+
return `${bundle.channel}/${bundle.platform}`;
|
|
94
71
|
}
|
|
95
|
-
function
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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()
|
|
104
81
|
};
|
|
82
|
+
mutations.set(key, mutation);
|
|
83
|
+
return mutation;
|
|
105
84
|
}
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return `${channel ?? "*"}|${platform ?? "*"}`;
|
|
111
|
-
}
|
|
112
|
-
function getManagementScopePrefix({ channel, platform }) {
|
|
113
|
-
if (channel && platform) return `${MANAGEMENT_INDEX_PREFIX}/channel/${encodeScopePart(channel)}/platform/${platform}`;
|
|
114
|
-
if (channel) return `${MANAGEMENT_INDEX_PREFIX}/channel/${encodeScopePart(channel)}`;
|
|
115
|
-
if (platform) return `${MANAGEMENT_INDEX_PREFIX}/platform/${platform}`;
|
|
116
|
-
return `${MANAGEMENT_INDEX_PREFIX}/all`;
|
|
117
|
-
}
|
|
118
|
-
function getManagementRootKey(scope) {
|
|
119
|
-
return `${getManagementScopePrefix(scope)}/root.json`;
|
|
120
|
-
}
|
|
121
|
-
function getManagementPageKey(scope, pageIndex) {
|
|
122
|
-
return `${getManagementScopePrefix(scope)}/pages/${String(pageIndex).padStart(4, "0")}.json`;
|
|
123
|
-
}
|
|
124
|
-
function createBundleWithUpdateJsonKey(bundle) {
|
|
125
|
-
const target = resolveStorageTarget(bundle);
|
|
126
|
-
return {
|
|
127
|
-
...bundle,
|
|
128
|
-
_updateJsonKey: `${bundle.channel}/${bundle.platform}/${target}/update.json`
|
|
129
|
-
};
|
|
85
|
+
function addTargetVersionAddition(mutations, bundle) {
|
|
86
|
+
const targetAppVersion = normalizeTargetAppVersion(bundle.targetAppVersion);
|
|
87
|
+
if (targetAppVersion == null) return;
|
|
88
|
+
getTargetVersionMutation(mutations, bundle).additions.add(targetAppVersion);
|
|
130
89
|
}
|
|
131
|
-
function
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
startOffsets.push(offset);
|
|
136
|
-
offset += page.count;
|
|
137
|
-
}
|
|
138
|
-
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);
|
|
139
94
|
}
|
|
140
|
-
function
|
|
141
|
-
return {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
limit,
|
|
145
|
-
offset: 0
|
|
146
|
-
})
|
|
147
|
-
};
|
|
95
|
+
function getManagementListPrefixes(where) {
|
|
96
|
+
if (where?.channel && where.platform) return [`${where.channel}/${where.platform}/`];
|
|
97
|
+
if (where?.channel) return [`${where.channel}/`];
|
|
98
|
+
return [""];
|
|
148
99
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!options?.includeChannels && scopeBundles.length === 0) return;
|
|
156
|
-
const pageKeys = [];
|
|
157
|
-
const pageDescriptors = [];
|
|
158
|
-
for (let pageIndex = 0; pageIndex * pageSize < scopeBundles.length; pageIndex++) {
|
|
159
|
-
const page = scopeBundles.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize);
|
|
160
|
-
const key = getManagementPageKey(scope, pageIndex);
|
|
161
|
-
pages.set(key, page);
|
|
162
|
-
pageKeys.push(key);
|
|
163
|
-
pageDescriptors.push({
|
|
164
|
-
key,
|
|
165
|
-
count: page.length,
|
|
166
|
-
firstId: page[0].id,
|
|
167
|
-
lastId: page.at(-1).id
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
const root = {
|
|
171
|
-
version: MANAGEMENT_INDEX_VERSION,
|
|
172
|
-
pageSize,
|
|
173
|
-
total: scopeBundles.length,
|
|
174
|
-
pages: pageDescriptors,
|
|
175
|
-
...options?.includeChannels ? { channels } : {}
|
|
176
|
-
};
|
|
177
|
-
scopes.push({
|
|
178
|
-
cacheKey: getManagementScopeCacheKey(scope),
|
|
179
|
-
rootKey: getManagementRootKey(scope),
|
|
180
|
-
root,
|
|
181
|
-
pageKeys
|
|
182
|
-
});
|
|
183
|
-
};
|
|
184
|
-
addScope({}, sortedAllBundles, { includeChannels: true });
|
|
185
|
-
for (const channel of channels) {
|
|
186
|
-
const channelBundles = sortedAllBundles.filter((bundle) => bundle.channel === channel);
|
|
187
|
-
addScope({ channel }, channelBundles);
|
|
188
|
-
for (const platform of ["ios", "android"]) {
|
|
189
|
-
const scopedBundles = channelBundles.filter((bundle) => bundle.platform === platform);
|
|
190
|
-
addScope({
|
|
191
|
-
channel,
|
|
192
|
-
platform
|
|
193
|
-
}, scopedBundles);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
for (const platform of ["ios", "android"]) {
|
|
197
|
-
const platformBundles = sortedAllBundles.filter((bundle) => bundle.platform === platform);
|
|
198
|
-
addScope({ platform }, platformBundles);
|
|
199
|
-
}
|
|
200
|
-
return {
|
|
201
|
-
pages,
|
|
202
|
-
scopes
|
|
203
|
-
};
|
|
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);
|
|
204
106
|
}
|
|
205
107
|
/**
|
|
206
108
|
* Creates a blob storage-based database plugin with lazy initialization.
|
|
@@ -211,11 +113,10 @@ function buildManagementIndexArtifacts(allBundles, pageSize) {
|
|
|
211
113
|
*/
|
|
212
114
|
const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
213
115
|
return (config, hooks) => {
|
|
214
|
-
const managementIndexPageSize = resolveManagementIndexPageSize(config);
|
|
215
116
|
const { listObjects, loadObject, uploadObject, deleteObject, shouldSkipLoadObjectError, invalidatePaths, apiBasePath } = factory(config);
|
|
216
117
|
const bundlesMap = /* @__PURE__ */ new Map();
|
|
217
118
|
const pendingBundlesMap = /* @__PURE__ */ new Map();
|
|
218
|
-
const
|
|
119
|
+
const locallyDeletedBundleIds = /* @__PURE__ */ new Set();
|
|
219
120
|
const loadOptionalObject = async (key) => {
|
|
220
121
|
try {
|
|
221
122
|
return await loadObject(key);
|
|
@@ -224,291 +125,29 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
224
125
|
throw error;
|
|
225
126
|
}
|
|
226
127
|
};
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
if (!allArtifact) throw new Error("all-bundles management index artifact not found");
|
|
230
|
-
return allArtifact;
|
|
231
|
-
};
|
|
232
|
-
const replaceManagementRootCache = (artifacts) => {
|
|
233
|
-
managementRootCache.clear();
|
|
234
|
-
for (const scope of artifacts.scopes) managementRootCache.set(scope.cacheKey, scope.root);
|
|
235
|
-
};
|
|
236
|
-
const createHydratedBundle = (bundle) => {
|
|
237
|
-
const hydratedBundle = createBundleWithUpdateJsonKey(bundle);
|
|
238
|
-
bundlesMap.set(hydratedBundle.id, hydratedBundle);
|
|
239
|
-
return hydratedBundle;
|
|
240
|
-
};
|
|
241
|
-
const loadStoredManagementRoot = async (scope) => {
|
|
242
|
-
const cacheKey = getManagementScopeCacheKey(scope);
|
|
243
|
-
const storedRoot = await loadOptionalObject(getManagementRootKey(scope));
|
|
244
|
-
if (storedRoot) {
|
|
245
|
-
managementRootCache.set(cacheKey, storedRoot);
|
|
246
|
-
return storedRoot;
|
|
247
|
-
}
|
|
248
|
-
managementRootCache.delete(cacheKey);
|
|
249
|
-
return null;
|
|
250
|
-
};
|
|
251
|
-
const loadManagementPage = async (descriptor, pageCache) => {
|
|
252
|
-
if (pageCache?.has(descriptor.key)) return pageCache.get(descriptor.key) ?? null;
|
|
253
|
-
const page = await loadOptionalObject(descriptor.key);
|
|
254
|
-
pageCache?.set(descriptor.key, page);
|
|
255
|
-
return page;
|
|
256
|
-
};
|
|
257
|
-
const loadBundleFromManagementRoot = async (root, bundleId) => {
|
|
258
|
-
const pageIndex = findPageIndexContainingId(root.pages, bundleId);
|
|
259
|
-
if (pageIndex < 0) return null;
|
|
260
|
-
const descriptor = root.pages[pageIndex];
|
|
261
|
-
const page = await loadManagementPage(descriptor);
|
|
262
|
-
if (!page) return null;
|
|
263
|
-
return page.find((item) => item.id === bundleId) ?? null;
|
|
264
|
-
};
|
|
265
|
-
const loadAllBundlesFromRoot = async (root) => {
|
|
266
|
-
const allBundles = [];
|
|
267
|
-
const pageCache = /* @__PURE__ */ new Map();
|
|
268
|
-
for (const descriptor of root.pages) {
|
|
269
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
270
|
-
if (!page) return null;
|
|
271
|
-
allBundles.push(...page);
|
|
272
|
-
}
|
|
273
|
-
return allBundles;
|
|
274
|
-
};
|
|
275
|
-
const persistManagementIndexArtifacts = async (nextArtifacts, previousArtifacts) => {
|
|
276
|
-
await forEachWithConcurrency(Array.from(nextArtifacts.pages.entries()), STORAGE_OPERATION_CONCURRENCY, ([key, page]) => uploadObject(key, page));
|
|
277
|
-
await forEachWithConcurrency(nextArtifacts.scopes, STORAGE_OPERATION_CONCURRENCY, (scope) => uploadObject(scope.rootKey, scope.root));
|
|
278
|
-
if (!previousArtifacts) return;
|
|
279
|
-
const nextPageKeys = new Set(nextArtifacts.pages.keys());
|
|
280
|
-
const nextRootKeys = new Set(nextArtifacts.scopes.map((scope) => scope.rootKey));
|
|
281
|
-
await forEachWithConcurrency(Array.from(previousArtifacts.pages.keys()).filter((key) => !nextPageKeys.has(key)), STORAGE_OPERATION_CONCURRENCY, (key) => deleteObject(key).catch(() => {}));
|
|
282
|
-
await forEachWithConcurrency(previousArtifacts.scopes.filter((scope) => !nextRootKeys.has(scope.rootKey)), STORAGE_OPERATION_CONCURRENCY, (scope) => deleteObject(scope.rootKey).catch(() => {}));
|
|
283
|
-
};
|
|
284
|
-
const ensureAllManagementRoot = async () => {
|
|
285
|
-
const storedAllRoot = await loadStoredManagementRoot({});
|
|
286
|
-
if (storedAllRoot && storedAllRoot.pageSize === managementIndexPageSize) return storedAllRoot;
|
|
287
|
-
const rebuiltBundles = sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
288
|
-
const nextArtifacts = buildManagementIndexArtifacts(rebuiltBundles, managementIndexPageSize);
|
|
289
|
-
await persistManagementIndexArtifacts(nextArtifacts, storedAllRoot ? buildManagementIndexArtifacts(rebuiltBundles, storedAllRoot.pageSize) : void 0);
|
|
290
|
-
replaceManagementRootCache(nextArtifacts);
|
|
291
|
-
return getAllManagementArtifact(nextArtifacts).root;
|
|
292
|
-
};
|
|
293
|
-
const loadManagementScopeRoot = async (scope) => {
|
|
294
|
-
const cacheKey = getManagementScopeCacheKey(scope);
|
|
295
|
-
if (cacheKey === ALL_SCOPE_CACHE_KEY) return ensureAllManagementRoot();
|
|
296
|
-
const storedRoot = await loadStoredManagementRoot(scope);
|
|
297
|
-
if (storedRoot) return storedRoot;
|
|
298
|
-
await ensureAllManagementRoot();
|
|
299
|
-
const storedScopedRoot = await loadStoredManagementRoot(scope);
|
|
300
|
-
if (storedScopedRoot) return storedScopedRoot;
|
|
301
|
-
managementRootCache.set(cacheKey, null);
|
|
302
|
-
return null;
|
|
303
|
-
};
|
|
304
|
-
const loadAllBundlesForManagementFallback = async () => {
|
|
305
|
-
const allRoot = await loadManagementScopeRoot({});
|
|
306
|
-
if (allRoot) {
|
|
307
|
-
const pagedBundles = await loadAllBundlesFromRoot(allRoot);
|
|
308
|
-
if (pagedBundles) return pagedBundles;
|
|
309
|
-
}
|
|
310
|
-
return sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
311
|
-
};
|
|
312
|
-
const loadCurrentBundlesForIndexRebuild = async () => {
|
|
313
|
-
return loadAllBundlesForManagementFallback();
|
|
128
|
+
const loadAllBundlesForManagementFallback = async (where) => {
|
|
129
|
+
return sortManagedBundles((await reloadBundles(getManagementListPrefixes(where))).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
314
130
|
};
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
const canonicalIds = new Set(canonicalBundles.map((bundle) => bundle.id));
|
|
322
|
-
const indexedIds = new Set(indexedBundles?.map((bundle) => bundle.id) ?? []);
|
|
323
|
-
const missingBundleIds = Array.from(canonicalIds).filter((id) => !indexedIds.has(id)).sort((left, right) => right.localeCompare(left));
|
|
324
|
-
const extraBundleIds = Array.from(indexedIds).filter((id) => !canonicalIds.has(id)).sort((left, right) => right.localeCompare(left));
|
|
325
|
-
return {
|
|
326
|
-
status: missingBundleIds.length === 0 && extraBundleIds.length === 0 && !rootMissing ? "ok" : rootMissing ? "missing" : "stale",
|
|
327
|
-
canonicalBundles: canonicalBundles.length,
|
|
328
|
-
indexedBundles: indexedBundles?.length ?? 0,
|
|
329
|
-
missingBundles: missingBundleIds.length,
|
|
330
|
-
extraBundles: extraBundleIds.length,
|
|
331
|
-
missingBundleIds: missingBundleIds.slice(0, 20),
|
|
332
|
-
extraBundleIds: extraBundleIds.slice(0, 20)
|
|
333
|
-
};
|
|
334
|
-
};
|
|
335
|
-
const findPageIndexContainingId = (pages, id) => {
|
|
336
|
-
return pages.findIndex((page) => id.localeCompare(page.firstId) <= 0 && id.localeCompare(page.lastId) >= 0);
|
|
337
|
-
};
|
|
338
|
-
const readPagedBundles = async ({ root, limit, offset, cursor }) => {
|
|
339
|
-
if (root.total === 0 || root.pages.length === 0) return createEmptyManagementResult(limit);
|
|
340
|
-
const pageStartOffsets = getPageStartOffsets(root.pages);
|
|
341
|
-
const pageCache = /* @__PURE__ */ new Map();
|
|
342
|
-
if (offset !== void 0) {
|
|
343
|
-
const normalizedOffset = Math.max(0, offset);
|
|
344
|
-
if (normalizedOffset >= root.total) return {
|
|
345
|
-
data: [],
|
|
346
|
-
pagination: require_calculatePagination.calculatePagination(root.total, {
|
|
347
|
-
limit,
|
|
348
|
-
offset: normalizedOffset
|
|
349
|
-
})
|
|
350
|
-
};
|
|
351
|
-
let pageIndex = 0;
|
|
352
|
-
for (let index = pageStartOffsets.length - 1; index >= 0; index--) if ((pageStartOffsets[index] ?? 0) <= normalizedOffset) {
|
|
353
|
-
pageIndex = index;
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
const startInPage = normalizedOffset - (pageStartOffsets[pageIndex] ?? 0);
|
|
357
|
-
const data = [];
|
|
358
|
-
for (let currentPageIndex = pageIndex; currentPageIndex < root.pages.length && (limit <= 0 || data.length < limit); currentPageIndex++) {
|
|
359
|
-
const descriptor = root.pages[currentPageIndex];
|
|
360
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
361
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
362
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
363
|
-
limit,
|
|
364
|
-
offset: normalizedOffset
|
|
365
|
-
});
|
|
366
|
-
data.push(...currentPageIndex === pageIndex ? page.slice(startInPage) : page);
|
|
367
|
-
}
|
|
368
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
369
|
-
return {
|
|
370
|
-
data: paginatedData,
|
|
371
|
-
pagination: {
|
|
372
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
373
|
-
limit,
|
|
374
|
-
offset: normalizedOffset
|
|
375
|
-
}),
|
|
376
|
-
...paginatedData.length > 0 && normalizedOffset + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
377
|
-
...paginatedData.length > 0 && normalizedOffset > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
378
|
-
}
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
if (cursor?.after) {
|
|
382
|
-
let pageIndex = root.pages.findIndex((page) => {
|
|
383
|
-
const containsCursor = cursor.after.localeCompare(page.firstId) <= 0 && cursor.after.localeCompare(page.lastId) >= 0;
|
|
384
|
-
const wholePageEligible = cursor.after.localeCompare(page.firstId) > 0;
|
|
385
|
-
return containsCursor || wholePageEligible;
|
|
386
|
-
});
|
|
387
|
-
if (pageIndex < 0) return {
|
|
388
|
-
data: [],
|
|
389
|
-
pagination: {
|
|
390
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
391
|
-
limit,
|
|
392
|
-
offset: root.total
|
|
393
|
-
}),
|
|
394
|
-
previousCursor: cursor.after
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
const data = [];
|
|
398
|
-
let startIndex = null;
|
|
399
|
-
while (pageIndex < root.pages.length && (limit <= 0 || data.length < limit)) {
|
|
400
|
-
const descriptor = root.pages[pageIndex];
|
|
401
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
402
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
403
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
404
|
-
limit,
|
|
405
|
-
cursor
|
|
406
|
-
});
|
|
407
|
-
const containsCursor = cursor.after.localeCompare(descriptor.firstId) <= 0 && cursor.after.localeCompare(descriptor.lastId) >= 0;
|
|
408
|
-
let eligiblePageBundles = page;
|
|
409
|
-
if (containsCursor) {
|
|
410
|
-
const startInPage = page.findIndex((bundle) => bundle.id.localeCompare(cursor.after) < 0);
|
|
411
|
-
if (startInPage < 0) eligiblePageBundles = [];
|
|
412
|
-
else {
|
|
413
|
-
eligiblePageBundles = page.slice(startInPage);
|
|
414
|
-
startIndex ??= (pageStartOffsets[pageIndex] ?? 0) + startInPage;
|
|
415
|
-
}
|
|
416
|
-
} else if (eligiblePageBundles.length > 0) startIndex ??= pageStartOffsets[pageIndex] ?? 0;
|
|
417
|
-
data.push(...eligiblePageBundles);
|
|
418
|
-
if (limit > 0 && data.length >= limit) break;
|
|
419
|
-
pageIndex += 1;
|
|
420
|
-
}
|
|
421
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
422
|
-
const resolvedStartIndex = startIndex ?? root.total;
|
|
423
|
-
return {
|
|
424
|
-
data: paginatedData,
|
|
425
|
-
pagination: {
|
|
426
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
427
|
-
limit,
|
|
428
|
-
offset: resolvedStartIndex
|
|
429
|
-
}),
|
|
430
|
-
...paginatedData.length > 0 && resolvedStartIndex + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
431
|
-
...paginatedData.length > 0 && resolvedStartIndex > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
432
|
-
}
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
if (cursor?.before) {
|
|
436
|
-
let pageIndex = -1;
|
|
437
|
-
for (let index = root.pages.length - 1; index >= 0; index--) {
|
|
438
|
-
const page = root.pages[index];
|
|
439
|
-
const containsCursor = cursor.before.localeCompare(page.firstId) <= 0 && cursor.before.localeCompare(page.lastId) >= 0;
|
|
440
|
-
const wholePageEligible = cursor.before.localeCompare(page.lastId) < 0;
|
|
441
|
-
if (containsCursor || wholePageEligible) {
|
|
442
|
-
pageIndex = index;
|
|
443
|
-
break;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
if (pageIndex < 0) return createEmptyManagementResult(limit);
|
|
447
|
-
let startIndex = null;
|
|
448
|
-
let collected = [];
|
|
449
|
-
while (pageIndex >= 0 && (limit <= 0 || collected.length < limit)) {
|
|
450
|
-
const descriptor = root.pages[pageIndex];
|
|
451
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
452
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
453
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
454
|
-
limit,
|
|
455
|
-
cursor
|
|
456
|
-
});
|
|
457
|
-
const eligiblePageBundles = cursor.before.localeCompare(descriptor.firstId) <= 0 && cursor.before.localeCompare(descriptor.lastId) >= 0 ? page.filter((bundle) => bundle.id.localeCompare(cursor.before) > 0) : page;
|
|
458
|
-
collected = [...eligiblePageBundles, ...collected];
|
|
459
|
-
if (eligiblePageBundles.length > 0) startIndex = pageStartOffsets[pageIndex] ?? 0;
|
|
460
|
-
if (limit > 0 && collected.length >= limit) break;
|
|
461
|
-
pageIndex -= 1;
|
|
462
|
-
}
|
|
463
|
-
if (startIndex === null || collected.length === 0) return createEmptyManagementResult(limit);
|
|
464
|
-
let paginatedData = collected;
|
|
465
|
-
if (limit > 0 && collected.length > limit) {
|
|
466
|
-
const dropCount = collected.length - limit;
|
|
467
|
-
paginatedData = collected.slice(dropCount);
|
|
468
|
-
startIndex += dropCount;
|
|
469
|
-
}
|
|
470
|
-
const pagination = require_calculatePagination.calculatePagination(root.total, {
|
|
471
|
-
limit,
|
|
472
|
-
offset: startIndex
|
|
473
|
-
});
|
|
474
|
-
return {
|
|
475
|
-
data: paginatedData,
|
|
476
|
-
pagination: {
|
|
477
|
-
...pagination,
|
|
478
|
-
...paginatedData.length > 0 && startIndex + paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {},
|
|
479
|
-
...paginatedData.length > 0 && startIndex > 0 ? { previousCursor: paginatedData[0]?.id } : {}
|
|
480
|
-
}
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
const pageIndex = 0;
|
|
484
|
-
const startInPage = 0;
|
|
485
|
-
const data = [];
|
|
486
|
-
for (let currentPageIndex = pageIndex; currentPageIndex < root.pages.length && (limit <= 0 || data.length < limit); currentPageIndex++) {
|
|
487
|
-
const descriptor = root.pages[currentPageIndex];
|
|
488
|
-
const page = await loadManagementPage(descriptor, pageCache);
|
|
489
|
-
if (!page) return require_paginateBundles.paginateBundles({
|
|
490
|
-
bundles: await loadAllBundlesForManagementFallback(),
|
|
491
|
-
limit,
|
|
492
|
-
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
|
|
493
137
|
});
|
|
494
|
-
data.push(...currentPageIndex === pageIndex ? page.slice(startInPage) : page);
|
|
495
138
|
}
|
|
496
|
-
const paginatedData = limit > 0 ? data.slice(0, limit) : data;
|
|
497
|
-
return {
|
|
498
|
-
data: paginatedData,
|
|
499
|
-
pagination: {
|
|
500
|
-
...require_calculatePagination.calculatePagination(root.total, {
|
|
501
|
-
limit,
|
|
502
|
-
offset: 0
|
|
503
|
-
}),
|
|
504
|
-
...paginatedData.length > 0 && paginatedData.length < root.total ? { nextCursor: paginatedData.at(-1)?.id } : {}
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
139
|
};
|
|
508
|
-
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 = [""]) {
|
|
509
146
|
bundlesMap.clear();
|
|
510
|
-
|
|
511
|
-
|
|
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) => ({
|
|
512
151
|
...bundle,
|
|
513
152
|
_updateJsonKey: key
|
|
514
153
|
}));
|
|
@@ -517,39 +156,18 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
517
156
|
for (const [id, bundle] of pendingBundlesMap.entries()) bundlesMap.set(id, bundle);
|
|
518
157
|
return (0, es_toolkit.orderBy)(Array.from(bundlesMap.values()), [(v) => v.id], ["desc"]);
|
|
519
158
|
}
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
* Returns true if the file was updated, false if no changes were made.
|
|
523
|
-
*/
|
|
524
|
-
async function updateTargetVersionsForPlatform(platform) {
|
|
525
|
-
const updateJsonPattern = new RegExp(`^[^/]+/${platform}/[^/]+/update\\.json$`);
|
|
526
|
-
const targetVersionsPattern = new RegExp(`^[^/]+/${platform}/target-app-versions\\.json$`);
|
|
527
|
-
const allKeys = await listObjects("");
|
|
528
|
-
const updateJsonKeys = allKeys.filter((key) => updateJsonPattern.test(key));
|
|
529
|
-
const targetVersionsKeys = allKeys.filter((key) => targetVersionsPattern.test(key));
|
|
530
|
-
const keysByChannel = updateJsonKeys.reduce((acc, key) => {
|
|
531
|
-
const channel = key.split("/")[0];
|
|
532
|
-
acc[channel] = acc[channel] || [];
|
|
533
|
-
acc[channel].push(key);
|
|
534
|
-
return acc;
|
|
535
|
-
}, {});
|
|
536
|
-
for (const key of targetVersionsKeys) {
|
|
537
|
-
const channel = key.split("/")[0];
|
|
538
|
-
if (!keysByChannel[channel]) keysByChannel[channel] = [];
|
|
539
|
-
}
|
|
540
|
-
for (const channel of Object.keys(keysByChannel)) {
|
|
541
|
-
const updateKeys = keysByChannel[channel];
|
|
159
|
+
async function applyTargetVersionMutations(mutations) {
|
|
160
|
+
await Promise.all(Array.from(mutations.values()).map(async ({ additions, channel, platform, removals }) => {
|
|
542
161
|
const targetKey = `${channel}/${platform}/target-app-versions.json`;
|
|
543
|
-
const currentVersions = updateKeys.map((key) => key.split("/")[2]);
|
|
544
162
|
const oldTargetVersions = await loadOptionalObject(targetKey) ?? [];
|
|
545
|
-
const newTargetVersions = oldTargetVersions.filter((
|
|
546
|
-
for (const
|
|
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);
|
|
547
165
|
if (JSON.stringify(oldTargetVersions) !== JSON.stringify(newTargetVersions)) await uploadObject(targetKey, newTargetVersions);
|
|
548
|
-
}
|
|
166
|
+
}));
|
|
549
167
|
}
|
|
550
168
|
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }, context) => {
|
|
551
169
|
const bundles = (await mapWithConcurrency(require_filterCompatibleAppVersions.filterCompatibleAppVersions(await loadOptionalObject(`${channel}/${platform}/target-app-versions.json`) ?? [], appVersion), STORAGE_OPERATION_CONCURRENCY, async (targetAppVersion) => {
|
|
552
|
-
return
|
|
170
|
+
return loadBundleObject(`${channel}/${platform}/${normalizeTargetAppVersion(targetAppVersion) ?? targetAppVersion}/update.json`);
|
|
553
171
|
})).flat();
|
|
554
172
|
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
555
173
|
args: {
|
|
@@ -566,7 +184,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
566
184
|
});
|
|
567
185
|
};
|
|
568
186
|
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }, context) => {
|
|
569
|
-
const bundles = await
|
|
187
|
+
const bundles = await loadBundleObject(`${channel}/${platform}/${fingerprintHash}/update.json`);
|
|
570
188
|
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
571
189
|
args: {
|
|
572
190
|
_updateStrategy: "fingerprint",
|
|
@@ -600,54 +218,16 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
600
218
|
targetAppVersion
|
|
601
219
|
});
|
|
602
220
|
};
|
|
603
|
-
const bundleIndexDiagnostics = {
|
|
604
|
-
async check() {
|
|
605
|
-
const canonicalBundles = await loadCanonicalBundlesForIndexRepair();
|
|
606
|
-
const allRoot = await loadStoredManagementRoot({});
|
|
607
|
-
return compareBundleIndex({
|
|
608
|
-
canonicalBundles,
|
|
609
|
-
indexedBundles: allRoot ? await loadAllBundlesFromRoot(allRoot) : null,
|
|
610
|
-
rootMissing: !allRoot
|
|
611
|
-
});
|
|
612
|
-
},
|
|
613
|
-
async repair() {
|
|
614
|
-
const canonicalBundles = await loadCanonicalBundlesForIndexRepair();
|
|
615
|
-
const previousRoot = await loadStoredManagementRoot({});
|
|
616
|
-
const previousBundles = previousRoot ? await loadAllBundlesFromRoot(previousRoot) : null;
|
|
617
|
-
const previousArtifacts = previousRoot && previousBundles ? buildManagementIndexArtifacts(previousBundles, previousRoot.pageSize) : void 0;
|
|
618
|
-
const nextArtifacts = buildManagementIndexArtifacts(canonicalBundles, managementIndexPageSize);
|
|
619
|
-
const indexedObjectKeys = await listObjects(`${MANAGEMENT_INDEX_PREFIX}/`);
|
|
620
|
-
const nextObjectKeys = new Set([...nextArtifacts.pages.keys(), ...nextArtifacts.scopes.map((scope) => scope.rootKey)]);
|
|
621
|
-
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
622
|
-
await forEachWithConcurrency(indexedObjectKeys.filter((key) => !nextObjectKeys.has(key)), STORAGE_OPERATION_CONCURRENCY, (key) => deleteObject(key).catch(() => {}));
|
|
623
|
-
replaceManagementRootCache(nextArtifacts);
|
|
624
|
-
return {
|
|
625
|
-
scannedBundles: canonicalBundles.length,
|
|
626
|
-
indexedBundles: canonicalBundles.length,
|
|
627
|
-
...summarizeManagementIndexArtifacts(nextArtifacts)
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
221
|
const createPlugin = require_createDatabasePlugin.createDatabasePlugin({
|
|
632
222
|
name,
|
|
633
223
|
factory: () => ({
|
|
634
224
|
supportsCursorPagination: true,
|
|
635
225
|
async getBundleById(bundleId) {
|
|
226
|
+
if (locallyDeletedBundleIds.has(bundleId)) return null;
|
|
636
227
|
const pendingBundle = pendingBundlesMap.get(bundleId);
|
|
637
228
|
if (pendingBundle) return removeBundleInternalKeys(pendingBundle);
|
|
638
229
|
const bundle = bundlesMap.get(bundleId);
|
|
639
230
|
if (bundle) return removeBundleInternalKeys(bundle);
|
|
640
|
-
const allRoot = await loadManagementScopeRoot({});
|
|
641
|
-
if (allRoot) {
|
|
642
|
-
const matchedBundle = await loadBundleFromManagementRoot(allRoot, bundleId);
|
|
643
|
-
if (matchedBundle) return removeBundleInternalKeys(createHydratedBundle(matchedBundle));
|
|
644
|
-
managementRootCache.delete(ALL_SCOPE_CACHE_KEY);
|
|
645
|
-
const refreshedAllRoot = await loadStoredManagementRoot({});
|
|
646
|
-
if (refreshedAllRoot) {
|
|
647
|
-
const refreshedBundle = await loadBundleFromManagementRoot(refreshedAllRoot, bundleId);
|
|
648
|
-
if (refreshedBundle) return removeBundleInternalKeys(createHydratedBundle(refreshedBundle));
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
231
|
const matchedBundle = (await reloadBundles()).find((item) => item.id === bundleId);
|
|
652
232
|
if (!matchedBundle) return null;
|
|
653
233
|
return removeBundleInternalKeys(matchedBundle);
|
|
@@ -658,18 +238,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
658
238
|
},
|
|
659
239
|
async getBundles(options) {
|
|
660
240
|
const { where, limit, offset, orderBy, cursor } = options;
|
|
661
|
-
|
|
662
|
-
if (scope) {
|
|
663
|
-
const root = await loadManagementScopeRoot(scope);
|
|
664
|
-
if (!root) return createEmptyManagementResult(limit);
|
|
665
|
-
return readPagedBundles({
|
|
666
|
-
root,
|
|
667
|
-
limit,
|
|
668
|
-
offset,
|
|
669
|
-
cursor
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
let allBundles = await loadAllBundlesForManagementFallback();
|
|
241
|
+
let allBundles = await loadAllBundlesForManagementFallback(where);
|
|
673
242
|
if (where) allBundles = allBundles.filter((bundle) => require_queryBundles.bundleMatchesQueryWhere(bundle, where));
|
|
674
243
|
return require_paginateBundles.paginateBundles({
|
|
675
244
|
bundles: allBundles,
|
|
@@ -680,14 +249,15 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
680
249
|
});
|
|
681
250
|
},
|
|
682
251
|
async getChannels() {
|
|
683
|
-
return (await
|
|
252
|
+
return [...new Set((await loadAllBundlesForManagementFallback()).map((bundle) => bundle.channel))].sort();
|
|
684
253
|
},
|
|
685
254
|
async commitBundle({ changedSets }) {
|
|
686
255
|
if (changedSets.length === 0) return;
|
|
687
256
|
const changedBundlesByKey = {};
|
|
688
257
|
const removalsByKey = {};
|
|
258
|
+
const targetVersionRemovalsByKey = {};
|
|
689
259
|
const pathsToInvalidate = /* @__PURE__ */ new Set();
|
|
690
|
-
const
|
|
260
|
+
const targetVersionMutations = /* @__PURE__ */ new Map();
|
|
691
261
|
for (const { operation, data } of changedSets) {
|
|
692
262
|
if (operation === "insert") {
|
|
693
263
|
const target = resolveStorageTarget(data);
|
|
@@ -696,11 +266,12 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
696
266
|
...data,
|
|
697
267
|
_updateJsonKey: key
|
|
698
268
|
};
|
|
269
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
699
270
|
bundlesMap.set(data.id, bundleWithKey);
|
|
700
271
|
pendingBundlesMap.set(data.id, bundleWithKey);
|
|
701
272
|
changedBundlesByKey[key] = changedBundlesByKey[key] || [];
|
|
702
273
|
changedBundlesByKey[key].push(removeBundleInternalKeys(bundleWithKey));
|
|
703
|
-
|
|
274
|
+
addTargetVersionAddition(targetVersionMutations, data);
|
|
704
275
|
addLookupInvalidationPaths(pathsToInvalidate, data);
|
|
705
276
|
continue;
|
|
706
277
|
}
|
|
@@ -710,10 +281,12 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
710
281
|
if (!bundle) throw new Error("Bundle to delete not found");
|
|
711
282
|
bundlesMap.delete(data.id);
|
|
712
283
|
pendingBundlesMap.delete(data.id);
|
|
284
|
+
locallyDeletedBundleIds.add(data.id);
|
|
713
285
|
const key = bundle._updateJsonKey;
|
|
714
286
|
removalsByKey[key] = removalsByKey[key] || [];
|
|
715
287
|
removalsByKey[key].push(bundle.id);
|
|
716
|
-
|
|
288
|
+
targetVersionRemovalsByKey[key] = targetVersionRemovalsByKey[key] || [];
|
|
289
|
+
targetVersionRemovalsByKey[key].push(bundle);
|
|
717
290
|
addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
718
291
|
continue;
|
|
719
292
|
}
|
|
@@ -730,11 +303,14 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
730
303
|
const oldKey = bundle._updateJsonKey;
|
|
731
304
|
removalsByKey[oldKey] = removalsByKey[oldKey] || [];
|
|
732
305
|
removalsByKey[oldKey].push(bundle.id);
|
|
306
|
+
targetVersionRemovalsByKey[oldKey] = targetVersionRemovalsByKey[oldKey] || [];
|
|
307
|
+
targetVersionRemovalsByKey[oldKey].push(bundle);
|
|
733
308
|
changedBundlesByKey[newKey] = changedBundlesByKey[newKey] || [];
|
|
734
309
|
updatedBundle._oldUpdateJsonKey = oldKey;
|
|
735
310
|
updatedBundle._updateJsonKey = newKey;
|
|
736
311
|
bundlesMap.set(data.id, updatedBundle);
|
|
737
312
|
pendingBundlesMap.set(data.id, updatedBundle);
|
|
313
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
738
314
|
changedBundlesByKey[newKey].push(removeBundleInternalKeys(updatedBundle));
|
|
739
315
|
const oldChannel = bundle.channel;
|
|
740
316
|
const nextChannel = updatedBundle.channel;
|
|
@@ -745,10 +321,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
745
321
|
channel: nextChannel
|
|
746
322
|
});
|
|
747
323
|
}
|
|
748
|
-
|
|
749
|
-
targetVersionPlatforms.add(bundle.platform);
|
|
750
|
-
targetVersionPlatforms.add(updatedBundle.platform);
|
|
751
|
-
}
|
|
324
|
+
addTargetVersionAddition(targetVersionMutations, updatedBundle);
|
|
752
325
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
753
326
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
754
327
|
continue;
|
|
@@ -756,17 +329,21 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
756
329
|
const currentKey = bundle._updateJsonKey;
|
|
757
330
|
bundlesMap.set(data.id, updatedBundle);
|
|
758
331
|
pendingBundlesMap.set(data.id, updatedBundle);
|
|
332
|
+
locallyDeletedBundleIds.delete(data.id);
|
|
759
333
|
changedBundlesByKey[currentKey] = changedBundlesByKey[currentKey] || [];
|
|
760
334
|
changedBundlesByKey[currentKey].push(removeBundleInternalKeys(updatedBundle));
|
|
761
335
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
336
|
+
addTargetVersionAddition(targetVersionMutations, updatedBundle);
|
|
762
337
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
763
338
|
}
|
|
764
339
|
}
|
|
765
340
|
await forEachWithConcurrency(Object.keys(removalsByKey), STORAGE_OPERATION_CONCURRENCY, async (oldKey) => {
|
|
766
341
|
const updatedBundles = (await loadOptionalObject(oldKey) ?? []).filter((b) => !removalsByKey[oldKey].includes(b.id));
|
|
767
342
|
updatedBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
768
|
-
if (updatedBundles.length === 0)
|
|
769
|
-
|
|
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);
|
|
770
347
|
});
|
|
771
348
|
await forEachWithConcurrency(Object.keys(changedBundlesByKey), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
772
349
|
const currentBundles = await loadOptionalObject(key) ?? [];
|
|
@@ -779,22 +356,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
779
356
|
currentBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
780
357
|
await uploadObject(key, currentBundles);
|
|
781
358
|
});
|
|
782
|
-
if (
|
|
783
|
-
const previousIndexBundles = await loadCurrentBundlesForIndexRebuild();
|
|
784
|
-
const storedIndexBundles = await loadStoredBundlesForIndexRebuild();
|
|
785
|
-
const nextIndexMap = new Map(storedIndexBundles.map((bundle) => [bundle.id, bundle]));
|
|
786
|
-
for (const { operation, data } of changedSets) {
|
|
787
|
-
if (operation === "delete") {
|
|
788
|
-
nextIndexMap.delete(data.id);
|
|
789
|
-
continue;
|
|
790
|
-
}
|
|
791
|
-
nextIndexMap.set(data.id, data);
|
|
792
|
-
}
|
|
793
|
-
const nextIndexBundles = sortManagedBundles(Array.from(nextIndexMap.values()));
|
|
794
|
-
const previousArtifacts = buildManagementIndexArtifacts(previousIndexBundles, managementIndexPageSize);
|
|
795
|
-
const nextArtifacts = buildManagementIndexArtifacts(nextIndexBundles, managementIndexPageSize);
|
|
796
|
-
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
797
|
-
replaceManagementRootCache(nextArtifacts);
|
|
359
|
+
if (targetVersionMutations.size > 0) await applyTargetVersionMutations(targetVersionMutations);
|
|
798
360
|
const encondedPaths = /* @__PURE__ */ new Set();
|
|
799
361
|
for (const path of pathsToInvalidate) encondedPaths.add(encodeURI(path));
|
|
800
362
|
await invalidatePaths(Array.from(encondedPaths));
|
|
@@ -803,13 +365,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
803
365
|
})
|
|
804
366
|
})({}, hooks);
|
|
805
367
|
return () => {
|
|
806
|
-
|
|
807
|
-
Object.defineProperty(plugin, "diagnostics", {
|
|
808
|
-
configurable: true,
|
|
809
|
-
enumerable: true,
|
|
810
|
-
value: { bundleIndex: bundleIndexDiagnostics }
|
|
811
|
-
});
|
|
812
|
-
return plugin;
|
|
368
|
+
return createPlugin();
|
|
813
369
|
};
|
|
814
370
|
};
|
|
815
371
|
};
|