@hot-updater/plugin-core 0.31.4 → 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.
Files changed (35) hide show
  1. package/dist/assetStorageLayout.cjs +34 -0
  2. package/dist/assetStorageLayout.d.cts +31 -0
  3. package/dist/assetStorageLayout.d.mts +31 -0
  4. package/dist/assetStorageLayout.mjs +30 -0
  5. package/dist/compressionFormat.cjs +2 -2
  6. package/dist/contentAddressedAssets.cjs +7 -0
  7. package/dist/contentAddressedAssets.d.cts +10 -0
  8. package/dist/contentAddressedAssets.d.mts +10 -0
  9. package/dist/contentAddressedAssets.mjs +7 -0
  10. package/dist/createBlobDatabasePlugin.cjs +155 -55
  11. package/dist/createBlobDatabasePlugin.d.cts +1 -0
  12. package/dist/createBlobDatabasePlugin.d.mts +1 -0
  13. package/dist/createBlobDatabasePlugin.mjs +154 -54
  14. package/dist/createDatabasePluginGetUpdateInfo.cjs +11 -3
  15. package/dist/createDatabasePluginGetUpdateInfo.mjs +11 -3
  16. package/dist/createStoragePlugin.cjs +3 -0
  17. package/dist/createStoragePlugin.mjs +3 -0
  18. package/dist/index.cjs +12 -0
  19. package/dist/index.d.cts +6 -2
  20. package/dist/index.d.mts +6 -2
  21. package/dist/index.mjs +5 -1
  22. package/dist/legacyAssetStorageLayout.cjs +12 -0
  23. package/dist/legacyAssetStorageLayout.mjs +12 -0
  24. package/dist/requestUpdateBundleState.cjs +20 -0
  25. package/dist/requestUpdateBundleState.d.cts +6 -0
  26. package/dist/requestUpdateBundleState.d.mts +6 -0
  27. package/dist/requestUpdateBundleState.mjs +19 -0
  28. package/dist/resolveUpdateInfoFromBundles.cjs +14 -0
  29. package/dist/resolveUpdateInfoFromBundles.d.cts +16 -0
  30. package/dist/resolveUpdateInfoFromBundles.d.mts +16 -0
  31. package/dist/resolveUpdateInfoFromBundles.mjs +13 -0
  32. package/dist/semverSatisfies.cjs +1 -1
  33. package/dist/types/index.d.cts +47 -1
  34. package/dist/types/index.d.mts +47 -1
  35. package/package.json +4 -4
