@absolutejs/absolute 0.20.0-beta.82 → 0.20.0-beta.84

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.
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-hdmKLU/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-wrP0vo/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  var __require = import.meta.require;
3
3
 
4
- // .angular-partial-tmp-hdmKLU/src/core/streamingSlotRegistrar.ts
4
+ // .angular-partial-tmp-wrP0vo/src/core/streamingSlotRegistrar.ts
5
5
  var STREAMING_SLOT_REGISTRAR_KEY = Symbol.for("absolutejs.streamingSlotRegistrar");
6
6
  var STREAMING_SLOT_WARNING_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotWarningController");
7
7
  var STREAMING_SLOT_COLLECTION_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotCollectionController");
@@ -48,7 +48,7 @@ var warnMissingStreamingSlotCollector = (primitiveName) => {
48
48
  getWarningController()?.maybeWarn(primitiveName);
49
49
  };
50
50
 
51
- // .angular-partial-tmp-hdmKLU/src/core/streamingSlotRegistry.ts
51
+ // .angular-partial-tmp-wrP0vo/src/core/streamingSlotRegistry.ts
52
52
  var STREAMING_SLOT_STORAGE_KEY = Symbol.for("absolutejs.streamingSlotAsyncLocalStorage");
53
53
  var isObjectRecord2 = (value) => Boolean(value) && typeof value === "object";
54
54
  var isAsyncLocalStorage = (value) => isObjectRecord2(value) && ("getStore" in value) && typeof value.getStore === "function" && ("run" in value) && typeof value.run === "function";
package/dist/build.js CHANGED
@@ -28480,7 +28480,7 @@ import {
28480
28480
  } from "crypto";
28481
28481
  import { readFile as readFile9, stat as stat3 } from "fs/promises";
28482
28482
  import path from "path";
28483
- var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updates", MAX_FILE_BYTES, MAX_TOTAL_BYTES, HASH, RELEASE, APP_ID, NAME, EXPO_DESCRIPTOR = "_absolute/expo-update.json", EXPO_CODE_SIGNING_ALGORITHM = "rsa-v1_5-sha256", MobileUpdateRegistryError, object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), text2 = (value, field) => {
28483
+ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updates", MAX_FILE_BYTES, MAX_TOTAL_BYTES, DAY_MS, DEFAULT_MIN_AGE_MS, DEFAULT_GRACE_PERIOD_MS, DEFAULT_RETAIN_RECENT = 5, HASH, RELEASE, APP_ID, NAME, EXPO_DESCRIPTOR = "_absolute/expo-update.json", EXPO_CODE_SIGNING_ALGORITHM = "rsa-v1_5-sha256", MobileUpdateRegistryError, object3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), text2 = (value, field) => {
28484
28484
  if (typeof value !== "string" || value.length === 0)
28485
28485
  throw new MobileUpdateRegistryError(`Mobile update ${field} is invalid`);
28486
28486
  return value;
@@ -28647,6 +28647,8 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28647
28647
  const releaseRoot = (manifest) => `${root(manifest.appId)}/releases/${manifest.releaseId}`;
28648
28648
  const manifestKey = (manifest) => `${releaseRoot(manifest)}/update.json`;
28649
28649
  const fileKey = (manifest, file5) => `${releaseRoot(manifest)}/files/${file5.path}`;
28650
+ const contentBlobKey = (appId, sha256) => `${root(appId)}/blobs/${sha256}`;
28651
+ const tombstoneKey = (appId, releaseId) => `${root(appId)}/gc/${releaseId}.json`;
28650
28652
  const channelKey = (appId, channel) => {
28651
28653
  if (!APP_ID.test(appId) || !NAME.test(channel))
28652
28654
  throw new MobileUpdateRegistryError("Mobile update channel identity is invalid");
@@ -28675,6 +28677,12 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28675
28677
  throw new MobileUpdateRegistryError("Stored mobile update channel identity changed");
28676
28678
  return value;
28677
28679
  };
