@hot-updater/plugin-core 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/createBlobDatabasePlugin.cjs +154 -54
- package/dist/createBlobDatabasePlugin.d.cts +1 -0
- package/dist/createBlobDatabasePlugin.d.mts +1 -0
- package/dist/createBlobDatabasePlugin.mjs +154 -54
- package/dist/createDatabasePluginGetUpdateInfo.cjs +11 -3
- package/dist/createDatabasePluginGetUpdateInfo.mjs +11 -3
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +4 -2
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +3 -1
- package/dist/requestUpdateBundleState.cjs +20 -0
- package/dist/requestUpdateBundleState.d.cts +6 -0
- package/dist/requestUpdateBundleState.d.mts +6 -0
- package/dist/requestUpdateBundleState.mjs +19 -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/dist/types/index.d.cts +24 -1
- package/dist/types/index.d.mts +24 -1
- package/package.json +4 -4
|
@@ -4,11 +4,29 @@ const require_createDatabasePlugin = require("./createDatabasePlugin.cjs");
|
|
|
4
4
|
const require_filterCompatibleAppVersions = require("./filterCompatibleAppVersions.cjs");
|
|
5
5
|
const require_queryBundles = require("./queryBundles.cjs");
|
|
6
6
|
const require_paginateBundles = require("./paginateBundles.cjs");
|
|
7
|
-
|
|
7
|
+
const require_resolveUpdateInfoFromBundles = require("./resolveUpdateInfoFromBundles.cjs");
|
|
8
8
|
let es_toolkit = require("es-toolkit");
|
|
9
9
|
let semver = require("semver");
|
|
10
10
|
semver = require_runtime.__toESM(semver);
|
|
11
11
|
//#region src/createBlobDatabasePlugin.ts
|
|
12
|
+
const STORAGE_OPERATION_CONCURRENCY = 8;
|
|
13
|
+
async function mapWithConcurrency(items, concurrency, mapper) {
|
|
14
|
+
const results = [];
|
|
15
|
+
let nextIndex = 0;
|
|
16
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
17
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
18
|
+
while (true) {
|
|
19
|
+
const index = nextIndex;
|
|
20
|
+
nextIndex += 1;
|
|
21
|
+
if (index >= items.length) break;
|
|
22
|
+
results[index] = await mapper(items[index], index);
|
|
23
|
+
}
|
|
24
|
+
}));
|
|
25
|
+
return results;
|
|
26
|
+
}
|
|
27
|
+
async function forEachWithConcurrency(items, concurrency, mapper) {
|
|
28
|
+
await mapWithConcurrency(items, concurrency, mapper);
|
|
29
|
+
}
|
|
12
30
|
function removeBundleInternalKeys(bundle) {
|
|
13
31
|
const { _updateJsonKey, _oldUpdateJsonKey, ...pureBundle } = bundle;
|
|
14
32
|
return pureBundle;
|
|
@@ -57,6 +75,12 @@ const MANAGEMENT_INDEX_PREFIX = "_index";
|
|
|
57
75
|
const MANAGEMENT_INDEX_VERSION = 1;
|
|
58
76
|
const DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE = 128;
|
|
59
77
|
const ALL_SCOPE_CACHE_KEY = "*|*";
|
|
78
|
+
function summarizeManagementIndexArtifacts(artifacts) {
|
|
79
|
+
return {
|
|
80
|
+
pagesWritten: artifacts.pages.size,
|
|
81
|
+
scopesWritten: artifacts.scopes.length
|
|
82
|
+
};
|
|
83
|
+
}
|
|
60
84
|
function resolveManagementIndexPageSize(config) {
|
|
61
85
|
const pageSize = config.managementIndexPageSize ?? DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE;
|
|
62
86
|
if (!Number.isInteger(pageSize) || pageSize < 1) throw new Error("managementIndexPageSize must be a positive integer.");
|
|
@@ -188,11 +212,18 @@ function buildManagementIndexArtifacts(allBundles, pageSize) {
|
|
|
188
212
|
const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
189
213
|
return (config, hooks) => {
|
|
190
214
|
const managementIndexPageSize = resolveManagementIndexPageSize(config);
|
|
191
|
-
const { listObjects, loadObject, uploadObject, deleteObject, invalidatePaths, apiBasePath } = factory(config);
|
|
215
|
+
const { listObjects, loadObject, uploadObject, deleteObject, shouldSkipLoadObjectError, invalidatePaths, apiBasePath } = factory(config);
|
|
192
216
|
const bundlesMap = /* @__PURE__ */ new Map();
|
|
193
217
|
const pendingBundlesMap = /* @__PURE__ */ new Map();
|
|
194
218
|
const managementRootCache = /* @__PURE__ */ new Map();
|
|
195
|
-
const
|
|
219
|
+
const loadOptionalObject = async (key) => {
|
|
220
|
+
try {
|
|
221
|
+
return await loadObject(key);
|
|
222
|
+
} catch (error) {
|
|
223
|
+
if (shouldSkipLoadObjectError?.(error, key)) return null;
|
|
224
|
+
throw error;
|
|
225
|
+
}
|
|
226
|
+
};
|
|
196
227
|
const getAllManagementArtifact = (artifacts) => {
|
|
197
228
|
const allArtifact = artifacts.scopes.find((scope) => scope.cacheKey === ALL_SCOPE_CACHE_KEY);
|
|
198
229
|
if (!allArtifact) throw new Error("all-bundles management index artifact not found");
|
|
@@ -209,7 +240,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
209
240
|
};
|
|
210
241
|
const loadStoredManagementRoot = async (scope) => {
|
|
211
242
|
const cacheKey = getManagementScopeCacheKey(scope);
|
|
212
|
-
const storedRoot = await
|
|
243
|
+
const storedRoot = await loadOptionalObject(getManagementRootKey(scope));
|
|
213
244
|
if (storedRoot) {
|
|
214
245
|
managementRootCache.set(cacheKey, storedRoot);
|
|
215
246
|
return storedRoot;
|
|
@@ -219,7 +250,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
219
250
|
};
|
|
220
251
|
const loadManagementPage = async (descriptor, pageCache) => {
|
|
221
252
|
if (pageCache?.has(descriptor.key)) return pageCache.get(descriptor.key) ?? null;
|
|
222
|
-
const page = await
|
|
253
|
+
const page = await loadOptionalObject(descriptor.key);
|
|
223
254
|
pageCache?.set(descriptor.key, page);
|
|
224
255
|
return page;
|
|
225
256
|
};
|
|
@@ -242,13 +273,13 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
242
273
|
return allBundles;
|
|
243
274
|
};
|
|
244
275
|
const persistManagementIndexArtifacts = async (nextArtifacts, previousArtifacts) => {
|
|
245
|
-
|
|
246
|
-
|
|
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));
|
|
247
278
|
if (!previousArtifacts) return;
|
|
248
279
|
const nextPageKeys = new Set(nextArtifacts.pages.keys());
|
|
249
280
|
const nextRootKeys = new Set(nextArtifacts.scopes.map((scope) => scope.rootKey));
|
|
250
|
-
|
|
251
|
-
|
|
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(() => {}));
|
|
252
283
|
};
|
|
253
284
|
const ensureAllManagementRoot = async () => {
|
|
254
285
|
const storedAllRoot = await loadStoredManagementRoot({});
|
|
@@ -281,6 +312,26 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
281
312
|
const loadCurrentBundlesForIndexRebuild = async () => {
|
|
282
313
|
return loadAllBundlesForManagementFallback();
|
|
283
314
|
};
|
|
315
|
+
const loadBundlesFromCanonicalManifests = async () => {
|
|
316
|
+
return sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
317
|
+
};
|
|
318
|
+
const loadStoredBundlesForIndexRebuild = loadBundlesFromCanonicalManifests;
|
|
319
|
+
const loadCanonicalBundlesForIndexRepair = loadBundlesFromCanonicalManifests;
|
|
320
|
+
const compareBundleIndex = ({ canonicalBundles, indexedBundles, rootMissing }) => {
|
|
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
|
+
};
|
|
284
335
|
const findPageIndexContainingId = (pages, id) => {
|
|
285
336
|
return pages.findIndex((page) => id.localeCompare(page.firstId) <= 0 && id.localeCompare(page.lastId) >= 0);
|
|
286
337
|
};
|
|
@@ -456,16 +507,15 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
456
507
|
};
|
|
457
508
|
async function reloadBundles() {
|
|
458
509
|
bundlesMap.clear();
|
|
459
|
-
const
|
|
460
|
-
return (await
|
|
510
|
+
const allBundles = (await mapWithConcurrency((await listObjects("")).filter((key) => /^[^/]+\/(?:ios|android)\/[^/]+\/update\.json$/.test(key)), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
511
|
+
return (await loadOptionalObject(key) ?? []).map((bundle) => ({
|
|
461
512
|
...bundle,
|
|
462
513
|
_updateJsonKey: key
|
|
463
514
|
}));
|
|
464
|
-
});
|
|
465
|
-
const allBundles = (await Promise.all(filePromises)).flat();
|
|
515
|
+
})).flat();
|
|
466
516
|
for (const bundle of allBundles) bundlesMap.set(bundle.id, bundle);
|
|
467
517
|
for (const [id, bundle] of pendingBundlesMap.entries()) bundlesMap.set(id, bundle);
|
|
468
|
-
return (0, es_toolkit.orderBy)(
|
|
518
|
+
return (0, es_toolkit.orderBy)(Array.from(bundlesMap.values()), [(v) => v.id], ["desc"]);
|
|
469
519
|
}
|
|
470
520
|
/**
|
|
471
521
|
* Updates target-app-versions.json for each channel on the given platform.
|
|
@@ -491,35 +541,44 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
491
541
|
const updateKeys = keysByChannel[channel];
|
|
492
542
|
const targetKey = `${channel}/${platform}/target-app-versions.json`;
|
|
493
543
|
const currentVersions = updateKeys.map((key) => key.split("/")[2]);
|
|
494
|
-
const oldTargetVersions = await
|
|
544
|
+
const oldTargetVersions = await loadOptionalObject(targetKey) ?? [];
|
|
495
545
|
const newTargetVersions = oldTargetVersions.filter((v) => currentVersions.includes(v));
|
|
496
546
|
for (const v of currentVersions) if (!newTargetVersions.includes(v)) newTargetVersions.push(v);
|
|
497
547
|
if (JSON.stringify(oldTargetVersions) !== JSON.stringify(newTargetVersions)) await uploadObject(targetKey, newTargetVersions);
|
|
498
548
|
}
|
|
499
549
|
}
|
|
500
|
-
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }) => {
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
550
|
+
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }, context) => {
|
|
551
|
+
const bundles = (await mapWithConcurrency(require_filterCompatibleAppVersions.filterCompatibleAppVersions(await loadOptionalObject(`${channel}/${platform}/target-app-versions.json`) ?? [], appVersion), STORAGE_OPERATION_CONCURRENCY, async (targetAppVersion) => {
|
|
552
|
+
return await loadOptionalObject(`${channel}/${platform}/${normalizeTargetAppVersion(targetAppVersion) ?? targetAppVersion}/update.json`) ?? [];
|
|
553
|
+
})).flat();
|
|
554
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
555
|
+
args: {
|
|
556
|
+
_updateStrategy: "appVersion",
|
|
557
|
+
appVersion,
|
|
558
|
+
bundleId,
|
|
559
|
+
channel,
|
|
560
|
+
cohort,
|
|
561
|
+
minBundleId,
|
|
562
|
+
platform
|
|
563
|
+
},
|
|
564
|
+
bundles,
|
|
565
|
+
context
|
|
512
566
|
});
|
|
513
567
|
};
|
|
514
|
-
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }) => {
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
568
|
+
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }, context) => {
|
|
569
|
+
const bundles = await loadOptionalObject(`${channel}/${platform}/${fingerprintHash}/update.json`) ?? [];
|
|
570
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
571
|
+
args: {
|
|
572
|
+
_updateStrategy: "fingerprint",
|
|
573
|
+
bundleId,
|
|
574
|
+
channel,
|
|
575
|
+
cohort,
|
|
576
|
+
fingerprintHash,
|
|
577
|
+
minBundleId,
|
|
578
|
+
platform
|
|
579
|
+
},
|
|
580
|
+
bundles,
|
|
581
|
+
context
|
|
523
582
|
});
|
|
524
583
|
};
|
|
525
584
|
const addAppVersionInvalidationPaths = (pathsToInvalidate, { platform, channel, targetAppVersion }) => {
|
|
@@ -541,7 +600,35 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
541
600
|
targetAppVersion
|
|
542
601
|
});
|
|
543
602
|
};
|
|
544
|
-
|
|
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
|
+
const createPlugin = require_createDatabasePlugin.createDatabasePlugin({
|
|
545
632
|
name,
|
|
546
633
|
factory: () => ({
|
|
547
634
|
supportsCursorPagination: true,
|
|
@@ -565,9 +652,9 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
565
652
|
if (!matchedBundle) return null;
|
|
566
653
|
return removeBundleInternalKeys(matchedBundle);
|
|
567
654
|
},
|
|
568
|
-
async getUpdateInfo(args) {
|
|
569
|
-
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args);
|
|
570
|
-
return getFingerprintUpdateInfo(args);
|
|
655
|
+
async getUpdateInfo(args, context) {
|
|
656
|
+
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args, context);
|
|
657
|
+
return getFingerprintUpdateInfo(args, context);
|
|
571
658
|
},
|
|
572
659
|
async getBundles(options) {
|
|
573
660
|
const { where, limit, offset, orderBy, cursor } = options;
|
|
@@ -600,11 +687,8 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
600
687
|
const changedBundlesByKey = {};
|
|
601
688
|
const removalsByKey = {};
|
|
602
689
|
const pathsToInvalidate = /* @__PURE__ */ new Set();
|
|
603
|
-
|
|
604
|
-
let isChannelChanged = false;
|
|
690
|
+
const targetVersionPlatforms = /* @__PURE__ */ new Set();
|
|
605
691
|
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
692
|
if (operation === "insert") {
|
|
609
693
|
const target = resolveStorageTarget(data);
|
|
610
694
|
const key = `${data.channel}/${data.platform}/${target}/update.json`;
|
|
@@ -616,6 +700,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
616
700
|
pendingBundlesMap.set(data.id, bundleWithKey);
|
|
617
701
|
changedBundlesByKey[key] = changedBundlesByKey[key] || [];
|
|
618
702
|
changedBundlesByKey[key].push(removeBundleInternalKeys(bundleWithKey));
|
|
703
|
+
if (data.targetAppVersion !== void 0) targetVersionPlatforms.add(data.platform);
|
|
619
704
|
addLookupInvalidationPaths(pathsToInvalidate, data);
|
|
620
705
|
continue;
|
|
621
706
|
}
|
|
@@ -628,6 +713,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
628
713
|
const key = bundle._updateJsonKey;
|
|
629
714
|
removalsByKey[key] = removalsByKey[key] || [];
|
|
630
715
|
removalsByKey[key].push(bundle.id);
|
|
716
|
+
if (bundle.targetAppVersion !== void 0) targetVersionPlatforms.add(bundle.platform);
|
|
631
717
|
addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
632
718
|
continue;
|
|
633
719
|
}
|
|
@@ -659,6 +745,10 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
659
745
|
channel: nextChannel
|
|
660
746
|
});
|
|
661
747
|
}
|
|
748
|
+
if (bundle.targetAppVersion !== void 0 || updatedBundle.targetAppVersion !== void 0) {
|
|
749
|
+
targetVersionPlatforms.add(bundle.platform);
|
|
750
|
+
targetVersionPlatforms.add(updatedBundle.platform);
|
|
751
|
+
}
|
|
662
752
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
663
753
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
664
754
|
continue;
|
|
@@ -672,14 +762,14 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
672
762
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
673
763
|
}
|
|
674
764
|
}
|
|
675
|
-
|
|
676
|
-
const updatedBundles = (await
|
|
765
|
+
await forEachWithConcurrency(Object.keys(removalsByKey), STORAGE_OPERATION_CONCURRENCY, async (oldKey) => {
|
|
766
|
+
const updatedBundles = (await loadOptionalObject(oldKey) ?? []).filter((b) => !removalsByKey[oldKey].includes(b.id));
|
|
677
767
|
updatedBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
678
768
|
if (updatedBundles.length === 0) await deleteObject(oldKey);
|
|
679
769
|
else await uploadObject(oldKey, updatedBundles);
|
|
680
|
-
})
|
|
681
|
-
|
|
682
|
-
const currentBundles = await
|
|
770
|
+
});
|
|
771
|
+
await forEachWithConcurrency(Object.keys(changedBundlesByKey), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
772
|
+
const currentBundles = await loadOptionalObject(key) ?? [];
|
|
683
773
|
const pureBundles = changedBundlesByKey[key].map((bundle) => bundle);
|
|
684
774
|
for (const changedBundle of pureBundles) {
|
|
685
775
|
const index = currentBundles.findIndex((b) => b.id === changedBundle.id);
|
|
@@ -688,10 +778,11 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
688
778
|
}
|
|
689
779
|
currentBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
690
780
|
await uploadObject(key, currentBundles);
|
|
691
|
-
})
|
|
692
|
-
if (
|
|
693
|
-
const
|
|
694
|
-
const
|
|
781
|
+
});
|
|
782
|
+
if (targetVersionPlatforms.size > 0) await Promise.all(Array.from(targetVersionPlatforms).map((platform) => updateTargetVersionsForPlatform(platform)));
|
|
783
|
+
const previousIndexBundles = await loadCurrentBundlesForIndexRebuild();
|
|
784
|
+
const storedIndexBundles = await loadStoredBundlesForIndexRebuild();
|
|
785
|
+
const nextIndexMap = new Map(storedIndexBundles.map((bundle) => [bundle.id, bundle]));
|
|
695
786
|
for (const { operation, data } of changedSets) {
|
|
696
787
|
if (operation === "delete") {
|
|
697
788
|
nextIndexMap.delete(data.id);
|
|
@@ -700,7 +791,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
700
791
|
nextIndexMap.set(data.id, data);
|
|
701
792
|
}
|
|
702
793
|
const nextIndexBundles = sortManagedBundles(Array.from(nextIndexMap.values()));
|
|
703
|
-
const previousArtifacts = buildManagementIndexArtifacts(
|
|
794
|
+
const previousArtifacts = buildManagementIndexArtifacts(previousIndexBundles, managementIndexPageSize);
|
|
704
795
|
const nextArtifacts = buildManagementIndexArtifacts(nextIndexBundles, managementIndexPageSize);
|
|
705
796
|
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
706
797
|
replaceManagementRootCache(nextArtifacts);
|
|
@@ -711,6 +802,15 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
711
802
|
}
|
|
712
803
|
})
|
|
713
804
|
})({}, hooks);
|
|
805
|
+
return () => {
|
|
806
|
+
const plugin = createPlugin();
|
|
807
|
+
Object.defineProperty(plugin, "diagnostics", {
|
|
808
|
+
configurable: true,
|
|
809
|
+
enumerable: true,
|
|
810
|
+
value: { bundleIndex: bundleIndexDiagnostics }
|
|
811
|
+
});
|
|
812
|
+
return plugin;
|
|
813
|
+
};
|
|
714
814
|
};
|
|
715
815
|
};
|
|
716
816
|
//#endregion
|
|
@@ -9,6 +9,7 @@ interface BlobOperations {
|
|
|
9
9
|
loadObject: <T>(key: string) => Promise<T | null>;
|
|
10
10
|
uploadObject: <T>(key: string, data: T) => Promise<void>;
|
|
11
11
|
deleteObject: (key: string) => Promise<void>;
|
|
12
|
+
shouldSkipLoadObjectError?: (error: unknown, key: string) => boolean;
|
|
12
13
|
invalidatePaths: (paths: string[]) => Promise<void>;
|
|
13
14
|
apiBasePath: string;
|
|
14
15
|
}
|
|
@@ -9,6 +9,7 @@ interface BlobOperations {
|
|
|
9
9
|
loadObject: <T>(key: string) => Promise<T | null>;
|
|
10
10
|
uploadObject: <T>(key: string, data: T) => Promise<void>;
|
|
11
11
|
deleteObject: (key: string) => Promise<void>;
|
|
12
|
+
shouldSkipLoadObjectError?: (error: unknown, key: string) => boolean;
|
|
12
13
|
invalidatePaths: (paths: string[]) => Promise<void>;
|
|
13
14
|
apiBasePath: string;
|
|
14
15
|
}
|
|
@@ -3,10 +3,28 @@ import { createDatabasePlugin } from "./createDatabasePlugin.mjs";
|
|
|
3
3
|
import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.mjs";
|
|
4
4
|
import { bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
|
|
5
5
|
import { paginateBundles } from "./paginateBundles.mjs";
|
|
6
|
-
import {
|
|
6
|
+
import { resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
|
|
7
7
|
import { orderBy } from "es-toolkit";
|
|
8
8
|
import semver from "semver";
|
|
9
9
|
//#region src/createBlobDatabasePlugin.ts
|
|
10
|
+
const STORAGE_OPERATION_CONCURRENCY = 8;
|
|
11
|
+
async function mapWithConcurrency(items, concurrency, mapper) {
|
|
12
|
+
const results = [];
|
|
13
|
+
let nextIndex = 0;
|
|
14
|
+
const workerCount = Math.min(concurrency, items.length);
|
|
15
|
+
await Promise.all(Array.from({ length: workerCount }, async () => {
|
|
16
|
+
while (true) {
|
|
17
|
+
const index = nextIndex;
|
|
18
|
+
nextIndex += 1;
|
|
19
|
+
if (index >= items.length) break;
|
|
20
|
+
results[index] = await mapper(items[index], index);
|
|
21
|
+
}
|
|
22
|
+
}));
|
|
23
|
+
return results;
|
|
24
|
+
}
|
|
25
|
+
async function forEachWithConcurrency(items, concurrency, mapper) {
|
|
26
|
+
await mapWithConcurrency(items, concurrency, mapper);
|
|
27
|
+
}
|
|
10
28
|
function removeBundleInternalKeys(bundle) {
|
|
11
29
|
const { _updateJsonKey, _oldUpdateJsonKey, ...pureBundle } = bundle;
|
|
12
30
|
return pureBundle;
|
|
@@ -55,6 +73,12 @@ const MANAGEMENT_INDEX_PREFIX = "_index";
|
|
|
55
73
|
const MANAGEMENT_INDEX_VERSION = 1;
|
|
56
74
|
const DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE = 128;
|
|
57
75
|
const ALL_SCOPE_CACHE_KEY = "*|*";
|
|
76
|
+
function summarizeManagementIndexArtifacts(artifacts) {
|
|
77
|
+
return {
|
|
78
|
+
pagesWritten: artifacts.pages.size,
|
|
79
|
+
scopesWritten: artifacts.scopes.length
|
|
80
|
+
};
|
|
81
|
+
}
|
|
58
82
|
function resolveManagementIndexPageSize(config) {
|
|
59
83
|
const pageSize = config.managementIndexPageSize ?? DEFAULT_MANAGEMENT_INDEX_PAGE_SIZE;
|
|
60
84
|
if (!Number.isInteger(pageSize) || pageSize < 1) throw new Error("managementIndexPageSize must be a positive integer.");
|
|
@@ -186,11 +210,18 @@ function buildManagementIndexArtifacts(allBundles, pageSize) {
|
|
|
186
210
|
const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
187
211
|
return (config, hooks) => {
|
|
188
212
|
const managementIndexPageSize = resolveManagementIndexPageSize(config);
|
|
189
|
-
const { listObjects, loadObject, uploadObject, deleteObject, invalidatePaths, apiBasePath } = factory(config);
|
|
213
|
+
const { listObjects, loadObject, uploadObject, deleteObject, shouldSkipLoadObjectError, invalidatePaths, apiBasePath } = factory(config);
|
|
190
214
|
const bundlesMap = /* @__PURE__ */ new Map();
|
|
191
215
|
const pendingBundlesMap = /* @__PURE__ */ new Map();
|
|
192
216
|
const managementRootCache = /* @__PURE__ */ new Map();
|
|
193
|
-
const
|
|
217
|
+
const loadOptionalObject = async (key) => {
|
|
218
|
+
try {
|
|
219
|
+
return await loadObject(key);
|
|
220
|
+
} catch (error) {
|
|
221
|
+
if (shouldSkipLoadObjectError?.(error, key)) return null;
|
|
222
|
+
throw error;
|
|
223
|
+
}
|
|
224
|
+
};
|
|
194
225
|
const getAllManagementArtifact = (artifacts) => {
|
|
195
226
|
const allArtifact = artifacts.scopes.find((scope) => scope.cacheKey === ALL_SCOPE_CACHE_KEY);
|
|
196
227
|
if (!allArtifact) throw new Error("all-bundles management index artifact not found");
|
|
@@ -207,7 +238,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
207
238
|
};
|
|
208
239
|
const loadStoredManagementRoot = async (scope) => {
|
|
209
240
|
const cacheKey = getManagementScopeCacheKey(scope);
|
|
210
|
-
const storedRoot = await
|
|
241
|
+
const storedRoot = await loadOptionalObject(getManagementRootKey(scope));
|
|
211
242
|
if (storedRoot) {
|
|
212
243
|
managementRootCache.set(cacheKey, storedRoot);
|
|
213
244
|
return storedRoot;
|
|
@@ -217,7 +248,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
217
248
|
};
|
|
218
249
|
const loadManagementPage = async (descriptor, pageCache) => {
|
|
219
250
|
if (pageCache?.has(descriptor.key)) return pageCache.get(descriptor.key) ?? null;
|
|
220
|
-
const page = await
|
|
251
|
+
const page = await loadOptionalObject(descriptor.key);
|
|
221
252
|
pageCache?.set(descriptor.key, page);
|
|
222
253
|
return page;
|
|
223
254
|
};
|
|
@@ -240,13 +271,13 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
240
271
|
return allBundles;
|
|
241
272
|
};
|
|
242
273
|
const persistManagementIndexArtifacts = async (nextArtifacts, previousArtifacts) => {
|
|
243
|
-
|
|
244
|
-
|
|
274
|
+
await forEachWithConcurrency(Array.from(nextArtifacts.pages.entries()), STORAGE_OPERATION_CONCURRENCY, ([key, page]) => uploadObject(key, page));
|
|
275
|
+
await forEachWithConcurrency(nextArtifacts.scopes, STORAGE_OPERATION_CONCURRENCY, (scope) => uploadObject(scope.rootKey, scope.root));
|
|
245
276
|
if (!previousArtifacts) return;
|
|
246
277
|
const nextPageKeys = new Set(nextArtifacts.pages.keys());
|
|
247
278
|
const nextRootKeys = new Set(nextArtifacts.scopes.map((scope) => scope.rootKey));
|
|
248
|
-
|
|
249
|
-
|
|
279
|
+
await forEachWithConcurrency(Array.from(previousArtifacts.pages.keys()).filter((key) => !nextPageKeys.has(key)), STORAGE_OPERATION_CONCURRENCY, (key) => deleteObject(key).catch(() => {}));
|
|
280
|
+
await forEachWithConcurrency(previousArtifacts.scopes.filter((scope) => !nextRootKeys.has(scope.rootKey)), STORAGE_OPERATION_CONCURRENCY, (scope) => deleteObject(scope.rootKey).catch(() => {}));
|
|
250
281
|
};
|
|
251
282
|
const ensureAllManagementRoot = async () => {
|
|
252
283
|
const storedAllRoot = await loadStoredManagementRoot({});
|
|
@@ -279,6 +310,26 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
279
310
|
const loadCurrentBundlesForIndexRebuild = async () => {
|
|
280
311
|
return loadAllBundlesForManagementFallback();
|
|
281
312
|
};
|
|
313
|
+
const loadBundlesFromCanonicalManifests = async () => {
|
|
314
|
+
return sortManagedBundles((await reloadBundles()).map((bundle) => removeBundleInternalKeys(bundle)));
|
|
315
|
+
};
|
|
316
|
+
const loadStoredBundlesForIndexRebuild = loadBundlesFromCanonicalManifests;
|
|
317
|
+
const loadCanonicalBundlesForIndexRepair = loadBundlesFromCanonicalManifests;
|
|
318
|
+
const compareBundleIndex = ({ canonicalBundles, indexedBundles, rootMissing }) => {
|
|
319
|
+
const canonicalIds = new Set(canonicalBundles.map((bundle) => bundle.id));
|
|
320
|
+
const indexedIds = new Set(indexedBundles?.map((bundle) => bundle.id) ?? []);
|
|
321
|
+
const missingBundleIds = Array.from(canonicalIds).filter((id) => !indexedIds.has(id)).sort((left, right) => right.localeCompare(left));
|
|
322
|
+
const extraBundleIds = Array.from(indexedIds).filter((id) => !canonicalIds.has(id)).sort((left, right) => right.localeCompare(left));
|
|
323
|
+
return {
|
|
324
|
+
status: missingBundleIds.length === 0 && extraBundleIds.length === 0 && !rootMissing ? "ok" : rootMissing ? "missing" : "stale",
|
|
325
|
+
canonicalBundles: canonicalBundles.length,
|
|
326
|
+
indexedBundles: indexedBundles?.length ?? 0,
|
|
327
|
+
missingBundles: missingBundleIds.length,
|
|
328
|
+
extraBundles: extraBundleIds.length,
|
|
329
|
+
missingBundleIds: missingBundleIds.slice(0, 20),
|
|
330
|
+
extraBundleIds: extraBundleIds.slice(0, 20)
|
|
331
|
+
};
|
|
332
|
+
};
|
|
282
333
|
const findPageIndexContainingId = (pages, id) => {
|
|
283
334
|
return pages.findIndex((page) => id.localeCompare(page.firstId) <= 0 && id.localeCompare(page.lastId) >= 0);
|
|
284
335
|
};
|
|
@@ -454,16 +505,15 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
454
505
|
};
|
|
455
506
|
async function reloadBundles() {
|
|
456
507
|
bundlesMap.clear();
|
|
457
|
-
const
|
|
458
|
-
return (await
|
|
508
|
+
const allBundles = (await mapWithConcurrency((await listObjects("")).filter((key) => /^[^/]+\/(?:ios|android)\/[^/]+\/update\.json$/.test(key)), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
509
|
+
return (await loadOptionalObject(key) ?? []).map((bundle) => ({
|
|
459
510
|
...bundle,
|
|
460
511
|
_updateJsonKey: key
|
|
461
512
|
}));
|
|
462
|
-
});
|
|
463
|
-
const allBundles = (await Promise.all(filePromises)).flat();
|
|
513
|
+
})).flat();
|
|
464
514
|
for (const bundle of allBundles) bundlesMap.set(bundle.id, bundle);
|
|
465
515
|
for (const [id, bundle] of pendingBundlesMap.entries()) bundlesMap.set(id, bundle);
|
|
466
|
-
return orderBy(
|
|
516
|
+
return orderBy(Array.from(bundlesMap.values()), [(v) => v.id], ["desc"]);
|
|
467
517
|
}
|
|
468
518
|
/**
|
|
469
519
|
* Updates target-app-versions.json for each channel on the given platform.
|
|
@@ -489,35 +539,44 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
489
539
|
const updateKeys = keysByChannel[channel];
|
|
490
540
|
const targetKey = `${channel}/${platform}/target-app-versions.json`;
|
|
491
541
|
const currentVersions = updateKeys.map((key) => key.split("/")[2]);
|
|
492
|
-
const oldTargetVersions = await
|
|
542
|
+
const oldTargetVersions = await loadOptionalObject(targetKey) ?? [];
|
|
493
543
|
const newTargetVersions = oldTargetVersions.filter((v) => currentVersions.includes(v));
|
|
494
544
|
for (const v of currentVersions) if (!newTargetVersions.includes(v)) newTargetVersions.push(v);
|
|
495
545
|
if (JSON.stringify(oldTargetVersions) !== JSON.stringify(newTargetVersions)) await uploadObject(targetKey, newTargetVersions);
|
|
496
546
|
}
|
|
497
547
|
}
|
|
498
|
-
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }) => {
|
|
499
|
-
const
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
548
|
+
const getAppVersionUpdateInfo = async ({ appVersion, bundleId, channel = "production", cohort, minBundleId, platform }, context) => {
|
|
549
|
+
const bundles = (await mapWithConcurrency(filterCompatibleAppVersions(await loadOptionalObject(`${channel}/${platform}/target-app-versions.json`) ?? [], appVersion), STORAGE_OPERATION_CONCURRENCY, async (targetAppVersion) => {
|
|
550
|
+
return await loadOptionalObject(`${channel}/${platform}/${normalizeTargetAppVersion(targetAppVersion) ?? targetAppVersion}/update.json`) ?? [];
|
|
551
|
+
})).flat();
|
|
552
|
+
return resolveUpdateInfoFromBundles({
|
|
553
|
+
args: {
|
|
554
|
+
_updateStrategy: "appVersion",
|
|
555
|
+
appVersion,
|
|
556
|
+
bundleId,
|
|
557
|
+
channel,
|
|
558
|
+
cohort,
|
|
559
|
+
minBundleId,
|
|
560
|
+
platform
|
|
561
|
+
},
|
|
562
|
+
bundles,
|
|
563
|
+
context
|
|
510
564
|
});
|
|
511
565
|
};
|
|
512
|
-
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }) => {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
566
|
+
const getFingerprintUpdateInfo = async ({ bundleId, channel = "production", cohort, fingerprintHash, minBundleId, platform }, context) => {
|
|
567
|
+
const bundles = await loadOptionalObject(`${channel}/${platform}/${fingerprintHash}/update.json`) ?? [];
|
|
568
|
+
return resolveUpdateInfoFromBundles({
|
|
569
|
+
args: {
|
|
570
|
+
_updateStrategy: "fingerprint",
|
|
571
|
+
bundleId,
|
|
572
|
+
channel,
|
|
573
|
+
cohort,
|
|
574
|
+
fingerprintHash,
|
|
575
|
+
minBundleId,
|
|
576
|
+
platform
|
|
577
|
+
},
|
|
578
|
+
bundles,
|
|
579
|
+
context
|
|
521
580
|
});
|
|
522
581
|
};
|
|
523
582
|
const addAppVersionInvalidationPaths = (pathsToInvalidate, { platform, channel, targetAppVersion }) => {
|
|
@@ -539,7 +598,35 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
539
598
|
targetAppVersion
|
|
540
599
|
});
|
|
541
600
|
};
|
|
542
|
-
|
|
601
|
+
const bundleIndexDiagnostics = {
|
|
602
|
+
async check() {
|
|
603
|
+
const canonicalBundles = await loadCanonicalBundlesForIndexRepair();
|
|
604
|
+
const allRoot = await loadStoredManagementRoot({});
|
|
605
|
+
return compareBundleIndex({
|
|
606
|
+
canonicalBundles,
|
|
607
|
+
indexedBundles: allRoot ? await loadAllBundlesFromRoot(allRoot) : null,
|
|
608
|
+
rootMissing: !allRoot
|
|
609
|
+
});
|
|
610
|
+
},
|
|
611
|
+
async repair() {
|
|
612
|
+
const canonicalBundles = await loadCanonicalBundlesForIndexRepair();
|
|
613
|
+
const previousRoot = await loadStoredManagementRoot({});
|
|
614
|
+
const previousBundles = previousRoot ? await loadAllBundlesFromRoot(previousRoot) : null;
|
|
615
|
+
const previousArtifacts = previousRoot && previousBundles ? buildManagementIndexArtifacts(previousBundles, previousRoot.pageSize) : void 0;
|
|
616
|
+
const nextArtifacts = buildManagementIndexArtifacts(canonicalBundles, managementIndexPageSize);
|
|
617
|
+
const indexedObjectKeys = await listObjects(`${MANAGEMENT_INDEX_PREFIX}/`);
|
|
618
|
+
const nextObjectKeys = new Set([...nextArtifacts.pages.keys(), ...nextArtifacts.scopes.map((scope) => scope.rootKey)]);
|
|
619
|
+
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
620
|
+
await forEachWithConcurrency(indexedObjectKeys.filter((key) => !nextObjectKeys.has(key)), STORAGE_OPERATION_CONCURRENCY, (key) => deleteObject(key).catch(() => {}));
|
|
621
|
+
replaceManagementRootCache(nextArtifacts);
|
|
622
|
+
return {
|
|
623
|
+
scannedBundles: canonicalBundles.length,
|
|
624
|
+
indexedBundles: canonicalBundles.length,
|
|
625
|
+
...summarizeManagementIndexArtifacts(nextArtifacts)
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
const createPlugin = createDatabasePlugin({
|
|
543
630
|
name,
|
|
544
631
|
factory: () => ({
|
|
545
632
|
supportsCursorPagination: true,
|
|
@@ -563,9 +650,9 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
563
650
|
if (!matchedBundle) return null;
|
|
564
651
|
return removeBundleInternalKeys(matchedBundle);
|
|
565
652
|
},
|
|
566
|
-
async getUpdateInfo(args) {
|
|
567
|
-
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args);
|
|
568
|
-
return getFingerprintUpdateInfo(args);
|
|
653
|
+
async getUpdateInfo(args, context) {
|
|
654
|
+
if (args._updateStrategy === "appVersion") return getAppVersionUpdateInfo(args, context);
|
|
655
|
+
return getFingerprintUpdateInfo(args, context);
|
|
569
656
|
},
|
|
570
657
|
async getBundles(options) {
|
|
571
658
|
const { where, limit, offset, orderBy, cursor } = options;
|
|
@@ -598,11 +685,8 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
598
685
|
const changedBundlesByKey = {};
|
|
599
686
|
const removalsByKey = {};
|
|
600
687
|
const pathsToInvalidate = /* @__PURE__ */ new Set();
|
|
601
|
-
|
|
602
|
-
let isChannelChanged = false;
|
|
688
|
+
const targetVersionPlatforms = /* @__PURE__ */ new Set();
|
|
603
689
|
for (const { operation, data } of changedSets) {
|
|
604
|
-
if (data.targetAppVersion !== void 0) isTargetAppVersionChanged = true;
|
|
605
|
-
if (operation === "update" && data.channel !== void 0) isChannelChanged = true;
|
|
606
690
|
if (operation === "insert") {
|
|
607
691
|
const target = resolveStorageTarget(data);
|
|
608
692
|
const key = `${data.channel}/${data.platform}/${target}/update.json`;
|
|
@@ -614,6 +698,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
614
698
|
pendingBundlesMap.set(data.id, bundleWithKey);
|
|
615
699
|
changedBundlesByKey[key] = changedBundlesByKey[key] || [];
|
|
616
700
|
changedBundlesByKey[key].push(removeBundleInternalKeys(bundleWithKey));
|
|
701
|
+
if (data.targetAppVersion !== void 0) targetVersionPlatforms.add(data.platform);
|
|
617
702
|
addLookupInvalidationPaths(pathsToInvalidate, data);
|
|
618
703
|
continue;
|
|
619
704
|
}
|
|
@@ -626,6 +711,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
626
711
|
const key = bundle._updateJsonKey;
|
|
627
712
|
removalsByKey[key] = removalsByKey[key] || [];
|
|
628
713
|
removalsByKey[key].push(bundle.id);
|
|
714
|
+
if (bundle.targetAppVersion !== void 0) targetVersionPlatforms.add(bundle.platform);
|
|
629
715
|
addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
630
716
|
continue;
|
|
631
717
|
}
|
|
@@ -657,6 +743,10 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
657
743
|
channel: nextChannel
|
|
658
744
|
});
|
|
659
745
|
}
|
|
746
|
+
if (bundle.targetAppVersion !== void 0 || updatedBundle.targetAppVersion !== void 0) {
|
|
747
|
+
targetVersionPlatforms.add(bundle.platform);
|
|
748
|
+
targetVersionPlatforms.add(updatedBundle.platform);
|
|
749
|
+
}
|
|
660
750
|
addLookupInvalidationPaths(pathsToInvalidate, updatedBundle);
|
|
661
751
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
662
752
|
continue;
|
|
@@ -670,14 +760,14 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
670
760
|
if (bundle.targetAppVersion && bundle.targetAppVersion !== updatedBundle.targetAppVersion) addLookupInvalidationPaths(pathsToInvalidate, bundle);
|
|
671
761
|
}
|
|
672
762
|
}
|
|
673
|
-
|
|
674
|
-
const updatedBundles = (await
|
|
763
|
+
await forEachWithConcurrency(Object.keys(removalsByKey), STORAGE_OPERATION_CONCURRENCY, async (oldKey) => {
|
|
764
|
+
const updatedBundles = (await loadOptionalObject(oldKey) ?? []).filter((b) => !removalsByKey[oldKey].includes(b.id));
|
|
675
765
|
updatedBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
676
766
|
if (updatedBundles.length === 0) await deleteObject(oldKey);
|
|
677
767
|
else await uploadObject(oldKey, updatedBundles);
|
|
678
|
-
})
|
|
679
|
-
|
|
680
|
-
const currentBundles = await
|
|
768
|
+
});
|
|
769
|
+
await forEachWithConcurrency(Object.keys(changedBundlesByKey), STORAGE_OPERATION_CONCURRENCY, async (key) => {
|
|
770
|
+
const currentBundles = await loadOptionalObject(key) ?? [];
|
|
681
771
|
const pureBundles = changedBundlesByKey[key].map((bundle) => bundle);
|
|
682
772
|
for (const changedBundle of pureBundles) {
|
|
683
773
|
const index = currentBundles.findIndex((b) => b.id === changedBundle.id);
|
|
@@ -686,10 +776,11 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
686
776
|
}
|
|
687
777
|
currentBundles.sort((a, b) => b.id.localeCompare(a.id));
|
|
688
778
|
await uploadObject(key, currentBundles);
|
|
689
|
-
})
|
|
690
|
-
if (
|
|
691
|
-
const
|
|
692
|
-
const
|
|
779
|
+
});
|
|
780
|
+
if (targetVersionPlatforms.size > 0) await Promise.all(Array.from(targetVersionPlatforms).map((platform) => updateTargetVersionsForPlatform(platform)));
|
|
781
|
+
const previousIndexBundles = await loadCurrentBundlesForIndexRebuild();
|
|
782
|
+
const storedIndexBundles = await loadStoredBundlesForIndexRebuild();
|
|
783
|
+
const nextIndexMap = new Map(storedIndexBundles.map((bundle) => [bundle.id, bundle]));
|
|
693
784
|
for (const { operation, data } of changedSets) {
|
|
694
785
|
if (operation === "delete") {
|
|
695
786
|
nextIndexMap.delete(data.id);
|
|
@@ -698,7 +789,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
698
789
|
nextIndexMap.set(data.id, data);
|
|
699
790
|
}
|
|
700
791
|
const nextIndexBundles = sortManagedBundles(Array.from(nextIndexMap.values()));
|
|
701
|
-
const previousArtifacts = buildManagementIndexArtifacts(
|
|
792
|
+
const previousArtifacts = buildManagementIndexArtifacts(previousIndexBundles, managementIndexPageSize);
|
|
702
793
|
const nextArtifacts = buildManagementIndexArtifacts(nextIndexBundles, managementIndexPageSize);
|
|
703
794
|
await persistManagementIndexArtifacts(nextArtifacts, previousArtifacts);
|
|
704
795
|
replaceManagementRootCache(nextArtifacts);
|
|
@@ -709,6 +800,15 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
|
|
|
709
800
|
}
|
|
710
801
|
})
|
|
711
802
|
})({}, hooks);
|
|
803
|
+
return () => {
|
|
804
|
+
const plugin = createPlugin();
|
|
805
|
+
Object.defineProperty(plugin, "diagnostics", {
|
|
806
|
+
configurable: true,
|
|
807
|
+
enumerable: true,
|
|
808
|
+
value: { bundleIndex: bundleIndexDiagnostics }
|
|
809
|
+
});
|
|
810
|
+
return plugin;
|
|
811
|
+
};
|
|
712
812
|
};
|
|
713
813
|
};
|
|
714
814
|
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
const require_filterCompatibleAppVersions = require("./filterCompatibleAppVersions.cjs");
|
|
3
|
-
|
|
3
|
+
const require_resolveUpdateInfoFromBundles = require("./resolveUpdateInfoFromBundles.cjs");
|
|
4
4
|
let _hot_updater_core = require("@hot-updater/core");
|
|
5
5
|
//#region src/createDatabasePluginGetUpdateInfo.ts
|
|
6
6
|
const normalizeAppVersionArgs = (args) => ({
|
|
@@ -18,10 +18,18 @@ const createDatabasePluginGetUpdateInfo = ({ getBundlesByFingerprint, getBundles
|
|
|
18
18
|
if (args._updateStrategy === "appVersion") {
|
|
19
19
|
const normalizedArgs = normalizeAppVersionArgs(args);
|
|
20
20
|
const compatibleAppVersions = require_filterCompatibleAppVersions.filterCompatibleAppVersions(await listTargetAppVersions(normalizedArgs, context), normalizedArgs.appVersion);
|
|
21
|
-
return
|
|
21
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
22
|
+
args: normalizedArgs,
|
|
23
|
+
bundles: compatibleAppVersions.length > 0 ? await getBundlesByTargetAppVersions(normalizedArgs, compatibleAppVersions, context) : [],
|
|
24
|
+
context
|
|
25
|
+
});
|
|
22
26
|
}
|
|
23
27
|
const normalizedArgs = normalizeFingerprintArgs(args);
|
|
24
|
-
return
|
|
28
|
+
return require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles({
|
|
29
|
+
args: normalizedArgs,
|
|
30
|
+
bundles: await getBundlesByFingerprint(normalizedArgs, context),
|
|
31
|
+
context
|
|
32
|
+
});
|
|
25
33
|
};
|
|
26
34
|
};
|
|
27
35
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
|
|
3
3
|
import { NIL_UUID } from "@hot-updater/core";
|
|
4
4
|
//#region src/createDatabasePluginGetUpdateInfo.ts
|
|
5
5
|
const normalizeAppVersionArgs = (args) => ({
|
|
@@ -17,10 +17,18 @@ const createDatabasePluginGetUpdateInfo = ({ getBundlesByFingerprint, getBundles
|
|
|
17
17
|
if (args._updateStrategy === "appVersion") {
|
|
18
18
|
const normalizedArgs = normalizeAppVersionArgs(args);
|
|
19
19
|
const compatibleAppVersions = filterCompatibleAppVersions(await listTargetAppVersions(normalizedArgs, context), normalizedArgs.appVersion);
|
|
20
|
-
return
|
|
20
|
+
return resolveUpdateInfoFromBundles({
|
|
21
|
+
args: normalizedArgs,
|
|
22
|
+
bundles: compatibleAppVersions.length > 0 ? await getBundlesByTargetAppVersions(normalizedArgs, compatibleAppVersions, context) : [],
|
|
23
|
+
context
|
|
24
|
+
});
|
|
21
25
|
}
|
|
22
26
|
const normalizedArgs = normalizeFingerprintArgs(args);
|
|
23
|
-
return
|
|
27
|
+
return resolveUpdateInfoFromBundles({
|
|
28
|
+
args: normalizedArgs,
|
|
29
|
+
bundles: await getBundlesByFingerprint(normalizedArgs, context),
|
|
30
|
+
context
|
|
31
|
+
});
|
|
24
32
|
};
|
|
25
33
|
};
|
|
26
34
|
//#endregion
|
package/dist/index.cjs
CHANGED
|
@@ -8,6 +8,8 @@ const require_semverSatisfies = require("./semverSatisfies.cjs");
|
|
|
8
8
|
const require_filterCompatibleAppVersions = require("./filterCompatibleAppVersions.cjs");
|
|
9
9
|
const require_queryBundles = require("./queryBundles.cjs");
|
|
10
10
|
const require_paginateBundles = require("./paginateBundles.cjs");
|
|
11
|
+
const require_requestUpdateBundleState = require("./requestUpdateBundleState.cjs");
|
|
12
|
+
const require_resolveUpdateInfoFromBundles = require("./resolveUpdateInfoFromBundles.cjs");
|
|
11
13
|
const require_createBlobDatabasePlugin = require("./createBlobDatabasePlugin.cjs");
|
|
12
14
|
const require_createDatabasePluginGetUpdateInfo = require("./createDatabasePluginGetUpdateInfo.cjs");
|
|
13
15
|
const require_createStorageKeyBuilder = require("./createStorageKeyBuilder.cjs");
|
|
@@ -41,12 +43,14 @@ exports.getCompressionMimeType = require_compressionFormat.getCompressionMimeTyp
|
|
|
41
43
|
exports.getContentAddressedAssetStoragePath = require_contentAddressedAssets.getContentAddressedAssetStoragePath;
|
|
42
44
|
exports.getContentType = require_compressionFormat.getContentType;
|
|
43
45
|
exports.getManifestAssetStoragePath = require_assetStorageLayout.getManifestAssetStoragePath;
|
|
46
|
+
exports.getRequestUpdateBundleSeeds = require_requestUpdateBundleState.getRequestUpdateBundleSeeds;
|
|
44
47
|
exports.isContentAddressedAssetBaseStorageUri = require_assetStorageLayout.isContentAddressedAssetBaseStorageUri;
|
|
45
48
|
exports.isNodeStoragePlugin = require_storageProfile.isNodeStoragePlugin;
|
|
46
49
|
exports.isRuntimeStoragePlugin = require_storageProfile.isRuntimeStoragePlugin;
|
|
47
50
|
exports.paginateBundles = require_paginateBundles.paginateBundles;
|
|
48
51
|
exports.parseStorageUri = require_parseStorageUri.parseStorageUri;
|
|
49
52
|
exports.resolveManifestAssetStorageUri = require_assetStorageLayout.resolveManifestAssetStorageUri;
|
|
53
|
+
exports.resolveUpdateInfoFromBundles = require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles;
|
|
50
54
|
exports.semverSatisfies = require_semverSatisfies.semverSatisfies;
|
|
51
55
|
exports.sortBundles = require_queryBundles.sortBundles;
|
|
52
56
|
exports.supportedIosPlatforms = require_index.supportedIosPlatforms;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BuiltIns, HasMultipleCallSignatures, Primitive, RequiredDeep } from "./types/utils.cjs";
|
|
2
|
-
import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.cjs";
|
|
2
|
+
import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.cjs";
|
|
3
3
|
import { PaginationOptions, calculatePagination } from "./calculatePagination.cjs";
|
|
4
4
|
import { CompressionFormat, CompressionFormatInfo, detectCompressionFormat, getCompressionMimeType, getContentType } from "./compressionFormat.cjs";
|
|
5
5
|
import { AssetStorageLayout, createStorageUriWithRelativePath, getAssetStorageLayout, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, resolveManifestAssetStorageUri } from "./assetStorageLayout.cjs";
|
|
@@ -14,7 +14,9 @@ import { generateMinBundleId } from "./generateMinBundleId.cjs";
|
|
|
14
14
|
import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.cjs";
|
|
15
15
|
import { paginateBundles } from "./paginateBundles.cjs";
|
|
16
16
|
import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.cjs";
|
|
17
|
+
import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.cjs";
|
|
18
|
+
import { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.cjs";
|
|
17
19
|
import { semverSatisfies } from "./semverSatisfies.cjs";
|
|
18
20
|
import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.cjs";
|
|
19
21
|
import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.cjs";
|
|
20
|
-
export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, AssetStorageLayout, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
|
|
22
|
+
export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, AssetStorageLayout, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, ResolveUpdateInfoFromBundlesOptions, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, getRequestUpdateBundleSeeds, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, resolveUpdateInfoFromBundles, semverSatisfies, sortBundles, supportedIosPlatforms };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { BuiltIns, HasMultipleCallSignatures, Primitive, RequiredDeep } from "./types/utils.mjs";
|
|
2
|
-
import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.mjs";
|
|
2
|
+
import { AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, supportedIosPlatforms } from "./types/index.mjs";
|
|
3
3
|
import { PaginationOptions, calculatePagination } from "./calculatePagination.mjs";
|
|
4
4
|
import { CompressionFormat, CompressionFormatInfo, detectCompressionFormat, getCompressionMimeType, getContentType } from "./compressionFormat.mjs";
|
|
5
5
|
import { AssetStorageLayout, createStorageUriWithRelativePath, getAssetStorageLayout, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, resolveManifestAssetStorageUri } from "./assetStorageLayout.mjs";
|
|
@@ -14,7 +14,9 @@ import { generateMinBundleId } from "./generateMinBundleId.mjs";
|
|
|
14
14
|
import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.mjs";
|
|
15
15
|
import { paginateBundles } from "./paginateBundles.mjs";
|
|
16
16
|
import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
|
|
17
|
+
import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.mjs";
|
|
18
|
+
import { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
|
|
17
19
|
import { semverSatisfies } from "./semverSatisfies.mjs";
|
|
18
20
|
import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
|
|
19
21
|
import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
|
|
20
|
-
export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, AssetStorageLayout, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
|
|
22
|
+
export { AbstractDatabasePlugin, AppVersionGetBundlesArgs, ApplePlatform, AssetStorageLayout, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, FingerprintGetBundlesArgs, GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, ResolveUpdateInfoFromBundlesOptions, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, getRequestUpdateBundleSeeds, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, resolveUpdateInfoFromBundles, semverSatisfies, sortBundles, supportedIosPlatforms };
|
package/dist/index.mjs
CHANGED
|
@@ -7,6 +7,8 @@ import { semverSatisfies } from "./semverSatisfies.mjs";
|
|
|
7
7
|
import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.mjs";
|
|
8
8
|
import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
|
|
9
9
|
import { paginateBundles } from "./paginateBundles.mjs";
|
|
10
|
+
import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.mjs";
|
|
11
|
+
import { resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
|
|
10
12
|
import { createBlobDatabasePlugin } from "./createBlobDatabasePlugin.mjs";
|
|
11
13
|
import { createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.mjs";
|
|
12
14
|
import { createStorageKeyBuilder } from "./createStorageKeyBuilder.mjs";
|
|
@@ -16,4 +18,4 @@ import { parseStorageUri } from "./parseStorageUri.mjs";
|
|
|
16
18
|
import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
|
|
17
19
|
import { supportedIosPlatforms } from "./types/index.mjs";
|
|
18
20
|
import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
|
|
19
|
-
export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, semverSatisfies, sortBundles, supportedIosPlatforms };
|
|
21
|
+
export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createStorageUriWithRelativePath, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getAssetStorageLayout, getCompressionMimeType, getContentAddressedAssetStoragePath, getContentType, getManifestAssetStoragePath, getRequestUpdateBundleSeeds, isContentAddressedAssetBaseStorageUri, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, resolveManifestAssetStorageUri, resolveUpdateInfoFromBundles, semverSatisfies, sortBundles, supportedIosPlatforms };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/requestUpdateBundleState.ts
|
|
2
|
+
const requestUpdateBundleSeeds = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const isWeakMapKey = (value) => typeof value === "object" && value !== null || typeof value === "function";
|
|
4
|
+
const toBundleSeeds = (seeds) => seeds.filter((seed) => !!seed);
|
|
5
|
+
const seedRequestUpdateBundles = (context, seeds) => {
|
|
6
|
+
if (!isWeakMapKey(context)) return;
|
|
7
|
+
const nextSeeds = toBundleSeeds(seeds);
|
|
8
|
+
if (nextSeeds.length === 0) return;
|
|
9
|
+
const bundlesById = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const seed of requestUpdateBundleSeeds.get(context) ?? []) bundlesById.set(seed.id, seed);
|
|
11
|
+
for (const seed of nextSeeds) bundlesById.set(seed.id, seed);
|
|
12
|
+
requestUpdateBundleSeeds.set(context, [...bundlesById.values()]);
|
|
13
|
+
};
|
|
14
|
+
const getRequestUpdateBundleSeeds = (context) => {
|
|
15
|
+
if (!isWeakMapKey(context)) return [];
|
|
16
|
+
return requestUpdateBundleSeeds.get(context) ?? [];
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.getRequestUpdateBundleSeeds = getRequestUpdateBundleSeeds;
|
|
20
|
+
exports.seedRequestUpdateBundles = seedRequestUpdateBundles;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Bundle, HotUpdaterContext } from "./types/index.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/requestUpdateBundleState.d.ts
|
|
4
|
+
declare const getRequestUpdateBundleSeeds: <TContext = unknown>(context: HotUpdaterContext<TContext> | undefined) => readonly Bundle[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getRequestUpdateBundleSeeds };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Bundle, HotUpdaterContext } from "./types/index.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/requestUpdateBundleState.d.ts
|
|
4
|
+
declare const getRequestUpdateBundleSeeds: <TContext = unknown>(context: HotUpdaterContext<TContext> | undefined) => readonly Bundle[];
|
|
5
|
+
//#endregion
|
|
6
|
+
export { getRequestUpdateBundleSeeds };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/requestUpdateBundleState.ts
|
|
2
|
+
const requestUpdateBundleSeeds = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
const isWeakMapKey = (value) => typeof value === "object" && value !== null || typeof value === "function";
|
|
4
|
+
const toBundleSeeds = (seeds) => seeds.filter((seed) => !!seed);
|
|
5
|
+
const seedRequestUpdateBundles = (context, seeds) => {
|
|
6
|
+
if (!isWeakMapKey(context)) return;
|
|
7
|
+
const nextSeeds = toBundleSeeds(seeds);
|
|
8
|
+
if (nextSeeds.length === 0) return;
|
|
9
|
+
const bundlesById = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const seed of requestUpdateBundleSeeds.get(context) ?? []) bundlesById.set(seed.id, seed);
|
|
11
|
+
for (const seed of nextSeeds) bundlesById.set(seed.id, seed);
|
|
12
|
+
requestUpdateBundleSeeds.set(context, [...bundlesById.values()]);
|
|
13
|
+
};
|
|
14
|
+
const getRequestUpdateBundleSeeds = (context) => {
|
|
15
|
+
if (!isWeakMapKey(context)) return [];
|
|
16
|
+
return requestUpdateBundleSeeds.get(context) ?? [];
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { getRequestUpdateBundleSeeds, seedRequestUpdateBundles };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require("./_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_requestUpdateBundleState = require("./requestUpdateBundleState.cjs");
|
|
3
|
+
let _hot_updater_core = require("@hot-updater/core");
|
|
4
|
+
let _hot_updater_js = require("@hot-updater/js");
|
|
5
|
+
//#region src/resolveUpdateInfoFromBundles.ts
|
|
6
|
+
const findSeedBundle = (bundles, bundleId) => bundles.find((bundle) => bundle.id === bundleId);
|
|
7
|
+
const resolveUpdateInfoFromBundles = async ({ args, bundles, context }) => {
|
|
8
|
+
const info = await (0, _hot_updater_js.getUpdateInfo)(bundles, args);
|
|
9
|
+
if (!info) return null;
|
|
10
|
+
require_requestUpdateBundleState.seedRequestUpdateBundles(context, [findSeedBundle(bundles, info.id), args.bundleId === _hot_updater_core.NIL_UUID ? null : findSeedBundle(bundles, args.bundleId)]);
|
|
11
|
+
return info;
|
|
12
|
+
};
|
|
13
|
+
//#endregion
|
|
14
|
+
exports.resolveUpdateInfoFromBundles = resolveUpdateInfoFromBundles;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Bundle as Bundle$1, HotUpdaterContext } from "./types/index.cjs";
|
|
2
|
+
import { GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
|
|
3
|
+
|
|
4
|
+
//#region src/resolveUpdateInfoFromBundles.d.ts
|
|
5
|
+
interface ResolveUpdateInfoFromBundlesOptions<TContext = unknown> {
|
|
6
|
+
readonly args: GetBundlesArgs;
|
|
7
|
+
readonly bundles: Bundle$1[];
|
|
8
|
+
readonly context?: HotUpdaterContext<TContext>;
|
|
9
|
+
}
|
|
10
|
+
declare const resolveUpdateInfoFromBundles: <TContext = unknown>({
|
|
11
|
+
args,
|
|
12
|
+
bundles,
|
|
13
|
+
context
|
|
14
|
+
}: ResolveUpdateInfoFromBundlesOptions<TContext>) => Promise<UpdateInfo | null>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Bundle as Bundle$1, HotUpdaterContext } from "./types/index.mjs";
|
|
2
|
+
import { GetBundlesArgs, UpdateInfo } from "@hot-updater/core";
|
|
3
|
+
|
|
4
|
+
//#region src/resolveUpdateInfoFromBundles.d.ts
|
|
5
|
+
interface ResolveUpdateInfoFromBundlesOptions<TContext = unknown> {
|
|
6
|
+
readonly args: GetBundlesArgs;
|
|
7
|
+
readonly bundles: Bundle$1[];
|
|
8
|
+
readonly context?: HotUpdaterContext<TContext>;
|
|
9
|
+
}
|
|
10
|
+
declare const resolveUpdateInfoFromBundles: <TContext = unknown>({
|
|
11
|
+
args,
|
|
12
|
+
bundles,
|
|
13
|
+
context
|
|
14
|
+
}: ResolveUpdateInfoFromBundlesOptions<TContext>) => Promise<UpdateInfo | null>;
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { seedRequestUpdateBundles } from "./requestUpdateBundleState.mjs";
|
|
2
|
+
import { NIL_UUID } from "@hot-updater/core";
|
|
3
|
+
import { getUpdateInfo } from "@hot-updater/js";
|
|
4
|
+
//#region src/resolveUpdateInfoFromBundles.ts
|
|
5
|
+
const findSeedBundle = (bundles, bundleId) => bundles.find((bundle) => bundle.id === bundleId);
|
|
6
|
+
const resolveUpdateInfoFromBundles = async ({ args, bundles, context }) => {
|
|
7
|
+
const info = await getUpdateInfo(bundles, args);
|
|
8
|
+
if (!info) return null;
|
|
9
|
+
seedRequestUpdateBundles(context, [findSeedBundle(bundles, info.id), args.bundleId === NIL_UUID ? null : findSeedBundle(bundles, args.bundleId)]);
|
|
10
|
+
return info;
|
|
11
|
+
};
|
|
12
|
+
//#endregion
|
|
13
|
+
export { resolveUpdateInfoFromBundles };
|
package/dist/types/index.d.cts
CHANGED
|
@@ -69,6 +69,28 @@ interface DatabaseBundleQueryOptions {
|
|
|
69
69
|
cursor?: DatabaseBundleCursor;
|
|
70
70
|
orderBy?: DatabaseBundleQueryOrder;
|
|
71
71
|
}
|
|
72
|
+
interface BundleIndexHealth {
|
|
73
|
+
status: "ok" | "missing" | "stale";
|
|
74
|
+
canonicalBundles: number;
|
|
75
|
+
indexedBundles: number;
|
|
76
|
+
missingBundles: number;
|
|
77
|
+
extraBundles: number;
|
|
78
|
+
missingBundleIds: string[];
|
|
79
|
+
extraBundleIds: string[];
|
|
80
|
+
}
|
|
81
|
+
interface BundleIndexRepairResult {
|
|
82
|
+
scannedBundles: number;
|
|
83
|
+
indexedBundles: number;
|
|
84
|
+
pagesWritten: number;
|
|
85
|
+
scopesWritten: number;
|
|
86
|
+
}
|
|
87
|
+
interface BundleIndexDiagnostics<TContext = unknown> {
|
|
88
|
+
check: (context?: HotUpdaterContext<TContext>) => Promise<BundleIndexHealth>;
|
|
89
|
+
repair?: (context?: HotUpdaterContext<TContext>) => Promise<BundleIndexRepairResult>;
|
|
90
|
+
}
|
|
91
|
+
interface DatabaseDiagnostics<TContext = unknown> {
|
|
92
|
+
bundleIndex?: BundleIndexDiagnostics<TContext>;
|
|
93
|
+
}
|
|
72
94
|
interface BuildPluginConfig {
|
|
73
95
|
outDir?: string;
|
|
74
96
|
}
|
|
@@ -80,6 +102,7 @@ interface DatabasePlugin<TContext = unknown> {
|
|
|
80
102
|
updateBundle: (targetBundleId: string, newBundle: Partial<Bundle>, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
81
103
|
appendBundle: (insertBundle: Bundle, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
82
104
|
commitBundle: (context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
105
|
+
diagnostics?: DatabaseDiagnostics<TContext>;
|
|
83
106
|
onUnmount?: () => Promise<void>;
|
|
84
107
|
name: string;
|
|
85
108
|
deleteBundle: (deleteBundle: Bundle, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
@@ -504,4 +527,4 @@ interface NativeBuildOptions {
|
|
|
504
527
|
scheme?: string;
|
|
505
528
|
}
|
|
506
529
|
//#endregion
|
|
507
|
-
export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
|
|
530
|
+
export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
|
package/dist/types/index.d.mts
CHANGED
|
@@ -69,6 +69,28 @@ interface DatabaseBundleQueryOptions {
|
|
|
69
69
|
cursor?: DatabaseBundleCursor;
|
|
70
70
|
orderBy?: DatabaseBundleQueryOrder;
|
|
71
71
|
}
|
|
72
|
+
interface BundleIndexHealth {
|
|
73
|
+
status: "ok" | "missing" | "stale";
|
|
74
|
+
canonicalBundles: number;
|
|
75
|
+
indexedBundles: number;
|
|
76
|
+
missingBundles: number;
|
|
77
|
+
extraBundles: number;
|
|
78
|
+
missingBundleIds: string[];
|
|
79
|
+
extraBundleIds: string[];
|
|
80
|
+
}
|
|
81
|
+
interface BundleIndexRepairResult {
|
|
82
|
+
scannedBundles: number;
|
|
83
|
+
indexedBundles: number;
|
|
84
|
+
pagesWritten: number;
|
|
85
|
+
scopesWritten: number;
|
|
86
|
+
}
|
|
87
|
+
interface BundleIndexDiagnostics<TContext = unknown> {
|
|
88
|
+
check: (context?: HotUpdaterContext<TContext>) => Promise<BundleIndexHealth>;
|
|
89
|
+
repair?: (context?: HotUpdaterContext<TContext>) => Promise<BundleIndexRepairResult>;
|
|
90
|
+
}
|
|
91
|
+
interface DatabaseDiagnostics<TContext = unknown> {
|
|
92
|
+
bundleIndex?: BundleIndexDiagnostics<TContext>;
|
|
93
|
+
}
|
|
72
94
|
interface BuildPluginConfig {
|
|
73
95
|
outDir?: string;
|
|
74
96
|
}
|
|
@@ -80,6 +102,7 @@ interface DatabasePlugin<TContext = unknown> {
|
|
|
80
102
|
updateBundle: (targetBundleId: string, newBundle: Partial<Bundle>, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
81
103
|
appendBundle: (insertBundle: Bundle, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
82
104
|
commitBundle: (context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
105
|
+
diagnostics?: DatabaseDiagnostics<TContext>;
|
|
83
106
|
onUnmount?: () => Promise<void>;
|
|
84
107
|
name: string;
|
|
85
108
|
deleteBundle: (deleteBundle: Bundle, context?: HotUpdaterContext<TContext>) => Promise<void>;
|
|
@@ -504,4 +527,4 @@ interface NativeBuildOptions {
|
|
|
504
527
|
scheme?: string;
|
|
505
528
|
}
|
|
506
529
|
//#endregion
|
|
507
|
-
export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
|
|
530
|
+
export { type AppVersionGetBundlesArgs$1 as AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BuildPlugin, BuildPluginConfig, type Bundle$1 as Bundle, BundleIndexDiagnostics, BundleIndexHealth, BundleIndexRepairResult, ConfigInput, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabaseDiagnostics, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs$1 as FingerprintGetBundlesArgs, type GetBundlesArgs$1 as GetBundlesArgs, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, type Platform$1 as Platform, PlatformConfig, RequestEnvContext, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo$1 as UpdateInfo, supportedIosPlatforms };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/plugin-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
"es-toolkit": "^1.32.0",
|
|
43
43
|
"mime": "^4.0.4",
|
|
44
44
|
"semver": "^7.7.2",
|
|
45
|
-
"@hot-updater/
|
|
46
|
-
"@hot-updater/
|
|
45
|
+
"@hot-updater/js": "0.33.0",
|
|
46
|
+
"@hot-updater/core": "0.33.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/node": "^20",
|
|
50
50
|
"@types/semver": "^7.5.8",
|
|
51
51
|
"typescript": "6.0.2",
|
|
52
|
-
"@hot-updater/test-utils": "0.
|
|
52
|
+
"@hot-updater/test-utils": "0.33.0"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
55
|
"build": "tsdown",
|