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

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,889 @@ 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 !== 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 !== 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
+ return {
29219
+ metadata: serverMetadata(loaded.absoluteMobileUpdateServer),
29220
+ registry: registry2
29221
+ };
29222
+ }, expoSigningOptions = (config) => {
29223
+ if (!config.updates?.expoCodeSigning)
29224
+ return;
29225
+ const entries = Object.entries(config.updateServer?.expoCodeSigningKeys ?? {});
29226
+ const keys = Object.fromEntries(entries.map(([keyId, key]) => {
29227
+ const privateKey = process.env[key.privateKeyEnv];
29228
+ if (!privateKey)
29229
+ throw new TypeError(`Expo update serving requires ${key.privateKeyEnv} on the trusted server.`);
29230
+ try {
29231
+ const certificate = new X509Certificate3(key.certificatePem);
29232
+ const expected = certificate.publicKey.export({
29233
+ format: "der",
29234
+ type: "spki"
29235
+ });
29236
+ const actual = createPublicKey3(createPrivateKey2(privateKey)).export({
29237
+ format: "der",
29238
+ type: "spki"
29239
+ });
29240
+ if (!expected.equals(actual))
29241
+ throw new Error("key mismatch");
29242
+ } catch (error) {
29243
+ throw new TypeError(`${key.privateKeyEnv} must contain the RSA private key matching Expo update key ${keyId}.`, { cause: error });
29244
+ }
29245
+ return [keyId, { certificate: key.certificatePem, privateKey }];
29246
+ }));
29247
+ return { keys };
29248
+ }, createAbsoluteMobileUpdateServerPlugin = async (config, projectRoot, options = {}) => {
29249
+ const { updates, updateServer: server } = config;
29250
+ if (!updates || !server?.autoMount)
29251
+ return new Elysia5({ name: "absolutejs-mobile-updates-disabled" });
29252
+ const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, server.registryModule);
29253
+ if (options.production && module.metadata.storage !== "durable")
29254
+ throw new TypeError("Mobile production updates require durable object storage. Re-run `absolute mobile update provision --storage s3 --force` or configure a durable adapter.");
29255
+ const manifest = new URL(updates.manifestUrl);
29256
+ if (!manifest.pathname.endsWith("/update.json"))
29257
+ throw new TypeError("Auto-mounted mobile update manifests must end in /update.json.");
29258
+ const route = manifest.pathname.slice(0, -"/update.json".length);
29259
+ const { createMobileUpdateHandler: createMobileUpdateHandler2 } = await Promise.resolve().then(() => (init_mobileUpdate(), exports_mobileUpdate));
29260
+ const handler = createMobileUpdateHandler2({
29261
+ appId: config.appId,
29262
+ channel: updates.channel,
29263
+ ...config.engine === "expo" ? { expoCodeSigning: expoSigningOptions(config) } : {},
29264
+ registry: module.registry,
29265
+ route
29266
+ });
29267
+ return new Elysia5({ name: "absolutejs-mobile-updates" }).all(`${route}/*`, ({ request }) => handler(request));
29268
+ }, inspectAbsoluteMobileUpdateServer = async (config, projectRoot) => {
29269
+ if (!config.updates)
29270
+ return;
29271
+ const module = await loadAbsoluteMobileUpdateServerModule(projectRoot, config.updateServer?.registryModule);
29272
+ if (module.metadata.storage !== "durable")
29273
+ throw new TypeError("Mobile production updates require durable object storage; the configured registry is local-only.");
29274
+ if (config.engine === "expo")
29275
+ expoSigningOptions(config);
29276
+ return module.metadata;
29277
+ }, publicKeysSource = (publicKeys) => JSON.stringify(publicKeys, null, "\t"), renderAbsoluteMobileUpdateRegistry = (options) => {
29278
+ const metadata = `export const absoluteMobileUpdateServer = {
29279
+ format: 1,
29280
+ provider: '${options.storage}',
29281
+ storage: '${options.storage === "local" ? "local" : "durable"}'
29282
+ } as const;`;
29283
+ if (options.storage === "local")
29284
+ return `import { fileURLToPath } from 'node:url';
29285
+ import { localBlobStore } from '@absolutejs/blob/local';
29286
+ import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
29287
+
29288
+ ${metadata}
29289
+
29290
+ const store = localBlobStore({
29291
+ root: process.env.ABSOLUTE_MOBILE_UPDATE_LOCAL_ROOT ??
29292
+ fileURLToPath(new URL('./.absolutejs/mobile/update-registry/', import.meta.url))
29293
+ });
29294
+
29295
+ export default createMobileUpdateRegistry({
29296
+ publicKeys: ${publicKeysSource(options.publicKeys)},
29297
+ store
29298
+ });
29299
+ `;
29300
+ return `import { S3Client } from '@aws-sdk/client-s3';
29301
+ import { awsS3BlobStore } from '@absolutejs/blob/aws-s3';
29302
+ import { createMobileUpdateRegistry } from '@absolutejs/deploy/mobile-update';
29303
+
29304
+ ${metadata}
29305
+
29306
+ const required = (name: string) => {
29307
+ const value = process.env[name];
29308
+ if (!value) throw new Error(\`Missing \${name}\`);
29309
+ return value;
29310
+ };
29311
+
29312
+ const client = new S3Client({
29313
+ region: process.env.ABSOLUTE_MOBILE_UPDATE_S3_REGION ?? 'auto',
29314
+ forcePathStyle: process.env.ABSOLUTE_MOBILE_UPDATE_S3_FORCE_PATH_STYLE === '1',
29315
+ ...(process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT
29316
+ ? { endpoint: process.env.ABSOLUTE_MOBILE_UPDATE_S3_ENDPOINT }
29317
+ : {})
29318
+ });
29319
+ const store = awsS3BlobStore({
29320
+ bucket: required('ABSOLUTE_MOBILE_UPDATE_S3_BUCKET'),
29321
+ client
29322
+ });
29323
+
29324
+ export default createMobileUpdateRegistry({
29325
+ publicKeys: ${publicKeysSource(options.publicKeys)},
29326
+ store
29327
+ });
29328
+ `;
29329
+ }, writeAbsoluteMobileUpdateRegistry = async (options) => {
29330
+ const path2 = projectPath(options.projectRoot, options.modulePath ?? DEFAULT_MOBILE_UPDATE_REGISTRY_MODULE);
29331
+ if (!options.force) {
29332
+ await access4(path2).then(() => {
29333
+ throw new TypeError(`Mobile update registry already exists: ${path2}. Pass --force to replace it.`);
29334
+ }, () => {
29335
+ return;
29336
+ });
29337
+ }
29338
+ await mkdir13(dirname31(path2), { recursive: true });
29339
+ await Bun.write(path2, renderAbsoluteMobileUpdateRegistry({
29340
+ publicKeys: options.publicKeys,
29341
+ storage: options.storage
29342
+ }));
29343
+ return path2;
29344
+ };
29345
+ var init_updateServer = () => {};
29346
+
28415
29347
  // src/react/bridgeInternals.ts