28680
+ const assertNotMarked = async (appId, releaseId) => {
28681
+ if (!APP_ID.test(appId) || !RELEASE.test(releaseId))
28682
+ throw new MobileUpdateRegistryError("Mobile update release identity is invalid");
28683
+ if (await options.store.head(tombstoneKey(appId, releaseId)))
28684
+ throw new MobileUpdateRegistryError("Mobile update release is marked for collection. Increase retention and apply garbage collection to restore it before promotion");
28685
+ };
28678
28686
  const writeChannel = async (input, signal) => {
28679
28687
  const value = {
28680
28688
  ...input,
@@ -28699,6 +28707,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28699
28707
  input.signal?.throwIfAborted();
28700
28708
  if (input.rollout <= 0 || input.rollout > 1)
28701
28709
  throw new MobileUpdateRegistryError("Mobile update rollout is invalid");
28710
+ await assertNotMarked(input.appId, input.releaseId);
28702
28711
  const release = await readManifest2(input.appId, input.releaseId);
28703
28712
  if (!release || release.manifest.channel !== input.channel)
28704
28713
  throw new MobileUpdateRegistryError("Mobile update was not published to this channel");
@@ -28744,19 +28753,271 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28744
28753
  status: "selected"
28745
28754
  };
28746
28755
  };