@@ -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 { getUpdateInfo } from "@hot-updater/js";
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 PLATFORMS = ["ios", "android"];
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 loadObject(getManagementRootKey(scope));
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 loadObject(descriptor.key);
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
- for (const [key, page] of nextArtifacts.pages.entries()) await uploadObject(key, page);
244
- for (const scope of nextArtifacts.scopes) await uploadObject(scope.rootKey, scope.root);
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
- for (const [key] of previousArtifacts.pages.entries()) if (!nextPageKeys.has(key)) await deleteObject(key).catch(() => {});
249
- for (const scope of previousArtifacts.scopes) if (!nextRootKeys.has(scope.rootKey)) await deleteObject(scope.rootKey).catch(() => {});
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 filePromises = (await listObjects("")).filter((key) => /^[^/]+\/(?:ios|android)\/[^/]+\/update\.json$/.test(key)).map(async (key) => {
458
- return (await loadObject(key) ?? []).map((bundle) => ({
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(allBundles, [(v) => v.id], ["desc"]);
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 loadObject(targetKey) ?? [];
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 matchingVersions = filterCompatibleAppVersions(await loadObject(`${channel}/${platform}/target-app-versions.json`) ?? [], appVersion);
500
- return getUpdateInfo((await Promise.allSettled(matchingVersions.map(async (targetAppVersion) => {
501
- return await loadObject(`${channel}/${platform}/${normalizeTargetAppVersion(targetAppVersion) ?? targetAppVersion}/update.json`) ?? [];
502
- }))).filter((entry) => entry.status === "fulfilled").flatMap((entry) => entry.value), {
503
- _updateStrategy: "appVersion",
504
- appVersion,
505
- bundleId,
506
- channel,
507
- cohort,
508
- minBundleId,
509
- platform
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
- return getUpdateInfo(await loadObject(`${channel}/${platform}/${fingerprintHash}/update.json`) ?? [], {
514
- _updateStrategy: "fingerprint",
515
- bundleId,
516
- channel,
517
- cohort,
518
- fingerprintHash,
519
- minBundleId,
520
- platform
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
- return createDatabasePlugin({
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
- let isTargetAppVersionChanged = false;
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
- for (const oldKey of Object.keys(removalsByKey)) await (async () => {
674
- const updatedBundles = (await loadObject(oldKey) ?? []).filter((b) => !removalsByKey[oldKey].includes(b.id));
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
- for (const key of Object.keys(changedBundlesByKey)) await (async () => {
680
- const currentBundles = await loadObject(key) ?? [];
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 (isTargetAppVersionChanged || isChannelChanged) for (const platform of PLATFORMS) await updateTargetVersionsForPlatform(platform);
691
- const currentIndexBundles = await loadCurrentBundlesForIndexRebuild();
692
- const nextIndexMap = new Map(currentIndexBundles.map((bundle) => [bundle.id, bundle]));
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(currentIndexBundles, managementIndexPageSize);
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
- let _hot_updater_js = require("@hot-updater/js");
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 (0, _hot_updater_js.getUpdateInfo)(compatibleAppVersions.length > 0 ? await getBundlesByTargetAppVersions(normalizedArgs, compatibleAppVersions, context) : [], normalizedArgs);
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 (0, _hot_updater_js.getUpdateInfo)(await getBundlesByFingerprint(normalizedArgs, context), normalizedArgs);
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 { getUpdateInfo } from "@hot-updater/js";
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 getUpdateInfo(compatibleAppVersions.length > 0 ? await getBundlesByTargetAppVersions(normalizedArgs, compatibleAppVersions, context) : [], normalizedArgs);
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 getUpdateInfo(await getBundlesByFingerprint(normalizedArgs, context), normalizedArgs);
27
+ return resolveUpdateInfoFromBundles({
28
+ args: normalizedArgs,
29
+ bundles: await getBundlesByFingerprint(normalizedArgs, context),
30
+ context
31
+ });
24
32
  };
25
33
  };
26
34
  //#endregion
@@ -45,6 +45,9 @@ const createProfiledStoragePlugin = ({ createProfiles, name, profileShape, suppo
45
45
  async downloadFile(storageUri, filePath) {
46
46
  return requireNodeProfile().downloadFile(storageUri, filePath);
47
47
  },
48
+ async exists(storageUri) {
49
+ return requireNodeProfile().exists(storageUri);
50
+ },
48
51
  async upload(key, filePath) {
49
52
  return requireNodeProfile().upload(key, filePath);
50
53
  }
@@ -45,6 +45,9 @@ const createProfiledStoragePlugin = ({ createProfiles, name, profileShape, suppo
45
45
  async downloadFile(storageUri, filePath) {
46
46
  return requireNodeProfile().downloadFile(storageUri, filePath);
47
47
  },
48
+ async exists(storageUri) {
49
+ return requireNodeProfile().exists(storageUri);
50
+ },
48
51
  async upload(key, filePath) {
49
52
  return requireNodeProfile().upload(key, filePath);
50
53
  }
package/dist/index.cjs CHANGED
@@ -1,11 +1,15 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_calculatePagination = require("./calculatePagination.cjs");
3
3
  const require_compressionFormat = require("./compressionFormat.cjs");
4
+ const require_contentAddressedAssets = require("./contentAddressedAssets.cjs");
5
+ const require_assetStorageLayout = require("./assetStorageLayout.cjs");
4
6
  const require_createDatabasePlugin = require("./createDatabasePlugin.cjs");
5
7
  const require_semverSatisfies = require("./semverSatisfies.cjs");
6
8
  const require_filterCompatibleAppVersions = require("./filterCompatibleAppVersions.cjs");
7
9
  const require_queryBundles = require("./queryBundles.cjs");
8
10
  const require_paginateBundles = require("./paginateBundles.cjs");
11
+ const require_requestUpdateBundleState = require("./requestUpdateBundleState.cjs");
12
+ const require_resolveUpdateInfoFromBundles = require("./resolveUpdateInfoFromBundles.cjs");
9
13
  const require_createBlobDatabasePlugin = require("./createBlobDatabasePlugin.cjs");
10
14
  const require_createDatabasePluginGetUpdateInfo = require("./createDatabasePluginGetUpdateInfo.cjs");
11
15
  const require_createStorageKeyBuilder = require("./createStorageKeyBuilder.cjs");
@@ -26,6 +30,7 @@ exports.createDatabasePluginGetUpdateInfo = require_createDatabasePluginGetUpdat
26
30
  exports.createNodeStoragePlugin = require_createStoragePlugin.createNodeStoragePlugin;
27
31
  exports.createRuntimeStoragePlugin = require_createStoragePlugin.createRuntimeStoragePlugin;
28
32
  exports.createStorageKeyBuilder = require_createStorageKeyBuilder.createStorageKeyBuilder;
33
+ exports.createStorageUriWithRelativePath = require_assetStorageLayout.createStorageUriWithRelativePath;
29
34
  exports.createUUIDv7 = require_uuidv7.createUUIDv7;
30
35
  exports.createUUIDv7WithSameTimestamp = require_uuidv7.createUUIDv7WithSameTimestamp;
31
36
  exports.createUniversalStoragePlugin = require_createStoragePlugin.createUniversalStoragePlugin;
@@ -33,12 +38,19 @@ exports.detectCompressionFormat = require_compressionFormat.detectCompressionFor
33
38
  exports.extractTimestampFromUUIDv7 = require_uuidv7.extractTimestampFromUUIDv7;
34
39
  exports.filterCompatibleAppVersions = require_filterCompatibleAppVersions.filterCompatibleAppVersions;
35
40
  exports.generateMinBundleId = require_generateMinBundleId.generateMinBundleId;
41
+ exports.getAssetStorageLayout = require_assetStorageLayout.getAssetStorageLayout;
36
42
  exports.getCompressionMimeType = require_compressionFormat.getCompressionMimeType;
43
+ exports.getContentAddressedAssetStoragePath = require_contentAddressedAssets.getContentAddressedAssetStoragePath;
37
44
  exports.getContentType = require_compressionFormat.getContentType;
45
+ exports.getManifestAssetStoragePath = require_assetStorageLayout.getManifestAssetStoragePath;
46
+ exports.getRequestUpdateBundleSeeds = require_requestUpdateBundleState.getRequestUpdateBundleSeeds;
47
+ exports.isContentAddressedAssetBaseStorageUri = require_assetStorageLayout.isContentAddressedAssetBaseStorageUri;
38
48
  exports.isNodeStoragePlugin = require_storageProfile.isNodeStoragePlugin;
39
49
  exports.isRuntimeStoragePlugin = require_storageProfile.isRuntimeStoragePlugin;
40
50
  exports.paginateBundles = require_paginateBundles.paginateBundles;
41
51
  exports.parseStorageUri = require_parseStorageUri.parseStorageUri;
52
+ exports.resolveManifestAssetStorageUri = require_assetStorageLayout.resolveManifestAssetStorageUri;
53
+ exports.resolveUpdateInfoFromBundles = require_resolveUpdateInfoFromBundles.resolveUpdateInfoFromBundles;
42
54
  exports.semverSatisfies = require_semverSatisfies.semverSatisfies;
43
55
  exports.sortBundles = require_queryBundles.sortBundles;
44
56
  exports.supportedIosPlatforms = require_index.supportedIosPlatforms;
package/dist/index.d.cts CHANGED
@@ -1,7 +1,9 @@
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
+ import { AssetStorageLayout, createStorageUriWithRelativePath, getAssetStorageLayout, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, resolveManifestAssetStorageUri } from "./assetStorageLayout.cjs";
6
+ import { getContentAddressedAssetStoragePath } from "./contentAddressedAssets.cjs";
5
7
  import { BlobDatabasePluginConfig, BlobOperations, createBlobDatabasePlugin } from "./createBlobDatabasePlugin.cjs";
6
8
  import { AbstractDatabasePlugin, CreateDatabasePluginOptions, createDatabasePlugin } from "./createDatabasePlugin.cjs";
7
9
  import { CreateDatabasePluginGetUpdateInfoOptions, createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.cjs";
@@ -12,7 +14,9 @@ import { generateMinBundleId } from "./generateMinBundleId.cjs";
12
14
  import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.cjs";
13
15
  import { paginateBundles } from "./paginateBundles.cjs";
14
16
  import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.cjs";
17
+ import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.cjs";
18
+ import { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.cjs";
15
19
  import { semverSatisfies } from "./semverSatisfies.cjs";
16
20
  import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.cjs";
17
21
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.cjs";
18
- export { AbstractDatabasePlugin, type AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, type Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs, type GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, type Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, 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,7 +1,9 @@
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
+ import { AssetStorageLayout, createStorageUriWithRelativePath, getAssetStorageLayout, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, resolveManifestAssetStorageUri } from "./assetStorageLayout.mjs";
6
+ import { getContentAddressedAssetStoragePath } from "./contentAddressedAssets.mjs";
5
7
  import { BlobDatabasePluginConfig, BlobOperations, createBlobDatabasePlugin } from "./createBlobDatabasePlugin.mjs";
6
8
  import { AbstractDatabasePlugin, CreateDatabasePluginOptions, createDatabasePlugin } from "./createDatabasePlugin.mjs";
7
9
  import { CreateDatabasePluginGetUpdateInfoOptions, createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.mjs";
@@ -12,7 +14,9 @@ import { generateMinBundleId } from "./generateMinBundleId.mjs";
12
14
  import { ParsedStorageUri, parseStorageUri } from "./parseStorageUri.mjs";
13
15
  import { paginateBundles } from "./paginateBundles.mjs";
14
16
  import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
17
+ import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.mjs";
18
+ import { ResolveUpdateInfoFromBundlesOptions, resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
15
19
  import { semverSatisfies } from "./semverSatisfies.mjs";
16
20
  import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
17
21
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
18
- export { AbstractDatabasePlugin, type AppVersionGetBundlesArgs, ApplePlatform, BasePluginArgs, BlobDatabasePluginConfig, BlobOperations, BuildPlugin, BuildPluginConfig, BuiltIns, type Bundle, CompressionFormat, CompressionFormatInfo, ConfigInput, CreateDatabasePluginGetUpdateInfoOptions, CreateDatabasePluginOptions, DatabaseBundleCursor, DatabaseBundleIdFilter, DatabaseBundleQueryOptions, DatabaseBundleQueryOrder, DatabaseBundleQueryWhere, DatabasePlugin, DatabasePluginHooks, type FingerprintGetBundlesArgs, type GetBundlesArgs, HasMultipleCallSignatures, HotUpdaterContext, IosBuildDestination, NativeBuildAndroidScheme, NativeBuildArgs, NativeBuildIosScheme, NativeBuildOptions, NodeStoragePlugin, NodeStorageProfile, Paginated, PaginatedResult, PaginationInfo, PaginationOptions, ParsedStorageUri, type Platform, PlatformConfig, Primitive, RequestEnvContext, RequiredDeep, RuntimeStoragePlugin, RuntimeStorageProfile, SigningConfig, StoragePlugin, StoragePluginHooks, StoragePluginProfiles, StorageResolveContext, UniversalStoragePlugin, type UpdateInfo, assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, 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
@@ -1,10 +1,14 @@
1
1
  import { calculatePagination } from "./calculatePagination.mjs";
2
2
  import { detectCompressionFormat, getCompressionMimeType, getContentType } from "./compressionFormat.mjs";
3
+ import { getContentAddressedAssetStoragePath } from "./contentAddressedAssets.mjs";
4
+ import { createStorageUriWithRelativePath, getAssetStorageLayout, getManifestAssetStoragePath, isContentAddressedAssetBaseStorageUri, resolveManifestAssetStorageUri } from "./assetStorageLayout.mjs";
3
5
  import { createDatabasePlugin } from "./createDatabasePlugin.mjs";
4
6
  import { semverSatisfies } from "./semverSatisfies.mjs";
5
7
  import { filterCompatibleAppVersions } from "./filterCompatibleAppVersions.mjs";
6
8
  import { bundleIdMatchesFilter, bundleMatchesQueryWhere, sortBundles } from "./queryBundles.mjs";
7
9
  import { paginateBundles } from "./paginateBundles.mjs";
10
+ import { getRequestUpdateBundleSeeds } from "./requestUpdateBundleState.mjs";
11
+ import { resolveUpdateInfoFromBundles } from "./resolveUpdateInfoFromBundles.mjs";
8
12
  import { createBlobDatabasePlugin } from "./createBlobDatabasePlugin.mjs";
9
13
  import { createDatabasePluginGetUpdateInfo } from "./createDatabasePluginGetUpdateInfo.mjs";
10
14
  import { createStorageKeyBuilder } from "./createStorageKeyBuilder.mjs";
@@ -14,4 +18,4 @@ import { parseStorageUri } from "./parseStorageUri.mjs";
14
18
  import { assertNodeStoragePlugin, assertRuntimeStoragePlugin, isNodeStoragePlugin, isRuntimeStoragePlugin } from "./storageProfile.mjs";
15
19
  import { supportedIosPlatforms } from "./types/index.mjs";
16
20
  import { createUUIDv7, createUUIDv7WithSameTimestamp, extractTimestampFromUUIDv7 } from "./uuidv7.mjs";
17
- export { assertNodeStoragePlugin, assertRuntimeStoragePlugin, bundleIdMatchesFilter, bundleMatchesQueryWhere, calculatePagination, createBlobDatabasePlugin, createDatabasePlugin, createDatabasePluginGetUpdateInfo, createNodeStoragePlugin, createRuntimeStoragePlugin, createStorageKeyBuilder, createUUIDv7, createUUIDv7WithSameTimestamp, createUniversalStoragePlugin, detectCompressionFormat, extractTimestampFromUUIDv7, filterCompatibleAppVersions, generateMinBundleId, getCompressionMimeType, getContentType, isNodeStoragePlugin, isRuntimeStoragePlugin, paginateBundles, parseStorageUri, 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,12 @@
1
+ //#region src/legacyAssetStorageLayout.ts
2
+ /**
3
+ * @internal
4
+ *
5
+ * Legacy manifest assets were stored below each bundle's `/files` directory
6
+ * using their manifest-relative path. Keep all old-layout path decisions here
7
+ * so support can be removed by deleting this module and the entrypoint branch
8
+ * that imports it.
9
+ */
10
+ const getLegacyManifestAssetStoragePath = ({ assetPath }) => assetPath;
11
+ //#endregion
12
+ exports.getLegacyManifestAssetStoragePath = getLegacyManifestAssetStoragePath;
@@ -0,0 +1,12 @@
1
+ //#region src/legacyAssetStorageLayout.ts
2
+ /**
3
+ * @internal
4
+ *
5
+ * Legacy manifest assets were stored below each bundle's `/files` directory
6
+ * using their manifest-relative path. Keep all old-layout path decisions here
7
+ * so support can be removed by deleting this module and the entrypoint branch
8
+ * that imports it.
9
+ */
10
+ const getLegacyManifestAssetStoragePath = ({ assetPath }) => assetPath;
11
+ //#endregion
12
+ export { getLegacyManifestAssetStoragePath };
@@ -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 };