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

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/build.js CHANGED
@@ -27618,10 +27618,14 @@ var DEFAULT_BATCH_SIZE = 12, DEFAULT_POLL_MS = 25, DEFAULT_MAX_PAUSE_MS = 2000,
27618
27618
  };
27619
27619
 
27620
27620
  // src/mobile/config.ts
27621
+ var exports_config = {};
27622
+ __export(exports_config, {
27623
+ normalizeAbsoluteMobileConfig: () => normalizeAbsoluteMobileConfig
27624
+ });
27621
27625
  import { readFileSync as readFileSync35 } from "fs";
27622
27626
  import { resolve as resolve44 } from "path";
27623
27627
  import { createHash as createHash5, createPublicKey, X509Certificate } from "crypto";
27624
- var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, UPDATE_NAME_PATTERN, UPDATE_PUBLIC_KEY_PATTERN, DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000, MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000, MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000, HOSTNAME_PATTERN, EXPO_RESERVED_ROUTE_PREFIXES, resolveProjectPath = (projectRoot, value, field) => {
27628
+ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, UPDATE_NAME_PATTERN, UPDATE_PUBLIC_KEY_PATTERN, ENVIRONMENT_NAME_PATTERN, DEFAULT_UPDATE_BOOT_TIMEOUT_MS = 20000, MINIMUM_UPDATE_BOOT_TIMEOUT_MS = 5000, MAXIMUM_UPDATE_BOOT_TIMEOUT_MS = 120000, HOSTNAME_PATTERN, EXPO_RESERVED_ROUTE_PREFIXES, resolveProjectPath = (projectRoot, value, field) => {
27625
27629
  const root = resolve44(projectRoot);
27626
27630
  const path = resolve44(root, value);
27627
27631
  if (path !== root && !path.startsWith(`${root}/`)) {
@@ -27806,6 +27810,48 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
27806
27810
  publicKeys,
27807
27811
  ...expoCodeSigning ? { expoCodeSigning } : {}
27808
27812
  };
27813
+ }, normalizeUpdateServer = (config, productionOrigin, projectRoot, updates) => {
27814
+ if (!updates || !config.updates)
27815
+ return;
27816
+ const registryModule = requireText(config.updates.server?.registry ?? "mobile.update.ts", "mobile.updates.server.registry");
27817
+ resolveProjectPath(projectRoot, registryModule, "mobile.updates.server.registry");
27818
+ const expoPrivateKeyEnv = requireText(config.updates.server?.expoPrivateKeyEnv ?? "ABSOLUTE_EXPO_UPDATE_PRIVATE_KEY", "mobile.updates.server.expoPrivateKeyEnv");
27819
+ if (!ENVIRONMENT_NAME_PATTERN.test(expoPrivateKeyEnv))
27820
+ throw new TypeError("mobile.updates.server.expoPrivateKeyEnv must be a valid environment variable name.");
27821
+ const autoMount = config.updates.server?.autoMount ?? true;
27822
+ if (autoMount) {
27823
+ const manifest = new URL(updates.manifestUrl);
27824
+ if (manifest.origin !== productionOrigin)
27825
+ throw new TypeError("mobile.updates.manifestUrl must use mobile.server.productionOrigin while mobile.updates.server.autoMount is enabled.");
27826
+ if (!manifest.pathname.endsWith("/update.json"))
27827
+ throw new TypeError("mobile.updates.manifestUrl must end in /update.json while mobile.updates.server.autoMount is enabled.");
27828
+ }
27829
+ const expoCodeSigningKeys = {};
27830
+ if (updates.expoCodeSigning)
27831
+ expoCodeSigningKeys[updates.expoCodeSigning.keyId] = {
27832
+ certificatePem: updates.expoCodeSigning.certificatePem,
27833
+ privateKeyEnv: expoPrivateKeyEnv
27834
+ };
27835
+ for (const [keyId, key] of Object.entries(config.updates.server?.expoCodeSigningKeys ?? {}).sort(([left], [right]) => left.localeCompare(right))) {
27836
+ if (!updates.expoCodeSigning)
27837
+ throw new TypeError("mobile.updates.server.expoCodeSigningKeys requires the Expo engine and expoCodeSigning.");
27838
+ if (!UPDATE_NAME_PATTERN.test(keyId))
27839
+ throw new TypeError("mobile.updates.server.expoCodeSigningKeys contains an invalid key ID.");
27840
+ if (expoCodeSigningKeys[keyId])
27841
+ throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} duplicates the active Expo key.`);
27842
+ const privateKeyEnv = requireText(key.privateKeyEnv, `mobile.updates.server.expoCodeSigningKeys.${keyId}.privateKeyEnv`);
27843
+ if (!ENVIRONMENT_NAME_PATTERN.test(privateKeyEnv))
27844
+ throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId}.privateKeyEnv must be a valid environment variable name.`);
27845
+ const certificatePath = resolveProjectPath(projectRoot, requireText(key.certificatePath, `mobile.updates.server.expoCodeSigningKeys.${keyId}.certificatePath`), `mobile.updates.server.expoCodeSigningKeys.${keyId}.certificatePath`);
27846
+ const { certificate, certificatePem } = readExpoCodeSigningCertificate(certificatePath);
27847
+ if (certificate.publicKey.asymmetricKeyType !== "rsa" || certificate.issuer !== certificate.subject || !certificate.verify(certificate.publicKey))
27848
+ throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} certificate must be a self-signed RSA root.`);
27849
+ const now = Date.now();
27850
+ if (now < Date.parse(certificate.validFrom) || now > Date.parse(certificate.validTo))
27851
+ throw new TypeError(`mobile.updates.server.expoCodeSigningKeys.${keyId} certificate is not currently valid.`);
27852
+ expoCodeSigningKeys[keyId] = { certificatePem, privateKeyEnv };
27853
+ }
27854
+ return { autoMount, expoCodeSigningKeys, registryModule };
27809
27855
  }, validateExpoNativeRouteSegment = (path, segment, index, count, parameters) => {
27810
27856
  if (segment === "*" && (index !== count - 1 || count === 1)) {
27811
27857
  throw new TypeError(`mobile.routes.native route ${path} must use * once, as the final segment after a static or parameterized prefix.`);
@@ -27865,6 +27911,7 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
27865
27911
  throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
27866
27912
  }
27867
27913
  const updates = normalizeUpdates(config, productionOrigin, projectRoot);
27914
+ const updateServer = normalizeUpdateServer(config, productionOrigin, projectRoot, updates);
27868
27915
  const observability = normalizeObservability(config, productionOrigin);
27869
27916
  return {
27870
27917
  androidCertificateFingerprints: normalizeCertificateFingerprints(config.deepLinks?.android?.sha256CertificateFingerprints),
@@ -27884,7 +27931,8 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
27884
27931
  platforms: normalizePlatforms(config.platforms),
27885
27932
  productionOrigin,
27886
27933
  pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile"),
27887
- ...updates ? { updates } : {}
27934
+ ...updates ? { updates } : {},
27935
+ ...updateServer ? { updateServer } : {}
27888
27936
  };
27889
27937
  };
27890
27938
  var init_config = __esm(() => {
@@ -27894,6 +27942,7 @@ var init_config = __esm(() => {
27894
27942
  CERTIFICATE_FINGERPRINT_PATTERN = /^[0-9A-F]{64}$/;
27895
27943
  UPDATE_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
27896
27944
  UPDATE_PUBLIC_KEY_PATTERN = /^[A-Za-z0-9+/]+={0,2}$/u;
27945
+ ENVIRONMENT_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/u;
27897
27946
  HOSTNAME_PATTERN = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))*$/;
27898
27947
  EXPO_RESERVED_ROUTE_PREFIXES = new Set([
27899
27948
  "_expo",
@@ -28412,6 +28461,919 @@ var init_mobilePreviewClientBundle = __esm(() => {
28412
28461
  init_rewriteImportsPlugin();
28413
28462
  });
28414
28463
 
28464
+ // node_modules/@absolutejs/deploy/dist/mobileUpdate.js
28465
+ var exports_mobileUpdate = {};
28466
+ __export(exports_mobileUpdate, {
28467
+ MOBILE_UPDATE_REGISTRY_FORMAT: () => MOBILE_UPDATE_REGISTRY_FORMAT,
28468
+ MobileUpdateRegistryError: () => MobileUpdateRegistryError,
28469
+ createMobileUpdateHandler: () => createMobileUpdateHandler,
28470
+ createMobileUpdateRegistry: () => createMobileUpdateRegistry,
28471
+ parseMobileUpdateManifest: () => parseMobileUpdateManifest
28472
+ });
28473
+ import {
28474
+ createHash as createHash6,
28475
+ createPrivateKey,
28476
+ createPublicKey as createPublicKey2,
28477
+ sign,
28478
+ verify,
28479
+ X509Certificate as X509Certificate2
28480
+ } from "crypto";
28481
+ import { readFile as readFile9, stat as stat3 } from "fs/promises";
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) => {
28484
+ if (typeof value !== "string" || value.length === 0)
28485
+ throw new MobileUpdateRegistryError(`Mobile update ${field} is invalid`);
28486
+ return value;
28487
+ }, iso = (value) => typeof value === "string" && Number.isFinite(Date.parse(value)) && new Date(value).toISOString() === value, safePath = (value) => {
28488
+ const file5 = text2(value, "file path").replaceAll("\\", "/");
28489
+ if (file5.startsWith("/") || file5.split("/").some((segment) => !segment || segment === "." || segment === ".."))
28490
+ throw new MobileUpdateRegistryError("Mobile update file path is invalid");
28491
+ return file5;
28492
+ }, expoAsset = (value) => {
28493
+ if (!object3(value))
28494
+ throw new MobileUpdateRegistryError("Expo update asset is invalid");
28495
+ const assetPath = safePath(value.path);
28496
+ if (value.extension !== undefined && (typeof value.extension !== "string" || !/^[A-Za-z0-9]+$/.test(value.extension)))
28497
+ throw new MobileUpdateRegistryError("Expo update asset extension is invalid");
28498
+ return {
28499
+ ...typeof value.extension === "string" ? { extension: value.extension } : {},
28500
+ path: assetPath
28501
+ };
28502
+ }, parseExpoUpdateDescriptor = (bytes) => {
28503
+ let value;
28504
+ try {
28505
+ value = JSON.parse(new TextDecoder().decode(bytes));
28506
+ } catch {
28507
+ throw new MobileUpdateRegistryError("Expo update descriptor is invalid");
28508
+ }
28509
+ if (!object3(value) || value.engine !== "expo" || value.format !== 1 || !object3(value.expoConfig) || !object3(value.platforms) || typeof value.runtimeVersion !== "string" || !HASH.test(value.runtimeVersion))
28510
+ throw new MobileUpdateRegistryError("Expo update descriptor is invalid");
28511
+ const platforms = {};
28512
+ for (const name of ["android", "ios"]) {
28513
+ const candidate = value.platforms[name];
28514
+ if (candidate === undefined)
28515
+ continue;
28516
+ if (!object3(candidate) || !Array.isArray(candidate.assets) || !object3(candidate.launchAsset))
28517
+ throw new MobileUpdateRegistryError("Expo update platform descriptor is invalid");
28518
+ platforms[name] = {
28519
+ assets: candidate.assets.map(expoAsset),
28520
+ launchAsset: expoAsset(candidate.launchAsset)
28521
+ };
28522
+ }
28523
+ if (Object.keys(platforms).length === 0)
28524
+ throw new MobileUpdateRegistryError("Expo update descriptor has no native platforms");
28525
+ return {
28526
+ engine: "expo",
28527
+ expoConfig: value.expoConfig,
28528
+ format: 1,
28529
+ platforms,
28530
+ runtimeVersion: value.runtimeVersion
28531
+ };
28532
+ }, parseMobileUpdateManifest = (value) => {
28533
+ if (!object3(value) || value.format !== 1)
28534
+ throw new MobileUpdateRegistryError("Mobile update manifest is invalid");
28535
+ const appId = text2(value.appId, "appId");
28536
+ const channel = text2(value.channel, "channel");
28537
+ const releaseId = text2(value.releaseId, "releaseId");
28538
+ const runtimeFingerprint = text2(value.runtimeFingerprint, "runtime");
28539
+ if (!APP_ID.test(appId) || !NAME.test(channel) || !RELEASE.test(releaseId))
28540
+ throw new MobileUpdateRegistryError("Mobile update identity is invalid");
28541
+ if (!HASH.test(runtimeFingerprint) || !iso(value.createdAt))
28542
+ throw new MobileUpdateRegistryError("Mobile update runtime or timestamp is invalid");
28543
+ if (value.classification !== "bug-fix" && value.classification !== "content" && value.classification !== "security")
28544
+ throw new MobileUpdateRegistryError("Mobile update classification is invalid");
28545
+ if (value.withinSubmittedPurpose !== true)
28546
+ throw new MobileUpdateRegistryError("Mobile update policy attestation is missing");
28547
+ if (!Array.isArray(value.files) || value.files.length === 0)
28548
+ throw new MobileUpdateRegistryError("Mobile update file inventory is invalid");
28549
+ const files = value.files.map((candidate) => {
28550
+ if (!object3(candidate))
28551
+ throw new MobileUpdateRegistryError("Mobile update file is invalid");
28552
+ const filePath = safePath(candidate.path);
28553
+ if (!Number.isSafeInteger(candidate.bytes) || Number(candidate.bytes) < 0 || Number(candidate.bytes) > MAX_FILE_BYTES || typeof candidate.sha256 !== "string" || !HASH.test(candidate.sha256))
28554
+ throw new MobileUpdateRegistryError(`Mobile update file ${filePath} is invalid`);
28555
+ return {
28556
+ bytes: Number(candidate.bytes),
28557
+ path: filePath,
28558
+ sha256: candidate.sha256
28559
+ };
28560
+ });
28561
+ if (files.reduce((total, file5) => total + file5.bytes, 0) > MAX_TOTAL_BYTES || new Set(files.map((file5) => file5.path)).size !== files.length || files.some((file5, index) => index > 0 ? file5.path.localeCompare(files[index - 1]?.path ?? "") <= 0 : false))
28562
+ throw new MobileUpdateRegistryError("Mobile update file inventory is invalid");
28563
+ const signatureKeyId = object3(value.signature) ? text2(value.signature.keyId, "signature key") : "";
28564
+ const signatureValue = object3(value.signature) ? text2(value.signature.value, "signature") : "";
28565
+ if (!object3(value.signature) || value.signature.algorithm !== "ecdsa-p256-sha256" || !NAME.test(signatureKeyId) || !/^[A-Za-z0-9+/]+={0,2}$/.test(signatureValue) || Buffer.from(signatureValue, "base64").byteLength !== 64 || Buffer.from(signatureValue, "base64").toString("base64") !== signatureValue)
28566
+ throw new MobileUpdateRegistryError("Mobile update signature is invalid");
28567
+ return {
28568
+ appId,
28569
+ channel,
28570
+ classification: value.classification,
28571
+ createdAt: value.createdAt,
28572
+ files,
28573
+ format: 1,
28574
+ releaseId,
28575
+ runtimeFingerprint,
28576
+ signature: {
28577
+ algorithm: "ecdsa-p256-sha256",
28578
+ keyId: signatureKeyId,
28579
+ value: signatureValue
28580
+ },
28581
+ withinSubmittedPurpose: true
28582
+ };
28583
+ }, canonicalValue = (value) => {
28584
+ if (Array.isArray(value))
28585
+ return value.map(canonicalValue);
28586
+ if (!object3(value))
28587
+ return value;
28588
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalValue(value[key])]));
28589
+ }, verifyManifestSignature = (manifest, publicKeys) => {
28590
+ const encoded = publicKeys[manifest.signature.keyId];
28591
+ if (!encoded)
28592
+ throw new MobileUpdateRegistryError("Mobile update signing key is not trusted");
28593
+ let publicKey;
28594
+ try {
28595
+ const der = Buffer.from(encoded, "base64");
28596
+ if (der.toString("base64") !== encoded)
28597
+ throw new Error("invalid base64");
28598
+ publicKey = createPublicKey2({ format: "der", key: der, type: "spki" });
28599
+ } catch {
28600
+ throw new MobileUpdateRegistryError("Mobile update trusted public key is invalid");
28601
+ }
28602
+ if (publicKey.asymmetricKeyType !== "ec" || publicKey.asymmetricKeyDetails?.namedCurve !== "prime256v1")
28603
+ throw new MobileUpdateRegistryError("Mobile update trusted public key must use ECDSA P-256");
28604
+ const { signature: _signature, ...unsigned } = manifest;
28605
+ if (!verify("sha256", new TextEncoder().encode(JSON.stringify(canonicalValue(unsigned))), { dsaEncoding: "ieee-p1363", key: publicKey }, Buffer.from(manifest.signature.value, "base64")))
28606
+ throw new MobileUpdateRegistryError("Mobile update signature verification failed");
28607
+ }, parseChannel = (value) => {
28608
+ if (!object3(value) || value.format !== MOBILE_UPDATE_REGISTRY_FORMAT)
28609
+ throw new MobileUpdateRegistryError("Mobile update channel is invalid");
28610
+ const appId = text2(value.appId, "channel appId");
28611
+ const channel = text2(value.channel, "channel");
28612
+ if (!APP_ID.test(appId) || !NAME.test(channel) || !iso(value.promotedAt) || typeof value.rollout !== "number" || value.rollout < 0 || value.rollout > 1 || value.releaseId !== undefined && (typeof value.releaseId !== "string" || !RELEASE.test(value.releaseId)) || value.fallbackReleaseId !== undefined && (typeof value.fallbackReleaseId !== "string" || !RELEASE.test(value.fallbackReleaseId)) || value.activationId !== undefined && (typeof value.activationId !== "string" || !HASH.test(value.activationId)) || value.activatedAt !== undefined && !iso(value.activatedAt) || value.activationId === undefined !== (value.activatedAt === undefined))
28613
+ throw new MobileUpdateRegistryError("Mobile update channel is invalid");
28614
+ return {
28615
+ ...value.activationId ? { activationId: value.activationId } : {},
28616
+ ...value.activatedAt ? { activatedAt: value.activatedAt } : {},
28617
+ appId,
28618
+ channel,
28619
+ ...value.fallbackReleaseId ? { fallbackReleaseId: value.fallbackReleaseId } : {},
28620
+ format: MOBILE_UPDATE_REGISTRY_FORMAT,
28621
+ promotedAt: value.promotedAt,
28622
+ ...value.releaseId ? { releaseId: value.releaseId } : {},
28623
+ rollout: value.rollout
28624
+ };
28625
+ }, normalizedPrefix = (value) => {
28626
+ const prefix = value.replace(/^\/+|\/+$/g, "");
28627
+ if (!prefix || prefix.split("/").some((segment) => segment === "." || segment === ".."))
28628
+ throw new MobileUpdateRegistryError("Mobile update prefix is invalid");
28629
+ return prefix;
28630
+ }, appHash = (appId) => createHash6("sha256").update(appId).digest("hex"), digest = (bytes) => createHash6("sha256").update(bytes).digest("hex"), json = (value) => new TextEncoder().encode(`${JSON.stringify(value, null, 2)}
28631
+ `), decode = (value) => JSON.parse(new TextDecoder().decode(value)), fileDigest = async (file5) => {
28632
+ const hasher = new Bun.CryptoHasher("sha256");
28633
+ for await (const chunk of file5.stream())
28634
+ hasher.update(chunk);
28635
+ return hasher.digest("hex");
28636
+ }, rolloutMember = (input) => {
28637
+ if (input.rollout === 0)
28638
+ return false;
28639
+ if (input.rollout === 1)
28640
+ return true;
28641
+ const value = createHash6("sha256").update(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${input.installationId}`).digest().readUInt32BE(0);
28642
+ return value / 4294967296 < input.rollout;
28643
+ }, createMobileUpdateRegistry = (options) => {
28644
+ const prefix = normalizedPrefix(options.prefix ?? DEFAULT_PREFIX);
28645
+ const clock = options.clock ?? (() => new Date);
28646
+ const root = (appId) => `${prefix}/${appHash(appId)}`;
28647
+ const releaseRoot = (manifest) => `${root(manifest.appId)}/releases/${manifest.releaseId}`;
28648
+ const manifestKey = (manifest) => `${releaseRoot(manifest)}/update.json`;
28649
+ const fileKey = (manifest, file5) => `${releaseRoot(manifest)}/files/${file5.path}`;
28650
+ const channelKey = (appId, channel) => {
28651
+ if (!APP_ID.test(appId) || !NAME.test(channel))
28652
+ throw new MobileUpdateRegistryError("Mobile update channel identity is invalid");
28653
+ return `${root(appId)}/channels/${channel}.json`;
28654
+ };
28655
+ const readManifest2 = async (appId, releaseId) => {
28656
+ const key = manifestKey({ appId, releaseId });
28657
+ const bytes = await options.store.get(key);
28658
+ if (!bytes)
28659
+ return null;
28660
+ const head = await options.store.head(key);
28661
+ if (!head || head.size !== bytes.byteLength || head.metadata?.sha256 !== digest(bytes))
28662
+ throw new MobileUpdateRegistryError("Stored mobile update manifest integrity failed");
28663
+ const manifest = parseMobileUpdateManifest(decode(bytes));
28664
+ verifyManifestSignature(manifest, options.publicKeys);
28665
+ if (manifest.appId !== appId || manifest.releaseId !== releaseId)
28666
+ throw new MobileUpdateRegistryError("Stored mobile update identity changed");
28667
+ return { key, manifest };
28668
+ };
28669
+ const readChannel = async (appId, channel) => {
28670
+ const bytes = await options.store.get(channelKey(appId, channel));
28671
+ if (!bytes)
28672
+ return null;
28673
+ const value = parseChannel(decode(bytes));
28674
+ if (value.appId !== appId || value.channel !== channel)
28675
+ throw new MobileUpdateRegistryError("Stored mobile update channel identity changed");
28676
+ return value;
28677
+ };
28678
+ const writeChannel = async (input, signal) => {
28679
+ const value = {
28680
+ ...input,
28681
+ format: MOBILE_UPDATE_REGISTRY_FORMAT,
28682
+ promotedAt: clock().toISOString()
28683
+ };
28684
+ const bytes = json(value);
28685
+ await options.store.put(channelKey(value.appId, value.channel), bytes, {
28686
+ cacheControl: "no-cache",
28687
+ contentType: "application/json",
28688
+ maxBytes: bytes.byteLength,
28689
+ metadata: {
28690
+ channel: value.channel,
28691
+ ...value.releaseId ? { releaseId: value.releaseId } : {},
28692
+ sha256: digest(bytes)
28693
+ },
28694
+ signal
28695
+ });
28696
+ return value;
28697
+ };
28698
+ const promoteUpdate = async (input) => {
28699
+ input.signal?.throwIfAborted();
28700
+ if (input.rollout <= 0 || input.rollout > 1)
28701
+ throw new MobileUpdateRegistryError("Mobile update rollout is invalid");
28702
+ const release = await readManifest2(input.appId, input.releaseId);
28703
+ if (!release || release.manifest.channel !== input.channel)
28704
+ throw new MobileUpdateRegistryError("Mobile update was not published to this channel");
28705
+ const existing = await readChannel(input.appId, input.channel);
28706
+ await writeChannel({
28707
+ appId: input.appId,
28708
+ channel: input.channel,
28709
+ ...existing?.releaseId && existing.releaseId !== input.releaseId ? { fallbackReleaseId: existing.releaseId } : existing?.fallbackReleaseId ? { fallbackReleaseId: existing.fallbackReleaseId } : {},
28710
+ releaseId: input.releaseId,
28711
+ rollout: input.rollout
28712
+ }, input.signal);
28713
+ return {
28714
+ appId: input.appId,
28715
+ channel: input.channel,
28716
+ releaseId: input.releaseId,
28717
+ rollout: input.rollout,
28718
+ stage: "promoted"
28719
+ };
28720
+ };
28721
+ const resolveUpdateState = async (input) => {
28722
+ const channel = await readChannel(input.appId, input.channel);
28723
+ if (!channel?.releaseId)
28724
+ return { status: "empty" };
28725
+ const selected = rolloutMember({
28726
+ appId: input.appId,
28727
+ channel: input.channel,
28728
+ installationId: input.installationId,
28729
+ releaseId: channel.releaseId,
28730
+ rollout: channel.rollout
28731
+ }) ? channel.releaseId : channel.fallbackReleaseId;
28732
+ if (!selected)
28733
+ return { status: "empty" };
28734
+ const release = await readManifest2(input.appId, selected);
28735
+ if (!release || release.manifest.runtimeFingerprint !== input.runtimeFingerprint)
28736
+ return { status: "incompatible" };
28737
+ return {
28738
+ ...selected === channel.releaseId && channel.activationId && channel.activatedAt ? {
28739
+ activationId: channel.activationId,
28740
+ activatedAt: channel.activatedAt
28741
+ } : {},
28742
+ manifest: release.manifest,
28743
+ manifestKey: release.key,
28744
+ status: "selected"
28745
+ };
28746
+ };
28747
+ return {
28748
+ publishUpdate: async (input) => {
28749
+ input.signal?.throwIfAborted();
28750
+ const manifest = parseMobileUpdateManifest(input.manifest);
28751
+ verifyManifestSignature(manifest, options.publicKeys);
28752
+ const localRoot = path.resolve(input.releaseDirectory);
28753
+ const localManifest = parseMobileUpdateManifest(JSON.parse(await readFile9(path.join(localRoot, "update.json"), "utf8")));
28754
+ if (JSON.stringify(localManifest) !== JSON.stringify(manifest))
28755
+ throw new MobileUpdateRegistryError("Local mobile update manifest changed");
28756
+ const existing = await readManifest2(manifest.appId, manifest.releaseId);
28757
+ let reused = existing !== null;
28758
+ if (existing && JSON.stringify(existing.manifest) !== JSON.stringify(manifest))
28759
+ throw new MobileUpdateRegistryError("Published mobile update is immutable");
28760
+ if (!existing) {
28761
+ for (const file5 of manifest.files) {
28762
+ const local = path.join(localRoot, "files", file5.path);
28763
+ const metadata = await stat3(local).catch(() => null);
28764
+ if (!metadata?.isFile() || metadata.size !== file5.bytes)
28765
+ throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} size changed`);
28766
+ if (await fileDigest(Bun.file(local)) !== file5.sha256)
28767
+ throw new MobileUpdateRegistryError(`Mobile update file ${file5.path} integrity failed`);
28768
+ const key = fileKey(manifest, file5);
28769
+ const stored = await options.store.head(key);
28770
+ if (!stored) {
28771
+ await options.store.put(key, Bun.file(local).stream(), {
28772
+ cacheControl: "public, max-age=31536000, immutable",
28773
+ contentType: "application/octet-stream",
28774
+ maxBytes: file5.bytes,
28775
+ metadata: { releaseid: manifest.releaseId, sha256: file5.sha256 },
28776
+ signal: input.signal
28777
+ });
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");
28780
+ }
28781
+ const bytes = json(manifest);
28782
+ await options.store.put(manifestKey(manifest), bytes, {
28783
+ cacheControl: "public, max-age=31536000, immutable",
28784
+ contentType: "application/json",
28785
+ maxBytes: bytes.byteLength,
28786
+ metadata: { releaseid: manifest.releaseId, sha256: digest(bytes) },
28787
+ signal: input.signal
28788
+ });
28789
+ if (!await readManifest2(manifest.appId, manifest.releaseId))
28790
+ throw new MobileUpdateRegistryError("Mobile update publication verification failed");
28791
+ reused = false;
28792
+ }
28793
+ await promoteUpdate({
28794
+ appId: manifest.appId,
28795
+ channel: manifest.channel,
28796
+ releaseId: manifest.releaseId,
28797
+ rollout: input.rollout,
28798
+ signal: input.signal
28799
+ });
28800
+ return {
28801
+ appId: manifest.appId,
28802
+ channel: manifest.channel,
28803
+ releaseId: manifest.releaseId,
28804
+ reused,
28805
+ rollout: input.rollout,
28806
+ stage: "published"
28807
+ };
28808
+ },
28809
+ promoteUpdate,
28810
+ rollbackUpdate: async (input) => {
28811
+ input.signal?.throwIfAborted();
28812
+ const existing = await readChannel(input.appId, input.channel);
28813
+ if (!existing)
28814
+ throw new MobileUpdateRegistryError("Mobile update channel does not exist");
28815
+ if (input.releaseId) {
28816
+ const release = await readManifest2(input.appId, input.releaseId);
28817
+ if (!release || release.manifest.channel !== input.channel)
28818
+ throw new MobileUpdateRegistryError("Mobile rollback release was not published");
28819
+ }
28820
+ const activatedAt = clock().toISOString();
28821
+ await writeChannel({
28822
+ ...input.releaseId ? {
28823
+ activationId: digest(new TextEncoder().encode(`${input.appId}\x00${input.channel}\x00${input.releaseId}\x00${activatedAt}`)),
28824
+ activatedAt
28825
+ } : {},
28826
+ appId: input.appId,
28827
+ channel: input.channel,
28828
+ ...existing.releaseId ? { fallbackReleaseId: existing.releaseId } : {},
28829
+ ...input.releaseId ? { releaseId: input.releaseId } : {},
28830
+ rollout: input.releaseId ? 1 : 0
28831
+ }, input.signal);
28832
+ return {
28833
+ appId: input.appId,
28834
+ channel: input.channel,
28835
+ ...input.releaseId ? { releaseId: input.releaseId } : {},
28836
+ stage: "rolled-back"
28837
+ };
28838
+ },
28839
+ resolveUpdate: async (input) => {
28840
+ const resolution = await resolveUpdateState(input);
28841
+ return resolution.status === "selected" ? { manifest: resolution.manifest, manifestKey: resolution.manifestKey } : null;
28842
+ },
28843
+ resolveUpdateState,
28844
+ readUpdateFile: async (input) => {
28845
+ const release = await readManifest2(input.appId, input.releaseId);
28846
+ if (!release)
28847
+ return null;
28848
+ const requested = safePath(input.path);
28849
+ const file5 = release.manifest.files.find((candidate) => candidate.path === requested);
28850
+ if (!file5)
28851
+ return null;
28852
+ const key = fileKey(release.manifest, file5);
28853
+ const [bytes, head] = await Promise.all([
28854
+ options.store.get(key),
28855
+ options.store.head(key)
28856
+ ]);
28857
+ if (!bytes || !head)
28858
+ 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)
28860
+ throw new MobileUpdateRegistryError("Stored mobile update file integrity failed");
28861
+ return { bytes, file: file5 };
28862
+ }
28863
+ };
28864
+ }, expoUpdateId = (releaseId) => {
28865
+ const hash = RELEASE.test(releaseId) ? releaseId.slice("amu_".length, "amu_".length + 32) : createHash6("sha256").update(releaseId).digest("hex").slice(0, 32);
28866
+ return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-${hash.slice(12, 16)}-${hash.slice(16, 20)}-${hash.slice(20)}`;
28867
+ }, expoContentType = (extension, launch) => {
28868
+ if (launch)
28869
+ return "application/javascript";
28870
+ const normalized = extension?.toLowerCase();
28871
+ if (normalized === "png")
28872
+ return "image/png";
28873
+ if (normalized === "jpg" || normalized === "jpeg")
28874
+ return "image/jpeg";
28875
+ if (normalized === "webp")
28876
+ return "image/webp";
28877
+ if (normalized === "gif")
28878
+ return "image/gif";
28879
+ if (normalized === "svg")
28880
+ return "image/svg+xml";
28881
+ if (normalized === "json")
28882
+ return "application/json";
28883
+ if (normalized === "ttf")
28884
+ return "font/ttf";
28885
+ if (normalized === "otf")
28886
+ return "font/otf";
28887
+ if (normalized === "woff")
28888
+ return "font/woff";
28889
+ if (normalized === "woff2")
28890
+ return "font/woff2";
28891
+ return "application/octet-stream";
28892
+ }, encodeUpdatePath = (value) => value.split("/").map(encodeURIComponent).join("/"), expoProtocolHeaders, resolveExpoCodeSigning = (value) => {
28893
+ if (!value)
28894
+ return;
28895
+ const entries = Object.entries(value.keys);
28896
+ if (entries.length === 0)
28897
+ throw new MobileUpdateRegistryError("Expo code signing requires at least one key");
28898
+ return new Map(entries.map(([keyId, material]) => {
28899
+ if (!NAME.test(keyId))
28900
+ throw new MobileUpdateRegistryError("Expo code-signing key ID is invalid");
28901
+ let certificate;
28902
+ let privateKey;
28903
+ try {
28904
+ certificate = new X509Certificate2(material.certificate);
28905
+ privateKey = createPrivateKey(material.privateKey);
28906
+ } catch (error) {
28907
+ throw new MobileUpdateRegistryError("Expo code-signing certificate or private key is invalid", { cause: error });
28908
+ }
28909
+ if (certificate.publicKey.asymmetricKeyType !== "rsa" || privateKey.asymmetricKeyType !== "rsa" || certificate.issuer !== certificate.subject || !certificate.verify(certificate.publicKey))
28910
+ throw new MobileUpdateRegistryError("Expo code signing requires a self-signed RSA root and private key");
28911
+ const certificatePublicKey = certificate.publicKey.export({
28912
+ format: "der",
28913
+ type: "spki"
28914
+ });
28915
+ const privatePublicKey = createPublicKey2(privateKey).export({
28916
+ format: "der",
28917
+ type: "spki"
28918
+ });
28919
+ if (!certificatePublicKey.equals(privatePublicKey))
28920
+ throw new MobileUpdateRegistryError("Expo code-signing private key does not match its certificate");
28921
+ const now = Date.now();
28922
+ if (now < Date.parse(certificate.validFrom) || now > Date.parse(certificate.validTo))
28923
+ throw new MobileUpdateRegistryError("Expo code-signing certificate is not currently valid");
28924
+ return [keyId, { keyId, privateKey }];
28925
+ }));
28926
+ }, expoSignatureExpectation = (value) => {
28927
+ const fields = new Map;
28928
+ for (const raw of value.split(",")) {
28929
+ const match = /^\s*([a-z][a-z0-9_-]*)(?:=(\?1|\?0|"[^"\\]*"|[a-z0-9._-]+))?\s*$/u.exec(raw);
28930
+ if (!match || fields.has(match[1]))
28931
+ throw new MobileUpdateRegistryError("Expo code-signing expectation is invalid");
28932
+ const encoded = match[2];
28933
+ fields.set(match[1], encoded === undefined || encoded === "?1" ? true : encoded.startsWith('"') ? encoded.slice(1, -1) : encoded);
28934
+ }
28935
+ return fields;
28936
+ }, expoExtraParam = (request, key) => {
28937
+ const value = request.headers.get("expo-extra-params");
28938
+ if (!value)
28939
+ return null;
28940
+ for (const raw of value.split(",")) {
28941
+ const match = /^\s*([a-z][a-z0-9_.*-]*)=(?:"((?:[^"\\]|\\["\\])*)"|([^\s,]+))\s*$/u.exec(raw);
28942
+ if (!match || match[1] !== key)
28943
+ continue;
28944
+ return match[2] !== undefined ? match[2].replace(/\\(["\\])/gu, "$1") : match[3] ?? null;
28945
+ }
28946
+ return null;
28947
+ }, requestedExpoSignature = (request, codeSigning) => {
28948
+ const expectation = request.headers.get("expo-expect-signature");
28949
+ if (!expectation)
28950
+ return;
28951
+ if (!codeSigning)
28952
+ throw new MobileUpdateRegistryError("Expo end-to-end code signing is not configured");
28953
+ const fields = expoSignatureExpectation(expectation);
28954
+ const keyId = fields.get("keyid");
28955
+ const algorithm = fields.get("alg");
28956
+ const signatureRequested = fields.get("sig") === true;
28957
+ if (!signatureRequested || keyId !== undefined && typeof keyId !== "string" || algorithm !== undefined && algorithm !== EXPO_CODE_SIGNING_ALGORITHM)
28958
+ throw new MobileUpdateRegistryError("Requested Expo code-signing parameters are unsupported");
28959
+ const selected = typeof keyId === "string" ? codeSigning.get(keyId) : codeSigning.size === 1 ? codeSigning.values().next().value : undefined;
28960
+ if (!selected)
28961
+ throw new MobileUpdateRegistryError("Requested Expo code-signing key is unavailable");
28962
+ return selected;
28963
+ }, expoSignatureHeader = (body, codeSigning) => {
28964
+ const signature = sign("RSA-SHA256", Buffer.from(body), codeSigning.privateKey);
28965
+ return `sig="${signature.toString("base64")}", keyid="${codeSigning.keyId}", alg="${EXPO_CODE_SIGNING_ALGORITHM}"`;
28966
+ }, expoRollbackResponse = (request, codeSigning) => {
28967
+ const current = request.headers.get("expo-current-update-id");
28968
+ const embedded = request.headers.get("expo-embedded-update-id");
28969
+ if (!current || current === embedded)
28970
+ return new Response(null, { status: 204 });
28971
+ const boundary = `absolutejs-${crypto.randomUUID()}`;
28972
+ const directive = JSON.stringify({
28973
+ parameters: { commitTime: new Date().toISOString() },
28974
+ type: "rollBackToEmbedded"
28975
+ });
28976
+ const body = [
28977
+ `--${boundary}`,
28978
+ 'content-disposition: form-data; name="directive"',
28979
+ "content-type: application/json; charset=utf-8",
28980
+ ...codeSigning ? [`expo-signature: ${expoSignatureHeader(directive, codeSigning)}`] : [],
28981
+ "",
28982
+ directive,
28983
+ `--${boundary}--`,
28984
+ ""
28985
+ ].join(`\r
28986
+ `);
28987
+ return new Response(body, {
28988
+ headers: {
28989
+ ...expoProtocolHeaders,
28990
+ "content-type": `multipart/mixed; boundary=${boundary}`
28991
+ }
28992
+ });
28993
+ }, createMobileUpdateHandler = (options) => {
28994
+ const route = (options.route ?? `/__absolute/mobile/updates/${options.channel}`).replace(/^\/+|\/+$/g, "");
28995
+ const allowedOrigins = new Set(options.allowedOrigins ?? ["capacitor://localhost", "https://localhost"]);
28996
+ const expoCodeSigning = resolveExpoCodeSigning(options.expoCodeSigning);
28997
+ return async (request) => {
28998
+ const origin = request.headers.get("origin");
28999
+ const cors = origin && allowedOrigins.has(origin) ? { "access-control-allow-origin": origin, vary: "Origin" } : {};
29000
+ if (request.method === "OPTIONS") {
29001
+ if (!origin || !allowedOrigins.has(origin))
29002
+ return new Response(null, { status: 403 });
29003
+ return new Response(null, {
29004
+ headers: {
29005
+ ...cors,
29006
+ "access-control-allow-headers": "x-absolute-mobile-app,x-absolute-mobile-channel,x-absolute-mobile-installation,x-absolute-mobile-release,x-absolute-mobile-runtime",
29007
+ "access-control-allow-methods": "GET,OPTIONS",
29008
+ "access-control-max-age": "600"
29009
+ },
29010
+ status: 204
29011
+ });
29012
+ }
29013
+ if (request.method !== "GET")
29014
+ return new Response(null, { status: 405 });
29015
+ const pathname = new URL(request.url).pathname.replace(/^\/+/, "");
29016
+ const relative19 = pathname.startsWith(`${route}/`) ? pathname.slice(route.length + 1) : "";
29017
+ if (relative19 === "update.json") {
29018
+ const expoProtocolVersion = request.headers.get("expo-protocol-version");
29019
+ const expoProtocol = expoProtocolVersion !== null;
29020
+ if (expoProtocol && expoProtocolVersion !== "1")
29021
+ return Response.json({
29022
+ error: `Unsupported Expo Updates protocol version: ${expoProtocolVersion}`
29023
+ }, { status: 406 });
29024
+ const appId = request.headers.get("x-absolute-mobile-app");
29025
+ const channel = request.headers.get("x-absolute-mobile-channel");
29026
+ const installationId = expoProtocol ? expoExtraParam(request, "absolute-installation") ?? request.headers.get("x-absolute-mobile-installation") : request.headers.get("x-absolute-mobile-installation");
29027
+ const runtimeFingerprint = expoProtocol ? request.headers.get("expo-runtime-version") : request.headers.get("x-absolute-mobile-runtime");
29028
+ if (appId !== options.appId || channel !== options.channel || !installationId || !runtimeFingerprint)
29029
+ return new Response(null, { status: 400 });
29030
+ const resolution = options.registry.resolveUpdateState ? await options.registry.resolveUpdateState({
29031
+ appId,
29032
+ channel,
29033
+ installationId,
29034
+ runtimeFingerprint
29035
+ }) : undefined;
29036
+ const selected = resolution ? resolution.status === "selected" ? resolution : null : await options.registry.resolveUpdate({
29037
+ appId,
29038
+ channel,
29039
+ installationId,
29040
+ runtimeFingerprint
29041
+ });
29042
+ if (expoProtocol) {
29043
+ let requestedCodeSigning;
29044
+ try {
29045
+ requestedCodeSigning = requestedExpoSignature(request, expoCodeSigning);
29046
+ } catch (error) {
29047
+ return Response.json({
29048
+ error: error instanceof Error ? error.message : "Expo code-signing negotiation failed"
29049
+ }, { status: expoCodeSigning ? 406 : 400 });
29050
+ }
29051
+ if (!selected) {
29052
+ if (resolution?.status === "incompatible")
29053
+ return new Response(null, { status: 204 });
29054
+ return expoRollbackResponse(request, requestedCodeSigning);
29055
+ }
29056
+ const platform2 = request.headers.get("expo-platform");
29057
+ if (platform2 !== "android" && platform2 !== "ios")
29058
+ return new Response(null, { status: 400 });
29059
+ const updateId = expoUpdateId((resolution?.status === "selected" ? resolution.activationId : undefined) ?? selected.manifest.releaseId);
29060
+ if (request.headers.get("expo-current-update-id") === updateId)
29061
+ return new Response(null, { status: 204 });
29062
+ const descriptorFile = await options.registry.readUpdateFile({
29063
+ appId,
29064
+ path: EXPO_DESCRIPTOR,
29065
+ releaseId: selected.manifest.releaseId
29066
+ });
29067
+ if (!descriptorFile)
29068
+ return new Response(null, { status: 409 });
29069
+ const descriptor = parseExpoUpdateDescriptor(descriptorFile.bytes);
29070
+ const platformUpdate = descriptor.platforms[platform2];
29071
+ if (!platformUpdate || descriptor.runtimeVersion !== runtimeFingerprint)
29072
+ return new Response(null, { status: 204 });
29073
+ const origin2 = new URL(request.url).origin;
29074
+ const releaseRoute = `${origin2}/${route}/${selected.manifest.releaseId}/files`;
29075
+ const protocolAsset = (asset, launch = false) => {
29076
+ const file22 = selected.manifest.files.find((candidate) => candidate.path === asset.path);
29077
+ if (!file22)
29078
+ throw new MobileUpdateRegistryError(`Expo update references missing signed asset ${asset.path}`);
29079
+ return {
29080
+ contentType: expoContentType(asset.extension, launch),
29081
+ ...asset.extension ? { fileExtension: `.${asset.extension}` } : {},
29082
+ key: file22.sha256,
29083
+ hash: Buffer.from(file22.sha256, "hex").toString("base64url"),
29084
+ url: `${releaseRoute}/${encodeUpdatePath(asset.path)}`
29085
+ };
29086
+ };
29087
+ const manifest = JSON.stringify({
29088
+ assets: platformUpdate.assets.map((asset) => protocolAsset(asset)),
29089
+ createdAt: (resolution?.status === "selected" ? resolution.activatedAt : undefined) ?? selected.manifest.createdAt,
29090
+ extra: {
29091
+ absolutejs: {
29092
+ channel: selected.manifest.channel,
29093
+ releaseId: selected.manifest.releaseId
29094
+ },
29095
+ expoClient: descriptor.expoConfig
29096
+ },
29097
+ id: updateId,
29098
+ launchAsset: protocolAsset(platformUpdate.launchAsset, true),
29099
+ metadata: {
29100
+ channel: selected.manifest.channel,
29101
+ releaseId: selected.manifest.releaseId
29102
+ },
29103
+ runtimeVersion: descriptor.runtimeVersion
29104
+ });
29105
+ return new Response(manifest, {
29106
+ headers: {
29107
+ ...expoProtocolHeaders,
29108
+ ...requestedCodeSigning ? {
29109
+ "expo-signature": expoSignatureHeader(manifest, requestedCodeSigning)
29110
+ } : {}
29111
+ }
29112
+ });
29113
+ }
29114
+ if (!selected)
29115
+ return new Response(null, { status: 204 });
29116
+ return Response.json(selected.manifest, {
29117
+ headers: {
29118
+ ...cors,
29119
+ "cache-control": "no-store",
29120
+ etag: `"${selected.manifest.releaseId}"`
29121
+ }
29122
+ });
29123
+ }
29124
+ const match = /^(amu_[a-f0-9]{64})\/files\/(.+)$/.exec(relative19);
29125
+ if (!match?.[1] || !match[2])
29126
+ return new Response(null, { status: 404 });
29127
+ const file5 = await options.registry.readUpdateFile({
29128
+ appId: options.appId,
29129
+ path: decodeURIComponent(match[2]),
29130
+ releaseId: match[1]
29131
+ });
29132
+ if (!file5)
29133
+ return new Response(null, { status: 404 });
29134
+ return new Response(new Blob([new Uint8Array(file5.bytes).buffer]), {
29135
+ headers: {
29136
+ ...cors,
29137
+ "cache-control": "public, max-age=31536000, immutable",
29138
+ "content-length": String(file5.file.bytes),
29139
+ "content-type": expoContentType(file5.file.path.includes(".") ? file5.file.path.slice(file5.file.path.lastIndexOf(".") + 1) : undefined, false),
29140
+ etag: `"${file5.file.sha256}"`
29141
+ }
29142
+ });
29143
+ };
29144
+ };
29145
+ var init_mobileUpdate = __esm(() => {
29146
+ MAX_FILE_BYTES = 32 * 1024 * 1024;
29147
+ MAX_TOTAL_BYTES = 128 * 1024 * 1024;
29148
+ HASH = /^[a-f0-9]{64}$/;
29149
+ RELEASE = /^amu_[a-f0-9]{64}$/;
29150
+ APP_ID = /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)+$/;
29151
+ NAME = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
29152
+ MobileUpdateRegistryError = class MobileUpdateRegistryError extends Error {
29153
+ };
29154
+ expoProtocolHeaders = {
29155
+ "cache-control": "private, max-age=0",
29156
+ "content-type": "application/expo+json",
29157
+ "expo-protocol-version": "1",
29158
+ "expo-sfv-version": "0"
29159
+ };
29160
+ });
29161
+
29162
+ // src/mobile/updateServer.ts
29163
+ var exports_updateServer = {};
29164
+ __export(exports_updateServer, {
29165
+ ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT: () => ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT,
29166
+ DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE: () => DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE,
29167
+ createAbsoluteMobileUpdateServerPlugin: () => createAbsoluteMobileUpdateServerPlugin,
29168
+ inspectAbsoluteMobileUpdateServer: () => inspectAbsoluteMobileUpdateServer,
29169
+ loadAbsoluteMobileUpdateServerModule: () => loadAbsoluteMobileUpdateServerModule,
29170
+ renderAbsoluteMobileUpdateRegistry: () => renderAbsoluteMobileUpdateRegistry,
29171
+ writeAbsoluteMobileUpdateRegistry: () => writeAbsoluteMobileUpdateRegistry
29172
+ });
29173
+ import {
29174
+ createPrivateKey as createPrivateKey2,
29175
+ createPublicKey as createPublicKey3,
29176
+ X509Certificate as X509Certificate3
29177
+ } from "crypto";
29178
+ import { access as access4, mkdir as mkdir13 } from "fs/promises";
29179
+ import { dirname as dirname31, isAbsolute as isAbsolute8, relative as relative19, resolve as resolve46, sep as sep4 } from "path";
29180
+ import { pathToFileURL as pathToFileURL3 } from "url";
29181
+ import { Elysia as Elysia5 } from "elysia";
29182
+ var ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT = 1, DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE = "mobile.update.ts", object4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), projectPath = (projectRoot, requested) => {
29183
+ const root = resolve46(projectRoot);
29184
+ const path2 = resolve46(root, requested);
29185
+ const projectRelative = relative19(root, path2);
29186
+ if (projectRelative === ".." || projectRelative.startsWith(`..${sep4}`) || isAbsolute8(projectRelative))
29187
+ throw new TypeError("mobile.updates.server.registry must remain inside the project.");
29188
+ return path2;
29189
+ }, isRegistry2 = (value) => object4(value) && [
29190
+ "publishUpdate",
29191
+ "promoteUpdate",
29192
+ "rollbackUpdate",
29193
+ "resolveUpdate",
29194
+ "readUpdateFile"
29195
+ ].every((method) => typeof value[method] === "function"), serverMetadata = (value) => {
29196
+ if (!object4(value))
29197
+ throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
29198
+ const { format, provider, storage } = value;
29199
+ if (format !== ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT || storage !== "local" && storage !== "durable" || typeof provider !== "string" || !provider)
29200
+ throw new TypeError("Mobile update registry must export valid absoluteMobileUpdateServer metadata. Run `absolute mobile update provision`.");
29201
+ const metadata = {
29202
+ format: ABSOLUTE_MOBILE_UPDATE_SERVER_FORMAT,
29203
+ provider,
29204
+ storage
29205
+ };
29206
+ return metadata;
29207
+ }, loadAbsoluteMobileUpdateServerModule = async (projectRoot, requestedModulePath = DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE) => {
29208
+ const modulePath = projectPath(projectRoot, requestedModulePath);
29209
+ await access4(modulePath).catch(() => {
29210
+ throw new TypeError(`Mobile update server registry does not exist: ${modulePath}. Run \`absolute mobile update provision\`.`);
29211
+ });
29212
+ const loaded = await import(pathToFileURL3(modulePath).href);
29213
+ if (!object4(loaded))
29214
+ throw new TypeError("Mobile update registry module has no exports.");
29215
+ const registry2 = loaded.default ?? loaded.registry;
29216
+ if (!isRegistry2(registry2))
29217
+ throw new TypeError("Mobile update registry must implement publication, promotion, rollback, resolution, and file reads.");
29218
+ const metadata = serverMetadata(loaded.absoluteMobileUpdateServer);
29219
+ const verifier = loaded.verifyAbsoluteMobileUpdateServer;
29220
+ if (metadata.storage === "durable" && typeof verifier !== "function")
29221
+ throw new TypeError("Mobile update registries marked durable must export verifyAbsoluteMobileUpdateServer(). Re-run `absolute mobile update provision --storage s3 --force` or provide an active durability check.");
29222
+ return {
29223
+ metadata,
29224
+ registry: registry2,
29225
+ ...typeof verifier === "function" ? {
29226
+ verifyDurability: async () => {
29227
+ await verifier();
29228
+ }
29229
+ } : {}
29230
+ };
29231
+ }, verifyDurableModule = async (module) => {
29232
+ if (module.metadata.storage !== "durable")
29233
+ throw new TypeError("Mobile production updates require durable object storage. Re-run `absolute mobile update provision --storage s3 --force` or configure a durable adapter.");
29234
+ try {
29235
+ await module.verifyDurability?.();
29236
+ } catch (error) {
29237
+ throw new TypeError(`Durable mobile update storage verification failed for ${module.metadata.provider}. Check the bucket, endpoint, credentials, and read/write/delete permissions.`, { cause: error });
29238
+ }
29239
+ }, expoSigningOptions = (config) => {
29240
+ if (!config.updates?.expoCodeSigning)
29241
+ return;
29242
+ const entries = Object.entries(config.updateServer?.expoCodeSigningKeys ?? {});
29243
+ const keys = Object.fromEntries(entries.map(([keyId, key]) => {
29244
+ const privateKey = process.env[key.privateKeyEnv];
29245
+ if (!privateKey)
29246
+ throw new TypeError(`Expo update serving requires ${key.privateKeyEnv} on the trusted server.`);
29247
+ try {
29248
+ const certificate = new X509Certificate3(key.certificatePem);
29249
+ const expected = certificate.publicKey.export({
29250
+ format: "der",
29251
+ type: "spki"
29252
+ });
29253
+ const actual = createPublicKey3(createPrivateKey2(privateKey)).export({
29254
+ format: "der",
29255
+ type: "spki"
29256
+ });
29257
+ if (!expected.equals(actual))
29258
+ throw new Error("key mismatch");
29259
+ } catch (error) {
29260
+ throw new TypeError(`${key.privateKeyEnv} must contain the RSA private key matching Expo update key ${keyId}.`, { cause: error });
29261
+ }
29262
+ return [keyId, { certificate: key.certificatePem, privateKey }];
29263
+ }));
29264
+ return { keys };
29265
+ }, createAbsoluteMobileUpdateServerPlugin = async (config, projectRoot, options = {}) => {
29266
+ const { updates, updateServer: server } = config;
29267
+ if (!updates || !server?.autoMount)
29268
+ return new Elysia5({ name: "absolutejs-mobile-updates-disabled" });
29269
+ const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, server.registryModule);
29270
+ if (options.production)
29271
+ await verifyDurableModule(module);
29272
+ const manifest = new URL(updates.manifestUrl);
29273
+ if (!manifest.pathname.endsWith("/update.json"))
29274
+ throw new TypeError("Auto-mounted mobile update manifests must end in /update.json.");
29275
+ const route = manifest.pathname.slice(0, -"/update.json".length);
29276
+ const { createMobileUpdateHandler: createMobileUpdateHandler2 } = await Promise.resolve().then(() => (init_mobileUpdate(), exports_mobileUpdate));
29277
+ const handler = createMobileUpdateHandler2({
29278
+ appId: config.appId,
29279
+ channel: updates.channel,
29280
+ ...config.engine === "expo" ? { expoCodeSigning: expoSigningOptions(config) } : {},
29281
+ registry: module.registry,
29282
+ route
29283
+ });
29284
+ return new Elysia5({ name: "absolutejs-mobile-updates" }).all(`${route}/*`, ({ request }) => handler(request));
29285
+ }, inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
29286
+ if (!config.updates)
29287
+ return;
29288
+ const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
29289
+ await verifyDurableModule(module);
29290
+ if (config.engine === "expo")
29291
+ expoSigningOptions(config);
29292
+ return module.metadata;
29293
+ }, publicKeysSource = (publicKeys) => JSON.stringify(publicKeys, null, "\t"), renderAbsoluteMobileUpdateRegistry = (options) => {
29294
+ const metadata = `export const absoluteMobileUpdateServer = {
29295
+ format: 1,
29296
+ provider: '${options.storage}',
29297
+ storage: '${options.storage === "local" ? "local" : "durable"}'
29298
+ } as const;`;
29299
+ if (options.storage === "local")
29300
+ return `import { fileURLToPath } from 'node:url';
29301
+ import { localBlobStore } from '@absolutejs/blob/local';
29302
+ import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
29303
+
29304
+ ${metadata}
29305
+
29306
+ const store = localBlobStore({
29307
+ root: process.env.ABSOLUTE_MOBILE_UPDATE_LOCAL_ROOT ??
29308
+ fileURLToPath(new URL('./.absolutejs/mobile/update-registry/', import.meta.url))
29309
+ });
29310
+
29311
+ export default createMobileUpdateRegistry({
29312
+ publicKeys: ${publicKeysSource(options.publicKeys)},
29313
+ store
29314
+ });
29315
+ `;
29316
+ return `import { randomUUID } from 'node:crypto';
29317
+ import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
29318
+ import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
29319
+ import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
29320
+
29321
+ ${metadata}
29322
+
29323
+ const required = (name: string) => {
29324
+ const value = process.env[name];
29325
+ if (!value) throw new Error(\`Missing \${name}\`);
29326
+ return value;
29327
+ };
29328
+
29329
+ const bucket = required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET');
29330
+ const client = new S3Client({
29331
+ region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
29332
+ forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
29333
+ ...(process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT
29334
+ ? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
29335
+ : {})
29336
+ });
29337
+ const store = awsS3BlobStore({ bucket, client });
29338
+
29339
+ export const verifyAbsoluteMobileUpdateServer = async () => {
29340
+ const key = \`absolutejs/mobile-updates/_health/\${randomUUID()}\`;
29341
+ const expected = randomUUID();
29342
+ let stored = false;
29343
+ try {
29344
+ await client.send(new PutObjectCommand({ Bucket: bucket, Key: key, Body: expected }));
29345
+ stored = true;
29346
+ const response = await client.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
29347
+ if ((await response.Body?.transformToString()) !== expected)
29348
+ throw new Error('Durability probe read did not match its write.');
29349
+ } finally {
29350
+ if (stored) await client.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
29351
+ }
29352
+ };
29353
+
29354
+ export default createMobileUpdateRegistry({
29355
+ publicKeys: ${publicKeysSource(options.publicKeys)},
29356
+ store
29357
+ });
29358
+ `;
29359
+ }, writeAbsoluteMobileUpdateRegistry = async (options) => {
29360
+ const path2 = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
29361
+ if (!options.force) {
29362
+ await access4(path2).then(() => {
29363
+ throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
29364
+ }, () => {
29365
+ return;
29366
+ });
29367
+ }
29368
+ await mkdir13(dirname31(path2), { recursive: true });
29369
+ await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
29370
+ publicKeys: options.publicKeys,
29371
+ storage: options.storage
29372
+ }));
29373
+ return path2;
29374
+ };
29375
+ var init_updateServer = () => {};
29376
+
28415
29377
  // src/react/bridgeInternals.ts