28756
+ const retentionValues = (input) => {
28757
+ if (!APP_ID.test(input.appId))
28758
+ throw new MobileUpdateRegistryError("Mobile update appId is invalid");
28759
+ const retainRecent = input.retainRecent ?? DEFAULT_RETAIN_RECENT;
28760
+ const minAgeMs = input.minAgeMs ?? DEFAULT_MIN_AGE_MS;
28761
+ if (!Number.isSafeInteger(retainRecent) || retainRecent < 0)
28762
+ throw new MobileUpdateRegistryError("Mobile update retained release count is invalid");
28763
+ if (!Number.isSafeInteger(minAgeMs) || minAgeMs < 0)
28764
+ throw new MobileUpdateRegistryError("Mobile update minimum release age is invalid");
28765
+ return { minAgeMs, retainRecent };
28766
+ };
28767
+ const listObjects = async (appId, signal) => {
28768
+ const list = options.store.list;
28769
+ if (!list)
28770
+ throw new MobileUpdateRegistryError("Mobile update storage does not support lifecycle listing");
28771
+ const objects = [];
28772
+ const cursors = new Set;
28773
+ let cursor;
28774
+ do {
28775
+ signal?.throwIfAborted();
28776
+ const page = await list({
28777
+ ...cursor ? { cursor } : {},
28778
+ prefix: `${root(appId)}/`
28779
+ });
28780
+ objects.push(...page.objects);
28781
+ if (!page.truncated)
28782
+ break;
28783
+ if (!page.cursor || cursors.has(page.cursor))
28784
+ throw new MobileUpdateRegistryError("Mobile update storage returned an invalid lifecycle cursor");
28785
+ cursors.add(page.cursor);
28786
+ cursor = page.cursor;
28787
+ } while (true);
28788
+ return objects;
28789
+ };
28790
+ const inventory = async (input) => {
28791
+ const { minAgeMs, retainRecent } = retentionValues(input);
28792
+ const objects = await listObjects(input.appId, input.signal);
28793
+ const appRoot = `${root(input.appId)}/`;
28794
+ const releasePrefix = `${appRoot}releases/`;
28795
+ const channelPrefix = `${appRoot}channels/`;
28796
+ const markerPrefix = `${appRoot}gc/`;
28797
+ const blobPrefix = `${appRoot}blobs/`;
28798
+ const objectKeysByRelease = new Map;
28799
+ const objectBytesByRelease = new Map;
28800
+ const objectKeysByDigest = new Map;
28801
+ const objectBytesByDigest = new Map;
28802
+ for (const blobObject of objects) {
28803
+ if (blobObject.key.startsWith(blobPrefix)) {
28804
+ const sha256 = blobObject.key.slice(blobPrefix.length);
28805
+ if (HASH.test(sha256)) {
28806
+ objectKeysByDigest.set(sha256, blobObject.key);
28807
+ objectBytesByDigest.set(sha256, blobObject.size);
28808
+ }
28809
+ }
28810
+ if (!blobObject.key.startsWith(releasePrefix))
28811
+ continue;
28812
+ const suffix = blobObject.key.slice(releasePrefix.length);
28813
+ const releaseId = suffix.slice(0, suffix.indexOf("/"));
28814
+ if (!RELEASE.test(releaseId))
28815
+ continue;
28816
+ objectKeysByRelease.set(releaseId, [
28817
+ ...objectKeysByRelease.get(releaseId) ?? [],
28818
+ blobObject.key
28819
+ ]);
28820
+ objectBytesByRelease.set(releaseId, (objectBytesByRelease.get(releaseId) ?? 0) + blobObject.size);
28821
+ }
28822
+ const channels = [];
28823
+ for (const blobObject of objects) {
28824
+ if (!blobObject.key.startsWith(channelPrefix) || !blobObject.key.endsWith(".json"))
28825
+ continue;
28826
+ const bytes = await options.store.get(blobObject.key);
28827
+ if (!bytes)
28828
+ throw new MobileUpdateRegistryError("Mobile update channel disappeared during lifecycle inspection");
28829
+ const channel = parseChannel(decode(bytes));
28830
+ if (channel.appId !== input.appId)
28831
+ throw new MobileUpdateRegistryError("Stored mobile update channel identity changed");
28832
+ channels.push(channel);
28833
+ }
28834
+ const markedAt = new Map;
28835
+ for (const blobObject of objects) {
28836
+ if (!blobObject.key.startsWith(markerPrefix) || !blobObject.key.endsWith(".json"))
28837
+ continue;
28838
+ const releaseId = blobObject.key.slice(markerPrefix.length, -".json".length);
28839
+ if (!RELEASE.test(releaseId))
28840
+ continue;
28841
+ const bytes = await options.store.get(blobObject.key);
28842
+ if (!bytes)
28843
+ continue;
28844
+ const marker = decode(bytes);
28845
+ if (!object3(marker) || marker.format !== 1 || marker.appId !== input.appId || marker.releaseId !== releaseId || !iso(marker.markedAt))
28846
+ throw new MobileUpdateRegistryError("Mobile update collection marker is invalid");
28847
+ markedAt.set(releaseId, marker.markedAt);
28848
+ }
28849
+ const active = new Set(channels.flatMap((channel) => channel.releaseId ? [channel.releaseId] : []));
28850
+ const fallback = new Set(channels.flatMap((channel) => channel.fallbackReleaseId ? [channel.fallbackReleaseId] : []));
28851
+ const manifests = [];
28852
+ for (const releaseId of objectKeysByRelease.keys()) {
28853
+ const release = await readManifest2(input.appId, releaseId);
28854
+ if (release)
28855
+ manifests.push(release.manifest);
28856
+ }
28857
+ const recent = new Set;
28858
+ const manifestsByChannel = new Map;
28859
+ for (const manifest of manifests)
28860
+ manifestsByChannel.set(manifest.channel, [
28861
+ ...manifestsByChannel.get(manifest.channel) ?? [],
28862
+ manifest
28863
+ ]);
28864
+ for (const releases2 of manifestsByChannel.values())
28865
+ for (const manifest of releases2.toSorted((left, right) => right.createdAt.localeCompare(left.createdAt)).slice(0, retainRecent))
28866
+ recent.add(manifest.releaseId);
28867
+ const now = clock().getTime();
28868
+ const releases = manifests.map((manifest) => {
28869
+ const protectedBy = [];
28870
+ if (active.has(manifest.releaseId))
28871
+ protectedBy.push("active");
28872
+ if (fallback.has(manifest.releaseId))
28873
+ protectedBy.push("fallback");
28874
+ if (recent.has(manifest.releaseId))
28875
+ protectedBy.push("recent");
28876
+ if (now - Date.parse(manifest.createdAt) < minAgeMs)
28877
+ protectedBy.push("age");
28878
+ return {
28879
+ bytes: objectBytesByRelease.get(manifest.releaseId) ?? 0,
28880
+ channel: manifest.channel,
28881
+ createdAt: manifest.createdAt,
28882
+ ...markedAt.has(manifest.releaseId) ? { markedAt: markedAt.get(manifest.releaseId) } : {},
28883
+ objectCount: objectKeysByRelease.get(manifest.releaseId)?.length ?? 0,
28884
+ protectedBy,
28885
+ releaseId: manifest.releaseId
28886
+ };
28887
+ }).toSorted((left, right) => right.createdAt.localeCompare(left.createdAt));
28888
+ const protectedReleaseIds = new Set(releases.filter((release) => release.protectedBy.length > 0).map((release) => release.releaseId));
28889
+ const protectedDigests = new Set(manifests.filter((manifest) => protectedReleaseIds.has(manifest.releaseId)).flatMap((manifest) => manifest.files.map((file5) => file5.sha256)));
28890
+ const reclaimableContentBytes = [...objectBytesByDigest].filter(([sha256]) => !protectedDigests.has(sha256)).reduce((total, [, bytes]) => total + bytes, 0);
28891
+ const contentBlobBytes = [...objectBytesByDigest.values()].reduce((total, bytes) => total + bytes, 0);
28892
+ const releaseBytes = releases.reduce((total, release) => total + release.bytes, 0);
28893
+ const totalBytes = objects.reduce((total, object22) => total + object22.size, 0);
28894
+ return {
28895
+ objectKeysByRelease,
28896
+ objectKeysByDigest,
28897
+ report: {
28898
+ appId: input.appId,
28899
+ channelCount: channels.length,
28900
+ contentBlobBytes,
28901
+ contentBlobCount: objectKeysByDigest.size,
28902
+ reclaimableBytes: releases.filter((release) => release.protectedBy.length === 0).reduce((total, release) => total + release.bytes, 0) + reclaimableContentBytes,
28903
+ reclaimableContentBytes,
28904
+ releaseBytes,
28905
+ releaseCount: releases.length,
28906
+ releases,
28907
+ totalBytes,
28908
+ totalObjectCount: objects.length,
28909
+ untrackedBytes: totalBytes - releaseBytes - contentBlobBytes
28910
+ }
28911
+ };
28912
+ };
28913
+ const pruneUpdates = async (input) => {
28914
+ const initial = await inventory(input);
28915
+ const result = {
28916
+ ...initial.report,
28917
+ dryRun: input.apply !== true,
28918
+ marked: [],
28919
+ reclaimedBytes: 0,
28920
+ restored: [],
28921
+ swept: [],
28922
+ sweptContentBlobs: []
28923
+ };
28924
+ if (input.apply !== true)
28925
+ return result;
28926
+ const remove = options.store.delete;
28927
+ if (!remove)
28928
+ throw new MobileUpdateRegistryError("Mobile update storage does not support lifecycle deletion");
28929
+ const gracePeriodMs = input.gracePeriodMs ?? DEFAULT_GRACE_PERIOD_MS;
28930
+ if (!Number.isSafeInteger(gracePeriodMs) || gracePeriodMs < 0)
28931
+ throw new MobileUpdateRegistryError("Mobile update collection grace period is invalid");
28932
+ const now = clock();
28933
+ for (const release of initial.report.releases) {
28934
+ input.signal?.throwIfAborted();
28935
+ const marker = tombstoneKey(input.appId, release.releaseId);
28936
+ if (release.protectedBy.length > 0) {
28937
+ if (release.markedAt) {
28938
+ await remove(marker);
28939
+ result.restored.push(release.releaseId);
28940
+ }
28941
+ continue;
28942
+ }
28943
+ if (!release.markedAt) {
28944
+ const bytes = json({
28945
+ appId: input.appId,
28946
+ format: 1,
28947
+ markedAt: now.toISOString(),
28948
+ releaseId: release.releaseId
28949
+ });
28950
+ await options.store.put(marker, bytes, {
28951
+ cacheControl: "no-cache",
28952
+ contentType: "application/json",
28953
+ maxBytes: bytes.byteLength,
28954
+ metadata: { releaseid: release.releaseId, sha256: digest(bytes) },
28955
+ signal: input.signal
28956
+ });
28957
+ result.marked.push(release.releaseId);
28958
+ }
28959
+ }
28960
+ const current = await inventory(input);
28961
+ for (const release of current.report.releases) {
28962
+ input.signal?.throwIfAborted();
28963
+ if (release.protectedBy.length > 0 || !release.markedAt || now.getTime() - Date.parse(release.markedAt) < gracePeriodMs || result.marked.includes(release.releaseId))
28964
+ continue;
28965
+ const checked = await inventory(input);
28966
+ const candidate = checked.report.releases.find((value) => value.releaseId === release.releaseId);
28967
+ if (!candidate || candidate.protectedBy.length > 0 || !candidate.markedAt)
28968
+ continue;
28969
+ const keys = checked.objectKeysByRelease.get(release.releaseId) ?? [];
28970
+ for (const key of keys.toSorted((left, right) => {
28971
+ const leftManifest = left.endsWith("/update.json");
28972
+ const rightManifest = right.endsWith("/update.json");
28973
+ return Number(leftManifest) - Number(rightManifest);
28974
+ }))
28975
+ await remove(key);
28976
+ await remove(tombstoneKey(input.appId, release.releaseId));
28977
+ result.reclaimedBytes += candidate.bytes;
28978
+ result.swept.push(release.releaseId);
28979
+ }
28980
+ const afterReleaseSweep = await inventory(input);
28981
+ const referencedDigests = new Set;
28982
+ for (const release of afterReleaseSweep.report.releases) {
28983
+ const manifest = await readManifest2(input.appId, release.releaseId);
28984
+ for (const file5 of manifest?.manifest.files ?? [])
28985
+ referencedDigests.add(file5.sha256);
28986
+ }
28987
+ for (const [sha256, key] of afterReleaseSweep.objectKeysByDigest) {
28988
+ if (referencedDigests.has(sha256))
28989
+ continue;
28990
+ const head = await options.store.head(key);
28991
+ await remove(key);
28992
+ result.reclaimedBytes += head?.size ?? 0;
28993
+ result.sweptContentBlobs.push(sha256);
28994
+ }
28995
+ return result;
28996
+ };
28747
28997
  return {
28998
+ inspectUpdateStorage: async (input) => (await inventory(input)).report,
28999
+ pruneUpdates,
28748
29000
  publishUpdate: async (input) => {
28749
29001
  input.signal?.throwIfAborted();
28750
29002
  const manifest = parseMobileUpdateManifest(input.manifest);
28751
29003
  verifyManifestSignature(manifest, options.publicKeys);
29004
+ await assertNotMarked(manifest.appId, manifest.releaseId);
28752
29005
  const localRoot = path.resolve(input.releaseDirectory);
28753
29006
  const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile9(path.join(localRoot, "update.json"), "utf8")));