28416
29348
  var INTERNALS_KEYS, isRecord8 = (val) => typeof val === "object" && val !== null, findInternals = (mod) => {
28417
29349
  for (const key of INTERNALS_KEYS) {
@@ -28457,10 +29389,10 @@ __export(exports_hmrCompiler, {
28457
29389
  encodeHmrComponentId: () => encodeHmrComponentId,
28458
29390
  getApplyMetadataModule: () => getApplyMetadataModule
28459
29391
  });
28460
- import { dirname as dirname31, relative as relative19, resolve as resolve46 } from "path";
29392
+ import { dirname as dirname32, relative as relative20, resolve as resolve47 } from "path";
28461
29393
  import { performance as performance2 } from "perf_hooks";
28462
29394
  var encodeHmrComponentId = (absoluteFilePath, className) => {
28463
- const projectRel = relative19(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
29395
+ const projectRel = relative20(process.cwd(), absoluteFilePath).replace(/\\/g, "/");
28464
29396
  return `${projectRel}@${className}`;
28465
29397
  }, getApplyMetadataModule = async (encodedId) => {
28466
29398
  const decoded = decodeURIComponent(encodedId);
@@ -28469,8 +29401,8 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
28469
29401
  return null;
28470
29402
  const filePathRel = decoded.slice(0, separatorIndex);
28471
29403
  const className = decoded.slice(separatorIndex + 1);
28472
- const componentFilePath = resolve46(process.cwd(), filePathRel);
28473
- const projectRelPath = relative19(process.cwd(), componentFilePath).replace(/\\/g, "/");
29404
+ const componentFilePath = resolve47(process.cwd(), filePathRel);
29405
+ const projectRelPath = relative20(process.cwd(), componentFilePath).replace(/\\/g, "/");
28474
29406
  const cacheKey3 = encodeURIComponent(`${projectRelPath}@${className}`);
28475
29407
  const { takePendingModule: takePendingModule2 } = await Promise.resolve().then(() => (init_fastHmrCompiler(), exports_fastHmrCompiler));
28476
29408
  const cached = takePendingModule2(cacheKey3);
@@ -28480,7 +29412,7 @@ var encodeHmrComponentId = (absoluteFilePath, className) => {
28480
29412
  const { resolveOwningComponents: resolveOwningComponents2 } = await Promise.resolve().then(() => (init_resolveOwningComponents(), exports_resolveOwningComponents));
28481
29413
  const owners = resolveOwningComponents2({
28482
29414
  changedFilePath: componentFilePath,
28483
- userAngularRoot: dirname31(componentFilePath)
29415
+ userAngularRoot: dirname32(componentFilePath)
28484
29416
  });
28485
29417
  const owner = owners.find((o3) => o3.className === className);
28486
29418
  const kind = owner?.kind ?? "component";
@@ -28502,7 +29434,7 @@ var exports_hmr = {};
28502
29434
  __export(exports_hmr, {
28503
29435
  hmr: () => hmr
28504
29436
  });
28505
- import Elysia5 from "elysia";
29437
+ import Elysia6 from "elysia";
28506
29438
  import { websocket } from "elysia/websocket";
28507
29439
  var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Reflect.get(globalThis, key), restoreStore = (store) => {
28508
29440
  if (!store || typeof store !== "object")
@@ -28578,8 +29510,8 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
28578
29510
  return null;
28579
29511
  if (!pathname.startsWith("/"))
28580
29512
  return null;
28581
- const { resolve: resolve47, normalize } = await import("path");
28582
- const candidate = resolve47(buildDir, pathname.slice(1));
29513
+ const { resolve: resolve48, normalize } = await import("path");
29514
+ const candidate = resolve48(buildDir, pathname.slice(1));
28583
29515
  const normalizedBuild = normalize(buildDir);
28584
29516
  if (!candidate.startsWith(normalizedBuild))
28585
29517
  return null;
@@ -28598,7 +29530,7 @@ var STORE_KEY = "__elysiaStore", restoredStores, getGlobalValue = (key) => Refle
28598
29530
  return candidate;
28599
29531
  }
28600
29532
  return null;
28601
- }, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia5({ name: "absolutejs-hmr" }).use(websocket({
29533
+ }, hmr = (hmrState, manifest, moduleServerHandler) => new Elysia6({ name: "absolutejs-hmr" }).use(websocket({
28602
29534
  idleTimeout: DEFAULT_WEBSOCKET_IDLE_TIMEOUT_SECONDS,
28603
29535
  sendPings: true
28604
29536
  })).request(async ({ request, store }) => {
@@ -28685,12 +29617,12 @@ __export(exports_devtoolsJson, {
28685
29617
  resolveDevtoolsUuidCachePath: () => resolveDevtoolsUuidCachePath
28686
29618
  });
28687
29619
  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";
29620
+ import { dirname as dirname33, join as join54, resolve as resolve48 } from "path";
29621
+ import { Elysia as Elysia7 } from "elysia";
28690
29622
  var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_KEY = "__absoluteDevtoolsWorkspaceUuid", getGlobalUuid = () => Reflect.get(globalThis, UUID_CACHE_KEY), setGlobalUuid = (uuid) => {
28691
29623
  Reflect.set(globalThis, UUID_CACHE_KEY, uuid);
28692
29624
  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) => {
29625
+ }, 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
29626
  if (!existsSync43(cachePath))
28695
29627
  return null;
28696
29628
  try {
@@ -28712,14 +29644,14 @@ var ENDPOINT = "/.well-known/appspecific/com.chrome.devtools.json", UUID_CACHE_K
28712
29644
  if (cachedUuid)
28713
29645
  return setGlobalUuid(cachedUuid);
28714
29646
  const uuid = crypto.randomUUID();
28715
- mkdirSync14(dirname32(cachePath), { recursive: true });
29647
+ mkdirSync14(dirname33(cachePath), { recursive: true });
28716
29648
  writeFileSync10(cachePath, uuid, "utf-8");
28717
29649
  return setGlobalUuid(uuid);
28718
29650
  }, devtoolsJson = (buildDir, options = {}) => {
28719
- const rootPath = resolve47(options.projectRoot ?? process.cwd());
29651
+ const rootPath = resolve48(options.projectRoot ?? process.cwd());
28720
29652
  const root = options.normalizeForWindowsContainer === false ? rootPath : normalizeDevtoolsWorkspaceRoot(rootPath);
28721
29653
  const uuid = getOrCreateUuid(buildDir, options);
28722
- return new Elysia6({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
29654
+ return new Elysia7({ name: "absolute-devtools-json" }).get(ENDPOINT, () => ({
28723
29655
  workspace: {
28724
29656
  root,
28725
29657
  uuid
@@ -28745,11 +29677,11 @@ __export(exports_imageOptimizer, {
28745
29677
  imageOptimizer: () => imageOptimizer
28746
29678
  });
28747
29679
  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) => {
29680
+ import { resolve as resolve49 } from "path";
29681
+ import { Elysia as Elysia8 } from "elysia";
29682
+ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avifInProgress, safeResolve = (path2, baseDir) => {
28751
29683
  try {
28752
- const resolved = validateSafePath(path, baseDir);
29684
+ const resolved = validateSafePath(path2, baseDir);
28753
29685
  if (existsSync44(resolved))
28754
29686
  return resolved;
28755
29687
  return null;
@@ -28758,7 +29690,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
28758
29690
  }
28759
29691
  }, resolveLocalImage = (url, buildDir) => {
28760
29692
  const cleanPath = url.startsWith("/") ? url.slice(1) : url;
28761
- return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve48(process.cwd()));
29693
+ return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve49(process.cwd()));
28762
29694
  }, parseQueryParams = (query, allowedSizes, defaultQuality) => {
28763
29695
  const url = typeof query["url"] === "string" ? query["url"] : undefined;
28764
29696
  const wParam = typeof query["w"] === "string" ? query["w"] : undefined;
@@ -28859,7 +29791,7 @@ var DEFAULT_CACHE_TTL_SECONDS = 60, MS_PER_SECOND = 1000, MAX_QUALITY = 100, avi
28859
29791
  }
28860
29792
  });
28861
29793
  }, imageOptimizer = (config, buildDir) => {
28862
- const plugin = new Elysia7({ name: "image-optimizer" });
29794
+ const plugin = new Elysia8({ name: "image-optimizer" });
28863
29795
  if (!config && config !== undefined)
28864
29796
  return plugin;
28865
29797
  if (config?.unoptimized)
@@ -28960,16 +29892,16 @@ var exports_requestInspector = {};
28960
29892
  __export(exports_requestInspector, {
28961
29893
  requestInspector: () => requestInspector
28962
29894
  });
28963
- import { Elysia as Elysia8 } from "elysia";
29895
+ import { Elysia as Elysia9 } from "elysia";
28964
29896
  var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
28965
29897
  globalThis.__absoluteRequestLog ??= [];
28966
29898
  return globalThis.__absoluteRequestLog;
28967
- }, classify = (path) => {
28968
- if (path.startsWith("/@") || path.includes("/__hmr"))
29899
+ }, classify = (path2) => {
29900
+ if (path2.startsWith("/@") || path2.includes("/__hmr"))
28969
29901
  return "hmr";
28970
- if (path.startsWith("/api"))
29902
+ if (path2.startsWith("/api"))
28971
29903
  return "api";
28972
- if (ASSET_EXTENSION.test(path) || path.startsWith("/assets/"))
29904
+ if (ASSET_EXTENSION.test(path2) || path2.startsWith("/assets/"))
28973
29905
  return "asset";
28974
29906
  return "page";
28975
29907
  }, pathOf = (url) => {
@@ -28996,7 +29928,7 @@ var RING_MAX = 200, DEFAULT_STATUS = 200, ASSET_EXTENSION, requestLog = () => {
28996
29928
  var init_requestInspector = __esm(() => {
28997
29929
  ASSET_EXTENSION = /\.(?:avif|css|gif|ico|jpe?g|js|json|map|mjs|otf|png|svg|ttf|txt|wasm|webp|woff2?)$/i;
28998
29930
  pending = new WeakMap;
28999
- requestInspector = new Elysia8({
29931
+ requestInspector = new Elysia9({
29000
29932
  name: "absolute-request-inspector"
29001
29933
  }).get("/__absolute/requests", () => requestLog()).request(({ request }) => {
29002
29934
  noteDevRequestStart();
@@ -29006,17 +29938,17 @@ var init_requestInspector = __esm(() => {
29006
29938
  });
29007
29939
  }).afterResponse(({ request, set, responseValue }) => {
29008
29940
  noteDevRequestEnd();
29009
- const path = pathOf(request.url);
29010
- if (path.startsWith("/__absolute"))
29941
+ const path2 = pathOf(request.url);
29942
+ if (path2.startsWith("/__absolute"))
29011
29943
  return;
29012
29944
  const entry = pending.get(request);
29013
29945
  const log2 = requestLog();
29014
29946
  log2.push({
29015
29947
  at: Date.now(),
29016
29948
  durationMs: entry === undefined ? 0 : performance.now() - entry.start,
29017
- kind: classify(path),
29949
+ kind: classify(path2),
29018
29950
  method: request.method,
29019
- path,
29951
+ path: path2,
29020
29952
  query: new URL(request.url).search,
29021
29953
  requestHeaders: entry?.headers ?? {},
29022
29954
  responseHeaders: toHeaderRecord(set.headers),
@@ -29029,7 +29961,7 @@ var init_requestInspector = __esm(() => {
29029
29961
  });
29030
29962
 
29031
29963
  // src/mobile/releaseArtifact.ts
29032
- import { createHash as createHash6 } from "crypto";
29964
+ import { createHash as createHash7 } from "crypto";
29033
29965
  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
29966
  if (typeof value !== "object" || value === null || Array.isArray(value)) {
29035
29967
  return false;
@@ -29066,7 +29998,7 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
29066
29998
  return normalizeCanonicalRecord(value, ancestors);
29067
29999
  }
29068
30000
  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) => {
30001
+ }, canonicalJson = (value) => JSON.stringify(normalizeCanonicalValue(value, new Set)), hashCanonicalValue = (value) => createHash7(SHA_256).update(canonicalJson(value)).digest("hex"), requireNonEmpty = (value, field) => {
29070
30002
  if (!value.trim()) {
29071
30003
  throw new TypeError(`${field} must not be empty.`);
29072
30004
  }
@@ -29255,11 +30187,11 @@ var init_releaseArtifact = __esm(() => {
29255
30187
  });
29256
30188
 
29257
30189
  // src/mobile/artifactStore.ts
29258
- import { createHash as createHash7 } from "crypto";
30190
+ import { createHash as createHash8 } from "crypto";
29259
30191
  import {
29260
- mkdir as mkdir13,
30192
+ mkdir as mkdir14,
29261
30193
  mkdtemp as mkdtemp2,
29262
- readFile as readFile9,
30194
+ readFile as readFile10,
29263
30195
  readdir as readdir5,
29264
30196
  rename as rename5,
29265
30197
  rm as rm13,
@@ -29268,18 +30200,18 @@ import {
29268
30200
  import { join as join55, resolve as resolvePath } from "path";
29269
30201
  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
30202
  const bytes = new Uint8Array(await blob.arrayBuffer());
29271
- return createHash7(SHA_2562).update(bytes).digest("hex");
30203
+ return createHash8(SHA_2562).update(bytes).digest("hex");
29272
30204
  }, blobFromBytes = (bytes) => {
29273
30205
  const buffer = new ArrayBuffer(bytes.byteLength);
29274
30206
  new Uint8Array(buffer).set(bytes);
29275
30207
  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) => {
30208
+ }, 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
30209
  if (!RELEASE_ID_PATTERN.test(releaseId)) {
29278
30210
  throw new TypeError("Invalid mobile compatibility release id.");
29279
30211
  }
29280
30212
  return releaseId;
29281
30213
  }, readStoredArtifact = async (releaseDirectory) => {
29282
- const serialized = await readFile9(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
30214
+ const serialized = await readFile10(join55(releaseDirectory, ARTIFACT_FILE), "utf8");
29283
30215
  const parsed = JSON.parse(serialized);
29284
30216
  return parseAbsoluteMobileCompatibilityArtifact(parsed);
29285
30217
  }, validateStoredIdentity = (artifact, appId, releaseId) => {
@@ -29423,11 +30355,11 @@ var DEFAULT_MAX_PRODUCER_BYTES = 134217728, SHA_2562 = "sha256", ARTIFACT_FILE =
29423
30355
  const validatedArtifact = parseAbsoluteMobileCompatibilityArtifact(release.artifact);
29424
30356
  const validated = await verifyAbsoluteMobileCompatibilityProducer({ artifact: validatedArtifact, producer: release.producer }, maxProducerBytes);
29425
30357
  const parent = appDirectory(validated.artifact.appId);
29426
- await mkdir13(parent, { recursive: true });
30358
+ await mkdir14(parent, { recursive: true });
29427
30359
  const staging = await mkdtemp2(join55(parent, ".stage-"));
29428
30360
  const producerPath = join55(staging, validated.artifact.producer.module);
29429
30361
  try {
29430
- await mkdir13(resolvePath(producerPath, ".."), {
30362
+ await mkdir14(resolvePath(producerPath, ".."), {
29431
30363
  recursive: true
29432
30364
  });
29433
30365
  await Promise.all([
@@ -29467,24 +30399,24 @@ __export(exports_materializedBundle, {
29467
30399
  materializeAbsoluteMobileCompatibilityBundle: () => materializeAbsoluteMobileCompatibilityBundle,
29468
30400
  readAbsoluteMobileMaterializedReleases: () => readAbsoluteMobileMaterializedReleases
29469
30401
  });
29470
- import { createHash as createHash8 } from "crypto";
30402
+ import { createHash as createHash9 } from "crypto";
29471
30403
  import {
29472
- access as access4,
29473
- mkdir as mkdir14,
30404
+ access as access5,
30405
+ mkdir as mkdir15,
29474
30406
  mkdtemp as mkdtemp3,
29475
- readFile as readFile10,
30407
+ readFile as readFile11,
29476
30408
  rename as rename6,
29477
30409
  rm as rm14,
29478
30410
  writeFile as writeFile12
29479
30411
  } from "fs/promises";
29480
- import { dirname as dirname33, join as join56, resolve as resolvePath2 } from "path";
29481
- import { pathToFileURL as pathToFileURL3 } from "url";
30412
+ import { dirname as dirname34, join as join56, resolve as resolvePath2 } from "path";
30413
+ import { pathToFileURL as pathToFileURL4 } from "url";
29482
30414
  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
30415
  const identity = JSON.stringify({
29484
30416
  currentReleaseId,
29485
30417
  releases: releases.map(({ releaseId }) => releaseId)
29486
30418
  });
29487
- return `amb_${createHash8("sha256").update(identity).digest("hex")}`;
30419
+ return `amb_${createHash9("sha256").update(identity).digest("hex")}`;
29488
30420
  }, parseBundleIndex = (value) => {
29489
30421
  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
30422
  throw new TypeError("Invalid materialized mobile compatibility bundle.");
@@ -29510,7 +30442,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29510
30442
  }, writeRelease = async (root, release) => {
29511
30443
  const directory = join56(root, release.artifact.releaseId);
29512
30444
  const producerPath = join56(directory, release.artifact.producer.module);
29513
- await mkdir14(dirname33(producerPath), { recursive: true });
30445
+ await mkdir15(dirname34(producerPath), { recursive: true });
29514
30446
  await Promise.all([
29515
30447
  writeFile12(join56(directory, ARTIFACT_FILE2), `${JSON.stringify(release.artifact, null, "\t")}
29516
30448
  `),
@@ -29519,7 +30451,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29519
30451
  }, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
29520
30452
  const destination = join56(bundlesRoot, bundleId);
29521
30453
  try {
29522
- await access4(destination);
30454
+ await access5(destination);
29523
30455
  return destination;
29524
30456
  } catch (error) {
29525
30457
  if (!errorHasCode2(error, "ENOENT"))
@@ -29537,7 +30469,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29537
30469
  throw error;
29538
30470
  }
29539
30471
  return destination;
29540
- }, readCompatibilityModule = (modulePath) => import(pathToFileURL3(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
30472
+ }, readCompatibilityModule = (modulePath) => import(pathToFileURL4(modulePath).href), resolveProducerHandler = (loaded, exportName) => {
29541
30473
  const value = loaded[exportName];
29542
30474
  if (!isRecord9(value) || typeof value.handle !== "function") {
29543
30475
  throw new TypeError(`Compatibility producer export ${exportName} must expose handle(request).`);
@@ -29556,7 +30488,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29556
30488
  };
29557
30489
  }, loadAbsoluteMobileMaterializedBundle = async (root) => {
29558
30490
  const resolvedRoot = resolvePath2(root);
29559
- const serialized = await readFile10(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
30491
+ const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
29560
30492
  const parsed = JSON.parse(serialized);
29561
30493
  const index = parseBundleIndex(parsed);
29562
30494
  const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -29591,7 +30523,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29591
30523
  });
29592
30524
  const root = resolvePath2(input.root);
29593
30525
  const bundlesRoot = join56(root, BUNDLES_DIRECTORY);
29594
- await mkdir14(bundlesRoot, { recursive: true });
30526
+ await mkdir15(bundlesRoot, { recursive: true });
29595
30527
  const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
29596
30528
  await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
29597
30529
  const index = {
@@ -29609,7 +30541,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
29609
30541
  }, readAbsoluteMobileMaterializedReleases = async (root) => {
29610
30542
  const resolvedRoot = resolvePath2(root);
29611
30543
  try {
29612
- const serialized = await readFile10(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
30544
+ const serialized = await readFile11(join56(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
29613
30545
  const parsed = JSON.parse(serialized);
29614
30546
  const index = parseBundleIndex(parsed);
29615
30547
  const bundleRoot = join56(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
@@ -30022,7 +30954,7 @@ var exports_compatibilityDispatcher = {};
30022
30954
  __export(exports_compatibilityDispatcher, {
30023
30955
  createAbsoluteMobileCompatibilityDispatcher: () => createAbsoluteMobileCompatibilityDispatcher
30024
30956
  });
30025
- import { Elysia as Elysia9 } from "elysia";
30957
+ import { Elysia as Elysia10 } from "elysia";
30026
30958
  var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADERS, MOBILE_CORS_METHODS, mobileWebViewOrigin = (request) => {
30027
30959
  const origin = request.headers.get("origin");
30028
30960
  return origin && MOBILE_WEBVIEW_ORIGINS.has(origin) ? origin : undefined;
@@ -30077,7 +31009,7 @@ var MOBILE_WEBVIEW_ORIGINS, MOBILE_REQUEST_HEADER_NAMES, MOBILE_CORS_ALLOW_HEADE
30077
31009
  throw new TypeError("currentReleaseId must identify a retained compatibility artifact.");
30078
31010
  }
30079
31011
  const resolveProducer = createProducerResolver(options.loadProducer);
30080
- return new Elysia9({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
31012
+ return new Elysia10({ name: "absolutejs-mobile-compatibility-dispatcher" }).request(async ({ request }) => {
30081
31013
  if (getCurrentAbsoluteMobileProducerContext())
30082
31014
  return;
30083
31015
  const preflight = mobilePreflightResponse(request);
@@ -30237,8 +31169,8 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30237
31169
  links.push(href);
30238
31170
  }
30239
31171
  return links;
30240
- }, fetchRoute = async (baseUrl, path) => {
30241
- const res = await fetchWithTimeout(`${baseUrl}${path}`, {
31172
+ }, fetchRoute = async (baseUrl, path2) => {
31173
+ const res = await fetchWithTimeout(`${baseUrl}${path2}`, {
30242
31174
  redirect: "manual"
30243
31175
  });
30244
31176
  if (!res.ok)
@@ -30252,21 +31184,21 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30252
31184
  const queue = ["/"];
30253
31185
  const routes = [];
30254
31186
  const crawlNextRoute = async () => {
30255
- const path = queue.shift();
30256
- if (!path) {
31187
+ const path2 = queue.shift();
31188
+ if (!path2) {
30257
31189
  return;
30258
31190
  }
30259
- if (visited.has(path)) {
31191
+ if (visited.has(path2)) {
30260
31192
  await crawlNextRoute();
30261
31193
  return;
30262
31194
  }
30263
- visited.add(path);
30264
- const html = await fetchRoute(baseUrl, path).catch(() => null);
31195
+ visited.add(path2);
31196
+ const html = await fetchRoute(baseUrl, path2).catch(() => null);
30265
31197
  if (!html) {
30266
31198
  await crawlNextRoute();
30267
31199
  return;
30268
31200
  }
30269
- routes.push(path);
31201
+ routes.push(path2);
30270
31202
  queue.push(...extractLinks(html, visited));
30271
31203
  await crawlNextRoute();
30272
31204
  };
@@ -30387,10 +31319,10 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
30387
31319
  };
30388
31320
  read();
30389
31321
  }, formatServerOutput = (output) => {
30390
- const text2 = output.join("").trim();
30391
- if (!text2)
31322
+ const text3 = output.join("").trim();
31323
+ if (!text3)
30392
31324
  return "";
30393
- return text2.length > SERVER_OUTPUT_LIMIT ? text2.slice(-SERVER_OUTPUT_LIMIT) : text2;
31325
+ return text3.length > SERVER_OUTPUT_LIMIT ? text3.slice(-SERVER_OUTPUT_LIMIT) : text3;
30394
31326
  }, createServerStartupError = (output) => {
30395
31327
  const serverOutput = formatServerOutput(output);
30396
31328
  const message = serverOutput ? `Server failed to start for pre-rendering.
@@ -30437,18 +31369,18 @@ __export(exports_prepare, {
30437
31369
  prepare: () => prepare,
30438
31370
  startDevPrebuild: () => startDevPrebuild
30439
31371
  });
30440
- import { createHash as createHash9 } from "crypto";
31372
+ import { createHash as createHash10 } from "crypto";
30441
31373
  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);
31374
+ import { basename as basename19, join as join58, relative as relative21, resolve as resolvePath3 } from "path";
31375
+ import { Elysia as Elysia11, NotFound } from "elysia";
31376
+ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_PLUGIN_RETRY_DELAY_MS = 50, waitForStaticPluginRetry = () => new Promise((resolve50) => {
31377
+ setTimeout(resolve50, STATIC_PLUGIN_RETRY_DELAY_MS);
30446
31378
  }), retryStaticPlugin = async (createStaticPlugin, options) => {
30447
31379
  try {
30448
31380
  return await createStaticPlugin(options);
30449
31381
  } catch (error) {
30450
31382
  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" });
31383
+ return new Elysia11({ name: "absolutejs-static-fallback" });
30452
31384
  }
30453
31385
  }, mountStaticPlugin = async (createStaticPlugin, options) => {
30454
31386
  try {
@@ -30459,7 +31391,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30459
31391
  }
30460
31392
  }, 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
31393
  if (!mobile)
30462
- return new Elysia10({ name: "absolutejs-mobile-disabled" });
31394
+ return new Elysia11({ name: "absolutejs-mobile-disabled" });
30463
31395
  const [
30464
31396
  { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 },
30465
31397
  { createAbsoluteMobilePreviewPlugin: createAbsoluteMobilePreviewPlugin2 }
@@ -30470,19 +31402,33 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30470
31402
  let nativeDevAdapterBundle;
30471
31403
  const getNativeDevAdapterBundle = () => nativeDevAdapterBundle ??= Promise.resolve().then(() => (init_devDeviceAdapter(), exports_devDeviceAdapter)).then(({ buildAbsoluteNativeDevAdapter: buildAbsoluteNativeDevAdapter2 }) => buildAbsoluteNativeDevAdapter2(process.cwd(), mobile));
30472
31404
  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(), {
31405
+ 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
31406
  headers: MOBILE_DEV_MODULE_HEADERS
30475
31407
  })).get(MOBILE_PREVIEW_CLIENT_PATH, async () => new Response(await getMobilePreviewClientBundle(), {
30476
31408
  headers: MOBILE_DEV_MODULE_HEADERS
30477
31409
  }));
30478
31410
  }, loadMobileAssociationPlugin = async (mobile) => {
30479
31411
  if (!mobile) {
30480
- return new Elysia10({ name: "absolutejs-mobile-associations-disabled" });
31412
+ return new Elysia11({ name: "absolutejs-mobile-associations-disabled" });
30481
31413
  }
30482
31414
  const { createAbsoluteMobileAssociationPlugin: createAbsoluteMobileAssociationPlugin2 } = await Promise.resolve().then(() => (init_associationFiles(), exports_associationFiles));
30483
31415
  return createAbsoluteMobileAssociationPlugin2(mobile, process.cwd(), {
30484
31416
  requireAll: true
30485
31417
  });
31418
+ }, loadMobileUpdatePlugin = async (mobile, production) => {
31419
+ if (!mobile?.updates)
31420
+ return new Elysia11({ name: "absolutejs-mobile-updates-unconfigured" });
31421
+ const [
31422
+ { normalizeAbsoluteMobileConfig: normalizeAbsoluteMobileConfig2 },
31423
+ { createAbsoluteMobileUpdateServerPlugin: createAbsoluteMobileUpdateServerPlugin2 }
31424
+ ] = await Promise.all([
31425
+ Promise.resolve().then(() => (init_config(), exports_config)),
31426
+ Promise.resolve().then(() => (init_updateServer(), exports_updateServer))
31427
+ ]);
31428
+ const normalized = normalizeAbsoluteMobileConfig2(mobile, process.cwd());
31429
+ return createAbsoluteMobileUpdateServerPlugin2(normalized, process.cwd(), {
31430
+ production
31431
+ });
30486
31432
  }, buildPrewarmDirs = (config) => {
30487
31433
  const dirs = [];
30488
31434
  if (config.svelteDirectory) {
@@ -30514,7 +31460,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30514
31460
  return files;
30515
31461
  }, PREWARM_MAX_PAUSE_MS = 60000, toWarmTasks = function* (files, warmCache, srcUrlPrefix) {
30516
31462
  for (const file5 of files) {
30517
- const rel = relative20(process.cwd(), file5).replace(/\\/g, "/");
31463
+ const rel = relative21(process.cwd(), file5).replace(/\\/g, "/");
30518
31464
  yield () => warmCache(`${srcUrlPrefix}${rel}`);
30519
31465
  }
30520
31466
  }, builtPageSources = () => {
@@ -30555,7 +31501,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30555
31501
  const srcPath = resolvePath3(devIndexDir, fileName);
30556
31502
  if (!existsSync45(srcPath))
30557
31503
  continue;
30558
- const rel = relative20(process.cwd(), srcPath).replace(/\\/g, "/");
31504
+ const rel = relative21(process.cwd(), srcPath).replace(/\\/g, "/");
30559
31505
  manifest[key] = `${SRC_URL_PREFIX2}${rel}`;
30560
31506
  }
30561
31507
  }, ICON_HASH_LENGTH = 8, registerIconVersioning = (buildDir) => {
@@ -30566,11 +31512,11 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30566
31512
  const cached = cache2.get(href);
30567
31513
  if (cached !== undefined)
30568
31514
  return cached;
30569
- const path = href.split("?")[0] ?? href;
30570
- const filePath = join58(buildDir, path);
31515
+ const path2 = href.split("?")[0] ?? href;
31516
+ const filePath = join58(buildDir, path2);
30571
31517
  let versioned = href;
30572
31518
  if (existsSync45(filePath)) {
30573
- const hash = createHash9("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
31519
+ const hash = createHash10("sha256").update(readFileSync39(filePath)).digest("hex").slice(0, ICON_HASH_LENGTH);
30574
31520
  versioned = href.includes("?") ? `${href}&v=${hash}` : `${href}?v=${hash}`;
30575
31521
  }
30576
31522
  cache2.set(href, versioned);
@@ -30675,12 +31621,13 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30675
31621
  const { requestInspector: requestInspector2 } = await Promise.resolve().then(() => (init_requestInspector(), exports_requestInspector));
30676
31622
  const { serverTiming } = await import("@elysia/server-timing");
30677
31623
  const mobileDevPlugin = await loadMobileDevPlugin(config.mobile);
30678
- const absolutejs = new Elysia10({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
31624
+ const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, false);
31625
+ const absolutejs = new Elysia11({ name: "absolutejs-runtime" }).use(requestInspector2).use(absoluteRequestContext).use(serverTiming()).use(devtoolsJson2(buildDir, {
30679
31626
  normalizeForWindowsContainer: config.dev?.devtools?.normalizeForWindowsContainer,
30680
31627
  projectRoot: config.dev?.devtools?.projectRoot,
30681
31628
  uuid: config.dev?.devtools?.uuid,
30682
31629
  uuidCachePath: config.dev?.devtools?.uuidCachePath
30683
- })).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(await mountStaticPlugin(staticPlugin, {
31630
+ })).use(imageOptimizer2(config.images, buildDir)).use(mobileDevPlugin).use(mobileUpdatePlugin).use(await mountStaticPlugin(staticPlugin, {
30684
31631
  alwaysStatic: true,
30685
31632
  assets: buildDir,
30686
31633
  directive: "no-cache",
@@ -30719,7 +31666,7 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30719
31666
  }, loadMobileCompatibilityPlugin = async (buildDir) => {
30720
31667
  const root = join58(buildDir, ".absolutejs", "mobile-compatibility");
30721
31668
  if (!existsSync45(join58(root, "current.json"))) {
30722
- return new Elysia10({ name: "absolutejs-mobile-compatibility-empty" });
31669
+ return new Elysia11({ name: "absolutejs-mobile-compatibility-empty" });
30723
31670
  }
30724
31671
  const [
30725
31672
  { loadAbsoluteMobileMaterializedBundle: loadAbsoluteMobileMaterializedBundle2 },
@@ -30730,12 +31677,12 @@ var MS_PER_SECOND2 = 1000, DEFAULT_PORT2 = 3000, MAX_STATIC_ROUTE_COUNT, STATIC_
30730
31677
  ]);
30731
31678
  const options = await loadAbsoluteMobileMaterializedBundle2(root);
30732
31679
  return createAbsoluteMobileCompatibilityDispatcher2(options);
30733
- }, createNotFoundPlugin = () => new Elysia10({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
31680
+ }, createNotFoundPlugin = () => new Elysia11({ name: "absolutejs-not-found" }).error("global", NotFound, async () => {
30734
31681
  const response = await renderFirstNotFound();
30735
31682
  if (response)
30736
31683
  return response;
30737
31684
  return;
30738
- }), createBuildErrorRecoveryPlugin = () => new Elysia10({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
31685
+ }), createBuildErrorRecoveryPlugin = () => new Elysia11({ name: "absolutejs-build-error-recovery" }).error("global", async ({ error }) => {
30739
31686
  const message = error instanceof Error ? error.message : String(error);
30740
31687
  const assetMatch = /^Asset "(.+)" not found in manifest\.$/.exec(message);
30741
31688
  if (!assetMatch)
@@ -30802,11 +31749,11 @@ This usually means a build-time error in a source file. Check the dev-server ter
30802
31749
  staticLimit: MAX_STATIC_ROUTE_COUNT
30803
31750
  });
30804
31751
  const generatedAssetsRoot = join58(buildDir, ".absolutejs");
30805
- const generatedAssetsPlugin = new Elysia10({
31752
+ const generatedAssetsPlugin = new Elysia11({
30806
31753
  name: "absolutejs-generated-assets"
30807
31754
  }).get("/.absolutejs/*", async ({ params, set }) => {
30808
31755
  const requestedPath = resolvePath3(generatedAssetsRoot, params["*"]);
30809
- if (relative20(generatedAssetsRoot, requestedPath).startsWith("..")) {
31756
+ if (relative21(generatedAssetsRoot, requestedPath).startsWith("..")) {
30810
31757
  set.status = 404;
30811
31758
  return "Not Found";
30812
31759
  }
@@ -30826,7 +31773,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30826
31773
  const hash = base.match(/[.-]([0-9a-z]{6,12})\.[0-9a-z]+$/i)?.[1];
30827
31774
  return hash ? /[0-9]/.test(hash) && /[a-z]/i.test(hash) : false;
30828
31775
  };
30829
- const assetCachePlugin = new Elysia10({
31776
+ const assetCachePlugin = new Elysia11({
30830
31777
  name: "absolutejs-asset-cache"
30831
31778
  }).afterHandle("global", ({ request, responseValue }) => {
30832
31779
  if (!(responseValue instanceof Response))
@@ -30843,13 +31790,14 @@ This usually means a build-time error in a source file. Check the dev-server ter
30843
31790
  const prerenderMap = loadPrerenderMap(prerenderDir);
30844
31791
  const mobileCompatibilityPlugin = await loadMobileCompatibilityPlugin(buildDir);
30845
31792
  const mobileAssociationPlugin = await loadMobileAssociationPlugin(config.mobile);
31793
+ const mobileUpdatePlugin = await loadMobileUpdatePlugin(config.mobile, true);
30846
31794
  recordStep("load prerender map", stepStartedAt);
30847
31795
  if (prerenderMap.size > 0) {
30848
31796
  const { PRERENDER_BYPASS_HEADER: PRERENDER_BYPASS_HEADER2, readTimestamp: readTimestamp2, rerenderRoute: rerenderRoute2 } = await Promise.resolve().then(() => (init_prerender(), exports_prerender));
30849
31797
  const revalidateMs = config.static?.revalidate ? config.static.revalidate * MS_PER_SECOND2 : 0;
30850
31798
  const port = Number(process.env.PORT) || DEFAULT_PORT2;
30851
31799
  const rerendering = new Set;
30852
- const prerenderPlugin = new Elysia10({
31800
+ const prerenderPlugin = new Elysia11({
30853
31801
  name: "prerendered-pages"
30854
31802
  }).request(({ request }) => {
30855
31803
  const url = new URL(request.url);
@@ -30872,7 +31820,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30872
31820
  });
30873
31821
  stepStartedAt = performance.now();
30874
31822
  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());
31823
+ 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
31824
  await withOpenApi(absolutejs2, config, process.cwd(), false);
30877
31825
  await withTelemetry(absolutejs2, config, process.cwd());
30878
31826
  recordStep("assemble production runtime", stepStartedAt);
@@ -30881,7 +31829,7 @@ This usually means a build-time error in a source file. Check the dev-server ter
30881
31829
  }
30882
31830
  stepStartedAt = performance.now();
30883
31831
  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());
31832
+ 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
31833
  await withOpenApi(absolutejs, config, process.cwd(), false);
30886
31834
  await withTelemetry(absolutejs, config, process.cwd());
30887
31835
  recordStep("assemble production runtime", stepStartedAt);
@@ -30961,7 +31909,7 @@ __export(exports_moduleServer, {
30961
31909
  warnIfReactFastRefreshUnsupported: () => warnIfReactFastRefreshUnsupported
30962
31910
  });
30963
31911
  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";
31912
+ import { basename as basename20, dirname as dirname35, extname as extname15, join as join59, resolve as resolve50, relative as relative22 } from "path";
30965
31913
  var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfig, tsTranspiler2, tsxTranspiler, TRANSPILABLE, ALL_EXPORTS_RE, STRING_CONTENTS_RE, preserveTypeExports = (originalSource, transpiled, valueExports) => {
30966
31914
  const codeOnly = originalSource.replace(STRING_CONTENTS_RE, '""');
30967
31915
  const allExports = [];
@@ -30981,10 +31929,10 @@ var SRC_PREFIX = "/@src/", BROWSER_DEFINE, jsTranspiler2, legacyDecoratorTsconfi
30981
31929
  ${stubs}
30982
31930
  `;
30983
31931
  }, resolveRelativeExtension = (srcPath, projectRoot, extensions) => {
30984
- const directHit = extensions.find((ext) => existsSync46(resolve49(projectRoot, srcPath + ext)));
31932
+ const directHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath + ext)));
30985
31933
  if (directHit)
30986
31934
  return srcPath + directHit;
30987
- const indexHit = extensions.find((ext) => existsSync46(resolve49(projectRoot, srcPath, `index${ext}`)));
31935
+ const indexHit = extensions.find((ext) => existsSync46(resolve50(projectRoot, srcPath, `index${ext}`)));
30988
31936
  if (indexHit)
30989
31937
  return `${srcPath}/index${indexHit}`;
30990
31938
  return srcPath;
@@ -31013,7 +31961,7 @@ ${stubs}
31013
31961
  return invalidationVersion > 0 ? `${mtime}.${invalidationVersion}` : `${mtime}`;
31014
31962
  }, srcUrl = (relPath, projectRoot) => {
31015
31963
  const base = `${SRC_PREFIX}${relPath.replace(/\\/g, "/")}`;
31016
- const absPath = resolve49(projectRoot, relPath);
31964
+ const absPath = resolve50(projectRoot, relPath);
31017
31965
  const cached = mtimeCache.get(absPath);
31018
31966
  if (cached !== undefined)
31019
31967
  return `${base}?v=${buildVersion(cached, absPath)}`;
@@ -31025,12 +31973,12 @@ ${stubs}
31025
31973
  return base;
31026
31974
  }
31027
31975
  }, resolveRelativeImport = (relPath, fileDir, projectRoot, extensions) => {
31028
- const absPath = resolve49(fileDir, relPath);
31029
- const rel = relative21(projectRoot, absPath);
31976
+ const absPath = resolve50(fileDir, relPath);
31977
+ const rel = relative22(projectRoot, absPath);
31030
31978
  const extension = extname15(rel);
31031
31979
  let srcPath = RESOLVED_MODULE_EXTENSIONS.has(extension) ? rel : resolveRelativeExtension(rel, projectRoot, extensions);
31032
31980
  if (extname15(srcPath) === ".svelte") {
31033
- srcPath = relative21(projectRoot, resolveSvelteModulePath(resolve49(projectRoot, srcPath)));
31981
+ srcPath = relative22(projectRoot, resolveSvelteModulePath(resolve50(projectRoot, srcPath)));
31034
31982
  }
31035
31983
  return srcUrl(srcPath, projectRoot);
31036
31984
  }, NODE_BUILTIN_RE, resolveAbsoluteSpecifier = (specifier, projectRoot) => {
@@ -31042,27 +31990,27 @@ ${stubs}
31042
31990
  "import"
31043
31991
  ]);
31044
31992
  if (fromExports)
31045
- return relative21(projectRoot, fromExports);
31993
+ return relative22(projectRoot, fromExports);
31046
31994
  try {
31047
31995
  const isScoped = specifier.startsWith("@");
31048
31996
  const parts = specifier.split("/");
31049
31997
  const packageName = isScoped ? `${parts[0]}/${parts[1]}` : parts[0];
31050
31998
  const subpath = isScoped ? parts.slice(2).join("/") : parts.slice(1).join("/");
31051
31999
  if (!subpath) {
31052
- const pkgDir = resolve49(projectRoot, "node_modules", packageName ?? "");
32000
+ const pkgDir = resolve50(projectRoot, "node_modules", packageName ?? "");
31053
32001
  const pkgJsonPath = join59(pkgDir, "package.json");
31054
32002
  if (existsSync46(pkgJsonPath)) {
31055
32003
  const pkg = JSON.parse(readFileSync40(pkgJsonPath, "utf-8"));
31056
32004
  const esmEntry = typeof pkg.module === "string" && pkg.module || typeof pkg.browser === "string" && pkg.browser;
31057
32005
  if (esmEntry) {
31058
- const resolved = resolve49(pkgDir, esmEntry);
32006
+ const resolved = resolve50(pkgDir, esmEntry);
31059
32007
  if (existsSync46(resolved))
31060
- return relative21(projectRoot, resolved);
32008
+ return relative22(projectRoot, resolved);
31061
32009
  }
31062
32010
  }
31063
32011
  }
31064
32012
  } catch {}
31065
- return relative21(projectRoot, Bun.resolveSync(specifier, projectRoot));
32013
+ return relative22(projectRoot, Bun.resolveSync(specifier, projectRoot));
31066
32014
  } catch {
31067
32015
  return;
31068
32016
  }
@@ -31095,28 +32043,28 @@ ${stubs}
31095
32043
  };
31096
32044
  result = result.replace(/^((?:import\s+[^"'`;]+?\s+from|export\s+[^"'`;]+?\s+from|import)\s*["'])([^"'./][^"']*)(["'])/gm, stubReplace);
31097
32045
  result = result.replace(/(import\s*\(\s*["'])([^"'./][^"']*)(["']\s*\))/g, stubReplace);
31098
- const fileDir = dirname34(filePath);
32046
+ const fileDir = dirname35(filePath);
31099
32047
  result = result.replace(/(from\s*["'])(\.\.?\/[^"']+)(["'])/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
31100
32048
  result = result.replace(/(import\s*\(\s*["'])(\.\.?\/[^"']+)(["']\s*\))/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, IMPORT_EXTENSIONS)}${suffix}` : _match);
31101
32049
  result = result.replace(/(import\s*["'])(\.\.?\/[^"']+)(["']\s*;?)/g, (_match, prefix, relPath, suffix) => isRealImport(relPath) ? `${prefix}${resolveRelativeImport(relPath, fileDir, projectRoot, SIDE_EFFECT_EXTENSIONS)}${suffix}` : _match);
31102
32050
  const rewriteAbsoluteToSrc = (_match, prefix, absPath, _ext, suffix) => {
31103
32051
  if (absPath.startsWith(projectRoot)) {
31104
- const rel2 = relative21(projectRoot, absPath).replace(/\\/g, "/");
32052
+ const rel2 = relative22(projectRoot, absPath).replace(/\\/g, "/");
31105
32053
  return `${prefix}${srcUrl(rel2, projectRoot)}${suffix}`;
31106
32054
  }
31107
- const rel = relative21(projectRoot, absPath).replace(/\\/g, "/");
32055
+ const rel = relative22(projectRoot, absPath).replace(/\\/g, "/");
31108
32056
  return `${prefix}${srcUrl(rel, projectRoot)}${suffix}`;
31109
32057
  };
31110
32058
  result = result.replace(/((?:from|import)\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["'])/g, rewriteAbsoluteToSrc);
31111
32059
  result = result.replace(/(import\s*\(\s*["'])(\/[^"']+\.(tsx?|jsx?|ts))(["']\s*\))/g, rewriteAbsoluteToSrc);
31112
32060
  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);
32061
+ const absPath = resolve50(fileDir, relPath);
32062
+ const rel = relative22(projectRoot, absPath);
31115
32063
  return `new URL('${srcUrl(rel, projectRoot)}', import.meta.url)`;
31116
32064
  });
31117
32065
  result = result.replace(/import\.meta\.resolve\(\s*["'](\.\.?\/[^"']+)["']\s*\)/g, (_match, relPath) => {
31118
- const absPath = resolve49(fileDir, relPath);
31119
- const rel = relative21(projectRoot, absPath);
32066
+ const absPath = resolve50(fileDir, relPath);
32067
+ const rel = relative22(projectRoot, absPath);
31120
32068
  return `'${srcUrl(rel, projectRoot)}'`;
31121
32069
  });
31122
32070
  return result;
@@ -31172,7 +32120,7 @@ ${code2}`;
31172
32120
  transpiled = `var $RefreshReg$ = window.$RefreshReg$ || function(){};
31173
32121
  ` + `var $RefreshSig$ = window.$RefreshSig$ || function(){ return function(t){ return t; }; };
31174
32122
  ${transpiled}`;
31175
- const relPath = relative21(projectRoot, filePath).replace(/\\/g, "/");
32123
+ const relPath = relative22(projectRoot, filePath).replace(/\\/g, "/");
31176
32124
  transpiled = transpiled.replace(/\binput\.tsx:/g, `${relPath}:`);
31177
32125
  transpiled += buildIslandMetadataExports(raw);
31178
32126
  return rewriteImports(transpiled, filePath, projectRoot, rewriter);
@@ -31333,11 +32281,11 @@ ${code2}`;
31333
32281
  if (compiled.css?.code) {
31334
32282
  const cssPath = `${filePath}.css`;
31335
32283
  svelteExternalCss.set(cssPath, compiled.css.code);
31336
- const cssUrl = srcUrl(relative21(projectRoot, cssPath), projectRoot);
32284
+ const cssUrl = srcUrl(relative22(projectRoot, cssPath), projectRoot);
31337
32285
  code2 = `import "${cssUrl}";
31338
32286
  ${code2}`;
31339
32287
  }
31340
- const moduleUrl = `${SRC_PREFIX}${relative21(projectRoot, filePath).replace(/\\/g, "/")}`;
32288
+ const moduleUrl = `${SRC_PREFIX}${relative22(projectRoot, filePath).replace(/\\/g, "/")}`;
31341
32289
  code2 = code2.replace(/if\s*\(import\.meta\.hot\)\s*\{/, `if (typeof window !== "undefined") {
31342
32290
  ` + ` if (!window.__SVELTE_HMR_ACCEPT__) window.__SVELTE_HMR_ACCEPT__ = {};
31343
32291
  ` + ` var __hmr_accept = function(cb) { window.__SVELTE_HMR_ACCEPT__[${JSON.stringify(moduleUrl)}] = cb; };`);
@@ -31437,8 +32385,8 @@ ${code2}`;
31437
32385
  code2 = injectVueHmr(code2, filePath, projectRoot, vueDir);
31438
32386
  return rewriteImports(code2, filePath, projectRoot, rewriter);
31439
32387
  }, injectVueHmr = (code2, filePath, projectRoot, vueDir) => {
31440
- const hmrBase = vueDir ? resolve49(vueDir) : projectRoot;
31441
- const hmrId = relative21(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
32388
+ const hmrBase = vueDir ? resolve50(vueDir) : projectRoot;
32389
+ const hmrId = relative22(hmrBase, filePath).replace(/\\/g, "/").replace(/\.vue$/, "");
31442
32390
  let result = code2.replace(/export\s+default\s+/, "var __hmr_comp__ = ");
31443
32391
  result += [
31444
32392
  "",
@@ -31451,14 +32399,14 @@ ${code2}`;
31451
32399
  ].join(`
31452
32400
  `);
31453
32401
  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;
32402
+ }, resolveSvelteModulePath = (path2) => {
32403
+ if (existsSync46(path2))
32404
+ return path2;
32405
+ if (existsSync46(`${path2}.ts`))
32406
+ return `${path2}.ts`;
32407
+ if (existsSync46(`${path2}.js`))
32408
+ return `${path2}.js`;
32409
+ return path2;
31462
32410
  }, jsResponse = (body) => {
31463
32411
  const etag = `"${Bun.hash(body).toString(BASE_36_RADIX)}"`;
31464
32412
  return new Response(body, {
@@ -31598,7 +32546,7 @@ export default {};
31598
32546
  const escaped = virtualCss.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$/g, "\\$");
31599
32547
  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
32548
  }, resolveSourcePath2 = (relPath, projectRoot) => {
31601
- const filePath = resolve49(projectRoot, relPath);
32549
+ const filePath = resolve50(projectRoot, relPath);
31602
32550
  const ext = extname15(filePath);
31603
32551
  if (ext === ".svelte")
31604
32552
  return { ext, filePath: resolveSvelteModulePath(filePath) };
@@ -31616,10 +32564,10 @@ export default {};
31616
32564
  return jsResponse(handleCssRequest(filePath));
31617
32565
  if (ext === ".json") {
31618
32566
  try {
31619
- const { readFile: readFile11, stat: stat4 } = await import("fs/promises");
32567
+ const { readFile: readFile12, stat: stat5 } = await import("fs/promises");
31620
32568
  const fileExists2 = async (p2) => {
31621
32569
  try {
31622
- await stat4(p2);
32570
+ await stat5(p2);
31623
32571
  return true;
31624
32572
  } catch {
31625
32573
  return false;
@@ -31635,14 +32583,14 @@ export default {};
31635
32583
  const absoluteCandidate = `/${tail.replace(/^\/+/, "")}`;
31636
32584
  const candidates = [
31637
32585
  absoluteCandidate,
31638
- resolve49(projectRoot, tail)
32586
+ resolve50(projectRoot, tail)
31639
32587
  ];
31640
32588
  try {
31641
32589
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_loadConfig(), exports_loadConfig));
31642
32590
  const cfg = await loadConfig2();
31643
- const angularDir = cfg.angularDirectory && resolve49(projectRoot, cfg.angularDirectory);
32591
+ const angularDir = cfg.angularDirectory && resolve50(projectRoot, cfg.angularDirectory);
31644
32592
  if (angularDir)
31645
- candidates.push(resolve49(angularDir, tail));
32593
+ candidates.push(resolve50(angularDir, tail));
31646
32594
  } catch {}
31647
32595
  for (const candidate of candidates) {
31648
32596
  if (await fileExists2(candidate)) {
@@ -31652,9 +32600,9 @@ export default {};
31652
32600
  }
31653
32601
  }
31654
32602
  }
31655
- const text2 = await readFile11(sourcePath, "utf-8");
31656
- JSON.parse(text2);
31657
- return jsResponse(`export default ${text2};`);
32603
+ const text3 = await readFile12(sourcePath, "utf-8");
32604
+ JSON.parse(text3);
32605
+ return jsResponse(`export default ${text3};`);
31658
32606
  } catch (err) {
31659
32607
  return new Response(`console.error('[ModuleServer] JSON load error in ${filePath}:', ${JSON.stringify(String(err))});`, {
31660
32608
  headers: { "Content-Type": "application/javascript" },
@@ -31672,8 +32620,8 @@ export default {};
31672
32620
  return transformAndCacheVue(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
31673
32621
  if (!TRANSPILABLE.has(ext))
31674
32622
  return;
31675
- const stat3 = statSync7(filePath);
31676
- const resolvedVueDir = vueDir ? resolve49(vueDir) : undefined;
32623
+ const stat4 = statSync7(filePath);
32624
+ const resolvedVueDir = vueDir ? resolve50(vueDir) : undefined;
31677
32625
  let content = REACT_EXTENSIONS.has(ext) ? transformReactFile(filePath, projectRoot, rewriter) : transformPlainFile(filePath, projectRoot, rewriter, resolvedVueDir);
31678
32626
  const isAngularGeneratedJs = ext === ".js" && filePath.replace(/\\/g, "/").includes("/.absolutejs/generated/angular/");
31679
32627
  if (isAngularGeneratedJs) {
@@ -31692,7 +32640,7 @@ export default {};
31692
32640
  }
31693
32641
  }
31694
32642
  }
31695
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32643
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31696
32644
  return jsResponse(content);
31697
32645
  }, cachedAngularUserRoot, getAngularUserRoot = async (_projectRoot) => {
31698
32646
  if (cachedAngularUserRoot !== undefined)
@@ -31700,14 +32648,14 @@ export default {};
31700
32648
  cachedAngularUserRoot = configuredAngularUserRoot ?? null;
31701
32649
  return cachedAngularUserRoot;
31702
32650
  }, configuredAngularUserRoot, transformAndCacheSvelte = async (filePath, projectRoot, rewriter, stylePreprocessors) => {
31703
- const stat3 = statSync7(filePath);
32651
+ const stat4 = statSync7(filePath);
31704
32652
  const content = await transformSvelteFile(filePath, projectRoot, rewriter, stylePreprocessors);
31705
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32653
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31706
32654
  return jsResponse(content);
31707
32655
  }, transformAndCacheVue = async (filePath, projectRoot, rewriter, vueDir, stylePreprocessors) => {
31708
- const stat3 = statSync7(filePath);
32656
+ const stat4 = statSync7(filePath);
31709
32657
  const content = await transformVueFile(filePath, projectRoot, rewriter, vueDir, stylePreprocessors);
31710
- setTransformed(filePath, content, stat3.mtimeMs, extractImportedFiles(content, projectRoot));
32658
+ setTransformed(filePath, content, stat4.mtimeMs, extractImportedFiles(content, projectRoot));
31711
32659
  return jsResponse(content);
31712
32660
  }, transformErrorResponse = (err) => {
31713
32661
  const errMsg = err instanceof Error ? err.message : String(err);
@@ -31732,7 +32680,7 @@ export default {};
31732
32680
  const relPath = pathname.slice(SRC_PREFIX.length);
31733
32681
  if (relPath === "bun:wrap" || relPath.startsWith("bun:wrap?"))
31734
32682
  return handleBunWrapRequest();
31735
- const virtualCssResponse = handleVirtualSvelteCss(resolve49(projectRoot, relPath));
32683
+ const virtualCssResponse = handleVirtualSvelteCss(resolve50(projectRoot, relPath));
31736
32684
  if (virtualCssResponse)
31737
32685
  return virtualCssResponse;
31738
32686
  const { filePath, ext } = resolveSourcePath2(relPath, projectRoot);
@@ -31748,11 +32696,11 @@ export default {};
31748
32696
  SRC_IMPORT_RE.lastIndex = 0;
31749
32697
  while ((match = SRC_IMPORT_RE.exec(content)) !== null) {
31750
32698
  if (match[1])
31751
- files.push(resolve49(projectRoot, match[1]));
32699
+ files.push(resolve50(projectRoot, match[1]));
31752
32700
  }
31753
32701
  return files;
31754
32702
  }, invalidateModule = (filePath) => {
31755
- const resolved = resolve49(filePath);
32703
+ const resolved = resolve50(filePath);
31756
32704
  invalidate(filePath);
31757
32705
  if (resolved !== filePath)
31758
32706
  invalidate(resolved);
@@ -31815,7 +32763,7 @@ export default {};
31815
32763
  return false;
31816
32764
  }
31817
32765
  const { patchManifestIndexes: patchManifestIndexes2 } = await Promise.resolve().then(() => (init_prepare(), exports_prepare));
31818
- patchManifestIndexes2(cached.manifest, resolve49(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
32766
+ patchManifestIndexes2(cached.manifest, resolve50(state.resolvedPaths.buildDir, "_src_indexes"), SRC_PREFIX);
31819
32767
  logPageBuild(entry.source, entry.framework, Math.round(durationMs));
31820
32768
  logStartupTimingBlock("AbsoluteJS on-demand page build", [
31821
32769
  { durationMs, label: entry.name }
@@ -31947,7 +32895,7 @@ __export(exports_rewriteImports, {
31947
32895
  rewriteVendorDirectories: () => rewriteVendorDirectories2
31948
32896
  });
31949
32897
  var rewriteImports2 = async (outputPaths, vendorPaths) => {
31950
- const jsFiles = outputPaths.filter((path) => path.endsWith(".js"));
32898
+ const jsFiles = outputPaths.filter((path2) => path2.endsWith(".js"));
31951
32899
  if (jsFiles.length === 0)
31952
32900
  return;
31953
32901
  if (Object.keys(vendorPaths).length === 0)
@@ -31981,13 +32929,13 @@ var init_rewriteImports = __esm(() => {
31981
32929
  });
31982
32930
 
31983
32931
  // src/core/pageResponseCache.ts
31984
- import { createHash as createHash10 } from "crypto";
32932
+ import { createHash as createHash11 } from "crypto";
31985
32933
  var STREAMING_PAGE_HEADER = "x-absolute-stream", HTML_CONTENT_TYPE = "text/html", streamingPageHeaders = (extra) => {
31986
32934
  const headers = new Headers(extra);
31987
32935
  headers.set("content-type", HTML_CONTENT_TYPE);
31988
32936
  headers.set(STREAMING_PAGE_HEADER, "1");
31989
32937
  return headers;
31990
- }, computeEtag = (html) => `W/"${createHash10("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
32938
+ }, computeEtag = (html) => `W/"${createHash11("sha1").update(html).digest("base64url")}"`, withPageCacheHeaders = async (response, request, options) => {
31991
32939
  const contentType = response.headers.get("content-type") ?? "";
31992
32940
  if (!contentType.includes(HTML_CONTENT_TYPE))
31993
32941
  return response;
@@ -32055,7 +33003,7 @@ var init_routeAssets = __esm(() => {
32055
33003
  });
32056
33004
 
32057
33005
  // src/ember/pageHandler.ts
32058
- import { pathToFileURL as pathToFileURL4 } from "url";
33006
+ import { pathToFileURL as pathToFileURL5 } from "url";
32059
33007
  var resolveRequestPathname2 = (request) => {
32060
33008
  if (!request)
32061
33009
  return;
@@ -32077,7 +33025,7 @@ var resolveRequestPathname2 = (request) => {
32077
33025
  }, emberCacheBuster = 0, buildRuntimeModuleSpecifier = (modulePath) => {
32078
33026
  if (emberCacheBuster === 0)
32079
33027
  return modulePath;
32080
- const moduleUrl = new URL(pathToFileURL4(modulePath).href);
33028
+ const moduleUrl = new URL(pathToFileURL5(modulePath).href);
32081
33029
  moduleUrl.searchParams.set("t", String(emberCacheBuster));
32082
33030
  return moduleUrl.href;
32083
33031
  }, invalidateEmberSsrCache = () => {
@@ -32178,11 +33126,11 @@ var exports_simpleHTMLHMR = {};
32178
33126
  __export(exports_simpleHTMLHMR, {
32179
33127
  handleHTMLUpdate: () => handleHTMLUpdate
32180
33128
  });
32181
- import { resolve as resolve50 } from "path";
33129
+ import { resolve as resolve51 } from "path";
32182
33130
  var handleHTMLUpdate = async (htmlFilePath) => {
32183
33131
  let htmlContent;
32184
33132
  try {
32185
- const resolvedPath = resolve50(htmlFilePath);
33133
+ const resolvedPath = resolve51(htmlFilePath);
32186
33134
  const file5 = Bun.file(resolvedPath);
32187
33135
  if (!await file5.exists()) {
32188
33136
  return null;
@@ -32208,11 +33156,11 @@ var exports_simpleHTMXHMR = {};
32208
33156
  __export(exports_simpleHTMXHMR, {
32209
33157
  handleHTMXUpdate: () => handleHTMXUpdate
32210
33158
  });
32211
- import { resolve as resolve51 } from "path";
33159
+ import { resolve as resolve52 } from "path";
32212
33160
  var handleHTMXUpdate = async (htmxFilePath) => {
32213
33161
  let htmlContent;
32214
33162
  try {
32215
- const resolvedPath = resolve51(htmxFilePath);
33163
+ const resolvedPath = resolve52(htmxFilePath);
32216
33164
  const file5 = Bun.file(resolvedPath);
32217
33165
  if (!await file5.exists()) {
32218
33166
  return null;
@@ -32243,12 +33191,12 @@ __export(exports_rebuildTrigger, {
32243
33191
  import { existsSync as existsSync47, readdirSync as readdirSync13, rmSync as rmSync4 } from "fs";
32244
33192
  import {
32245
33193
  basename as basename21,
32246
- dirname as dirname35,
32247
- isAbsolute as isAbsolute8,
33194
+ dirname as dirname36,
33195
+ isAbsolute as isAbsolute9,
32248
33196
  join as join60,
32249
- relative as relative22,
33197
+ relative as relative23,
32250
33198
  resolve as resolvePath4,
32251
- sep as sep4
33199
+ sep as sep5
32252
33200
  } from "path";
32253
33201
  var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSsrCssCaches = () => {
32254
33202
  clearSpaRouteCssCaches();
@@ -32607,14 +33555,14 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32607
33555
  const relFromDir = normalizedSource.slice(normalizedDir.length + 1);
32608
33556
  const { buildDir } = state.resolvedPaths;
32609
33557
  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 });
33558
+ const { mkdir: mkdir16, copyFile, readFile: readFile12 } = await import("fs/promises");
33559
+ await mkdir16(dirname36(destPath), { recursive: true });
32612
33560
  await copyFile(absSource, destPath);
32613
- const bytes = await readFile11(destPath);
33561
+ const bytes = await readFile12(destPath);
32614
33562
  const webPath = urlPrefix ? `/${urlPrefix}/${relFromDir}` : `/${relFromDir}`;
32615
33563
  state.assetStore.set(webPath, new Uint8Array(bytes));
32616
33564
  state.fileHashes.set(absSource, currentHash);
32617
- logHmrUpdate(relative22(process.cwd(), filePath));
33565
+ logHmrUpdate(relative23(process.cwd(), filePath));
32618
33566
  broadcastToClients(state, {
32619
33567
  data: {
32620
33568
  framework: urlPrefix || "public",
@@ -32634,7 +33582,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32634
33582
  return;
32635
33583
  if (framework === "unknown") {
32636
33584
  invalidate(resolvePath4(filePath));
32637
- const relPath = relative22(process.cwd(), filePath);
33585
+ const relPath = relative23(process.cwd(), filePath);
32638
33586
  logHmrUpdate(relPath);
32639
33587
  const { angularDir } = state.resolvedPaths;
32640
33588
  let hasAngularDependent = false;
@@ -32790,7 +33738,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
32790
33738
  const keepStemsByDir = new Map;
32791
33739
  const prefixByDir = new Map;
32792
33740
  for (const artifact of freshOutputs) {
32793
- const dir = dirname35(artifact.path);
33741
+ const dir = dirname36(artifact.path);
32794
33742
  const name = basename21(artifact.path);
32795
33743
  const [prefix] = name.split(".");
32796
33744
  if (!prefix)
@@ -33156,8 +34104,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33156
34104
  };
33157
34105
  return ({ immediate = false } = {}) => {
33158
34106
  if (!ctx.debouncedPromise) {
33159
- ctx.debouncedPromise = new Promise((resolve52) => {
33160
- ctx.debouncedResolve = resolve52;
34107
+ ctx.debouncedPromise = new Promise((resolve53) => {
34108
+ ctx.debouncedResolve = resolve53;
33161
34109
  });
33162
34110
  }
33163
34111
  const scheduled = ctx.debouncedPromise;
@@ -33183,7 +34131,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33183
34131
  const angularDirAbs = resolvePath4(angularDir);
33184
34132
  const filesUnderAngular = Array.from(editedFiles).filter((file5) => {
33185
34133
  const abs = resolvePath4(file5);
33186
- return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep4);
34134
+ return abs === angularDirAbs || abs.startsWith(angularDirAbs + sep5);
33187
34135
  });
33188
34136
  if (filesUnderAngular.length === 0)
33189
34137
  return;
@@ -33226,7 +34174,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33226
34174
  try {
33227
34175
  const { invalidateModule: invalidateModule2 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
33228
34176
  for (const tsFile of tsFilesToRefresh) {
33229
- const rel = relative22(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
34177
+ const rel = relative23(angularDirAbs, tsFile).replace(/\\/g, "/").replace(/\.[tj]sx?$/, ".js");
33230
34178
  const compiledFile = resolvePath4(compiledRoot, rel);
33231
34179
  invalidateModule2(compiledFile);
33232
34180
  }
@@ -33381,7 +34329,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33381
34329
  }, getModuleUrl = async (pageFile) => {
33382
34330
  const { invalidateModule: invalidateModule2, warmCache: warmCache2, SRC_URL_PREFIX: SRC_URL_PREFIX3 } = await Promise.resolve().then(() => (init_moduleServer(), exports_moduleServer));
33383
34331
  invalidateModule2(pageFile);
33384
- const rel = relative22(process.cwd(), pageFile).replace(/\\/g, "/");
34332
+ const rel = relative23(process.cwd(), pageFile).replace(/\\/g, "/");
33385
34333
  const url = `${SRC_URL_PREFIX3}${rel}`;
33386
34334
  await warmCache2(url);
33387
34335
  return url;
@@ -33409,7 +34357,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33409
34357
  const pageModuleUrl = await getReactModuleUrl(broadcastTarget);
33410
34358
  if (pageModuleUrl) {
33411
34359
  const serverDuration = Date.now() - startTime;
33412
- state.lastHmrPath = relative22(process.cwd(), primaryFile).replace(/\\/g, "/");
34360
+ state.lastHmrPath = relative23(process.cwd(), primaryFile).replace(/\\/g, "/");
33413
34361
  state.lastHmrFramework = "react";
33414
34362
  broadcastToClients(state, {
33415
34363
  data: {
@@ -33702,8 +34650,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33702
34650
  };
33703
34651
  return () => {
33704
34652
  if (!ctx.debouncedPromise) {
33705
- ctx.debouncedPromise = new Promise((resolve52) => {
33706
- ctx.debouncedResolve = resolve52;
34653
+ ctx.debouncedPromise = new Promise((resolve53) => {
34654
+ ctx.debouncedResolve = resolve53;
33707
34655
  });
33708
34656
  }
33709
34657
  if (ctx.debounceTimer)
@@ -33914,7 +34862,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33914
34862
  if (vueSpaRoutesBySource.size > 0) {
33915
34863
  const spaManifestEntries = await writeSpaSideManifests(vueSpaRoutesBySource, (pascalName) => {
33916
34864
  const fromManifest = state.manifest[pascalName];
33917
- return typeof fromManifest === "string" && isAbsolute8(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
34865
+ return typeof fromManifest === "string" && isAbsolute9(fromManifest) && fromManifest.endsWith(".js") ? fromManifest : undefined;
33918
34866
  });
33919
34867
  Object.assign(state.manifest, spaManifestEntries);
33920
34868
  }
@@ -33984,8 +34932,8 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
33984
34932
  };
33985
34933
  return () => {
33986
34934
  if (!ctx.debouncedPromise) {
33987
- ctx.debouncedPromise = new Promise((resolve52) => {
33988
- ctx.debouncedResolve = resolve52;
34935
+ ctx.debouncedPromise = new Promise((resolve53) => {
34936
+ ctx.debouncedResolve = resolve53;
33989
34937
  });
33990
34938
  }
33991
34939
  if (ctx.debounceTimer)
@@ -34038,7 +34986,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34038
34986
  const duration = Date.now() - startTime;
34039
34987
  const [primary] = emberFiles;
34040
34988
  if (primary) {
34041
- state.lastHmrPath = relative22(process.cwd(), primary).replace(/\\/g, "/");
34989
+ state.lastHmrPath = relative23(process.cwd(), primary).replace(/\\/g, "/");
34042
34990
  state.lastHmrFramework = "ember";
34043
34991
  logHmrUpdate(primary, "ember", duration);
34044
34992
  }
@@ -34135,7 +35083,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34135
35083
  if (!buildReference?.source) {
34136
35084
  return;
34137
35085
  }
34138
- const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname35(buildInfo.resolvedRegistryPath), buildReference.source);
35086
+ const sourcePath = buildReference.source.startsWith("file://") ? new URL(buildReference.source).pathname : resolvePath4(dirname36(buildInfo.resolvedRegistryPath), buildReference.source);
34139
35087
  islandFiles.add(resolvePath4(sourcePath));
34140
35088
  }, resolveIslandSourceFiles = async (config) => {
34141
35089
  const registryPath = config.islands?.registry;
@@ -34307,7 +35255,7 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34307
35255
  const baseName = fileName.replace(/\.vue$/, "");
34308
35256
  const pascalName = toPascal(baseName);
34309
35257
  const vueRoot = config.vueDirectory;
34310
- const hmrId = vueRoot ? relative22(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
35258
+ const hmrId = vueRoot ? relative23(vueRoot, vuePagePath).replace(/\\/g, "/").replace(/\.vue$/, "") : baseName;
34311
35259
  const cssKey = `${pascalName}CSS`;
34312
35260
  const cssUrl = manifest[cssKey] || null;
34313
35261
  const { vueHmrMetadata: vueHmrMetadata2 } = await Promise.resolve().then(() => (init_compileVue(), exports_compileVue));
@@ -34521,10 +35469,10 @@ var moduleServerPromise, getModuleServer = () => moduleServerPromise, clearDevSs
34521
35469
  if (sourceVersion !== undefined) {
34522
35470
  moduleVersions[update.sourceFile] = sourceVersion;
34523
35471
  }
34524
- Object.values(update.modulePaths).forEach((path) => {
34525
- const pathVersion = moduleVersionsStore.get(path);
35472
+ Object.values(update.modulePaths).forEach((path2) => {
35473
+ const pathVersion = moduleVersionsStore.get(path2);
34526
35474
  if (pathVersion !== undefined) {
34527
- moduleVersions[path] = pathVersion;
35475
+ moduleVersions[path2] = pathVersion;
34528
35476
  }
34529
35477
  });
34530
35478
  }, handleModuleUpdates = (state, allModuleUpdates, manifest) => {
@@ -34986,7 +35934,7 @@ var toSafeFileName6 = (specifier) => {
34986
35934
  } catch {
34987
35935
  return false;
34988
35936
  }
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) => {
35937
+ }, 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
35938
  const dep = [];
34991
35939
  const framework = [];
34992
35940
  try {
@@ -35030,22 +35978,22 @@ var toSafeFileName6 = (specifier) => {
35030
35978
  };
35031
35979
  }, collectBareImportsFromFile = async (entryPath, transpiler7, maxDepth = 8) => {
35032
35980
  const { readFileSync: readFileSync41 } = await import("fs");
35033
- const { dirname: dirname36 } = await import("path");
35981
+ const { dirname: dirname37 } = await import("path");
35034
35982
  const seenFiles = new Set;
35035
35983
  const bareOut = new Set;
35036
35984
  const queue = [
35037
35985
  { depth: 0, path: entryPath }
35038
35986
  ];
35039
35987
  while (queue.length > 0) {
35040
- const { path, depth } = queue.shift();
35041
- if (seenFiles.has(path))
35988
+ const { path: path2, depth } = queue.shift();
35989
+ if (seenFiles.has(path2))
35042
35990
  continue;
35043
- seenFiles.add(path);
35991
+ seenFiles.add(path2);
35044
35992
  if (depth > maxDepth)
35045
35993
  continue;
35046
35994
  let content;
35047
35995
  try {
35048
- content = readFileSync41(path, "utf-8");
35996
+ content = readFileSync41(path2, "utf-8");
35049
35997
  } catch {
35050
35998
  continue;
35051
35999
  }
@@ -35055,7 +36003,7 @@ var toSafeFileName6 = (specifier) => {
35055
36003
  } catch {
35056
36004
  continue;
35057
36005
  }
35058
- const fromDir = dirname36(path);
36006
+ const fromDir = dirname37(path2);
35059
36007
  for (const imp of imports) {
35060
36008
  const child = imp.path;
35061
36009
  if (child.startsWith(".") || child.startsWith("/")) {
@@ -35075,7 +36023,7 @@ var toSafeFileName6 = (specifier) => {
35075
36023
  }
35076
36024
  return Array.from(bareOut);
35077
36025
  }, MAX_DISCOVERY_FILES = 2000, collectTransitiveImports = async (specs, alreadyVendored, alreadyScanned) => {
35078
- const { dirname: dirname36 } = await import("path");
36026
+ const { dirname: dirname37 } = await import("path");
35079
36027
  const transpiler7 = new Bun.Transpiler({ loader: "js" });
35080
36028
  const newSpecs = new Set;
35081
36029
  const queue = [...specs].map((spec) => ({ from: process.cwd(), spec }));
@@ -35096,7 +36044,7 @@ var toSafeFileName6 = (specifier) => {
35096
36044
  }
35097
36045
  visited += 1;
35098
36046
  const bareImports = await collectBareImportsFromFile(resolved, transpiler7);
35099
- const importerDirectory = dirname36(resolved);
36047
+ const importerDirectory = dirname37(resolved);
35100
36048
  for (const child of bareImports) {
35101
36049
  if (!isBareSpecifier3(child))
35102
36050
  continue;
@@ -35159,11 +36107,11 @@ var toSafeFileName6 = (specifier) => {
35159
36107
  const output = lastResult.outputs[0];
35160
36108
  if (!output)
35161
36109
  return lastResult;
35162
- const text2 = await output.text();
36110
+ const text3 = await output.text();
35163
36111
  REQUIRE_CALL_RE.lastIndex = 0;
35164
36112
  const requiredSpecs = new Set;
35165
36113
  let match;
35166
- while ((match = REQUIRE_CALL_RE.exec(text2)) !== null) {
36114
+ while ((match = REQUIRE_CALL_RE.exec(text3)) !== null) {
35167
36115
  const requiredSpec = match[1];
35168
36116
  if (requiredSpec && externalsSet.has(requiredSpec)) {
35169
36117
  requiredSpecs.add(requiredSpec);
@@ -35310,7 +36258,7 @@ __export(exports_vendorCache, {
35310
36258
  saveVendorCache: () => saveVendorCache,
35311
36259
  vendorCacheEnabled: () => vendorCacheEnabled
35312
36260
  });
35313
- import { createHash as createHash11 } from "crypto";
36261
+ import { createHash as createHash12 } from "crypto";
35314
36262
  import {
35315
36263
  copyFileSync as copyFileSync4,
35316
36264
  existsSync as existsSync48,
@@ -35318,10 +36266,10 @@ import {
35318
36266
  readdirSync as readdirSync14,
35319
36267
  readFileSync as readFileSync41
35320
36268
  } 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";
36269
+ import { mkdir as mkdir16, readFile as readFile12, rename as rename7, rm as rm16, writeFile as writeFile13 } from "fs/promises";
36270
+ import { basename as basename22, join as join62, resolve as resolve53 } from "path";
35323
36271
  var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeVendorCacheKey = (inputs) => {
35324
- const hash = createHash11("sha256");
36272
+ const hash = createHash12("sha256");
35325
36273
  hash.update(String(CACHE_FORMAT_VERSION3));
35326
36274
  hash.update("\x00");
35327
36275
  hash.update(inputs.lockfileHash);
@@ -35339,19 +36287,19 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35339
36287
  }
35340
36288
  for (const dir of inputs.vendorDirs) {
35341
36289
  hash.update("\x00v");
35342
- hash.update(basename22(resolve52(dir, "..")));
36290
+ hash.update(basename22(resolve53(dir, "..")));
35343
36291
  }
35344
36292
  return hash.digest("hex").slice(0, KEY_LENGTH);
35345
36293
  }, readLockfileHash = (projectRoot = process.cwd()) => {
35346
- const hash = createHash11("sha256");
36294
+ const hash = createHash12("sha256");
35347
36295
  let found = false;
35348
36296
  for (const name of LOCKFILES) {
35349
- const path = join62(projectRoot, name);
35350
- if (!existsSync48(path))
36297
+ const path2 = join62(projectRoot, name);
36298
+ if (!existsSync48(path2))
35351
36299
  continue;
35352
36300
  found = true;
35353
36301
  hash.update(name);
35354
- hash.update(readFileSync41(path));
36302
+ hash.update(readFileSync41(path2));
35355
36303
  }
35356
36304
  return found ? hash.digest("hex") : null;
35357
36305
  }, vendorCacheEnabled = () => process.env.ABSOLUTE_DEV_VENDOR_CACHE !== "0", copyTree = (fromDir, toDir) => {
@@ -35378,13 +36326,13 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35378
36326
  continue;
35379
36327
  copyTree(dir, join62(stagingDir, slotName(index, dir)));
35380
36328
  }
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()) => {
36329
+ }, 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
36330
  const cacheDir2 = cacheDirFor(key, projectRoot);
35383
36331
  const payloadPath = join62(cacheDir2, "payload.json");
35384
36332
  if (!existsSync48(payloadPath))
35385
36333
  return null;
35386
36334
  try {
35387
- const payload = JSON.parse(await readFile11(payloadPath, "utf8"));
36335
+ const payload = JSON.parse(await readFile12(payloadPath, "utf8"));
35388
36336
  if (!isVendorCachePayload(payload))
35389
36337
  return null;
35390
36338
  copySlotsInto(cacheDir2, vendorDirs);
@@ -35399,7 +36347,7 @@ var CACHE_ROOT2, CACHE_FORMAT_VERSION3 = 1, KEY_LENGTH = 32, LOCKFILES, computeV
35399
36347
  const stagingDir = `${cacheDir2}.${process.pid}.tmp`;
35400
36348
  try {
35401
36349
  await rm16(stagingDir, { force: true, recursive: true });
35402
- await mkdir15(stagingDir, { recursive: true });
36350
+ await mkdir16(stagingDir, { recursive: true });
35403
36351
  copySlotsFrom(stagingDir, vendorDirs);
35404
36352
  await writeFile13(join62(stagingDir, "payload.json"), JSON.stringify(payload));
35405
36353
  await rm16(cacheDir2, { force: true, recursive: true });
@@ -35430,8 +36378,8 @@ __export(exports_devBuild, {
35430
36378
  });
35431
36379
  import { readdir as readdir6 } from "fs/promises";
35432
36380
  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) => {
36381
+ import { resolve as resolve54 } from "path";
36382
+ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve54(import.meta.dir, "../dev/client"), collectDepVendorSourceDirs = (config) => {
35435
36383
  const configuredDirs = [
35436
36384
  ...collectConfigVendorSourceDirs(config),
35437
36385
  devClientVendorSourceDir()
@@ -35454,7 +36402,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35454
36402
  return Object.keys(config).length > 0 ? config : null;
35455
36403
  }, reloadConfig = async () => {
35456
36404
  try {
35457
- const configPath2 = resolve53(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
36405
+ const configPath2 = resolve54(process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
35458
36406
  const source = await Bun.file(configPath2).text();
35459
36407
  return parseDirectoryConfig(source);
35460
36408
  } catch {
@@ -35506,7 +36454,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35506
36454
  setEmberVendorPaths(computeEmberVendorPaths());
35507
36455
  }
35508
36456
  const newWatchPaths = getWatchPaths(state.config, state.resolvedPaths);
35509
- const addedPaths = newWatchPaths.filter((path) => !oldWatchPaths.has(path));
36457
+ const addedPaths = newWatchPaths.filter((path2) => !oldWatchPaths.has(path2));
35510
36458
  if (addedPaths.length > 0) {
35511
36459
  buildInitialDependencyGraph(state.dependencyGraph, addedPaths);
35512
36460
  addFileWatchers(state, addedPaths, (filePath) => {
@@ -35569,7 +36517,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35569
36517
  });
35570
36518
  }
35571
36519
  }, handleCachedReload = async () => {
35572
- const serverMtime = statSync8(resolve53(Bun.main)).mtimeMs;
36520
+ const serverMtime = statSync8(resolve54(Bun.main)).mtimeMs;
35573
36521
  const lastMtime = globalThis.__hmrServerMtime;
35574
36522
  globalThis.__hmrServerMtime = serverMtime;
35575
36523
  const cached = globalThis.__hmrDevResult;
@@ -35601,8 +36549,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35601
36549
  return;
35602
36550
  await detectConfigChanges(cached);
35603
36551
  await rebuildManifest(cached);
35604
- }, tryReadPackageVersion = async (path) => {
35605
- const pkg = await Bun.file(path).json().catch(() => null);
36552
+ }, tryReadPackageVersion = async (path2) => {
36553
+ const pkg = await Bun.file(path2).json().catch(() => null);
35606
36554
  if (!pkg || pkg.name !== "@absolutejs/absolute") {
35607
36555
  return false;
35608
36556
  }
@@ -35610,8 +36558,8 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35610
36558
  return true;
35611
36559
  }, resolveAbsoluteVersion2 = async () => {
35612
36560
  const candidates = [
35613
- resolve53(import.meta.dir, "..", "..", "package.json"),
35614
- resolve53(import.meta.dir, "..", "package.json")
36561
+ resolve54(import.meta.dir, "..", "..", "package.json"),
36562
+ resolve54(import.meta.dir, "..", "package.json")
35615
36563
  ];
35616
36564
  const [candidate, ...remaining] = candidates;
35617
36565
  if (!candidate) {
@@ -35637,7 +36585,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35637
36585
  const entries = await readdir6(vendorDir).catch(() => emptyStringArray);
35638
36586
  await Promise.all(entries.filter((entry) => entry.endsWith(".js")).map(async (entry) => {
35639
36587
  const webPath = `/${framework}/vendor/${entry}`;
35640
- const bytes = await Bun.file(resolve53(vendorDir, entry)).bytes();
36588
+ const bytes = await Bun.file(resolve54(vendorDir, entry)).bytes();
35641
36589
  assetStore.set(webPath, bytes);
35642
36590
  }));
35643
36591
  }, devBuild = async (config) => {
@@ -35823,11 +36771,11 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35823
36771
  }
35824
36772
  stepStartedAt = performance.now();
35825
36773
  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");
36774
+ const reactVendorDir = resolve54(state.resolvedPaths.buildDir, "react", "vendor");
36775
+ const angularVendorDir = resolve54(state.resolvedPaths.buildDir, "angular", "vendor");
36776
+ const svelteVendorDir = resolve54(state.resolvedPaths.buildDir, "svelte", "vendor");
36777
+ const vueVendorDir = resolve54(state.resolvedPaths.buildDir, "vue", "vendor");
36778
+ const depVendorDir = resolve54(state.resolvedPaths.buildDir, "vendor");
35831
36779
  const { buildDepVendor: buildDepVendor2 } = await Promise.resolve().then(() => (init_buildDepVendor(), exports_buildDepVendor));
35832
36780
  const activeVendorDirs = [
35833
36781
  config.reactDirectory ? reactVendorDir : null,
@@ -35950,7 +36898,7 @@ var FRAMEWORK_DIR_KEYS, devClientVendorSourceDir = () => resolve53(import.meta.d
35950
36898
  manifest
35951
36899
  };
35952
36900
  globalThis.__hmrDevResult = result;
35953
- globalThis.__hmrServerMtime = statSync8(resolve53(Bun.main)).mtimeMs;
36901
+ globalThis.__hmrServerMtime = statSync8(resolve54(Bun.main)).mtimeMs;
35954
36902
  return result;
35955
36903
  };
35956
36904
  var init_devBuild = __esm(() => {
@@ -35991,5 +36939,5 @@ export {
35991
36939
  devBuild
35992
36940
  };
35993
36941
 
35994
- //# debugId=45E97F77A3254DD664756E2164756E21
36942
+ //# debugId=C21B5771D51EC59A64756E2164756E21
35995
36943
  //# sourceMappingURL=build.js.map