28416
29378
  var INTERNALS_KEYS, isRecord8 = (val) => typeof val === "object" && val !== null, findInternals = (mod) => {
28417
29379
  for (const key of INTERNALS_KEYS) {
@@ -28457,10 +29419,10 @@ __export(exports_hmrCompiler, {
28457
29419
  encodeHmrComponentId: () => encodeHmrComponentId,
28458
29420
  getApplyMetadataModule: () => getApplyMetadataModule
28459
29421
  });
28460
- import { dirname as dirname31, relative as relative19, resolve as resolve46 } from "path";
29422
+ import { dirname as dirname32, relative as relative20, resolve as resolve47 } from "path";
28461
29423
  import { performance as performance2 } from "perf_hooks";
28462
29424
  var encodeHmrComponentId = (absoluteFilePath, className) => {
28463
- const projectRel = relative19(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
29425
+ const projectRel = relative20(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
28464
29426
  return `${projectRel}@${className}`;
28465
29427
  }, getApplyMetadataModule = async (encodedId) => {
28466
29428
  const decoded = decodeURIComponent(encodedId);
@@ -28469,8 +29431,8 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
28469
29431
  return null;
28470
29432
  const filePathRel = decoded.slice(0, separatorIndex);
28471
29433
  const className = decoded.slice(separatorIndex + 1);
28472
- const componentFilePath = resolve46(process.cwd(), filePathRel);
28473
- const projectRelPath = relative19(process.cwd(), componentFilePath).replace(/\\/g, "/");
29434
+ const componentFilePath = resolve47(process.cwd(), filePathRel);
29435
+ const projectRelPath = relative20(process.cwd(), componentFilePath).replace(/\\/g, "/");
28474
29436
  const cacheKey3 = encodeURIComponent(`${projectRelPath}@${className}`);
28475
29437
  const { takePendingModule: takePendingModule2 } = await Promise.resolve().then(() => (init_fastHmrCompiler(), exports_fastHmrCompiler));
28476
29438
  const cached = takePendingModule2(cacheKey3);
@@ -28480,7 +29442,7 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
28480
29442
  const { resolveOwningComponents: resolveOwningComponents2 } = await Promise.resolve().then(() => (init_resolveOwningComponents(), exports_resolveOwningComponents));
28481
29443
  const owners = resolveOwningComponents2({
28482
29444
  changedFilePath: componentFilePath,
28483
- userAngularRoot: dirname31(componentFilePath)
29445
+ userAngularRoot: dirname32(componentFilePath)
28484
29446
  });
28485
29447
  const owner = owners.find((o3) => o3.className === className);
28486
29448
  const kind = owner?.kind ?? "component";
@@ -28502,7 +29464,7 @@ var exports_hmr = {};
28502
29464
  __export(exports_hmr, {
28503
29465
  hmr: () => hmr
28504
29466
  });
28505
- import Elysia5 from "elysia";
29467
+ import Elysia6 from "elysia";
28506
29468
  import { websocket } from "elysia/websocket";
28507
29469
  var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Reflect.get(globalThis, key), restoreStore = (store) => {
28508
29470
  if (!store || typeof store !== "object")
@@ -28578,8 +29540,8 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
28578
29540
  return null;
28579
29541
  if (!pathname.startsWith("/"))
28580
29542
  return null;
28581
- const { resolve: resolve47, normalize } = await import("path");
28582
- const candidate = resolve47(buildDir, pathname.slice(1));
29543
+ const { resolve: resolve48, normalize } = await import("path");
29544
+ const candidate = resolve48(buildDir, pathname.slice(1));
28583
29545
  const normalizedBuild = normalize(buildDir);
28584
29546
  if (!candidate.startsWith(normalizedBuild))
28585
29547
  return null;
@@ -28598,7 +29560,7 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
28598
29560
  return candidate;
28599
29561
  }
28600
29562
  return null;
28601
- }, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia5({ name: "absolutejs-hmr" }).use(websocket({
29563
+ }, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia6({ name: "absolutejs-hmr" }).use(websocket({
28602
29564
  idleTimeout: DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS,
28603
29565
  sendPings: true
28604
29566
  })).request(async ({ request, store }) => {
@@ -28685,12 +29647,12 @@ __export(exports_devtoolsJson, {
28685
29647
  resolveDevtoolsUuidCachePath: () => resolveDevtoolsUuidCachePath
28686
29648
  });
28687
29649
  import { existsSync as existsSync43, mkdirSync as mkdirSync14, readFileSync as readFileSync37, writeFileSync as writeFileSync10 } from "fs";
28688
- import { dirname as dirname32, join as join54, resolve as resolve47 } from "path";
28689
- import { Elysia as Elysia6 } from "elysia";
29650
+ import { dirname as dirname33, join as join54, resolve as resolve48 } from "path";
29651
+ import { Elysia as Elysia7 } from "elysia";
28690
29652
  var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_KEY = "__absoluteDevtoolsWorkspaceUuid", getGlobalUuid = () => Reflect.get(globalThis, UUID_CACHE_KEY), setGlobalUuid = (uuid) => {
28691
29653
  Reflect.set(globalThis, UUID_CACHE_KEY, uuid);
28692
29654
  return uuid;
28693
- }, isUuidV4 = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value), resolveDevtoolsUuidCachePath = (buildDir, uuidCachePath) => resolve47(uuidCachePath ?? join54(buildDir, ".absolute", "chrome-devtools-workspace-uuid")), readCachedUuid = (cachePath) => {
29655
+ }, isUuidV4 = (value) => /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value), resolveDevtoolsUuidCachePath = (buildDir, uuidCachePath) => resolve48(uuidCachePath ?? join54(buildDir, ".absolute", "chrome-devtools-workspace-uuid")), readCachedUuid = (cachePath) => {
28694
29656
  if (!existsSync43(cachePath))
28695
29657
  return null;
28696
29658
  try {
@@ -28712,14 +29674,14 @@ var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_K
28712
29674
  if (cachedUuid)
28713
29675
  return setGlobalUuid(cachedUuid);
28714
29676
  const uuid = crypto.randomUUID();
28715
- mkdirSync14(dirname32(cachePath), { recursive: true });
29677
+ mkdirSync14(dirname33(cachePath), { recursive: true });
28716
29678
  writeFileSync10(cachePath, uuid, "utf-8");
28717
29679
  return setGlobalUuid(uuid);
28718
29680
  }, devtoolsJson = (buildDir, options = {}) => {
28719
- const rootPath = resolve47(options.projectRoot ?? process.cwd());
29681
+ const rootPath = resolve48(options.projectRoot ?? process.cwd());
28720
29682
  const root = options.normalizeForWindowsContainer === false ? rootPath : normalizeDevtoolsWorkspaceRoot(rootPath);
28721
29683
  const uuid = getOrCreateUuid(buildDir, options);
28722
- return new Elysia6({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
29684
+ return new Elysia7({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
28723
29685
  workspace: {
28724
29686
  root,
28725
29687
  uuid
@@ -28745,11 +29707,11 @@ __export(exports_imageOptimizer, {
28745
29707
  imageOptimizer: () => imageOptimizer
28746
29708
  });
28747
29709
  import { existsSync as existsSync44 } from "fs";
28748
- import { resolve as resolve48 } from "path";
28749
- import { Elysia as Elysia7 } from "elysia";
28750
- var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (path, baseDir) => {
29710
+ import { resolve as resolve49 } from "path";
29711
+ import { Elysia as Elysia8 } from "elysia";
29712
+ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (path2, baseDir) => {
28751
29713
  try {
28752
- const resolved = validateSafePath(path, baseDir);
29714
+ const resolved = validateSafePath(path2, baseDir);
28753
29715
  if (existsSync44(resolved))
28754
29716
  return resolved;
28755
29717
  return null;
@@ -28758,7 +29720,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
28758
29720
  }
28759
29721
  }, resolveLocalImage = (url, buildDir) => {
28760
29722
  const cleanPath = url.startsWith("/") ? url.slice(1) : url;
28761
- return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve48(process.cwd()));
29723
+ return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve49(process.cwd()));
28762
29724
  }, parseQueryParams = (query, allowedSizes, defaultQuality) => {
28763
29725
  const url = typeof query["url"] === "string" ? query["url"] : undefined;
28764
29726
  const wParam = typeof query["w"] === "string" ? query["w"] : undefined;
@@ -28859,7 +29821,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
28859
29821
  }
28860
29822
  });
28861
29823
  }, imageOptimizer = (config, buildDir) => {
28862
- const plugin = new Elysia7({ name: "image-optimizer" });
29824
+ const plugin = new Elysia8({ name: "image-optimizer" });
28863
29825
  if (!config && config !== undefined)
28864
29826
  return plugin;
28865
29827
  if (config?.unoptimized)
@@ -28960,16 +29922,16 @@ var exports_requestInspector = {};
28960
29922
  __export(exports_requestInspector, {
28961
29923
  requestInspector: () => requestInspector
28962
29924
  });
28963
- import { Elysia as Elysia8 } from "elysia";
29925
+ import { Elysia as Elysia9 } from "elysia";
28964
29926
  var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
28965
29927
  globalThis.__absoluteRequestLog ??= [];
28966
29928
  return globalThis.__absoluteRequestLog;
28967
- }, classify = (path) => {
28968
- if (path.startsWith("/@") || path.includes("/__hmr"))
29929
+ }, classify = (path2) => {
29930
+ if (path2.startsWith("/@") || path2.includes("/__hmr"))
28969
29931
  return "hmr";
28970
- if (path.startsWith("/api"))
29932
+ if (path2.startsWith("/api"))
28971
29933
  return "api";
28972
- if (ASSET_EXTENSION.test(path) || path.startsWith("/assets/"))
29934
+ if (ASSET_EXTENSION.test(path2) || path2.startsWith("/assets/"))
28973
29935
  return "asset";
28974
29936
  return "page";
28975
29937
  }, pathOf = (url) => {
@@ -28996,7 +29958,7 @@ var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
28996
29958
  var init_requestInspector = __esm(() => {
28997
29959
  ASSET_EXTENSION = /\.(?:avif|css|gif|ico|jpe?g|js|json|map|mjs|otf|png|svg|ttf|txt|wasm|webp|woff2?)$/i;
28998
29960
  pending = new WeakMap;
28999
- requestInspector = new Elysia8({
29961
+ requestInspector = new Elysia9({
29000
29962
  name: "absolute-request-inspector"
29001
29963
  }).get("/__absolute/requests", () => requestLog()).request(({ request }) => {
29002
29964
  noteDevRequestStart();
@@ -29006,17 +29968,17 @@ var init_requestInspector = __esm(() => {
29006
29968
  });
29007
29969
  }).afterResponse(({ request, set, responseValue }) => {
29008
29970
  noteDevRequestEnd();
29009
- const path = pathOf(request.url);
29010
- if (path.startsWith("/__absolute"))
29971
+ const path2 = pathOf(request.url);
29972
+ if (path2.startsWith("/__absolute"))
29011
29973
  return;
29012
29974
  const entry = pending.get(request);
29013
29975
  const log2 = requestLog();
29014
29976
  log2.push({
29015
29977
  at: Date.now(),
29016
29978
  durationMs: entry === undefined ? 0 : performance.now() - entry.start,
29017
- kind: classify(path),
29979
+ kind: classify(path2),
29018
29980
  method: request.method,
29019
- path,
29981
+ path: path2,
29020
29982
  query: new URL(request.url).search,
29021
29983
  requestHeaders: entry?.headers ?? {},
29022
29984
  responseHeaders: toHeaderRecord(set.headers),
@@ -29029,7 +29991,7 @@ var init_requestInspector = __esm(() => {
29029
29991
  });
29030
29992
 
29031
29993
  // src/mobile/releaseArtifact.ts
29032
- import { createHash as createHash6 } from "crypto";
29994
+ import { createHash as createHash7 } from "crypto";
29033
29995
  var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIONS = 3, SHA_256 = "sha256", RELEASE_ID_PREFIX = "amc_", MODULE_SEGMENT_PARENT = "..", EXPORT_NAME_PATTERN, frameworks2, isCanonicalRecord = (value) => {
29034
29996
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
29035
29997
  return false;
@@ -29066,7 +30028,7 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
29066
30028
  return normalizeCanonicalRecord(value, ancestors);
29067
30029
  }
29068
30030
  throw new TypeError("Compatibility metadata must contain only finite JSON values.");
29069
- }, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) => createHash6(SHA_256).update(canonicalJson(value)).digest("hex"), requireNonEmpty = (value, field) => {
30031
+ }, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) => createHash7(SHA_256).update(canonicalJson(value)).digest("hex"), requireNonEmpty = (value, field) => {
29070
30032
  if (!value.trim()) {
29071
30033
  throw new TypeError(`${field} must not be empty.`);
29072
30034
  }
@@ -29255,11 +30217,11 @@ var init_releaseArtifact = __esm(() => {
29255
30217
  });
29256
30218
 
29257
30219
  // src/mobile/artifactStore.ts
29258
- import { createHash as createHash7 } from "crypto";
30220
+ import { createHash as createHash8 } from "crypto";
29259
30221
  import {
29260
- mkdir as mkdir13,
30222
+ mkdir as mkdir14,
29261
30223
  mkdtemp as mkdtemp2,
29262
- readFile as readFile9,
30224
+ readFile as readFile10,
29263
30225
  readdir as readdir5,
29264
30226
  rename as rename5,
29265
30227
  rm as rm13,
@@ -29268,18 +30230,18 @@ import {
29268
30230
  import { join as join55, resolve as resolvePath } from "path";
29269
30231
  var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE = "artifact.json", RELEASE_ID_PATTERN, DEFAULT_BLOB_PREFIX = "absolutejs/mobile-compatibility", hashBlob = async (blob) => {
29270
30232
  const bytes = new Uint8Array(await blob.arrayBuffer());
29271
- return createHash7(SHA_2562).update(bytes).digest("hex");
30233
+ return createHash8(SHA_2562).update(bytes).digest("hex");
29272
30234
  }, blobFromBytes = (bytes) => {
29273
30235
  const buffer = new ArrayBuffer(bytes.byteLength);
29274
30236
  new Uint8Array(buffer).set(bytes);
29275
30237
  return new Blob([buffer]);
29276
- }, errorHasCode = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, appDirectoryName = (appId) => createHash7(SHA_2562).update(appId).digest("hex"), requireReleaseId = (releaseId) => {
30238
+ }, errorHasCode = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, appDirectoryName = (appId) => createHash8(SHA_2562).update(appId).digest("hex"), requireReleaseId = (releaseId) => {
29277
30239
  if (!RELEASE_ID_PATTERN.test(releaseId)) {
29278
30240
  throw new TypeError("Invalid mobile compatibility release id.");
29279
30241
  }
29280
30242
  return releaseId;
29281
30243
  }, readStoredArtifact = async (releaseDirectory) => {
29282
- const serialized = await readFile9(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
30244
+ const serialized = await readFile10(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
29283
30245
  const parsed = JSON.parse(serialized);
29284
30246
  return parseAbsoluteMobileCompatibilityArtifact(parsed);
29285
30247
  }, validateStoredIdentity = (artifact, appId, releaseId) => {
@@ -29423,11 +30385,11 @@ var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE =
29423
30385
  const validatedArtifact = parseAbsoluteMobileCompatibilityArtifact(release.artifact);
29424
30386
  const validated = await verifyAbsoluteMobileCompatibilityProducer({ artifact: validatedArtifact, producer: release.producer }, maxProducerBytes);
29425
30387
  const parent = appDirectory(validated.artifact.appId);
29426
- await mkdir13(parent, { recursive: true });
30388
+ await mkdir14(parent, { recursive: true });
29427
30389
  const staging = await mkdtemp2(join55(parent, ".stage-"));
29428
30390
  const producerPath = join55(staging, validated.artifact.producer.module);
29429
30391
  try {
29430
- await mkdir13(resolvePath(producerPath, ".."), {
30392
+ await mkdir14(resolvePath(producerPath, ".."), {
29431
30393
  recursive: true
29432
30394
  });
29433
30395
  await Promise.all([
@@ -29467,24 +30429,24 @@ __export(exports_materializedBundle, {
29467
30429
  materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
29468
30430
  readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
29469
30431
  });
29470
- import { createHash as createHash8 } from "crypto";
30432
+ import { createHash as createHash9 } from "crypto";
29471
30433
  import {
29472
- access as access4,
29473
- mkdir as mkdir14,
30434
+ access as access5,
30435
+ mkdir as mkdir15,
29474
30436
  mkdtemp as mkdtemp3,
29475
- readFile as readFile10,
30437
+ readFile as readFile11,
29476
30438
  rename as rename6,
29477
30439
  rm as rm14,
29478
30440
  writeFile as writeFile12
29479
30441
  } from "fs/promises";
29480
- import { dirname as dirname33, join as join56, resolve as resolvePath2 } from "path";
29481
- import { pathToFileURL as pathToFileURL3 } from "url";
30442
+ import { dirname as dirname34, join as join56, resolve as resolvePath2 } from "path";
30443
+ import { pathToFileURL as pathToFileURL4 } from "url";
29482
30444
  var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE2 = "artifact.json", BUNDLE_ID_PATTERN, isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), errorHasCode2 = (error, code2) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code2, bundleIdFor = (currentReleaseId, releases) => {
29483
30445
  const identity = JSON.stringify({
29484
30446
  currentReleaseId,
29485
30447
  releases: releases.map(({ releaseId }) => releaseId)
29486
30448
  });
29487
- return `amb_${createHash8("sha256").update(identity).digest("hex")}`;
30449
+ return `amb_${createHash9("sha256").update(identity).digest("hex")}`;
29488
30450
  }, parseBundleIndex = (value) => {
29489
30451
  if (!isRecord9(value) || value.format !== ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT || typeof value.bundleId !== "string" || !BUNDLE_ID_PATTERN.test(value.bundleId) || typeof value.currentReleaseId !== "string" || !Array.isArray(value.releases)) {
29490
30452
  throw new TypeError("Invalid materialized mobile compatibility bundle.");
@@ -29510,7 +30472,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29510
30472
  }, writeRelease = async (root, release) => {
29511
30473
  const directory = join56(root, release.artifact.releaseId);
29512
30474
  const producerPath = join56(directory, release.artifact.producer.module);
29513
- await mkdir14(dirname33(producerPath), { recursive: true });
30475
+ await mkdir15(dirname34(producerPath), { recursive: true });
29514
30476
  await Promise.all([
29515
30477
  writeFile12(join56(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
29516
30478
  `),
@@ -29519,7 +30481,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29519
30481
  }, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
29520
30482
  const destination = join56(bundlesRoot, bundleId);
29521
30483
  try {
29522
- await access4(destination);
30484
+ await access5(destination);
29523
30485
  return destination;
29524
30486
  } catch (error) {
29525
30487
  if (!errorHasCode2(error, "ENOENT"))
@@ -29537,7 +30499,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29537
30499
  throw error;
29538
30500
  }
29539
30501
  return destination;
29540
- }, readCompatibilityModule = (modulePath) => import(pathToFileURL3(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
30502
+ }, readCompatibilityModule = (modulePath) => import(pathToFileURL4(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
29541
30503
  const value = loaded[exportName];
29542
30504
  if (!isRecord9(value) || typeof value.handle !== "function") {
29543
30505
  throw new TypeError(`Compatibility producer export ${exportName} must expose handle(request).`);
@@ -29556,7 +30518,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29556
30518
  };
29557
30519
  }, loadAbsoluteMobileMaterializedBundle = async (root) => {
29558
30520
  const resolvedRoot = resolvePath2(root);
29559
- const serialized = await readFile10(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
30521
+ const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
29560
30522
  const parsed = JSON.parse(serialized);
29561
30523
  const index = parseBundleIndex(parsed);
29562
30524
  const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -29591,7 +30553,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29591
30553
  });
29592
30554
  const root = resolvePath2(input.root);
29593
30555
  const bundlesRoot = join56(root, BUNDLES_DIRECTORY);
29594
- await mkdir14(bundlesRoot, { recursive: true });
30556
+ await mkdir15(bundlesRoot, { recursive: true });
29595
30557
  const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
29596
30558
  await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
29597
30559
  const index = {
@@ -29609,7 +30571,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29609
30571
  }, readAbsoluteMobileMaterializedReleases = async (root) => {
29610
30572
  const resolvedRoot = resolvePath2(root);
29611
30573
  try {
29612
- const serialized = await readFile10(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
30574
+ const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
29613
30575
  const parsed = JSON.parse(serialized);
29614
30576
  const index = parseBundleIndex(parsed);
29615
30577
  const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -30022,7 +30984,7 @@ var exports_compatibilityDispatcher = {};
30022
30984
  __export(exports_compatibilityDispatcher, {
30023
30985
  createAbsoluteMobileCompatibilityDispatcher: () => createAbsoluteMobileCompatibilityDispatcher
30024
30986
  });
30025
- import { Elysia as Elysia9 } from "elysia";
30987
+ import { Elysia as Elysia10 } from "elysia";
30026
30988
  var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADERS, MOBILE_CORS_METHODS, mobileWebViewOrigin = (request) => {
30027
30989
  const origin = request.headers.get("origin");
30028
30990
  return origin && MOBILE_WEBVIEW_ORIGINS.has(origin) ? origin : undefined;
@@ -30077,7 +31039,7 @@ var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADE
30077
31039
  throw new TypeError("currentReleaseId must identify a retained compatibility artifact.");
30078
31040
  }
30079
31041
  const resolveProducer = createProducerResolver(options.loadProducer);
30080
- return new Elysia9({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
31042
+ return new Elysia10({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
30081
31043
  if (getCurrentAbsoluteMobileProducerContext())
30082
31044
  return;
30083
31045
  const preflight = mobilePreflightResponse(request);
@@ -30237,8 +31199,8 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30237
31199
  links.push(href);
30238
31200
  }
30239
31201
  return links;
30240
- }, fetchRoute = async (baseUrl, path) => {
30241
- const res = await fetchWithTimeout(`${baseUrl}${path}`, {
31202
+ }, fetchRoute = async (baseUrl, path2) => {
31203
+ const res = await fetchWithTimeout(`${baseUrl}${path2}`, {
30242
31204
  redirect: "manual"
30243
31205
  });
30244
31206
  if (!res.ok)
@@ -30252,21 +31214,21 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30252
31214
  const queue = ["/"];
30253
31215
  const routes = [];
30254
31216
  const crawlNextRoute = async () => {
30255
- const path = queue.shift();
30256
- if (!path) {
31217
+ const path2 = queue.shift();
31218
+ if (!path2) {
30257
31219
  return;
30258
31220
  }
30259
- if (visited.has(path)) {
31221
+ if (visited.has(path2)) {
30260
31222
  await crawlNextRoute();
30261
31223
  return;
30262
31224
  }
30263
- visited.add(path);
30264
- const html = await fetchRoute(baseUrl, path).catch(() => null);
31225
+ visited.add(path2);
31226
+ const html = await fetchRoute(baseUrl, path2).catch(() => null);
30265
31227
  if (!html) {
30266
31228
  await crawlNextRoute();
30267
31229
  return;
30268
31230
  }
30269
- routes.push(path);
31231
+ routes.push(path2);
30270
31232
  queue.push(...extractLinks(html, visited));
30271
31233
  await crawlNextRoute();
30272
31234
  };
@@ -30387,10 +31349,10 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30387
31349
  };
30388
31350
  read();
30389
31351
  }, formatServerOutput = (output) => {
30390
- const text2 = output.join("").trim();
30391
- if (!text2)
31352
+ const text3 = output.join("").trim();
31353
+ if (!text3)
30392
31354
  return "";
30393
- return text2.length > SERVER_OUTPUT_LIMIT ? text2.slice(-SERVER_OUTPUT_LIMIT) : text2;
31355
+ return text3.length > SERVER_OUTPUT_LIMIT ? text3.slice(-SERVER_OUTPUT_LIMIT) : text3;
30394
31356
  }, createServerStartupError = (output) => {
30395
31357
  const serverOutput = formatServerOutput(output);
30396
31358
  const message = serverOutput ? `Server failed to start for pre-rendering.
@@ -30437,18 +31399,18 @@ __export(exports_prepare, {
30437
31399
  prepare: () => prepare,
30438
31400
  startDevPrebuild: () => startDevPrebuild
30439
31401
  });
30440
- import { createHash as createHash9 } from "crypto";
31402
+ import { createHash as createHash10 } from "crypto";
30441
31403
  import { existsSync as existsSync45, readdirSync as readdirSync12, readFileSync as readFileSync39 } from "fs";
30442
- import { basename as basename19, join as join58, relative as relative20, resolve as resolvePath3 } from "path";
30443
- import { Elysia as Elysia10, NotFound } from "elysia";
30444
- var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((resolve49) => {
30445
- setTimeout(resolve49, STATIC_PLUGIN_RETRY_DELAY_MS);
31404
+ import { basename as basename19, join as join58, relative as relative21, resolve as resolvePath3 } from "path";
31405
+ import { Elysia as Elysia11, NotFound } from "elysia";
31406
+ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((resolve50) => {
31407
+ setTimeout(resolve50, STATIC_PLUGIN_RETRY_DELAY_MS);
30446
31408
  }), retryStaticPlugin = async (createStaticPlugin, options) => {
30447
31409
  try {
30448
31410
  return await createStaticPlugin(options);
30449
31411
  } catch (error) {
30450
31412
  logWarn(`Static asset routes were skipped this cycle \u2014 a build file was unavailable mid-rebuild: ${error instanceof Error ? error.message : String(error)}`);
30451
- return new Elysia10({ name: "absolutejs-static-fallback" });
31413
+ return new Elysia11({ name: "absolutejs-static-fallback" });
30452
31414
  }
30453
31415
  }, mountStaticPlugin = async (createStaticPlugin, options) => {
30454
31416
  try {
@@ -30459,7 +31421,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30459
31421
  }
30460
31422
  }, MOBILE_DEV_MODULE_HEADERS, NATIVE_DEVICE_ADAPTER_PATH = "/__absolute/native-device-adapter.js", MOBILE_PREVIEW_CLIENT_PATH = "/__absolute/mobile-preview-client.js", loadMobileDevPlugin = async (mobile) => {
30461
31423
  if (!mobile)
30462
- return new Elysia10({ name: "absolutejs-mobile-disabled" });
31424
+ return new Elysia11({ name: "absolutejs-mobile-disabled" });
30463
31425
  const [
30464
31426
  { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 },
30465
31427
  { createAbsoluteMobilePreviewPlugin: createAbsoluteMobilePreviewPlugin2 }
@@ -30470,19 +31432,33 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30470
31432
  let nativeDevAdapterBundle;
30471
31433
  const getNativeDevAdapterBundle = () => nativeDevAdapterBundle ??= Promise.resolve().then(() => (init_devDeviceAdapter(), exports_devDeviceAdapter)).then(({ buildAbsoluteNativeDevAdapter: buildAbsoluteNativeDevAdapter2 }) => buildAbsoluteNativeDevAdapter2(process.cwd(), mobile));
30472
31434
  const getMobilePreviewClientBundle = () => Promise.resolve().then(() => (init_mobilePreviewClientBundle(), exports_mobilePreviewClientBundle)).then(({ getAbsoluteMobilePreviewClientBundle: getAbsoluteMobilePreviewClientBundle2 }) => getAbsoluteMobilePreviewClientBundle2());
30473
- return new Elysia10({ name: "absolutejs-mobile-dev" }).use(createAbsoluteMobileAssociationPlugin2(mobile, process.cwd())).use(createAbsoluteMobilePreviewPlugin2(mobile)).get(NATIVE_DEVICE_ADAPTER_PATH, async () => new Response(await getNativeDevAdapterBundle(), {
31435
+ return new Elysia11({ name: "absolutejs-mobile-dev" }).use(createAbsoluteMobileAssociationPlugin2(mobile, process.cwd())).use(createAbsoluteMobilePreviewPlugin2(mobile)).get(NATIVE_DEVICE_ADAPTER_PATH, async () => new Response(await getNativeDevAdapterBundle(), {
30474
31436
  headers: MOBILE_DEV_MODULE_HEADERS
30475
31437
  })).get(MOBILE_PREVIEW_CLIENT_PATH, async () => new Response(await getMobilePreviewClientBundle(), {
30476
31438
  headers: MOBILE_DEV_MODULE_HEADERS
30477
31439
  }));
30478
31440
  }, loadMobileAssociationPlugin = async (mobile) => {
30479
31441
  if (!mobile) {
30480
- return new Elysia10({ name: "absolutejs-mobile-associations-disabled" });
31442
+ return new Elysia11({ name: "absolutejs-mobile-associations-disabled" });
30481
31443
  }
30482
31444
  const { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 } = await Promise.resolve().then(() => (init_associationFiles(), exports_associationFiles));
30483
31445
  return createAbsoluteMobileAssociationPlugin2(mobile, process.cwd(), {
30484
31446
  requireAll: true
30485
31447
  });
31448
+ }, loadMobileUpdatePlugin = async (mobile, production) => {
31449
+ if (!mobile?.updates)
31450
+ return new Elysia11({ name: "absolutejs-mobile-updates-unconfigured" });
31451
+ const [
31452
+ { normalizeAbsoluteMobileConfig: normalizeAbsoluteMobileConfig2 },
31453
+ { createAbsoluteMobileUpdateServerPlugin: createAbsoluteMobileUpdateServerPlugin2 }
31454
+ ] = await Promise.all([
31455
+ Promise.resolve().then(() => (init_config(), exports_config)),
31456
+ Promise.resolve().then(() => (init_updateServer(), exports_updateServer))
31457
+ ]);
31458
+ const normalized = normalizeAbsoluteMobileConfig2(mobile, process.cwd());
31459
+ return createAbsoluteMobileUpdateServerPlugin2(normalized, process.cwd(), {
31460
+ production
31461
+ });
30486
31462
  }, buildPrewarmDirs = (config) => {
30487
31463
  const dirs = [];
30488
31464
  if (config.svelteDirectory) {
@@ -30514,7 +31490,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30514
31490
  return files;
30515
31491
  }, PREWARM_MAX_PAUSE_MS = 60000, toWarmTasks = function* (files, warmCache, srcUrlPrefix) {
30516
31492
  for (const file5 of files) {
30517
- const rel = relative20(process.cwd(), file5).replace(/\\/g, "/");
31493
+ const rel = relative21(process.cwd(), file5).replace(/\\/g, "/");
30518
31494
  yield () => warmCache(`${srcUrlPrefix}${rel}`);
30519
31495
  }
30520
31496
  }, builtPageSources = () => {
@@ -30555,7 +31531,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30555
31531
  const srcPath = resolvePath3(devIndexDir, fileName);
30556
31532
  if (!existsSync45(srcPath))
30557
31533
  continue;
30558
- const rel = relative20(process.cwd(), srcPath).replace(/\\/g, "/");
31534
+ const rel = relative21(process.cwd(), srcPath).replace(/\\/g, "/");
30559
31535
  manifest[key] = `${SRC_URL_PREFIX2}${rel}`;
30560
31536
  }
30561
31537
  }, ICON_HASH_LENGTH = 8, registerIconVersioning = (buildDir) => {
@@ -30566,11 +31542,11 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30566
31542
  const cached = cache2.get(href);
30567
31543
  if (cached !== undefined)
30568
31544
  return cached;
30569
- const path = href.split("?")[0] ?? href;
30570
- const filePath = join58(buildDir, path);
31545
+ const path2 = href.split("?")[0] ?? href;
31546
+ const filePath = join58(buildDir, path2);
30571
31547
  let versioned = href;
30572
31548
  if (existsSync45(filePath)) {
30573
- const hash = createHash9("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
31549
+ const hash = createHash10("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
30574
31550
  versioned = href.includes("?") ? `${href}&v=${hash}` : `${href}?v=${hash}`;
30575
31551
  }
30576
31552
  cache2.set(href, versioned);
@@ -30675,12 +31651,13 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30675
31651
  const { requestInspector: requestInspector2 } = await Promise.resolve().then(() => (init_requestInspector(), exports_requestInspector));
30676
31652
  const { serverTiming } = await import("@elysia/server-timing");
30677
31653
  const mobileDevPlugin = await loadMobileDevPlugin(config.mobile);
30678
- const absolutejs = new Elysia10({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
31654
+ const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, false);
31655
+ const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
30679
31656
  normalizeForWindowsContainer: config.dev?.devtools?.normalizeForWindowsContainer,
30680
31657
  projectRoot: config.dev?.devtools?.projectRoot,
30681
31658
  uuid: config.dev?.devtools?.uuid,
30682
31659
  uuidCachePath: config.dev?.devtools?.uuidCachePath
30683
- })).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(await mountStaticPlugin(staticPlugin, {
31660
+ })).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(mobileUpdatePlugin).use(await mountStaticPlugin(staticPlugin, {
30684
31661
  alwaysStatic: true,
30685
31662
  assets: buildDir,
30686
31663
  directive: "no-cache",
@@ -30719,7 +31696,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30719
31696
  }, loadMobileCompatibilityPlugin = async (buildDir) => {
30720
31697
  const root = join58(buildDir, ".absolutejs", "mobile-compatibility");
30721
31698
  if (!existsSync45(join58(root, "current.json"))) {
30722
- return new Elysia10({ name: "absolutejs-mobile-compatibility-empty" });
31699
+ return new Elysia11({ name: "absolutejs-mobile-compatibility-empty" });
30723
31700
  }
30724
31701
  const [
30725
31702
  { loadAbsoluteMobileMaterializedBundle: loadAbsoluteMobileMaterializedBundle2 },
@@ -30730,12 +31707,12 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30730
31707
  ]);
30731
31708
  const options = await loadAbsoluteMobileMaterializedBundle2(root);
30732
31709
  return createAbsoluteMobileCompatibilityDispatcher2(options);
30733
- }, createNotFoundPlugin = () => new Elysia10({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
31710
+ }, createNotFoundPlugin = () => new Elysia11({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
30734
31711
  const response = await renderFirstNotFound();
30735
31712
  if (response)
30736
31713
  return response;
30737
31714
  return;
30738
- }), createBuildErrorRecoveryPlugin = () => new Elysia10({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
31715
+ }), createBuildErrorRecoveryPlugin = () => new Elysia11({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
30739
31716
  const message = error instanceof Error ? error.message : String(error);
30740
31717
  const assetMatch = /^Asset "(.+)" not found in manifest\.$/.exec(message);
30741
31718
  if (!assetMatch)
@@ -30802,11 +31779,11 @@ This usually means a build-time error in a source file. Check the dev-server ter
30802
31779
  staticLimit: MAX_STATIC_ROUTE_COUNT
30803
31780
  });
30804
31781
  const generatedAssetsRoot = join58(buildDir, ".absolutejs");
30805
- const generatedAssetsPlugin = new Elysia10({
31782
+ const generatedAssetsPlugin = new Elysia11({
30806
31783
  name: "absolutejs-generated-assets"
30807
31784
  }).get("/.absolutejs/*", async ({ params, set }) => {
30808
31785
  const requestedPath = resolvePath3(generatedAssetsRoot, params["*"]);
30809
- if (relative20(generatedAssetsRoot, requestedPath).startsWith("..")) {
31786
+ if (relative21(generatedAssetsRoot, requestedPath).startsWith("..")) {
30810
31787
  set.status = 404;
30811
31788
  return "Not Found";
30812
31789
  }
@@ -30826,7 +31803,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30826
31803
  const hash = base.match(/[.-]([0-9a-z]{6,12})\.[0-9a-z]+$/i)?.[1];
30827
31804
  return hash ? /[0-9]/.test(hash) && /[a-z]/i.test(hash) : false;
30828
31805
  };
30829
- const assetCachePlugin = new Elysia10({
31806
+ const assetCachePlugin = new Elysia11({
30830
31807
  name: "absolutejs-asset-cache"
30831
31808
  }).afterHandle("global", ({ request, responseValue }) => {
30832
31809
  if (!(responseValue instanceof Response))
@@ -30843,13 +31820,14 @@ This usually means a build-time error in a source file. Check the dev-server ter
30843
31820
  const prerenderMap = loadPrerenderMap(prerenderDir);
30844
31821
  const mobileCompatibilityPlugin = await loadMobileCompatibilityPlugin(buildDir);
30845
31822
  const mobileAssociationPlugin = await loadMobileAssociationPlugin(config.mobile);
31823
+ const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, true);
30846
31824
  recordStep("load prerender map", stepStartedAt);
30847
31825
  if (prerenderMap.size > 0) {
30848
31826
  const { PRERENDER_BYPASS_HEADER: PRERENDER_BYPASS_HEADER2, readTimestamp: readTimestamp2, rerenderRoute: rerenderRoute2 } = await Promise.resolve().then(() => (init_prerender(), exports_prerender));
30849
31827
  const revalidateMs = config.static?.revalidate ? config.static.revalidate * MS_PER_SECOND2 : 0;
30850
31828
  const port = Number(process.env.PORT) || DEFAULT_PORT2;
30851
31829
  const rerendering = new Set;
30852
- const prerenderPlugin = new Elysia10({
31830
+ const prerenderPlugin = new Elysia11({
30853
31831
  name: "prerendered-pages"
30854
31832
  }).request(({ request }) => {
30855
31833
  const url = new URL(request.url);
@@ -30872,7 +31850,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30872
31850
  });
30873
31851
  stepStartedAt = performance.now();
30874
31852
  const { imageOptimizer: imageOptimizer3 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
30875
- const absolutejs2 = new Elysia10({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(assetCachePlugin).use(imageOptimizer3(config.images, buildDir)).use(prerenderPlugin).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
31853
+ const absolutejs2 = new Elysia11({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(mobileUpdatePlugin).use(assetCachePlugin).use(imageOptimizer3(config.images, buildDir)).use(prerenderPlugin).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
30876
31854
  await withOpenApi(absolutejs2, config, process.cwd(), false);
30877
31855
  await withTelemetry(absolutejs2, config, process.cwd());
30878
31856
  recordStep("assemble production runtime", stepStartedAt);
@@ -30881,7 +31859,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30881
31859
  }
30882
31860
  stepStartedAt = performance.now();
30883
31861
  const { imageOptimizer: imageOptimizer2 } = await Promise.resolve().then(() => (init_imageOptimizer(), exports_imageOptimizer));
30884
- const absolutejs = new Elysia10({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(assetCachePlugin).use(imageOptimizer2(config.images, buildDir)).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
31862
+ const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(absoluteRequestContext).use(mobileAssociationPlugin).use(mobileCompatibilityPlugin).use(mobileUpdatePlugin).use(assetCachePlugin).use(imageOptimizer2(config.images, buildDir)).use(staticFiles).use(generatedAssetsPlugin).use(createNotFoundPlugin());
30885
31863
  await withOpenApi(absolutejs, config, process.cwd(), false);
30886
31864
  await withTelemetry(absolutejs, config, process.cwd());
30887
31865
  recordStep("assemble production runtime", stepStartedAt);
@@ -30961,7 +31939,7 @@ __export(exports_moduleServer, {
30961
31939
  warnIfReactFastRefreshUnsupported: () => warnIfReactFastRefreshUnsupported
30962
31940
  });
30963
31941
  import { existsSync as existsSync46, readFileSync as readFileSync40, realpathSync as realpathSync3, statSync as statSync7 } from "fs";
30964
- import { basename as basename20, dirname as dirname34, extname as extname15, join as join59, resolve as resolve49, relative as relative21 } from "path";
31942
+ import { basename as basename20, dirname as dirname35, extname as extname15, join as join59, resolve as resolve50, relative as relative22 } from "path";
30965
31943
  var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfig, tsTranspiler2, tsxTranspiler, TRANSPILABLE, ALL_EXPORTS_RE, STRING_CONTENTS_RE, preserveTypeExports = (originalSource, transpiled, valueExports) => {
30966
31944
  const codeOnly = originalSource.replace(STRING_CONTENTS_RE, '""');
30967
31945
  const allExports = [];
@@ -30981,10 +31959,10 @@ var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfi
30981
31959
  ${stubs}
30982
31960
  `;
30983
31961
  }, resolveRelativeExtension = (srcPath, projectRoot, extensions) => {
30984
- const directHit = extensions.find((ext) => existsSync46(resolve49(projectRoot, srcPath + ext)));
31962
+ const directHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath + ext)));
30985
31963
  if (directHit)
30986
31964
  return srcPath + directHit;
30987
- const indexHit = extensions.find((ext) => existsSync46(resolve49(projectRoot, srcPath, `index${ext}`)));
31965
+ const indexHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath, `index${ext}`)));
30988
31966
  if (indexHit)
30989
31967
  return `${srcPath}/index${indexHit}`;
30990
31968
  return srcPath;
@@ -31013,7 +31991,7 @@ ${stubs}
31013
31991
  return invalidationVersion > 0 ? `${mtime}.${invalidationVersion}` : `${mtime}`;
31014
31992
  }, srcUrl = (relPath, projectRoot) => {
31015
31993
  const base = `${SRC_PREFIX}${relPath.replace(/\\/g, "/")}`;
31016
- const absPath = resolve49(projectRoot, relPath);
31994
+ const absPath = resolve50(projectRoot, relPath);
31017
31995
  const cached = mtimeCache.get(absPath);
31018
31996
  if (cached !== undefined)
31019
31997
  return `${base}?v=${buildVersion(cached, absPath)}`;
@@ -31025,12 +32003,12 @@ ${stubs}
31025
32003
  return base;
31026
32004
  }
31027
32005
  }, resolveRelativeImport = (relPath, fileDir, projectRoot, extensions) => {
31028
- const absPath = resolve49(fileDir, relPath);
31029
- const rel = relative21(projectRoot, absPath);
32006
+ const absPath = resolve50(fileDir, relPath);
32007
+ const rel = relative22(projectRoot, absPath);
31030
32008
  const extension = extname15(rel);
31031
32009
  let srcPath = RESOLVED_MODULE_EXTENSIONS.has(extension) ? rel : resolveRelativeExtension(rel, projectRoot, extensions);
31032
32010
  if (extname15(srcPath) === ".svelte") {
31033
- srcPath = relative21(projectRoot, resolveSvelteModulePath(resolve49(projectRoot, srcPath)));
32011
+ srcPath = relative22(projectRoot, resolveSvelteModulePath(resolve50(projectRoot, srcPath)));
31034
32012
  }
31035
32013
  return srcUrl(srcPath, projectRoot);
31036
32014
  }, NODE_BUILTIN_RE, resolveAbsoluteSpecifier = (specifier, projectRoot) => {
@@ -31042,27 +32020,27 @@ ${stubs}
31042
32020
  "import"
31043
32021
  ]);
31044
32022
  if (fromExports)
31045
- return relative21(projectRoot, fromExports);
32023
+ return relative22(projectRoot, fromExports);
31046
32024
  try {
31047
32025
  const isScoped = specifier.startsWith("@");
31048
32026
  const parts = specifier.split("/");
31049
32027
  const packageName = isScoped ? `${parts[0]}/${parts[1]}` : parts[0];
31050
32028
  const subpath = isScoped ? parts.slice(2).join("/") : parts.slice(1).join("/");
31051
32029
  if (!subpath) {
31052
- const pkgDir = resolve49(projectRoot, "node_modules", packageName ?? "");
32030
+ const pkgDir = resolve50(projectRoot, "node_modules", packageName ?? "");
31053
32031
  const pkgJsonPath = join59(pkgDir, "package.json");
31054
32032
  if (existsSync46(pkgJsonPath)) {
31055
32033
  const pkg = JSON.parse(readFileSync40(pkgJsonPath, "utf-8"));
31056
32034
  const esmEntry = typeof pkg.module === "string" && pkg.module || typeof pkg.browser === "string" && pkg.browser;
31057
32035
  if (esmEntry) {
31058
- const resolved = resolve49(pkgDir, esmEntry);
32036
+ const resolved = resolve50(pkgDir, esmEntry);
31059
32037
  if (existsSync46(resolved))
31060
- return relative21(projectRoot, resolved);
32038
+ return relative22(projectRoot, resolved);
31061
32039
  }
31062
32040
  }
31063
32041
  }
31064
32042
  } catch {}
31065
- return relative21(projectRoot, Bun.resolveSync(specifier, projectRoot));
32043
+ return relative22(projectRoot, Bun.resolveSync(specifier, projectRoot));
31066
32044
  } catch {
31067
32045
  return;
31068
32046
  }
@@ -31095,28 +32073,28 @@ ${stubs}
31095
32073
  };
31096
32074
  result = result.replace(/^((?:import\s+[^"'`;]+?\s+from|export\s+[^"'`;]+?\s+from|import)\s*["'])([^"'./][^"']*)(["'])/gm, stubReplace);
31097
32075
  result = result.replace(/(import\s*\(\s*["'])([^"'./][^"']*)(["']\s*\))/g, stubReplace);
31098
- const fileDir = dirname34(filePath);
32076
+ const fileDir = dirname35(filePath);
31099
32077
  result = result.replace(/(from\s*["'])(\.\.?\/[^"']+)(["'])/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
31100
32078
  result = result.replace(/(import\s*\(\s*["'])(\.\.?\/[^"']+)(["']\s*\))/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
31101
32079
  result = result.replace(/(import\s*["'])(\.\.?\/[^"']+)(["']\s*;?)/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, SIDE_EFFECT_EXTENSIONS)}${suffix}` : _match);
31102
32080
  const rewriteAbsoluteToSrc = (_match, prefix, absPath, _ext, suffix) => {
31103
32081
  if (absPath.startsWith(projectRoot)) {
31104
- const rel2 = relative21(projectRoot, absPath).replace(/\\/g, "/");
32082
+ const rel2 = relative22(projectRoot, absPath).replace(/\\/g, "/");
31105
32083
  return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
31106
32084
  }
31107
- const rel = relative21(projectRoot, absPath).replace(/\\/g, "/");
32085
+ const rel = relative22(projectRoot, absPath).replace(/\\/g, "/");
31108
32086
  return `${prefix}${srcUrl(rel, projectRoot)}${suffix}`;
31109
32087
  };
31110
32088
  result = result.replace(/((?:from|import)\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["'])/g, rewriteAbsoluteToSrc);
31111
32089
  result = result.replace(/(import\s*\(\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["']\s*\))/g, rewriteAbsoluteToSrc);
31112
32090
  result = result.replace(/new\s+URL\(\s*["'](\.\.?\/[^"']+)["']\s*,\s*import\.meta\.url\s*\)/g, (_match, relPath) => {
31113
- const absPath = resolve49(fileDir, relPath);
31114
- const rel = relative21(projectRoot, absPath);
32091
+ const absPath = resolve50(fileDir, relPath);
32092
+ const rel = relative22(projectRoot, absPath);
31115
32093
  return `new URL('${srcUrl(rel, projectRoot)}', import.meta.url)`;
31116
32094
  });
31117
32095
  result = result.replace(/import\.meta\.resolve\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g, (_match, relPath) => {
31118
- const absPath = resolve49(fileDir, relPath);
31119
- const rel = relative21(projectRoot, absPath);
32096
+ const absPath = resolve50(fileDir, relPath);
32097
+ const rel = relative22(projectRoot, absPath);
31120
32098
  return `'${srcUrl(rel, projectRoot)}'`;
31121
32099
  });
31122
32100
  return result;
@@ -31172,7 +32150,7 @@ ${code2}`;
31172
32150
  transpiled = `var $RefreshReg$ = window.$RefreshReg$ || function(){};
31173
32151
  ` + `var $RefreshSig$ = window.$RefreshSig$ || function(){ return function(t){ return t; }; };
31174
32152
  ${transpiled}`;
31175
- const relPath = relative21(projectRoot, filePath).replace(/\\/g, "/");
32153
+ const relPath = relative22(projectRoot, filePath).replace(/\\/g, "/");
31176
32154
  transpiled = transpiled.replace(/\binput\.tsx:/g, `${relPath}:`);
31177
32155
  transpiled += buildIslandMetadataExports(raw);
31178
32156
  return rewriteImports(transpiled, filePath, projectRoot, rewriter);
@@ -31333,11 +32311,11 @@ ${code2}`;
31333
32311
  if (compiled.css?.code) {
31334
32312
  const cssPath = `${filePath}.css`;
31335
32313
  svelteExternalCss.set(cssPath, compiled.css.code);
31336
- const cssUrl = srcUrl(relative21(projectRoot, cssPath), projectRoot);
32314
+ const cssUrl = srcUrl(relative22(projectRoot, cssPath), projectRoot);
31337
32315
  code2 = `import "${cssUrl}";
31338
32316
  ${code2}`;
31339
32317
  }
31340
- const moduleUrl = `${SRC_PREFIX}${relative21(projectRoot, filePath).replace(/\\/g, "/")}`;
32318
+ const moduleUrl = `${SRC_PREFIX}${relative22(projectRoot, filePath).replace(/\\/g, "/")}`;
31341
32319
  code2 = code2.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
31342
32320
  ` + ` if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
31343
32321
  ` + ` var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleUrl)}] = cb; };`);
@@ -31437,8 +32415,8 @@ ${code2}`;
31437
32415
  code2 = injectVueHmr(code2, filePath, projectRoot, vueDir);
31438
32416
  return rewriteImports(code2, filePath, projectRoot, rewriter);
31439
32417
  }, injectVueHmr = (code2, filePath, projectRoot, vueDir) => {
31440
- const hmrBase = vueDir ? resolve49(vueDir) : projectRoot;
31441
- const hmrId = relative21(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
32418
+ const hmrBase = vueDir ? resolve50(vueDir) : projectRoot;
32419
+ const hmrId = relative22(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
31442
32420
  let result = code2.replace(/export\s+default\s+/, "var __hmr_comp__ = ");
31443
32421
  result += [
31444
32422
  "",
@@ -31451,14 +32429,14 @@ ${code2}`;
31451
32429
  ].join(`
31452
32430
  `);
31453
32431
  return result;
31454
- }, resolveSvelteModulePath = (path) => {
31455
- if (existsSync46(path))
31456
- return path;
31457
- if (existsSync46(`${path}.ts`))
31458
- return `${path}.ts`;
31459
- if (existsSync46(`${path}.js`))
31460
- return `${path}.js`;
31461
- return path;
32432
+ }, resolveSvelteModulePath = (path2) => {
32433
+ if (existsSync46(path2))
32434
+ return path2;
32435
+ if (existsSync46(`${path2}.ts`))
32436
+ return `${path2}.ts`;
32437
+ if (existsSync46(`${path2}.js`))
32438
+ return `${path2}.js`;
32439
+ return path2;
31462
32440
  }, jsResponse = (body) => {
31463
32441
  const etag = `"${Bun.hash(body).toString(BASE_36_RADIX)}"`;
31464
32442
  return new Response(body, {
@@ -31598,7 +32576,7 @@ export default {};
31598
32576
  const escaped = virtualCss.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
31599
32577
  return jsResponse(`var s=document.createElement('style');s.textContent=\`${escaped}\`;s.dataset.svelteHmr=${JSON.stringify(cssCheckPath)};var p=document.querySelector('style[data-svelte-hmr="${cssCheckPath}"]');if(p)p.remove();document.head.appendChild(s);`);
31600
32578
  }, resolveSourcePath2 = (relPath, projectRoot) => {
31601
- const filePath = resolve49(projectRoot, relPath);
32579
+ const filePath = resolve50(projectRoot, relPath);
31602
32580
  const ext = extname15(filePath);
31603
32581
  if (ext === ".svelte")
31604
32582
  return { ext, filePath: resolveSvelteModulePath(filePath) };
@@ -31616,10 +32594,10 @@ export default {};
31616
32594
  return jsResponse(handleCssRequest(filePath));
31617
32595
  if (ext === ".json") {
31618
32596
  try {
31619
- const { readFile: readFile11, stat: stat4 } = await import("fs/promises");
32597
+ const { readFile: readFile12, stat: stat5 } = await import("fs/promises");
31620
32598
  const fileExists2 = async (p2) => {
31621
32599
  try {
31622
- await stat4(p2);
32600
+ await stat5(p2);
31623
32601
  return true;
31624
32602
  } catch {
31625
32603
  return false;
@@ -31635,14 +32613,14 @@ export default {};
31635
32613
  const absoluteCandidate = `/${tail.replace(/^\/+/, "")}`;
31636
32614
  const candidates = [
31637
32615
  absoluteCandidate,
31638
- resolve49(projectRoot, tail)
32616
+ resolve50(projectRoot, tail)
31639
32617
  ];
31640
32618
  try {
31641
32619
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_loadConfig(), exports_loadConfig));
31642
32620
  const cfg = await loadConfig2();
31643
- const angularDir = cfg.angularDirectory && resolve49(projectRoot, cfg.angularDirectory);
32621
+ const angularDir = cfg.angularDirectory && resolve50(projectRoot, cfg.angularDirectory);
31644
32622
  if (angularDir)
31645
- candidates.push(resolve49(angularDir, tail));
32623
+ candidates.push(resolve50(angularDir, tail));
31646
32624
  } catch {}
31647
32625
  for (const candidate of candidates) {
31648
32626
  if (await fileExists2(candidate)) {
@@ -31652,9 +32630,9 @@ export default {};
31652
32630
  }
31653
32631
  }
31654
32632
  }
31655
- const text2 = await readFile11(sourcePath, "utf-8");
31656
- JSON.parse(text2);
31657
- return jsResponse(`export default ${text2};`);
32633
+ const text3 = await readFile12(sourcePath, "utf-8");
32634
+ JSON.parse(text3);
32635
+ return jsResponse(`export default ${text3};`);
31658
32636
  } catch (err) {
31659
32637
  return new Response(`console.error('[ModuleServer] JSON load error in ${filePath}:', ${JSON.stringify(String(err))});`, {
31660
32638
  headers: { "Content-Type": "application/javascript" },
@@ -31672,8 +32650,8 @@ export default {};
31672
32650
  return transformAndCacheVue(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
31673
32651
  if (!TRANSPILABLE.has(ext))
31674
32652
  return;
31675
- const stat3 = statSync7(filePath);
31676
- const resolvedVueDir = vueDir ? resolve49(vueDir) : undefined;
32653
+ const stat4 = statSync7(filePath);
32654
+ const resolvedVueDir = vueDir ? resolve50(vueDir) : undefined;
31677
32655
  let content = REACT_EXTENSIONS.has(ext) ? transformReactFile(filePath, projectRoot, rewriter) : transformPlainFile(filePath, projectRoot, rewriter, resolvedVueDir);
31678
32656
  const isAngularGeneratedJs = ext === ".js" && filePath.replace(/\\/g, "/").includes("/.absolutejs/generated/angular/");
31679
32657
  if (isAngularGeneratedJs) {
@@ -31692,7 +32670,7 @@ export default {};
31692
32670
  }
31693
32671
  }
31694
32672
  }
31695
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32673
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31696
32674
  return jsResponse(content);
31697
32675
  }, cachedAngularUserRoot, getAngularUserRoot = async (_projectRoot) => {
31698
32676
  if (cachedAngularUserRoot !== undefined)
@@ -31700,14 +32678,14 @@ export default {};
31700
32678
  cachedAngularUserRoot = configuredAngularUserRoot ?? null;
31701
32679
  return cachedAngularUserRoot;
31702
32680
  }, configuredAngularUserRoot, transformAndCacheSvelte = async (filePath, projectRoot, rewriter, stylePreprocessors) => {
31703
- const stat3 = statSync7(filePath);
32681
+ const stat4 = statSync7(filePath);
31704
32682
  const content = await transformSvelteFile(filePath, projectRoot, rewriter, stylePreprocessors);
31705
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32683
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31706
32684
  return jsResponse(content);
31707
32685
  }, transformAndCacheVue = async (filePath, projectRoot, rewriter, vueDir, stylePreprocessors) => {
31708
- const stat3 = statSync7(filePath);
32686
+ const stat4 = statSync7(filePath);
31709
32687
  const content = await transformVueFile(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
31710
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32688
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31711
32689
  return jsResponse(content);
31712
32690
  }, transformErrorResponse = (err) => {
31713
32691
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -31732,7 +32710,7 @@ export default {};
31732
32710
  const relPath = pathname.slice(SRC_PREFIX.length);
31733
32711
  if (relPath === "bun:wrap" || relPath.startsWith("bun:wrap?"))
31734
32712
  return handleBunWrapRequest();
31735
- const virtualCssResponse = handleVirtualSvelteCss(resolve49(projectRoot, relPath));
32713
+ const virtualCssResponse = handleVirtualSvelteCss(resolve50(projectRoot, relPath));
31736
32714
  if (virtualCssResponse)
31737
32715
  return virtualCssResponse;
31738
32716
  const { filePath, ext } = resolveSourcePath2(relPath, projectRoot);
@@ -31748,11 +32726,11 @@ export default {};
31748
32726
  SRC_IMPORT_RE.lastIndex = 0;
31749
32727
  while ((match = SRC_IMPORT_RE.exec(content)) !== null) {
31750
32728
  if (match[1])
31751
- files.push(resolve49(projectRoot, match[1]));
32729
+ files.push(resolve50(projectRoot, match[1]));
31752
32730
  }
31753
32731
  return files;
31754
32732
  }, invalidateModule = (filePath) => {
31755
- const resolved = resolve49(filePath);
32733
+ const resolved = resolve50(filePath);
31756
32734
  invalidate(filePath);
31757
32735
  if (resolved !== filePath)
31758
32736
  invalidate(resolved);
@@ -31815,7 +32793,7 @@ export default {};
31815
32793
  return false;
31816
32794
  }
31817
32795
  const { patchManifestIndexes: patchManifestIndexes2 } = await Promise.resolve().then(() => (init_prepare(), exports_prepare));
31818
- patchManifestIndexes2(cached.manifest, resolve49(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
32796
+ patchManifestIndexes2(cached.manifest, resolve50(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
31819
32797
  logPageBuild(entry.source, entry.framework, Math.round(durationMs));
31820
32798
  logStartupTimingBlock("AbsoluteJS on-demand page build", [
31821
32799
  { durationMs, label: entry.name }
@@ -31947,7 +32925,7 @@ __export(exports_rewriteImports, {
31947
32925
  rewriteVendorDirectories: () => rewriteVendorDirectories2
31948
32926
  });
31949
32927
  var rewriteImports2 = async (outputPaths, vendorPaths) => {
31950
- const jsFiles = outputPaths.filter((path) => path.endsWith(".js"));
32928
+ const jsFiles = outputPaths.filter((path2) => path2.endsWith(".js"));
31951
32929
  if (jsFiles.length === 0)
31952
32930
  return;
31953
32931
  if (Object.keys(vendorPaths).length === 0)
@@ -31981,13 +32959,13 @@ var init_rewriteImports = __esm(() => {
31981
32959
  });
31982
32960
 
31983
32961
  // src/core/pageResponseCache.ts
31984
- import { createHash as createHash10 } from "crypto";
32962
+ import { createHash as createHash11 } from "crypto";
31985
32963
  var STREAMING_PAGE_HEADER = "x-absolute-stream", HTML_CONTENT_TYPE = "text/html", streamingPageHeaders = (extra) => {
31986
32964
  const headers = new Headers(extra);
31987
32965
  headers.set("content-type", HTML_CONTENT_TYPE);
31988
32966
  headers.set(STREAMING_PAGE_HEADER, "1");
31989
32967
  return headers;
31990
- }, computeEtag = (html) => `W/"${createHash10("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
32968
+ }, computeEtag = (html) => `W/"${createHash11("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
31991
32969
  const contentType = response.headers.get("content-type") ?? "";
31992
32970
  if (!contentType.includes(HTML_CONTENT_TYPE))
31993
32971
  return response;
@@ -32055,7 +33033,7 @@ var init_routeAssets = __esm(() => {
32055
33033
  });
32056
33034
 
32057
33035
  // src/ember/pageHandler.ts
32058
- import { pathToFileURL as pathToFileURL4 } from "url";
33036
+ import { pathToFileURL as pathToFileURL5 } from "url";
32059
33037
  var resolveRequestPathname2 = (request) => {
32060
33038
  if (!request)
32061
33039
  return;
@@ -32077,7 +33055,7 @@ var resolveRequestPathname2 = (request) => {
32077
33055
  }, emberCacheBuster = 0, buildRuntimeModuleSpecifier = (modulePath) => {
32078
33056
  if (emberCacheBuster === 0)
32079
33057
  return modulePath;
32080
- const moduleUrl = new URL(pathToFileURL4(modulePath).href);
33058
+ const moduleUrl = new URL(pathToFileURL5(modulePath).href);
32081
33059
  moduleUrl.searchParams.set("t", String(emberCacheBuster));
32082
33060
  return moduleUrl.href;
32083
33061
  }, invalidateEmberSsrCache = () => {
@@ -32178,11 +33156,11 @@ var exports_simpleHTMLHMR = {};
32178
33156
  __export(exports_simpleHTMLHMR, {
32179
33157
  handleHTMLUpdate: () => handleHTMLUpdate
32180
33158
  });
32181
- import { resolve as resolve50 } from "path";
33159
+ import { resolve as resolve51 } from "path";
32182
33160
  var handleHTMLUpdate = async (htmlFilePath) => {
32183
33161
  let htmlContent;
32184
33162
  try {
32185
- const resolvedPath = resolve50(htmlFilePath);
33163
+ const resolvedPath = resolve51(htmlFilePath);
32186
33164
  const file5 = Bun.file(resolvedPath);
32187
33165
  if (!await file5.exists()) {
32188
33166
  return null;
@@ -32208,11 +33186,11 @@ var exports_simpleHTMXHMR = {};
32208
33186
  __export(exports_simpleHTMXHMR, {
32209
33187
  handleHTMXUpdate: () => handleHTMXUpdate
32210
33188
  });
32211
- import { resolve as resolve51 } from "path";
33189
+ import { resolve as resolve52 } from "path";
32212
33190
  var handleHTMXUpdate = async (htmxFilePath) => {
32213
33191
  let htmlContent;
32214
33192
  try {
32215
- const resolvedPath = resolve51(htmxFilePath);
33193
+ const resolvedPath = resolve52(htmxFilePath);
32216
33194
  const file5 = Bun.file(resolvedPath);
32217
33195
  if (!await file5.exists()) {
32218
33196
  return null;
@@ -32243,12 +33221,12 @@ __export(exports_rebuildTrigger, {
32243
33221
  import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4 } from "fs";
32244
33222
  import {
32245
33223
  basename as basename21,
32246
- dirname as dirname35,
32247
- isAbsolute as isAbsolute8,
33224
+ dirname as dirname36,
33225
+ isAbsolute as isAbsolute9,
32248
33226
  join as join60,
32249
- relative as relative22,
33227
+ relative as relative23,
32250
33228
  resolve as resolvePath4,
32251
- sep as sep4
33229
+ sep as sep5
32252
33230
  } from "path";
32253
33231
  var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSsrCssCaches = () => {
32254
33232
  clearSpaRouteCssCaches();
@@ -32607,14 +33585,14 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32607
33585
  const relFromDir = normalizedSource.slice(normalizedDir.length + 1);
32608
33586
  const { buildDir } = state.resolvedPaths;
32609
33587
  const destPath = resolvePath4(buildDir, urlPrefix ? `${urlPrefix}/${relFromDir}` : relFromDir);
32610
- const { mkdir: mkdir15, copyFile, readFile: readFile11 } = await import("fs/promises");
32611
- await mkdir15(dirname35(destPath), { recursive: true });
33588
+ const { mkdir: mkdir16, copyFile, readFile: readFile12 } = await import("fs/promises");
33589
+ await mkdir16(dirname36(destPath), { recursive: true });
32612
33590
  await copyFile(absSource, destPath);
32613
- const bytes = await readFile11(destPath);
33591
+ const bytes = await readFile12(destPath);
32614
33592
  const webPath = urlPrefix ? `/${urlPrefix}/${relFromDir}` : `/${relFromDir}`;
32615
33593
  state.assetStore.set(webPath, new Uint8Array(bytes));
32616
33594
  state.fileHashes.set(absSource, currentHash);
32617
- logHmrUpdate(relative22(process.cwd(), filePath));
33595
+ logHmrUpdate(relative23(process.cwd(), filePath));
32618
33596
  broadcastToClients(state, {
32619
33597
  data: {
32620
33598
  framework: urlPrefix || "public",
@@ -32634,7 +33612,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32634
33612
  return;
32635
33613
  if (framework === "unknown") {
32636
33614
  invalidate(resolvePath4(filePath));
32637
- const relPath = relative22(process.cwd(), filePath);
33615
+ const relPath = relative23(process.cwd(), filePath);
32638
33616
  logHmrUpdate(relPath);
32639
33617
  const { angularDir } = state.resolvedPaths;
32640
33618
  let hasAngularDependent = false;
@@ -32790,7 +33768,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32790
33768
  const keepStemsByDir = new Map;
32791
33769
  const prefixByDir = new Map;
32792
33770
  for (const artifact of freshOutputs) {
32793
- const dir = dirname35(artifact.path);
33771
+ const dir = dirname36(artifact.path);
32794
33772
  const name = basename21(artifact.path);
32795
33773
  const [prefix] = name.split(".");
32796
33774
  if (!prefix)
@@ -33156,8 +34134,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33156
34134
  };
33157
34135
  return ({ immediate = false } = {}) => {
33158
34136
  if (!ctx.debouncedPromise) {
33159
- ctx.debouncedPromise = new Promise((resolve52) => {
33160
- ctx.debouncedResolve = resolve52;
34137
+ ctx.debouncedPromise = new Promise((resolve53) => {
34138
+ ctx.debouncedResolve = resolve53;
33161
34139
  });
33162
34140
  }
33163
34141
  const scheduled = ctx.debouncedPromise;
@@ -33183,7 +34161,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33183
34161
  const angularDirAbs = resolvePath4(angularDir);
33184
34162
  const filesUnderAngular = Array.from(editedFiles).filter((file5) => {
33185
34163
  const abs = resolvePath4(file5);
33186
- return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep4);
34164
+ return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep5);
33187
34165
  });
33188
34166
  if (filesUnderAngular.length === 0)
33189
34167
  return;
@@ -33226,7 +34204,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33226
34204
  try {
33227
34205
  const { invalidateModule: invalidateModule2 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
33228
34206
  for (const tsFile of tsFilesToRefresh) {
33229
- const rel = relative22(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
34207
+ const rel = relative23(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
33230
34208
  const compiledFile = resolvePath4(compiledRoot, rel);
33231
34209
  invalidateModule2(compiledFile);
33232
34210
  }
@@ -33381,7 +34359,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33381
34359
  }, getModuleUrl = async (pageFile) => {
33382
34360
  const { invalidateModule: invalidateModule2, warmCache: warmCache2, SRC_URL_PREFIX: SRC_URL_PREFIX3 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
33383
34361
  invalidateModule2(pageFile);
33384
- const rel = relative22(process.cwd(), pageFile).replace(/\\/g, "/");
34362
+ const rel = relative23(process.cwd(), pageFile).replace(/\\/g, "/");
33385
34363
  const url = `${SRC_URL_PREFIX3}${rel}`;
33386
34364
  await warmCache2(url);
33387
34365
  return url;
@@ -33409,7 +34387,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33409
34387
  const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
33410
34388
  if (pageModuleUrl) {
33411
34389
  const serverDuration = Date.now() - startTime;
33412
- state.lastHmrPath = relative22(process.cwd(), primaryFile).replace(/\\/g, "/");
34390
+ state.lastHmrPath = relative23(process.cwd(), primaryFile).replace(/\\/g, "/");
33413
34391
  state.lastHmrFramework = "react";
33414
34392
  broadcastToClients(state, {
33415
34393
  data: {
@@ -33702,8 +34680,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33702
34680
  };
33703
34681
  return () => {
33704
34682
  if (!ctx.debouncedPromise) {
33705
- ctx.debouncedPromise = new Promise((resolve52) => {
33706
- ctx.debouncedResolve = resolve52;
34683
+ ctx.debouncedPromise = new Promise((resolve53) => {
34684
+ ctx.debouncedResolve = resolve53;
33707
34685
  });
33708
34686
  }
33709
34687
  if (ctx.debounceTimer)
@@ -33914,7 +34892,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33914
34892
  if (vueSpaRoutesBySource.size > 0) {
33915
34893
  const spaManifestEntries = await writeSpaSideManifests(vueSpaRoutesBySource, (pascalName) => {
33916
34894
  const fromManifest = state.manifest[pascalName];
33917
- return typeof fromManifest === "string" && isAbsolute8(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
34895
+ return typeof fromManifest === "string" && isAbsolute9(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
33918
34896
  });
33919
34897
  Object.assign(state.manifest, spaManifestEntries);
33920
34898
  }
@@ -33984,8 +34962,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33984
34962
  };
33985
34963
  return () => {
33986
34964
  if (!ctx.debouncedPromise) {
33987
- ctx.debouncedPromise = new Promise((resolve52) => {
33988
- ctx.debouncedResolve = resolve52;
34965
+ ctx.debouncedPromise = new Promise((resolve53) => {
34966
+ ctx.debouncedResolve = resolve53;
33989
34967
  });
33990
34968
  }
33991
34969
  if (ctx.debounceTimer)
@@ -34038,7 +35016,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34038
35016
  const duration = Date.now() - startTime;
34039
35017
  const [primary] = emberFiles;
34040
35018
  if (primary) {
34041
- state.lastHmrPath = relative22(process.cwd(), primary).replace(/\\/g, "/");
35019
+ state.lastHmrPath = relative23(process.cwd(), primary).replace(/\\/g, "/");
34042
35020
  state.lastHmrFramework = "ember";
34043
35021
  logHmrUpdate(primary, "ember", duration);
34044
35022
  }
@@ -34135,7 +35113,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34135
35113
  if (!buildReference?.source) {
34136
35114
  return;
34137
35115
  }
34138
- const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname35(buildInfo.resolvedRegistryPath), buildReference.source);
35116
+ const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname36(buildInfo.resolvedRegistryPath), buildReference.source);
34139
35117
  islandFiles.add(resolvePath4(sourcePath));
34140
35118
  }, resolveIslandSourceFiles = async (config) => {
34141
35119
  const registryPath = config.islands?.registry;
@@ -34307,7 +35285,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34307
35285
  const baseName = fileName.replace(/\.vue$/, "");
34308
35286
  const pascalName = toPascal(baseName);
34309
35287
  const vueRoot = config.vueDirectory;
34310
- const hmrId = vueRoot ? relative22(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
35288
+ const hmrId = vueRoot ? relative23(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
34311
35289
  const cssKey = `${pascalName}CSS`;
34312
35290
  const cssUrl = manifest[cssKey] || null;
34313
35291
  const { vueHmrMetadata: vueHmrMetadata2 } = await Promise.resolve().then(() => (init_compileVue(), exports_compileVue));
@@ -34521,10 +35499,10 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34521
35499
  if (sourceVersion !== undefined) {
34522
35500
  moduleVersions[update.sourceFile] = sourceVersion;
34523
35501
  }
34524
- Object.values(update.modulePaths).forEach((path) => {
34525
- const pathVersion = moduleVersionsStore.get(path);
35502
+ Object.values(update.modulePaths).forEach((path2) => {
35503
+ const pathVersion = moduleVersionsStore.get(path2);
34526
35504
  if (pathVersion !== undefined) {
34527
- moduleVersions[path] = pathVersion;
35505
+ moduleVersions[path2] = pathVersion;
34528
35506
  }
34529
35507
  });
34530
35508
  }, handleModuleUpdates = (state, allModuleUpdates, manifest) => {
@@ -34986,7 +35964,7 @@ var toSafeFileName6 = (specifier) => {
34986
35964
  } catch {
34987
35965
  return false;
34988
35966
  }
34989
- }, isBareSpecifier3 = (spec) => !spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("@src/"), isAbsolutePackageSpecifier = (spec) => spec === "@absolutejs/absolute" || spec.startsWith("@absolutejs/absolute/"), FRAMEWORK_SPECIFIERS, FRAMEWORK_NAMESPACE_PREFIXES, isFrameworkSpecifier = (spec) => FRAMEWORK_SPECIFIERS.has(spec) || FRAMEWORK_NAMESPACE_PREFIXES.some((prefix) => spec.startsWith(prefix)), FRAMEWORK_EXTERNALS, isSkippedFile = (file5) => file5.includes("node_modules") || file5.includes("/build/") || file5.includes("/dist/") || file5.includes("/indexes/") || isTestSourcePath(file5), isDepSpecifier = (path) => isBareSpecifier3(path) && !isBuiltin2(path) && !isFrameworkSpecifier(path) && !isAbsolutePackageSpecifier(path), isFrameworkRootCandidate = (path) => isBareSpecifier3(path) && isFrameworkSpecifier(path) && !isAbsolutePackageSpecifier(path), readFileSpecifiers = async (file5, transpiler7) => {
35967
+ }, isBareSpecifier3 = (spec) => !spec.startsWith(".") && !spec.startsWith("/") && !spec.startsWith("@src/"), isAbsolutePackageSpecifier = (spec) => spec === "@absolutejs/absolute" || spec.startsWith("@absolutejs/absolute/"), FRAMEWORK_SPECIFIERS, FRAMEWORK_NAMESPACE_PREFIXES, isFrameworkSpecifier = (spec) => FRAMEWORK_SPECIFIERS.has(spec) || FRAMEWORK_NAMESPACE_PREFIXES.some((prefix) => spec.startsWith(prefix)), FRAMEWORK_EXTERNALS, isSkippedFile = (file5) => file5.includes("node_modules") || file5.includes("/build/") || file5.includes("/dist/") || file5.includes("/indexes/") || isTestSourcePath(file5), isDepSpecifier = (path2) => isBareSpecifier3(path2) && !isBuiltin2(path2) && !isFrameworkSpecifier(path2) && !isAbsolutePackageSpecifier(path2), isFrameworkRootCandidate = (path2) => isBareSpecifier3(path2) && isFrameworkSpecifier(path2) && !isAbsolutePackageSpecifier(path2), readFileSpecifiers = async (file5, transpiler7) => {
34990
35968
  const dep = [];
34991
35969
  const framework = [];
34992
35970
  try {
@@ -35030,22 +36008,22 @@ var toSafeFileName6 = (specifier) => {
35030
36008
  };
35031
36009
  }, collectBareImportsFromFile = async (entryPath, transpiler7, maxDepth = 8) => {
35032
36010
  const { readFileSync: readFileSync41 } = await import("fs");
35033
- const { dirname: dirname36 } = await import("path");
36011
+ const { dirname: dirname37 } = await import("path");
35034
36012
  const seenFiles = new Set;
35035
36013
  const bareOut = new Set;
35036
36014
  const queue = [
35037
36015
  { depth: 0, path: entryPath }
35038
36016
  ];
35039
36017
  while (queue.length > 0) {
35040
- const { path, depth } = queue.shift();
35041
- if (seenFiles.has(path))
36018
+ const { path: path2, depth } = queue.shift();
36019
+ if (seenFiles.has(path2))
35042
36020
  continue;
35043
- seenFiles.add(path);
36021
+ seenFiles.add(path2);
35044
36022
  if (depth > maxDepth)
35045
36023
  continue;
35046
36024
  let content;
35047
36025
  try {
35048
- content = readFileSync41(path, "utf-8");
36026
+ content = readFileSync41(path2, "utf-8");
35049
36027
  } catch {
35050
36028
  continue;
35051
36029
  }
@@ -35055,7 +36033,7 @@ var toSafeFileName6 = (specifier) => {
35055
36033
  } catch {
35056
36034
  continue;
35057
36035
  }
35058
- const fromDir = dirname36(path);
36036
+ const fromDir = dirname37(path2);
35059
36037
  for (const imp of imports) {
35060
36038
  const child = imp.path;
35061
36039
  if (child.startsWith(".") || child.startsWith("/")) {
@@ -35075,7 +36053,7 @@ var toSafeFileName6 = (specifier) => {
35075
36053
  }
35076
36054
  return Array.from(bareOut);
35077
36055
  }, MAX_DISCOVERY_FILES = 2000, collectTransitiveImports = async (specs, alreadyVendored, alreadyScanned) => {
35078
- const { dirname: dirname36 } = await import("path");
36056
+ const { dirname: dirname37 } = await import("path");
35079
36057
  const transpiler7 = new Bun.Transpiler({ loader: "js" });
35080
36058
  const newSpecs = new Set;
35081
36059
  const queue = [...specs].map((spec) => ({ from: process.cwd(), spec }));
@@ -35096,7 +36074,7 @@ var toSafeFileName6 = (specifier) => {
35096
36074
  }
35097
36075
  visited += 1;
35098
36076
  const bareImports = await collectBareImportsFromFile(resolved, transpiler7);
35099
- const importerDirectory = dirname36(resolved);
36077
+ const importerDirectory = dirname37(resolved);
35100
36078
  for (const child of bareImports) {
35101
36079
  if (!isBareSpecifier3(child))
35102
36080
  continue;
@@ -35159,11 +36137,11 @@ var toSafeFileName6 = (specifier) => {
35159
36137
  const output = lastResult.outputs[0];
35160
36138
  if (!output)
35161
36139
  return lastResult;
35162
- const text2 = await output.text();
36140
+ const text3 = await output.text();
35163
36141
  REQUIRE_CALL_RE.lastIndex = 0;
35164
36142
  const requiredSpecs = new Set;
35165
36143
  let match;
35166
- while ((match = REQUIRE_CALL_RE.exec(text2)) !== null) {
36144
+ while ((match = REQUIRE_CALL_RE.exec(text3)) !== null) {
35167
36145
  const requiredSpec = match[1];
35168
36146
  if (requiredSpec && externalsSet.has(requiredSpec)) {
35169
36147
  requiredSpecs.add(requiredSpec);
@@ -35310,7 +36288,7 @@ __export(exports_vendorCache, {
35310
36288
  saveVendorCache: () => saveVendorCache,
35311
36289
  vendorCacheEnabled: () => vendorCacheEnabled
35312
36290
  });
35313
- import { createHash as createHash11 } from "crypto";
36291
+ import { createHash as createHash12 } from "crypto";
35314
36292
  import {
35315
36293
  copyFileSync as copyFileSync4,
35316
36294
  existsSync as existsSync48,
@@ -35318,10 +36296,10 @@ import {
35318
36296
  readdirSync as readdirSync14,
35319
36297
  readFileSync as readFileSync41
35320
36298
  } from "fs";
35321
- import { mkdir as mkdir15, readFile as readFile11, rename as rename7, rm as rm16, writeFile as writeFile13 } from "fs/promises";
35322
- import { basename as basename22, join as join62, resolve as resolve52 } from "path";
36299
+ import { mkdir as mkdir16, readFile as readFile12, rename as rename7, rm as rm16, writeFile as writeFile13 } from "fs/promises";
36300
+ import { basename as basename22, join as join62, resolve as resolve53 } from "path";
35323
36301
  var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeVendorCacheKey = (inputs) => {
35324
- const hash = createHash11("sha256");
36302
+ const hash = createHash12("sha256");
35325
36303
  hash.update(String(CACHE_FORMAT_VERSION3));
35326
36304
  hash.update("\x00");
35327
36305
  hash.update(inputs.lockfileHash);
@@ -35339,19 +36317,19 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35339
36317
  }
35340
36318
  for (const dir of inputs.vendorDirs) {
35341
36319
  hash.update("\x00v");
35342
- hash.update(basename22(resolve52(dir, "..")));
36320
+ hash.update(basename22(resolve53(dir, "..")));
35343
36321
  }
35344
36322
  return hash.digest("hex").slice(0, KEY_LENGTH);
35345
36323
  }, readLockfileHash = (projectRoot = process.cwd()) => {
35346
- const hash = createHash11("sha256");
36324
+ const hash = createHash12("sha256");
35347
36325
  let found = false;
35348
36326
  for (const name of LOCKFILES) {
35349
- const path = join62(projectRoot, name);
35350
- if (!existsSync48(path))
36327
+ const path2 = join62(projectRoot, name);
36328
+ if (!existsSync48(path2))
35351
36329
  continue;
35352
36330
  found = true;
35353
36331
  hash.update(name);
35354
- hash.update(readFileSync41(path));
36332
+ hash.update(readFileSync41(path2));
35355
36333
  }
35356
36334
  return found ? hash.digest("hex") : null;
35357
36335
  }, vendorCacheEnabled = () => process.env.ABSOLUTE_DEV_VENDOR_CACHE !== "0", copyTree = (fromDir, toDir) => {
@@ -35378,13 +36356,13 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35378
36356
  continue;
35379
36357
  copyTree(dir, join62(stagingDir, slotName(index, dir)));
35380
36358
  }
35381
- }, isVendorCachePayload = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "depPaths") === "object", cacheDirFor = (key, projectRoot) => resolve52(projectRoot, CACHE_ROOT2, key), slotName = (index, dir) => `${index}-${basename22(resolve52(dir, ".."))}`, restoreVendorCache = async (key, vendorDirs, projectRoot = process.cwd()) => {
36359
+ }, isVendorCachePayload = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "depPaths") === "object", cacheDirFor = (key, projectRoot) => resolve53(projectRoot, CACHE_ROOT2, key), slotName = (index, dir) => `${index}-${basename22(resolve53(dir, ".."))}`, restoreVendorCache = async (key, vendorDirs, projectRoot = process.cwd()) => {
35382
36360
  const cacheDir2 = cacheDirFor(key, projectRoot);
35383
36361
  const payloadPath = join62(cacheDir2, "payload.json");
35384
36362
  if (!existsSync48(payloadPath))
35385
36363
  return null;
35386
36364
  try {
35387
- const payload = JSON.parse(await readFile11(payloadPath, "utf8"));
36365
+ const payload = JSON.parse(await readFile12(payloadPath, "utf8"));
35388
36366
  if (!isVendorCachePayload(payload))
35389
36367
  return null;
35390
36368
  copySlotsInto(cacheDir2, vendorDirs);
@@ -35399,7 +36377,7 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35399
36377
  const stagingDir = `${cacheDir2}.${process.pid}.tmp`;
35400
36378
  try {
35401
36379
  await rm16(stagingDir, { force: true, recursive: true });
35402
- await mkdir15(stagingDir, { recursive: true });
36380
+ await mkdir16(stagingDir, { recursive: true });
35403
36381
  copySlotsFrom(stagingDir, vendorDirs);
35404
36382
  await writeFile13(join62(stagingDir, "payload.json"), JSON.stringify(payload));
35405
36383
  await rm16(cacheDir2, { force: true, recursive: true });
@@ -35430,8 +36408,8 @@ __export(exports_devBuild, {
35430
36408
  });
35431
36409
  import { readdir as readdir6 } from "fs/promises";
35432
36410
  import { existsSync as existsSync49, statSync as statSync8 } from "fs";
35433
- import { resolve as resolve53 } from "path";
35434
- var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
36411
+ import { resolve as resolve54 } from "path";
36412
+ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve54(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
35435
36413
  const configuredDirs = [
35436
36414
  ...collectConfigVendorSourceDirs(config),
35437
36415
  devClientVendorSourceDir()
@@ -35454,7 +36432,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35454
36432
  return Object.keys(config).length > 0 ? config : null;
35455
36433
  }, reloadConfig = async () => {
35456
36434
  try {
35457
- const configPath2 = resolve53(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
36435
+ const configPath2 = resolve54(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
35458
36436
  const source = await Bun.file(configPath2).text();
35459
36437
  return parseDirectoryConfig(source);
35460
36438
  } catch {
@@ -35506,7 +36484,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35506
36484
  setEmberVendorPaths(computeEmberVendorPaths());
35507
36485
  }
35508
36486
  const newWatchPaths = getWatchPaths(state.config, state.resolvedPaths);
35509
- const addedPaths = newWatchPaths.filter((path) => !oldWatchPaths.has(path));
36487
+ const addedPaths = newWatchPaths.filter((path2) => !oldWatchPaths.has(path2));
35510
36488
  if (addedPaths.length > 0) {
35511
36489
  buildInitialDependencyGraph(state.dependencyGraph, addedPaths);
35512
36490
  addFileWatchers(state, addedPaths, (filePath) => {
@@ -35569,7 +36547,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35569
36547
  });
35570
36548
  }
35571
36549
  }, handleCachedReload = async () => {
35572
- const serverMtime = statSync8(resolve53(Bun.main)).mtimeMs;
36550
+ const serverMtime = statSync8(resolve54(Bun.main)).mtimeMs;
35573
36551
  const lastMtime = globalThis.__hmrServerMtime;
35574
36552
  globalThis.__hmrServerMtime = serverMtime;
35575
36553
  const cached = globalThis.__hmrDevResult;
@@ -35601,8 +36579,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35601
36579
  return;
35602
36580
  await detectConfigChanges(cached);
35603
36581
  await rebuildManifest(cached);
35604
- }, tryReadPackageVersion = async (path) => {
35605
- const pkg = await Bun.file(path).json().catch(() => null);
36582
+ }, tryReadPackageVersion = async (path2) => {
36583
+ const pkg = await Bun.file(path2).json().catch(() => null);
35606
36584
  if (!pkg || pkg.name !== "@absolutejs/absolute") {
35607
36585
  return false;
35608
36586
  }
@@ -35610,8 +36588,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35610
36588
  return true;
35611
36589
  }, resolveAbsoluteVersion2 = async () => {
35612
36590
  const candidates = [
35613
- resolve53(import.meta.dir, "..", "..", "package.json"),
35614
- resolve53(import.meta.dir, "..", "package.json")
36591
+ resolve54(import.meta.dir, "..", "..", "package.json"),
36592
+ resolve54(import.meta.dir, "..", "package.json")
35615
36593
  ];
35616
36594
  const [candidate, ...remaining] = candidates;
35617
36595
  if (!candidate) {
@@ -35637,7 +36615,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35637
36615
  const entries = await readdir6(vendorDir).catch(() => emptyStringArray);
35638
36616
  await Promise.all(entries.filter((entry) => entry.endsWith(".js")).map(async (entry) => {
35639
36617
  const webPath = `/${framework}/vendor/${entry}`;
35640
- const bytes = await Bun.file(resolve53(vendorDir, entry)).bytes();
36618
+ const bytes = await Bun.file(resolve54(vendorDir, entry)).bytes();
35641
36619
  assetStore.set(webPath, bytes);
35642
36620
  }));
35643
36621
  }, devBuild = async (config) => {
@@ -35823,11 +36801,11 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35823
36801
  }
35824
36802
  stepStartedAt = performance.now();
35825
36803
  setBootPhase("build vendor bundles");
35826
- const reactVendorDir = resolve53(state.resolvedPaths.buildDir, "react", "vendor");
35827
- const angularVendorDir = resolve53(state.resolvedPaths.buildDir, "angular", "vendor");
35828
- const svelteVendorDir = resolve53(state.resolvedPaths.buildDir, "svelte", "vendor");
35829
- const vueVendorDir = resolve53(state.resolvedPaths.buildDir, "vue", "vendor");
35830
- const depVendorDir = resolve53(state.resolvedPaths.buildDir, "vendor");
36804
+ const reactVendorDir = resolve54(state.resolvedPaths.buildDir, "react", "vendor");
36805
+ const angularVendorDir = resolve54(state.resolvedPaths.buildDir, "angular", "vendor");
36806
+ const svelteVendorDir = resolve54(state.resolvedPaths.buildDir, "svelte", "vendor");
36807
+ const vueVendorDir = resolve54(state.resolvedPaths.buildDir, "vue", "vendor");
36808
+ const depVendorDir = resolve54(state.resolvedPaths.buildDir, "vendor");
35831
36809
  const { buildDepVendor: buildDepVendor2 } = await Promise.resolve().then(() => (init_buildDepVendor(), exports_buildDepVendor));
35832
36810
  const activeVendorDirs = [
35833
36811
  config.reactDirectory ? reactVendorDir : null,
@@ -35950,7 +36928,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35950
36928
  manifest
35951
36929
  };
35952
36930
  globalThis.__hmrDevResult = result;
35953
- globalThis.__hmrServerMtime = statSync8(resolve53(Bun.main)).mtimeMs;
36931
+ globalThis.__hmrServerMtime = statSync8(resolve54(Bun.main)).mtimeMs;
35954
36932
  return result;
35955
36933
  };
35956
36934
  var init_devBuild = __esm(() => {
@@ -35991,5 +36969,5 @@ export {
35991
36969
  devBuild
35992
36970
  };
35993
36971
 
35994
- //# debugId=45E97F77A3254DD664756E2164756E21
36972
+ //# debugId=7849DC008DCD28AC64756E2164756E21
35995
36973
  //# sourceMappingURL=build.js.map