28754
29007
  if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
28755
29008
  throw new MobileUpdateRegistryError("Local mobile update manifest changed");
28756
29009
  const existing = await readManifest2(manifest.appId, manifest.releaseId);
28757
29010
  let reused = existing !== null;
29011
+ let storedBytes = 0;
29012
+ let storedFiles = 0;
29013
+ let reusedBytes = 0;
29014
+ let reusedFiles = 0;
28758
29015
  if (existing && JSON.stringify(existing.manifest) !== JSON.stringify(manifest))
28759
29016
  throw new MobileUpdateRegistryError("Published mobile update is immutable");
29017
+ if (existing) {
29018
+ reusedBytes = manifest.files.reduce((total, file5) => total + file5.bytes, 0);
29019
+ reusedFiles = manifest.files.length;
29020
+ }
28760
29021
  if (!existing) {
28761
29022
  for (const file5 of manifest.files) {
28762
29023
  const local = path.join(localRoot, "files", file5.path);
@@ -28765,18 +29026,24 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28765
29026
  throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} size changed`);
28766
29027
  if (await fileDigest(Bun.file(local)) !== file5.sha256)
28767
29028
  throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} integrity failed`);
28768
- const key = fileKey(manifest, file5);
29029
+ const key = contentBlobKey(manifest.appId, file5.sha256);
28769
29030
  const stored = await options.store.head(key);
28770
29031
  if (!stored) {
28771
29032
  await options.store.put(key, Bun.file(local).stream(), {
28772
29033
  cacheControl: "public, max-age=31536000, immutable",
28773
29034
  contentType: "application/octet-stream",
28774
29035
  maxBytes: file5.bytes,
28775
- metadata: { releaseid: manifest.releaseId, sha256: file5.sha256 },
29036
+ metadata: { sha256: file5.sha256 },
28776
29037
  signal: input.signal
28777
29038
  });
28778
- } else if (stored.size !== file5.bytes || stored.metadata?.sha256 !== file5.sha256 || (stored.metadata?.releaseid ?? stored.metadata?.releaseId) !== manifest.releaseId)
28779
- throw new MobileUpdateRegistryError("Stored mobile update file identity changed");
29039
+ storedBytes += file5.bytes;
29040
+ storedFiles += 1;
29041
+ } else if (stored.size !== file5.bytes || stored.metadata?.sha256 !== file5.sha256)
29042
+ throw new MobileUpdateRegistryError("Stored mobile update content identity changed");
29043
+ else {
29044
+ reusedBytes += file5.bytes;
29045
+ reusedFiles += 1;
29046
+ }
28780
29047
  }
28781
29048
  const bytes = json(manifest);
28782
29049
  await options.store.put(manifestKey(manifest), bytes, {
@@ -28800,8 +29067,12 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28800
29067
  return {
28801
29068
  appId: manifest.appId,
28802
29069
  channel: manifest.channel,
29070
+ storedBytes,
29071
+ storedFiles,
28803
29072
  releaseId: manifest.releaseId,
28804
29073
  reused,
29074
+ reusedBytes,
29075
+ reusedFiles,
28805
29076
  rollout: input.rollout,
28806
29077
  stage: "published"
28807
29078
  };
@@ -28813,6 +29084,7 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28813
29084
  if (!existing)
28814
29085
  throw new MobileUpdateRegistryError("Mobile update channel does not exist");
28815
29086
  if (input.releaseId) {
29087
+ await assertNotMarked(input.appId, input.releaseId);
28816
29088
  const release = await readManifest2(input.appId, input.releaseId);
28817
29089
  if (!release || release.manifest.channel !== input.channel)
28818
29090
  throw new MobileUpdateRegistryError("Mobile rollback release was not published");
@@ -28849,14 +29121,16 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
28849
29121
  const file5 = release.manifest.files.find((candidate) => candidate.path === requested);
28850
29122
  if (!file5)
28851
29123
  return null;
28852
- const key = fileKey(release.manifest, file5);
29124
+ const legacyKey = fileKey(release.manifest, file5);
29125
+ const legacyHead = await options.store.head(legacyKey);
29126
+ const key = legacyHead ? legacyKey : contentBlobKey(release.manifest.appId, file5.sha256);
28853
29127
  const [bytes, head] = await Promise.all([
28854
29128
  options.store.get(key),
28855
- options.store.head(key)
29129
+ legacyHead ? Promise.resolve(legacyHead) : options.store.head(key)
28856
29130
  ]);
28857
29131
  if (!bytes || !head)
28858
29132
  return null;
28859
- if (bytes.byteLength !== file5.bytes || head.size !== file5.bytes || head.metadata?.sha256 !== file5.sha256 || (head.metadata?.releaseid ?? head.metadata?.releaseId) !== release.manifest.releaseId || digest(bytes) !== file5.sha256)
29133
+ if (bytes.byteLength !== file5.bytes || head.size !== file5.bytes || head.metadata?.sha256 !== file5.sha256 || legacyHead && (head.metadata?.releaseid ?? head.metadata?.releaseId) !== release.manifest.releaseId || digest(bytes) !== file5.sha256)
28860
29134
  throw new MobileUpdateRegistryError("Stored mobile update file integrity failed");
28861
29135
  return { bytes, file: file5 };
28862
29136
  }
@@ -29145,6 +29419,9 @@ var MOBILE_UPDATE_REGISTRY_FORMAT = 1, DEFAULT_PREFIX = "absolutejs/mobile-updat
29145
29419
  var init_mobileUpdate = __esm(() => {
29146
29420
  MAX_FILE_BYTES = 32 * 1024 * 1024;
29147
29421
  MAX_TOTAL_BYTES = 128 * 1024 * 1024;
29422
+ DAY_MS = 24 * 60 * 60 * 1000;
29423
+ DEFAULT_MIN_AGE_MS = 30 * DAY_MS;
29424
+ DEFAULT_GRACE_PERIOD_MS = 7 * DAY_MS;
29148
29425
  HASH = /^[a-f0-9]{64}$/;
29149
29426
  RELEASE = /^amu_[a-f0-9]{64}$/;
29150
29427
  APP_ID = /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)+$/;
@@ -36969,5 +37246,5 @@ export {
36969
37246
  devBuild
36970
37247
  };
36971
37248
 
36972
- //# debugId=7849DC008DCD28AC64756E2164756E21
37249
+ //# debugId=5BE2EBFD6FC5145B64756E2164756E21
36973
37250
  //# sourceMappingURL=build.js.map