@absolutejs/absolute 0.20.0-beta.4 → 0.20.0-beta.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  2. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  3. package/dist/angular/index.js +341 -22
  4. package/dist/angular/index.js.map +8 -5
  5. package/dist/angular/server.js +341 -22
  6. package/dist/angular/server.js.map +8 -5
  7. package/dist/build.js +94 -22
  8. package/dist/build.js.map +9 -9
  9. package/dist/cli/index.js +986 -557
  10. package/dist/dev/client/cssUtils.ts +16 -2
  11. package/dist/dev/client/handlers/rebuild.ts +11 -1
  12. package/dist/dev/client/hmrTiming.ts +14 -7
  13. package/dist/index.js +364 -191
  14. package/dist/index.js.map +17 -17
  15. package/dist/mobile/browser.js +14 -1
  16. package/dist/mobile/browser.js.map +3 -3
  17. package/dist/mobile/index.js +588 -99
  18. package/dist/mobile/index.js.map +15 -13
  19. package/dist/mobile/remoteMacAgentEntry.js +8 -8
  20. package/dist/src/angular/pageHandler.d.ts +3 -0
  21. package/dist/src/cli/config/server.d.ts +1 -1
  22. package/dist/src/core/pageHandlers.d.ts +11 -2
  23. package/dist/src/mobile/androidEmulatorController.d.ts +6 -1
  24. package/dist/src/mobile/buildPipeline.d.ts +1 -0
  25. package/dist/src/mobile/capacitorBundle.d.ts +11 -1
  26. package/dist/src/mobile/client.d.ts +4 -0
  27. package/dist/src/mobile/index.d.ts +1 -0
  28. package/dist/src/mobile/nativeAuth.d.ts +17 -0
  29. package/dist/src/mobile/releaseArtifact.d.ts +2 -0
  30. package/dist/src/mobile/shellAuth.d.ts +8 -0
  31. package/dist/src/mobile/shellBootstrap.d.ts +11 -1
  32. package/dist/src/mobile/shellSync.d.ts +2 -0
  33. package/dist/src/mobile/staticDocument.d.ts +5 -0
  34. package/dist/src/mobile/transport.d.ts +9 -1
  35. package/dist/src/plugins/imageOptimizer.d.ts +1 -1
  36. package/dist/src/svelte/pageHandler.d.ts +3 -0
  37. package/dist/src/vue/pageHandler.d.ts +3 -0
  38. package/dist/svelte/index.js +312 -23
  39. package/dist/svelte/index.js.map +7 -4
  40. package/dist/svelte/server.js +307 -18
  41. package/dist/svelte/server.js.map +7 -4
  42. package/dist/vue/index.js +312 -23
  43. package/dist/vue/index.js.map +7 -4
  44. package/dist/vue/server.js +307 -18
  45. package/dist/vue/server.js.map +7 -4
  46. package/package.json +21 -9
package/dist/cli/index.js CHANGED
@@ -247,7 +247,8 @@ var heldLocks, HELD_LOCKS_ENV = "ABSOLUTE_HELD_BUILD_DIRECTORY_LOCKS", exitHandl
247
247
  });
248
248
  process.on("uncaughtException", (err) => {
249
249
  releaseAllSync();
250
- throw err;
250
+ console.error(err);
251
+ process.exit(1);
251
252
  });
252
253
  }, isAlreadyExistsError = (error) => error instanceof Error && ("code" in error) && Reflect.get(error, "code") === "EEXIST", lockPathForBuildDirectory = (buildDirectory) => join3(dirname2(buildDirectory), ".absolutejs", "build.lock"), readHeldLockEnv = () => new Set((process.env[HELD_LOCKS_ENV] ?? "").split(`
253
254
  `).filter((entry) => entry.length > 0)), writeHeldLockEnv = (locks) => {
@@ -736,8 +737,9 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
736
737
  return normalized;
737
738
  }, normalizeProductionOrigin = (value) => {
738
739
  const parsed = new URL(requireText(value, "mobile.server.productionOrigin"));
739
- if (parsed.protocol !== "https:") {
740
- throw new TypeError("mobile.server.productionOrigin must use HTTPS in production.");
740
+ const isLoopbackHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]");
741
+ if (parsed.protocol !== "https:" && !isLoopbackHttp) {
742
+ throw new TypeError("mobile.server.productionOrigin must use HTTPS, except for a loopback development origin.");
741
743
  }
742
744
  if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
743
745
  throw new TypeError("mobile.server.productionOrigin must be an origin without credentials, path, query, or hash.");
@@ -759,9 +761,8 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
759
761
  }
760
762
  return value;
761
763
  };
762
- const normalized = new Set([
763
- normalizeHostname(new URL(productionOrigin).hostname)
764
- ]);
764
+ const productionHostname = new URL(productionOrigin).hostname;
765
+ const normalized = new Set(productionHostname === "[::1]" ? [] : [normalizeHostname(productionHostname)]);
765
766
  for (const host of hosts ?? []) {
766
767
  normalized.add(normalizeHostname(host));
767
768
  }
@@ -795,7 +796,7 @@ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FIN
795
796
  throw new TypeError("mobile.appId must use reverse-domain notation, for example com.example.app.");
796
797
  }
797
798
  const productionOrigin = normalizeProductionOrigin(config.server.productionOrigin);
798
- const deepLinkScheme = config.deepLinks?.scheme?.trim().toLowerCase();
799
+ const deepLinkScheme = (config.deepLinks?.scheme ?? appId).trim().toLowerCase();
799
800
  if (deepLinkScheme && !SCHEME_PATTERN.test(deepLinkScheme)) {
800
801
  throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
801
802
  }
@@ -823,15 +824,59 @@ var init_config = __esm(() => {
823
824
  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])?))*$/;
824
825
  });
825
826
 
827
+ // src/mobile/nativeAuth.ts
828
+ import { readFileSync as readFileSync5 } from "fs";
829
+ import { join as join5 } from "path";
830
+ var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth", ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS", ABSOLUTE_NATIVE_AUTH_SCOPES, ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync", readPackageManifest = (projectRoot) => {
831
+ try {
832
+ return JSON.parse(readFileSync5(join5(projectRoot, "package.json"), "utf8"));
833
+ } catch {
834
+ return;
835
+ }
836
+ }, packageManifestHas = (manifest, packageName) => {
837
+ if (typeof manifest !== "object" || manifest === null)
838
+ return false;
839
+ return [
840
+ Reflect.get(manifest, "dependencies"),
841
+ Reflect.get(manifest, "devDependencies"),
842
+ Reflect.get(manifest, "optionalDependencies"),
843
+ Reflect.get(manifest, "peerDependencies")
844
+ ].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
845
+ }, createAbsoluteMobileAuthManifest = (config) => {
846
+ const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
847
+ return {
848
+ clientId: `absolutejs-native:${config.appId}`,
849
+ issuer: config.productionOrigin,
850
+ redirectUri: `${scheme}://auth/callback`,
851
+ scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
852
+ };
853
+ }, installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
854
+ const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
855
+ const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
856
+ if (serialized === undefined)
857
+ delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
858
+ else
859
+ process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
860
+ return auth;
861
+ }, projectUsesAbsoluteAuth = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_AUTH_PACKAGE), projectUsesAbsoluteSync = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_SYNC_PACKAGE), resolveAbsoluteMobileAuthManifest = (projectRoot, config) => projectUsesAbsoluteAuth(projectRoot) ? createAbsoluteMobileAuthManifest(config) : undefined, serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefined ? undefined : JSON.stringify([
862
+ {
863
+ ...auth,
864
+ name: `${config.appName} native app`
865
+ }
866
+ ]);
867
+ var init_nativeAuth = __esm(() => {
868
+ ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
869
+ });
870
+
826
871
  // src/cli/utils.ts
827
872
  var {$: $2 } = globalThis.Bun;
828
873
  import { execSync } from "child_process";
829
- import { existsSync as existsSync3, readFileSync as readFileSync5 } from "fs";
874
+ import { existsSync as existsSync3, readFileSync as readFileSync6 } from "fs";
830
875
  import { createServer as createServer2 } from "net";
831
876
  import { resolve as resolve3 } from "path";
832
877
  var COMPOSE_PATH = "db/docker-compose.db.yml", DEFAULT_SERVER_ENTRY = "src/backend/server.ts", isWSLEnvironment = () => {
833
878
  try {
834
- const release = readFileSync5("/proc/version", "utf-8");
879
+ const release = readFileSync6("/proc/version", "utf-8");
835
880
  return /microsoft|wsl/i.test(release);
836
881
  } catch {
837
882
  return false;
@@ -965,7 +1010,7 @@ var init_utils = __esm(() => {
965
1010
  // src/mobile/emulatorDoctor.ts
966
1011
  import { access } from "fs/promises";
967
1012
  import { homedir as homedir3 } from "os";
968
- import { join as join5 } from "path";
1013
+ import { join as join6 } from "path";
969
1014
  var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command) => {
970
1015
  try {
971
1016
  const result = Bun.spawnSync(command, {
@@ -1010,15 +1055,15 @@ var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command)
1010
1055
  }
1011
1056
  }, absoluteManagedAndroidSdkRoot = (host, env = process.env) => {
1012
1057
  if (host === "windows") {
1013
- return join5(env.LOCALAPPDATA ?? join5(homedir3(), "AppData", "Local"), "AbsoluteJS", "Android", "Sdk");
1058
+ return join6(env.LOCALAPPDATA ?? join6(homedir3(), "AppData", "Local"), "AbsoluteJS", "Android", "Sdk");
1014
1059
  }
1015
1060
  if (host === "wsl") {
1016
1061
  const localAppData = windowsLocalAppDataFromWsl();
1017
1062
  if (localAppData) {
1018
- return join5(localAppData, "AbsoluteJS", "Android", "Sdk");
1063
+ return join6(localAppData, "AbsoluteJS", "Android", "Sdk");
1019
1064
  }
1020
1065
  }
1021
- return join5(homedir3(), ".absolutejs", "android-sdk");
1066
+ return join6(homedir3(), ".absolutejs", "android-sdk");
1022
1067
  }, pathExists = async (path) => {
1023
1068
  try {
1024
1069
  await access(path);
@@ -1071,7 +1116,7 @@ var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command)
1071
1116
  const capture = input.capture ?? captureCommand;
1072
1117
  const androidRoot = input.androidRoot === null ? undefined : input.androidRoot ?? env.ANDROID_HOME ?? env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host, env);
1073
1118
  const windowsAndroidTools = host === "windows" || host === "wsl";
1074
- const android = (segments) => androidRoot ? join5(androidRoot, ...segments) : undefined;
1119
+ const android = (segments) => androidRoot ? join6(androidRoot, ...segments) : undefined;
1075
1120
  const paths = (values) => values.filter((value) => Boolean(value));
1076
1121
  const adb = await findExecutable("adb", paths([
1077
1122
  android(["platform-tools", windowsAndroidTools ? "adb.exe" : "adb"])
@@ -1238,7 +1283,7 @@ import { createHash, randomUUID } from "crypto";
1238
1283
  import {
1239
1284
  dirname as dirname3,
1240
1285
  isAbsolute,
1241
- join as join6,
1286
+ join as join7,
1242
1287
  relative as relative2,
1243
1288
  resolve as resolve5,
1244
1289
  sep,
@@ -1405,11 +1450,11 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1405
1450
  return;
1406
1451
  throw new DOMException("Android development startup was cancelled.", "AbortError");
1407
1452
  }, journalPaths = (projectRoot) => {
1408
- const root = join6(projectRoot, ".absolutejs", "mobile", "dev-session");
1453
+ const root = join7(projectRoot, ".absolutejs", "mobile", "dev-session");
1409
1454
  return {
1410
- backup: join6(root, "capacitor.config.backup.json"),
1411
- journal: join6(root, "journal.json"),
1412
- manifestBackup: join6(root, "AndroidManifest.backup.xml"),
1455
+ backup: join7(root, "capacitor.config.backup.json"),
1456
+ journal: join7(root, "journal.json"),
1457
+ manifestBackup: join7(root, "AndroidManifest.backup.xml"),
1413
1458
  root
1414
1459
  };
1415
1460
  }, isInside = (root, path) => {
@@ -1417,7 +1462,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1417
1462
  const resolvedPath = resolve5(path);
1418
1463
  const relativePath = relative2(resolvedRoot, resolvedPath);
1419
1464
  return relativePath === "" || relativePath !== ".." && !relativePath.startsWith(`..${sep}`) && !isAbsolute(relativePath);
1420
- }, isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value), nativeCachePath = (projectRoot) => join6(projectRoot, ".absolutejs", "mobile", "cache", "android-debug.json"), parseNativeCache = (value) => {
1465
+ }, isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value), nativeCachePath = (projectRoot) => join7(projectRoot, ".absolutejs", "mobile", "cache", "android-debug.json"), parseNativeCache = (value) => {
1421
1466
  if (!isRecord(value))
1422
1467
  return null;
1423
1468
  const { appId, fingerprint, format, installations } = value;
@@ -1449,7 +1494,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1449
1494
  });
1450
1495
  }
1451
1496
  }, nativeDependencySources = async (nativeDirectory) => {
1452
- const settings = await readFile2(join6(nativeDirectory, "capacitor.settings.gradle"), "utf8");
1497
+ const settings = await readFile2(join7(nativeDirectory, "capacitor.settings.gradle"), "utf8");
1453
1498
  const pattern = new RegExp(CAPACITOR_PROJECT_DIRECTORY_PATTERN.source, CAPACITOR_PROJECT_DIRECTORY_PATTERN.flags);
1454
1499
  const dependencies = [...settings.matchAll(pattern)].map((match) => ({
1455
1500
  name: (match[1] ?? "").slice(1).replaceAll(/[^a-zA-Z0-9_.-]/gu, "_"),
@@ -1489,17 +1534,17 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1489
1534
  }, collectNativeDirectory = async (root, label, directory, ignorePublicBundle) => {
1490
1535
  const entries = await readdir(directory, { withFileTypes: true });
1491
1536
  entries.sort((left, right) => left.name.localeCompare(right.name));
1492
- const records = await Promise.all(entries.map((entry) => collectNativePath(root, label, join6(directory, entry.name), entry.isDirectory(), entry.isFile(), entry.isSymbolicLink(), ignorePublicBundle)));
1537
+ const records = await Promise.all(entries.map((entry) => collectNativePath(root, label, join7(directory, entry.name), entry.isDirectory(), entry.isFile(), entry.isSymbolicLink(), ignorePublicBundle)));
1493
1538
  return records.flat();
1494
1539
  }, hashNativeTree = async (root, label, ignorePublicBundle) => {
1495
1540
  const resolvedRoot = await realpath(root);
1496
1541
  const records = await collectNativeDirectory(resolvedRoot, label, resolvedRoot, ignorePublicBundle);
1497
1542
  return createHash("sha256").update(records.join("")).digest("hex");
1498
- }, fingerprintAbsoluteAndroidNativeProject = async (project) => {
1543
+ }, fingerprintAbsoluteAndroidNativeProject = async (project, options = {}) => {
1499
1544
  const { dependencies } = await nativeDependencySources(project.nativeDirectory);
1500
1545
  const roots = [
1501
1546
  {
1502
- ignorePublicBundle: true,
1547
+ ignorePublicBundle: options.includePublicBundle !== true,
1503
1548
  label: "android",
1504
1549
  source: project.nativeDirectory
1505
1550
  },
@@ -1560,7 +1605,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1560
1605
  }
1561
1606
  return source.replace("<application", `<application
1562
1607
  android:usesCleartextTraffic="true"`);
1563
- }, writeDevConfig = async (projectRoot, nativeConfigPath, nativeManifestPath, port, https, entry) => {
1608
+ }, writeDevConfig = async (projectRoot, nativeConfigPath, nativeManifestPath, port, https, entry, embeddedBundle) => {
1564
1609
  const paths = journalPaths(projectRoot);
1565
1610
  await repairAbsoluteAndroidDevSession(projectRoot);
1566
1611
  const source = await readFile2(nativeConfigPath, "utf8");
@@ -1583,14 +1628,16 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1583
1628
  `, {
1584
1629
  flag: "wx"
1585
1630
  });
1586
- const currentServer = parsed.server;
1587
- const developmentUrl = new URL(`${https ? "https" : "http"}://localhost:${port}${entry}`);
1588
- developmentUrl.searchParams.set("__absolute_target", "capacitor-android");
1589
- parsed.server = {
1590
- ...typeof currentServer === "object" && currentServer !== null ? currentServer : {},
1591
- cleartext: !https,
1592
- url: developmentUrl.href
1593
- };
1631
+ if (!embeddedBundle) {
1632
+ const currentServer = parsed.server;
1633
+ const developmentUrl = new URL(`${https ? "https" : "http"}://localhost:${port}${entry}`);
1634
+ developmentUrl.searchParams.set("__absolute_target", "capacitor-android");
1635
+ parsed.server = {
1636
+ ...typeof currentServer === "object" && currentServer !== null ? currentServer : {},
1637
+ cleartext: !https,
1638
+ url: developmentUrl.href
1639
+ };
1640
+ }
1594
1641
  await writeFile2(nativeConfigPath, `${JSON.stringify(parsed, null, "\t")}
1595
1642
  `);
1596
1643
  await writeFile2(nativeManifestPath, androidDevelopmentManifest(manifestSource, !https));
@@ -1636,7 +1683,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1636
1683
  }
1637
1684
  return result.stdout.trim();
1638
1685
  }, mirroredCapacitorDependencies = async (project, capture) => {
1639
- const settingsPath = join6(project.nativeDirectory, "capacitor.settings.gradle");
1686
+ const settingsPath = join7(project.nativeDirectory, "capacitor.settings.gradle");
1640
1687
  const settings = await readFile2(settingsPath, "utf8");
1641
1688
  const dependencies = [];
1642
1689
  const rewrittenSettings = settings.replace(CAPACITOR_PROJECT_DIRECTORY_PATTERN, (_statement, projectName, sourcePath) => {
@@ -1682,7 +1729,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1682
1729
  ].join("; ");
1683
1730
  return Buffer.from(source, "utf16le").toString("base64");
1684
1731
  }, gradleArtifactPath = (nativeDirectory, task, windows = false) => {
1685
- const pathJoin = windows ? win32.join : join6;
1732
+ const pathJoin = windows ? win32.join : join7;
1686
1733
  if (task === "assembleDebug") {
1687
1734
  return pathJoin(nativeDirectory, "app", "build", "outputs", "apk", "debug", "app-debug.apk");
1688
1735
  }
@@ -1695,7 +1742,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1695
1742
  if (task !== "assembleRelease" || await pathExists2(primary)) {
1696
1743
  return primary;
1697
1744
  }
1698
- return join6(nativeDirectory, "app", "build", "outputs", "apk", "release", "app-release-unsigned.apk");
1745
+ return join7(nativeDirectory, "app", "build", "outputs", "apk", "release", "app-release-unsigned.apk");
1699
1746
  }, buildAbsoluteAndroidGradleArtifact = async (options) => {
1700
1747
  const { project, task } = options;
1701
1748
  const capture = options.capture ?? captureCommand2;
@@ -1807,7 +1854,18 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1807
1854
  "-c",
1808
1855
  "android.intent.category.LAUNCHER",
1809
1856
  "1"
1810
- ], androidPackageUid = (project, serial, capture, env) => {
1857
+ ], stopAndroidAppCommand = (project, serial) => [
1858
+ project.adb,
1859
+ "-s",
1860
+ serial,
1861
+ "shell",
1862
+ "am",
1863
+ "force-stop",
1864
+ project.config.appId
1865
+ ], launchAndroidApp = async (project, serial, description, run, options) => {
1866
+ await requireSuccess(stopAndroidAppCommand(project, serial), `${description} reset`, run, options);
1867
+ await requireSuccess(androidLaunchCommand(project, serial), description, run, options);
1868
+ }, androidPackageUid = (project, serial, capture, env) => {
1811
1869
  const result = capture([
1812
1870
  project.adb,
1813
1871
  "-s",
@@ -1886,18 +1944,18 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1886
1944
  if (!adb || !emulator) {
1887
1945
  throw new Error("Android SDK tools disappeared after readiness checks.");
1888
1946
  }
1889
- const cap = join6(projectRoot, "node_modules", ".bin", host === "windows" ? "cap.cmd" : "cap");
1947
+ const cap = join7(projectRoot, "node_modules", ".bin", host === "windows" ? "cap.cmd" : "cap");
1890
1948
  if (!await pathExists2(cap)) {
1891
1949
  throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
1892
1950
  }
1893
1951
  await writeAbsoluteCapacitorConfig(config, { projectRoot });
1894
1952
  await mkdir(config.bundleDirectory, { recursive: true });
1895
- const placeholder = join6(config.bundleDirectory, "index.html");
1953
+ const placeholder = join7(config.bundleDirectory, "index.html");
1896
1954
  if (!await pathExists2(placeholder)) {
1897
1955
  await writeFile2(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
1898
1956
  `);
1899
1957
  }
1900
- const nativeDirectory = join6(config.nativeProjectDirectory, "android");
1958
+ const nativeDirectory = join7(config.nativeProjectDirectory, "android");
1901
1959
  if (!await pathExists2(nativeDirectory)) {
1902
1960
  if (!options.createNativeProject) {
1903
1961
  throw new Error("Android native project has not been created.");
@@ -1958,8 +2016,8 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1958
2016
  await requireSuccess([project.cap, "sync", "android"], "Capacitor Android synchronization", run, { cwd: project.projectRoot, env, signal: options.signal });
1959
2017
  throwIfAborted(options.signal);
1960
2018
  transition("configuring");
1961
- const nativeConfigPath = join6(project.nativeDirectory, "app", "src", "main", "assets", "capacitor.config.json");
1962
- const nativeManifestPath = join6(project.nativeDirectory, "app", "src", "main", "AndroidManifest.xml");
2019
+ const nativeConfigPath = join7(project.nativeDirectory, "app", "src", "main", "assets", "capacitor.config.json");
2020
+ const nativeManifestPath = join7(project.nativeDirectory, "app", "src", "main", "AndroidManifest.xml");
1963
2021
  let connectedSerial;
1964
2022
  let nativeLogs = null;
1965
2023
  const closeNativeLogs = async () => {
@@ -1970,11 +2028,13 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
1970
2028
  });
1971
2029
  };
1972
2030
  try {
1973
- await writeDevConfig(project.projectRoot, nativeConfigPath, nativeManifestPath, options.port, options.https === true, project.config.entry);
2031
+ await writeDevConfig(project.projectRoot, nativeConfigPath, nativeManifestPath, options.port, options.https === true, project.config.entry, options.embeddedBundle === true);
1974
2032
  throwIfAborted(options.signal);
1975
2033
  logHttpsCertificateRequirement(options.https, log);
1976
2034
  const fingerprintStartedAt = performance.now();
1977
- const nativeFingerprintPromise = fingerprintAbsoluteAndroidNativeProject(project).then((fingerprint) => {
2035
+ const nativeFingerprintPromise = fingerprintAbsoluteAndroidNativeProject(project, {
2036
+ includePublicBundle: options.embeddedBundle === true
2037
+ }).then((fingerprint) => {
1978
2038
  phaseDurations.fingerprinting = performance.now() - fingerprintStartedAt;
1979
2039
  return fingerprint;
1980
2040
  });
@@ -2013,14 +2073,17 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
2013
2073
  const { nativeCacheHit, uid } = installedApp;
2014
2074
  throwIfAborted(options.signal);
2015
2075
  transition("launching");
2016
- await requireSuccess(androidLaunchCommand(project, serial), "Android app launch", run, { env, signal: options.signal });
2076
+ await launchAndroidApp(project, serial, "Android app launch", run, {
2077
+ env,
2078
+ signal: options.signal
2079
+ });
2017
2080
  throwIfAborted(options.signal);
2018
2081
  if (options.nativeLog)
2019
2082
  transition("streaming-logs");
2020
2083
  nativeLogs = attachAndroidNativeLogs(project, serial, capture, env, options, uid);
2021
2084
  transition("ready");
2022
2085
  phaseDurations.total = performance.now() - startupStartedAt;
2023
- log(`Android emulator connected (${serial}) with HMR on port ${options.port} in ${getDurationString(phaseDurations.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
2086
+ log(options.embeddedBundle === true ? `Android emulator connected (${serial}) with the embedded bundle and backend on port ${options.port} in ${getDurationString(phaseDurations.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).` : `Android emulator connected (${serial}) with HMR on port ${options.port} in ${getDurationString(phaseDurations.total)} (${nativeCacheHit ? "native cache hit" : "native build installed"}).`);
2024
2087
  log(`Android startup: ${androidTimingSummary(phaseDurations)}.`);
2025
2088
  let closed = false;
2026
2089
  const close = async () => {
@@ -2053,7 +2116,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, DEV_JOURNAL_F
2053
2116
  }
2054
2117
  transition("launching");
2055
2118
  try {
2056
- await requireSuccess(androidLaunchCommand(project, serial), "Android app relaunch", run, { env, signal: options.signal });
2119
+ await launchAndroidApp(project, serial, "Android app relaunch", run, { env, signal: options.signal });
2057
2120
  transition("ready");
2058
2121
  log(`Android app relaunched on ${serial}.`);
2059
2122
  } catch (error) {
@@ -2104,7 +2167,7 @@ var init_androidEmulatorController = __esm(() => {
2104
2167
  import { createHash as createHash2 } from "crypto";
2105
2168
  import { cp, mkdir as mkdir2, mkdtemp, readFile as readFile3, rm as rm2 } from "fs/promises";
2106
2169
  import { tmpdir } from "os";
2107
- import { basename as basename2, join as join7 } from "path";
2170
+ import { basename as basename2, join as join8 } from "path";
2108
2171
  var ANDROID_API = 36, ANDROID_BUILD_TOOLS = "36.0.0", COMMAND_LINE_TOOLS_VERSION = "15859902", LICENSE_ACCEPTANCE_RESPONSES = 100, COMMAND_LINE_TOOLS, defaultRun = async (command, options = {}) => {
2109
2172
  const subprocess = Bun.spawn(command, {
2110
2173
  env: options.env,
@@ -2136,7 +2199,7 @@ var ANDROID_API = 36, ANDROID_BUILD_TOOLS = "36.0.0", COMMAND_LINE_TOOLS_VERSION
2136
2199
  exitCode: result.exitCode,
2137
2200
  stdout: result.stdout.toString()
2138
2201
  };
2139
- }, commandPath = (root, host, tool) => join7(root, "cmdline-tools", "latest", "bin", host === "windows" || host === "wsl" ? `${tool}.bat` : tool), executablePath = (root, host, directory, tool) => join7(root, directory, host === "windows" || host === "wsl" ? `${tool}.exe` : tool), windowsPath = (path) => {
2202
+ }, commandPath = (root, host, tool) => join8(root, "cmdline-tools", "latest", "bin", host === "windows" || host === "wsl" ? `${tool}.bat` : tool), executablePath = (root, host, directory, tool) => join8(root, directory, host === "windows" || host === "wsl" ? `${tool}.exe` : tool), windowsPath = (path) => {
2140
2203
  const match = /^\/mnt\/([a-z])\/(.*)$/i.exec(path);
2141
2204
  if (!match)
2142
2205
  return path;
@@ -2210,10 +2273,10 @@ var ANDROID_API = 36, ANDROID_BUILD_TOOLS = "36.0.0", COMMAND_LINE_TOOLS_VERSION
2210
2273
  if (digest !== release.sha256) {
2211
2274
  throw new Error(`Android command-line-tools checksum mismatch: expected ${release.sha256}, received ${digest}.`);
2212
2275
  }
2213
- const temporary = await mkdtemp(join7(tmpdir(), "absolutejs-android-sdk-"));
2276
+ const temporary = await mkdtemp(join8(tmpdir(), "absolutejs-android-sdk-"));
2214
2277
  try {
2215
- const archive = join7(temporary, "command-line-tools.zip");
2216
- const extracted = join7(temporary, "extracted");
2278
+ const archive = join8(temporary, "command-line-tools.zip");
2279
+ const extracted = join8(temporary, "extracted");
2217
2280
  await Bun.write(archive, bytes);
2218
2281
  await mkdir2(extracted, { recursive: true });
2219
2282
  const extraction = plan.host === "windows" ? [
@@ -2230,12 +2293,12 @@ var ANDROID_API = 36, ANDROID_BUILD_TOOLS = "36.0.0", COMMAND_LINE_TOOLS_VERSION
2230
2293
  if (await input.run(extraction) !== 0) {
2231
2294
  throw new Error("Failed to extract Android command-line tools.");
2232
2295
  }
2233
- const destination = join7(plan.androidRoot, "cmdline-tools", "latest");
2234
- await mkdir2(join7(plan.androidRoot, "cmdline-tools"), {
2296
+ const destination = join8(plan.androidRoot, "cmdline-tools", "latest");
2297
+ await mkdir2(join8(plan.androidRoot, "cmdline-tools"), {
2235
2298
  recursive: true
2236
2299
  });
2237
2300
  await rm2(destination, { force: true, recursive: true });
2238
- await cp(join7(extracted, "cmdline-tools"), destination, {
2301
+ await cp(join8(extracted, "cmdline-tools"), destination, {
2239
2302
  recursive: true
2240
2303
  });
2241
2304
  } finally {
@@ -2420,7 +2483,7 @@ import {
2420
2483
  stat,
2421
2484
  writeFile as writeFile3
2422
2485
  } from "fs/promises";
2423
- import { dirname as dirname4, isAbsolute as isAbsolute2, join as join8, relative as relative3, resolve as resolve6, sep as sep2 } from "path";
2486
+ import { dirname as dirname4, isAbsolute as isAbsolute2, join as join9, relative as relative3, resolve as resolve6, sep as sep2 } from "path";
2424
2487
  var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), requireManifest = (value) => {
2425
2488
  if (!isRecord2(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
2426
2489
  throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
@@ -2470,7 +2533,7 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2470
2533
  }, ignoredFingerprintDirectories, fingerprintFiles = async (root, current = root) => {
2471
2534
  const entries = await readdir2(current, { withFileTypes: true });
2472
2535
  const nested = await Promise.all(entries.sort((left, right) => left.name.localeCompare(right.name)).map(async (entry) => {
2473
- const path = join8(current, entry.name);
2536
+ const path = join9(current, entry.name);
2474
2537
  const projectRelative = relative3(root, path).replaceAll("\\", "/");
2475
2538
  const ignored = entry.isDirectory() && (ignoredFingerprintDirectories.has(entry.name) || projectRelative === "App/App/public");
2476
2539
  if (ignored)
@@ -2504,7 +2567,7 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2504
2567
  return;
2505
2568
  const entries = await readdir2(root, { withFileTypes: true });
2506
2569
  const matches = await Promise.all(entries.map(async (entry) => {
2507
- const path = join8(root, entry.name);
2570
+ const path = join9(root, entry.name);
2508
2571
  if (entry.isDirectory() && entry.name.endsWith(extension))
2509
2572
  return path;
2510
2573
  if (entry.isFile() && entry.name.endsWith(extension))
@@ -2527,10 +2590,10 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2527
2590
  throw new TypeError("iOS build number must be a positive integer.");
2528
2591
  return value;
2529
2592
  }, installRelease = async (artifactPath, metadata, outputRoot) => {
2530
- const releaseRoot = join8(outputRoot, metadata.releaseId);
2531
- const destination = join8(releaseRoot, "App.ipa");
2593
+ const releaseRoot = join9(outputRoot, metadata.releaseId);
2594
+ const destination = join9(releaseRoot, "App.ipa");
2532
2595
  if (await pathExists3(releaseRoot)) {
2533
- const value = JSON.parse(await readFile4(join8(releaseRoot, "release.json"), "utf8"));
2596
+ const value = JSON.parse(await readFile4(join9(releaseRoot, "release.json"), "utf8"));
2534
2597
  if (!isRecord2(value) || value.artifact !== "App.ipa" || Object.entries(metadata).some(([key, expected]) => Reflect.get(value, key) !== expected)) {
2535
2598
  throw new TypeError(`Immutable iOS release ${metadata.releaseId} does not match its content.`);
2536
2599
  }
@@ -2550,14 +2613,14 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2550
2613
  };
2551
2614
  }
2552
2615
  await mkdir3(dirname4(releaseRoot), { recursive: true });
2553
- const staging = await mkdtemp2(join8(dirname4(releaseRoot), ".ios-stage-"));
2616
+ const staging = await mkdtemp2(join9(dirname4(releaseRoot), ".ios-stage-"));
2554
2617
  try {
2555
- await copyFile2(artifactPath, join8(staging, "App.ipa"));
2618
+ await copyFile2(artifactPath, join9(staging, "App.ipa"));
2556
2619
  const complete = {
2557
2620
  ...metadata,
2558
2621
  artifact: "App.ipa"
2559
2622
  };
2560
- await writeFile3(join8(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
2623
+ await writeFile3(join9(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
2561
2624
  `, { flag: "wx" });
2562
2625
  await rename3(staging, releaseRoot);
2563
2626
  return { artifactPath: destination, metadata: complete, releaseRoot };
@@ -2574,10 +2637,10 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2574
2637
  const marketingVersion = options.config.iosVersion;
2575
2638
  if (!marketingVersion)
2576
2639
  throw new TypeError("iOS release builds require mobile.ios.version in absolutejs.config.ts.");
2577
- const manifest = requireManifest(JSON.parse(await readFile4(join8(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
2640
+ const manifest = requireManifest(JSON.parse(await readFile4(join9(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
2578
2641
  if (manifest.appId !== options.config.appId)
2579
2642
  throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
2580
- const nativeDirectory = join8(options.config.nativeProjectDirectory, "ios");
2643
+ const nativeDirectory = join9(options.config.nativeProjectDirectory, "ios");
2581
2644
  let buildNumber = requireBuildNumber(options.buildNumber);
2582
2645
  if (options.prepareBuildNumber) {
2583
2646
  const nativeFingerprint = await fingerprintAbsoluteIosNativeProject(nativeDirectory);
@@ -2586,10 +2649,10 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2586
2649
  }
2587
2650
  const stagingParent = resolve6(options.projectRoot, ".absolutejs/mobile");
2588
2651
  await mkdir3(stagingParent, { recursive: true });
2589
- const staging = await mkdtemp2(join8(stagingParent, ".ios-build-"));
2590
- const archivePath = join8(staging, "App.xcarchive");
2591
- const exportPath = join8(staging, "export");
2592
- const exportPlist = join8(staging, "ExportOptions.plist");
2652
+ const staging = await mkdtemp2(join9(stagingParent, ".ios-build-"));
2653
+ const archivePath = join9(staging, "App.xcarchive");
2654
+ const exportPath = join9(staging, "export");
2655
+ const exportPlist = join9(staging, "ExportOptions.plist");
2593
2656
  await mkdir3(exportPath, { recursive: true });
2594
2657
  await writeFile3(exportPlist, exportOptions());
2595
2658
  const run = options.run ?? defaultRun2;
@@ -2601,7 +2664,7 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2601
2664
  const archiveExit = await run([
2602
2665
  "xcodebuild",
2603
2666
  "-workspace",
2604
- join8(nativeDirectory, "App", "App.xcworkspace"),
2667
+ join9(nativeDirectory, "App", "App.xcworkspace"),
2605
2668
  "-scheme",
2606
2669
  "App",
2607
2670
  "-configuration",
@@ -2615,7 +2678,7 @@ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array
2615
2678
  ], { cwd: nativeDirectory });
2616
2679
  if (archiveExit !== 0)
2617
2680
  throw new TypeError("Xcode failed to archive the iOS app.");
2618
- const archivedApp = await findByExtension(join8(archivePath, "Products", "Applications"), ".app");
2681
+ const archivedApp = await findByExtension(join9(archivePath, "Products", "Applications"), ".app");
2619
2682
  const capture = options.capture ?? defaultCapture2;
2620
2683
  const signed = archivedApp ? capture([
2621
2684
  "codesign",
@@ -2688,7 +2751,7 @@ import {
2688
2751
  rm as rm4,
2689
2752
  writeFile as writeFile4
2690
2753
  } from "fs/promises";
2691
- import { dirname as dirname5, isAbsolute as isAbsolute3, join as join9, relative as relative4, resolve as resolve7, sep as sep3 } from "path";
2754
+ import { dirname as dirname5, isAbsolute as isAbsolute3, join as join10, relative as relative4, resolve as resolve7, sep as sep3 } from "path";
2692
2755
  var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000, BOOT_POLL_MS = 1000, DEV_JOURNAL_FORMAT2 = 1, NATIVE_CACHE_FORMAT2 = 1, isRecord3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), pathExists4 = async (path) => {
2693
2756
  try {
2694
2757
  await access5(path);
@@ -2874,14 +2937,14 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
2874
2937
  const leftPro = left.name.includes("Pro") ? 1 : 0;
2875
2938
  return rightPro - leftPro;
2876
2939
  })[0], journalPaths2 = (projectRoot) => {
2877
- const root = join9(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
2940
+ const root = join10(projectRoot, ".absolutejs", "mobile", "ios-dev-session");
2878
2941
  return {
2879
- configBackup: join9(root, "capacitor-config.backup"),
2880
- infoBackup: join9(root, "Info.plist.backup"),
2881
- journal: join9(root, "journal.json"),
2942
+ configBackup: join10(root, "capacitor-config.backup"),
2943
+ infoBackup: join10(root, "Info.plist.backup"),
2944
+ journal: join10(root, "journal.json"),
2882
2945
  root
2883
2946
  };
2884
- }, nativeCachePath2 = (projectRoot) => join9(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json"), isInside2 = (root, path) => {
2947
+ }, nativeCachePath2 = (projectRoot) => join10(projectRoot, ".absolutejs", "mobile", "ios-native-cache.json"), isInside2 = (root, path) => {
2885
2948
  const value = relative4(resolve7(root), resolve7(path));
2886
2949
  return value === "" || !value.startsWith(`..${sep3}`) && value !== ".." && !isAbsolute3(value);
2887
2950
  }, parseJournal2 = (value) => {
@@ -2938,8 +3001,8 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
2938
3001
  }, writeDevProjection = async (project, port, https) => {
2939
3002
  const paths = journalPaths2(project.projectRoot);
2940
3003
  await repairAbsoluteIosDevSession(project.projectRoot);
2941
- const nativeConfigPath = join9(project.nativeDirectory, "App", "App", "capacitor.config.json");
2942
- const infoPath = join9(project.nativeDirectory, "App", "App", "Info.plist");
3004
+ const nativeConfigPath = join10(project.nativeDirectory, "App", "App", "capacitor.config.json");
3005
+ const infoPath = join10(project.nativeDirectory, "App", "App", "Info.plist");
2943
3006
  const [configSource, infoSource] = await Promise.all([
2944
3007
  readFile5(nativeConfigPath, "utf8"),
2945
3008
  readFile5(infoPath, "utf8")
@@ -3076,12 +3139,12 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3076
3139
  ]);
3077
3140
  return result.exitCode === 0 && result.stdout.trim() ? result.stdout.trim() : undefined;
3078
3141
  }, buildIosDebugApp = async (project, udid, fingerprint, run, signal) => {
3079
- const derivedDataPath = join9(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash4("sha256").update(project.config.appId).digest("hex").slice(0, 16));
3142
+ const derivedDataPath = join10(project.projectRoot, ".absolutejs", "mobile", "ios-derived-data", createHash4("sha256").update(project.config.appId).digest("hex").slice(0, 16));
3080
3143
  await mkdir4(derivedDataPath, { recursive: true });
3081
3144
  await requireSuccess2([
3082
3145
  project.xcodebuild,
3083
3146
  "-workspace",
3084
- join9(project.nativeDirectory, "App", "App.xcworkspace"),
3147
+ join10(project.nativeDirectory, "App", "App.xcworkspace"),
3085
3148
  "-scheme",
3086
3149
  "App",
3087
3150
  "-configuration",
@@ -3092,7 +3155,7 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3092
3155
  derivedDataPath,
3093
3156
  "build"
3094
3157
  ], "iOS simulator build", run, { cwd: project.nativeDirectory, signal });
3095
- const appPath = join9(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
3158
+ const appPath = join10(derivedDataPath, "Build", "Products", "Debug-iphonesimulator", "App.app");
3096
3159
  if (!await pathExists4(appPath))
3097
3160
  throw new Error(`Xcode did not produce the simulator app at ${appPath}.`);
3098
3161
  return appPath;
@@ -3168,16 +3231,16 @@ var ABSOLUTE_IOS_SIMULATOR_NAME = "AbsoluteJS iPhone", BOOT_TIMEOUT_MS = 180000,
3168
3231
  const xcodebuild = checks.find((check) => check.id === "ios.xcodebuild")?.path;
3169
3232
  if (!xcrun || !xcodebuild)
3170
3233
  throw new Error("Xcode tools disappeared after readiness checks.");
3171
- const cap = join9(projectRoot, "node_modules", ".bin", "cap");
3234
+ const cap = join10(projectRoot, "node_modules", ".bin", "cap");
3172
3235
  if (!await pathExists4(cap))
3173
3236
  throw new Error("Capacitor CLI is not installed. Run absolute mobile init first.");
3174
3237
  await writeAbsoluteCapacitorConfig(config, { projectRoot });
3175
3238
  await mkdir4(config.bundleDirectory, { recursive: true });
3176
- const placeholder = join9(config.bundleDirectory, "index.html");
3239
+ const placeholder = join10(config.bundleDirectory, "index.html");
3177
3240
  if (!await pathExists4(placeholder))
3178
3241
  await writeFile4(placeholder, `<!doctype html><title>AbsoluteJS mobile development</title>
3179
3242
  `);
3180
- const nativeDirectory = join9(config.nativeProjectDirectory, "ios");
3243
+ const nativeDirectory = join10(config.nativeProjectDirectory, "ios");
3181
3244
  if (!await pathExists4(nativeDirectory)) {
3182
3245
  if (!options.createNativeProject)
3183
3246
  throw new Error("iOS native project has not been created.");
@@ -3389,13 +3452,13 @@ import { homedir as homedir4 } from "os";
3389
3452
  import {
3390
3453
  dirname as dirname6,
3391
3454
  isAbsolute as isAbsolute4,
3392
- join as join10,
3455
+ join as join11,
3393
3456
  posix,
3394
3457
  relative as relative5,
3395
3458
  resolve as resolvePath,
3396
3459
  sep as sep4
3397
3460
  } from "path";
3398
- var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join10(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
3461
+ var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join11(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
3399
3462
  format: PROFILE_FORMAT,
3400
3463
  profiles: {}
3401
3464
  }), loadStore = async (path = defaultProfilePath()) => {
@@ -3544,9 +3607,9 @@ var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () =
3544
3607
  await saveStore(store, profilePath);
3545
3608
  return true;
3546
3609
  }, projectIdentity = (projectRoot, appId) => createHash5("sha256").update(`${resolvePath(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20), createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
3547
- cap: join10(resolvePath(projectRoot), "node_modules", ".bin", "cap"),
3610
+ cap: join11(resolvePath(projectRoot), "node_modules", ".bin", "cap"),
3548
3611
  config,
3549
- nativeDirectory: join10(config.nativeProjectDirectory, "ios"),
3612
+ nativeDirectory: join11(config.nativeProjectDirectory, "ios"),
3550
3613
  profile,
3551
3614
  projectRoot: resolvePath(projectRoot),
3552
3615
  remote: true,
@@ -3593,8 +3656,8 @@ var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () =
3593
3656
  return { ...artifact, remotePath, uploaded: true };
3594
3657
  }, materializeAbsoluteRemoteMacAgent = async (projectRoot) => {
3595
3658
  const shippedCandidates = [
3596
- join10(import.meta.dir, "remoteMacAgentEntry.js"),
3597
- join10(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
3659
+ join11(import.meta.dir, "remoteMacAgentEntry.js"),
3660
+ join11(import.meta.dir, "..", "mobile", "remoteMacAgentEntry.js")
3598
3661
  ];
3599
3662
  let path;
3600
3663
  for (const candidate of shippedCandidates) {
@@ -3605,13 +3668,13 @@ var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () =
3605
3668
  }
3606
3669
  if (!path) {
3607
3670
  const sourceCandidates = [
3608
- join10(import.meta.dir, "remoteMacAgentEntry.ts"),
3609
- join10(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
3671
+ join11(import.meta.dir, "remoteMacAgentEntry.ts"),
3672
+ join11(import.meta.dir, "..", "..", "src", "mobile", "remoteMacAgentEntry.ts")
3610
3673
  ];
3611
3674
  const source = await sourceCandidates.reduce(async (found, candidate) => await found ?? (await Bun.file(candidate).exists() ? candidate : undefined), Promise.resolve(undefined));
3612
3675
  if (!source)
3613
3676
  throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
3614
- const outdir = join10(resolvePath(projectRoot), ".absolutejs", "mobile", "remote-agent");
3677
+ const outdir = join11(resolvePath(projectRoot), ".absolutejs", "mobile", "remote-agent");
3615
3678
  await mkdir5(outdir, { recursive: true });
3616
3679
  const result = await Bun.build({
3617
3680
  entrypoints: [source],
@@ -3621,7 +3684,7 @@ var PROFILE_FORMAT = 1, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () =
3621
3684
  });
3622
3685
  if (!result.success)
3623
3686
  throw new AggregateError(result.logs, "Failed to build the AbsoluteJS remote Mac agent.");
3624
- path = join10(outdir, "remoteMacAgentEntry.js");
3687
+ path = join11(outdir, "remoteMacAgentEntry.js");
3625
3688
  }
3626
3689
  const bytes = await Bun.file(path).arrayBuffer();
3627
3690
  const sha256 = createHash5("sha256").update(new Uint8Array(bytes)).digest("hex");
@@ -3934,14 +3997,14 @@ import {
3934
3997
  copyFileSync,
3935
3998
  existsSync as existsSync4,
3936
3999
  mkdirSync as mkdirSync4,
3937
- readFileSync as readFileSync6,
4000
+ readFileSync as readFileSync7,
3938
4001
  rmSync
3939
4002
  } from "fs";
3940
4003
  import { platform as platform2 } from "os";
3941
- import { join as join11 } from "path";
4004
+ import { join as join12 } from "path";
3942
4005
  var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[36m[dev]\x1B[0m ${msg}`), devWarn = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[33m[dev]\x1B[0m \x1B[33m${msg}\x1B[0m`), certFilesExist = () => existsSync4(CERT_PATH) && existsSync4(KEY_PATH), isCertExpired = () => {
3943
4006
  try {
3944
- const certPem = readFileSync6(CERT_PATH, "utf-8");
4007
+ const certPem = readFileSync7(CERT_PATH, "utf-8");
3945
4008
  const proc = Bun.spawnSync(["openssl", "x509", "-enddate", "-noout"], {
3946
4009
  stdin: new TextEncoder().encode(certPem)
3947
4010
  });
@@ -4030,8 +4093,8 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
4030
4093
  return null;
4031
4094
  try {
4032
4095
  return {
4033
- cert: readFileSync6(paths.cert, "utf-8"),
4034
- key: readFileSync6(paths.key, "utf-8")
4096
+ cert: readFileSync7(paths.cert, "utf-8"),
4097
+ key: readFileSync7(paths.key, "utf-8")
4035
4098
  };
4036
4099
  } catch {
4037
4100
  return null;
@@ -4127,7 +4190,7 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
4127
4190
  if (platform2() !== "linux")
4128
4191
  return false;
4129
4192
  try {
4130
- return /microsoft|wsl/i.test(readFileSync6("/proc/version", "utf-8"));
4193
+ return /microsoft|wsl/i.test(readFileSync7("/proc/version", "utf-8"));
4131
4194
  } catch {
4132
4195
  return false;
4133
4196
  }
@@ -4150,13 +4213,13 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
4150
4213
  const caRoot = mkcertCaRoot();
4151
4214
  if (!caRoot)
4152
4215
  return false;
4153
- const rootCa = join11(caRoot, "rootCA.pem");
4216
+ const rootCa = join12(caRoot, "rootCA.pem");
4154
4217
  if (!existsSync4(rootCa))
4155
4218
  return false;
4156
4219
  const winTemp = windowsTempDir();
4157
4220
  if (!winTemp)
4158
4221
  return false;
4159
- const staged = join11(winTemp, "absolutejs-mkcert-rootCA.crt");
4222
+ const staged = join12(winTemp, "absolutejs-mkcert-rootCA.crt");
4160
4223
  try {
4161
4224
  copyFileSync(rootCa, staged);
4162
4225
  } catch {
@@ -4192,7 +4255,7 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
4192
4255
  devLog("Trusted the local CA in the Windows store \u2014 Chrome/Edge on Windows now accept dev HTTPS");
4193
4256
  } else {
4194
4257
  const caRoot = mkcertCaRoot();
4195
- const hint = caRoot ? toWindowsPath(join11(caRoot, "rootCA.pem")) : null;
4258
+ const hint = caRoot ? toWindowsPath(join12(caRoot, "rootCA.pem")) : null;
4196
4259
  devWarn("Could not auto-trust the local CA on Windows; Windows browsers may warn.");
4197
4260
  if (hint) {
4198
4261
  console.log(` Run in PowerShell: Import-Certificate -FilePath "${hint}" -CertStoreLocation Cert:\\CurrentUser\\Root`);
@@ -4208,9 +4271,9 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
4208
4271
  return true;
4209
4272
  };
4210
4273
  var init_devCert = __esm(() => {
4211
- CERT_DIR = join11(process.cwd(), ".absolutejs");
4212
- CERT_PATH = join11(CERT_DIR, "cert.pem");
4213
- KEY_PATH = join11(CERT_DIR, "key.pem");
4274
+ CERT_DIR = join12(process.cwd(), ".absolutejs");
4275
+ CERT_PATH = join12(CERT_DIR, "cert.pem");
4276
+ KEY_PATH = join12(CERT_DIR, "key.pem");
4214
4277
  });
4215
4278
 
4216
4279
  // src/cli/scripts/eslintChunked.ts
@@ -4436,7 +4499,7 @@ import { createHash as createHash6 } from "crypto";
4436
4499
  import {
4437
4500
  existsSync as existsSync7,
4438
4501
  mkdirSync as mkdirSync5,
4439
- readFileSync as readFileSync8,
4502
+ readFileSync as readFileSync9,
4440
4503
  renameSync,
4441
4504
  rmSync as rmSync3,
4442
4505
  writeFileSync as writeFileSync5
@@ -4478,7 +4541,7 @@ var DEFAULT_CACHE_LOCATION = ".absolutejs/eslint-cache", CACHE_CONTRACT_VERSION
4478
4541
  return;
4479
4542
  hash.update(label);
4480
4543
  hash.update("\x00");
4481
- hash.update(readFileSync8(path));
4544
+ hash.update(readFileSync9(path));
4482
4545
  hash.update("\x00");
4483
4546
  }, packageNameFor = (specifier) => {
4484
4547
  if (specifier.startsWith("@"))
@@ -4488,7 +4551,7 @@ var DEFAULT_CACHE_LOCATION = ".absolutejs/eslint-cache", CACHE_CONTRACT_VERSION
4488
4551
  }, configPackageNames = (configPath2) => {
4489
4552
  if (!configPath2)
4490
4553
  return [];
4491
- const source = readFileSync8(configPath2, "utf-8");
4554
+ const source = readFileSync9(configPath2, "utf-8");
4492
4555
  const names = new Set;
4493
4556
  for (const match of source.matchAll(/(?:from\s+|import\s*(?:\(\s*)?|require\s*\(\s*)(['"])([^'".][^'"]*)\1/g)) {
4494
4557
  const [, , specifier] = match;
@@ -4511,7 +4574,7 @@ var DEFAULT_CACHE_LOCATION = ".absolutejs/eslint-cache", CACHE_CONTRACT_VERSION
4511
4574
  if (!existsSync7(manifestPath))
4512
4575
  return configPackageNames(configPath2);
4513
4576
  try {
4514
- const manifest = JSON.parse(readFileSync8(manifestPath, "utf-8"));
4577
+ const manifest = JSON.parse(readFileSync9(manifestPath, "utf-8"));
4515
4578
  const lintPackages = manifestDependencyNames(manifest).filter((name) => /eslint|typescript/.test(name));
4516
4579
  return [
4517
4580
  ...new Set([...lintPackages, ...configPackageNames(configPath2)])
@@ -4558,7 +4621,7 @@ var DEFAULT_CACHE_LOCATION = ".absolutejs/eslint-cache", CACHE_CONTRACT_VERSION
4558
4621
  const cachePath = resolve10(cwd, options.cacheLocation);
4559
4622
  const metadataPath = fingerprintLocation(options.cacheLocation, cwd);
4560
4623
  const fingerprint = options.fingerprint ?? createEslintCacheFingerprint(cwd);
4561
- const prior = existsSync7(metadataPath) ? readFileSync8(metadataPath, "utf-8").trim() : null;
4624
+ const prior = existsSync7(metadataPath) ? readFileSync9(metadataPath, "utf-8").trim() : null;
4562
4625
  if (prior === fingerprint)
4563
4626
  return false;
4564
4627
  rmSync3(cachePath, { force: true, recursive: true });
@@ -4646,7 +4709,7 @@ var DEFAULT_CACHE_LOCATION = ".absolutejs/eslint-cache", CACHE_CONTRACT_VERSION
4646
4709
  return;
4647
4710
  let source;
4648
4711
  try {
4649
- source = readFileSync8(configPath2, "utf-8");
4712
+ source = readFileSync9(configPath2, "utf-8");
4650
4713
  } catch {
4651
4714
  return;
4652
4715
  }
@@ -4913,7 +4976,7 @@ var isRecord4 = (value) => typeof value === "object" && value !== null, getIslan
4913
4976
  var init_islands = () => {};
4914
4977
 
4915
4978
  // src/build/islandEntries.ts
4916
- import { dirname as dirname8, extname, join as join14, relative as relative8, resolve as resolve12 } from "path";
4979
+ import { dirname as dirname8, extname, join as join15, relative as relative8, resolve as resolve12 } from "path";
4917
4980
  import ts from "typescript";
4918
4981
  var frameworks, isRecord5 = (value) => typeof value === "object" && value !== null, resolveRegistryExport = (mod) => {
4919
4982
  if (isRecord5(mod.islandRegistry))
@@ -5456,13 +5519,19 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
5456
5519
  if (!isCanonicalRecord(value) || !isPageFramework2(value.framework)) {
5457
5520
  throw new TypeError("Compatibility artifact contains an invalid page.");
5458
5521
  }
5522
+ const styleBundleHash = typeof value.styleBundleHash === "string" ? value.styleBundleHash : undefined;
5523
+ const styleBundlePath = typeof value.styleBundlePath === "string" ? value.styleBundlePath : undefined;
5524
+ if (Boolean(styleBundleHash) !== Boolean(styleBundlePath)) {
5525
+ throw new TypeError("Compatibility page style hash and path must be provided together.");
5526
+ }
5459
5527
  return {
5460
5528
  bundleHash: readString(value.bundleHash, "page.bundleHash"),
5461
5529
  bundlePath: readString(value.bundlePath, "page.bundlePath"),
5462
5530
  contract: readString(value.contract, "page.contract"),
5463
5531
  framework: value.framework,
5464
5532
  pageId: readString(value.pageId, "page.pageId"),
5465
- propsSchemaHash: readString(value.propsSchemaHash, "page.propsSchemaHash")
5533
+ propsSchemaHash: readString(value.propsSchemaHash, "page.propsSchemaHash"),
5534
+ ...styleBundleHash && styleBundlePath ? { styleBundleHash, styleBundlePath } : {}
5466
5535
  };
5467
5536
  }, parseCompatibilityRoute = (value) => {
5468
5537
  if (!isCanonicalRecord(value) || value.method !== "GET" && value.method !== "HEAD") {
@@ -5490,14 +5559,23 @@ var ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT = 1, ABSOLUTE_MOBILE_RETAINED_GENERATIO
5490
5559
  throw new TypeError("producer.module must be a safe relative path.");
5491
5560
  }
5492
5561
  return module;
5493
- }, normalizePage = (page) => ({
5494
- bundleHash: requireNonEmpty(page.bundleHash, "page.bundleHash"),
5495
- bundlePath: requireNonEmpty(page.bundlePath, "page.bundlePath"),
5496
- contract: requireNonEmpty(page.contract, "page.contract"),
5497
- framework: page.framework,
5498
- pageId: requireNonEmpty(page.pageId, "page.pageId"),
5499
- propsSchemaHash: requireNonEmpty(page.propsSchemaHash, "page.propsSchemaHash")
5500
- }), normalizeRoute = (route) => {
5562
+ }, normalizePage = (page) => {
5563
+ if (Boolean(page.styleBundleHash) !== Boolean(page.styleBundlePath)) {
5564
+ throw new TypeError("Compatibility page style hash and path must be provided together.");
5565
+ }
5566
+ return {
5567
+ bundleHash: requireNonEmpty(page.bundleHash, "page.bundleHash"),
5568
+ bundlePath: requireNonEmpty(page.bundlePath, "page.bundlePath"),
5569
+ contract: requireNonEmpty(page.contract, "page.contract"),
5570
+ framework: page.framework,
5571
+ pageId: requireNonEmpty(page.pageId, "page.pageId"),
5572
+ propsSchemaHash: requireNonEmpty(page.propsSchemaHash, "page.propsSchemaHash"),
5573
+ ...page.styleBundleHash && page.styleBundlePath ? {
5574
+ styleBundleHash: requireNonEmpty(page.styleBundleHash, "page.styleBundleHash"),
5575
+ styleBundlePath: requireNonEmpty(page.styleBundlePath, "page.styleBundlePath")
5576
+ } : {}
5577
+ };
5578
+ }, normalizeRoute = (route) => {
5501
5579
  if (!route.pattern.startsWith("/")) {
5502
5580
  throw new TypeError("route.pattern must start with /.");
5503
5581
  }
@@ -5590,32 +5668,68 @@ var init_releaseArtifact = __esm(() => {
5590
5668
  ]);
5591
5669
  });
5592
5670
 
5671
+ // src/utils/stringModifiers.ts
5672
+ var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toPascal = (str) => {
5673
+ if (!str.includes("-") && !str.includes("_")) {
5674
+ return str.charAt(0).toUpperCase() + str.slice(1);
5675
+ }
5676
+ return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
5677
+ };
5678
+
5593
5679
  // src/mobile/buildRelease.ts
5594
5680
  import { createHash as createHash8 } from "crypto";
5595
- import { readFile as readFile7 } from "fs/promises";
5596
- import { join as join15, relative as relative9, resolve as resolve13 } from "path";
5597
- var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex"), readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]), resolveAssetPath = (buildDirectory, assetPath) => {
5681
+ import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile6 } from "fs/promises";
5682
+ import { basename as basename6, dirname as dirname9, extname as extname3, join as join16, relative as relative9, resolve as resolve13 } from "path";
5683
+ var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex"), STATIC_SCRIPT_PATTERN, rewriteStaticScriptPaths = (source, manifest) => source.replace(STATIC_SCRIPT_PATTERN, (match, prefix, path, suffix) => {
5684
+ if (path.endsWith("/htmx.min.js"))
5685
+ return match;
5686
+ const key = toPascal(basename6(path, extname3(path)));
5687
+ const builtPath = manifest[key];
5688
+ return builtPath ? `${prefix}${builtPath}${suffix}` : match;
5689
+ }), readPageMetadata = (route) => parseAbsoluteMobileBuildPageMetadata(route.hooks?.detail?.[ABSOLUTE_MOBILE_ROUTE_DETAIL]), resolveAssetPath = (buildDirectory, assetPath) => {
5598
5690
  const resolvedBuildDirectory = resolve13(buildDirectory);
5599
5691
  const resolvedAsset = resolve13(assetPath);
5600
5692
  if (resolvedAsset.startsWith(`${resolvedBuildDirectory}/`)) {
5601
5693
  return resolvedAsset;
5602
5694
  }
5603
- return join15(buildDirectory, assetPath.replace(/^\/+/, ""));
5695
+ return join16(buildDirectory, assetPath.replace(/^\/+/, ""));
5604
5696
  }, pageFor = async (metadata, manifest, buildDirectory) => {
5605
5697
  const assetPath = manifest[metadata.bundleKey];
5606
5698
  if (!assetPath) {
5607
5699
  throw new TypeError(`Mobile page ${metadata.pageId} references missing manifest asset ${metadata.bundleKey}.`);
5608
5700
  }
5609
- const resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
5610
- const bytes = await readFile7(resolvedAssetPath);
5701
+ let resolvedAssetPath = resolveAssetPath(buildDirectory, assetPath);
5702
+ if (metadata.framework === "html" || metadata.framework === "htmx") {
5703
+ const source = await readFile7(resolvedAssetPath, "utf8");
5704
+ const rewritten = rewriteStaticScriptPaths(source, manifest);
5705
+ const documentHash = sha256(new TextEncoder().encode(rewritten));
5706
+ resolvedAssetPath = join16(buildDirectory, ".absolutejs", "mobile-pages", `${documentHash}.html`);
5707
+ await mkdir7(dirname9(resolvedAssetPath), { recursive: true });
5708
+ await writeFile6(resolvedAssetPath, rewritten);
5709
+ }
5710
+ const pageAssetKey = metadata.bundleKey.replace(/Index$/u, "");
5711
+ const styleAssetPath = [
5712
+ `${pageAssetKey}BundledCSS`,
5713
+ `${pageAssetKey}CompiledCSS`
5714
+ ].map((key) => manifest[key]).find((path) => typeof path === "string");
5715
+ const resolvedStylePath = styleAssetPath ? resolveAssetPath(buildDirectory, styleAssetPath) : undefined;
5716
+ const [bytes, styleBytes] = await Promise.all([
5717
+ readFile7(resolvedAssetPath),
5718
+ resolvedStylePath ? readFile7(resolvedStylePath) : undefined
5719
+ ]);
5611
5720
  const bundlePath = `/${relative9(resolve13(buildDirectory), resolvedAssetPath).replaceAll("\\", "/")}`;
5721
+ const styleBundlePath = resolvedStylePath ? `/${relative9(resolve13(buildDirectory), resolvedStylePath).replaceAll("\\", "/")}` : undefined;
5612
5722
  return {
5613
5723
  bundleHash: sha256(bytes),
5614
5724
  bundlePath,
5615
5725
  contract: metadata.contract,
5616
5726
  framework: metadata.framework,
5617
5727
  pageId: metadata.pageId,
5618
- propsSchemaHash: metadata.propsSchemaHash
5728
+ propsSchemaHash: metadata.propsSchemaHash,
5729
+ ...styleBytes && styleBundlePath ? {
5730
+ styleBundleHash: sha256(styleBytes),
5731
+ styleBundlePath
5732
+ } : {}
5619
5733
  };
5620
5734
  }, buildAbsoluteMobileCompatibilityRelease = async (options) => {
5621
5735
  const [captured, producerBytes] = await Promise.all([
@@ -5636,11 +5750,19 @@ var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex"), readP
5636
5750
  const pages = await Promise.all([...metadataByPage.values()].map((metadata) => pageFor(metadata, options.manifest, options.buildDirectory)));
5637
5751
  const producerHash = sha256(producerBytes);
5638
5752
  const appBuild = `ambuild_${sha256(new TextEncoder().encode(JSON.stringify({
5639
- pages: pages.map(({ bundleHash, bundlePath, contract, pageId }) => ({
5753
+ pages: pages.map(({
5754
+ bundleHash,
5755
+ bundlePath,
5756
+ contract,
5757
+ pageId,
5758
+ styleBundleHash,
5759
+ styleBundlePath
5760
+ }) => ({
5640
5761
  bundleHash,
5641
5762
  bundlePath,
5642
5763
  contract,
5643
- pageId
5764
+ pageId,
5765
+ ...styleBundleHash && styleBundlePath ? { styleBundleHash, styleBundlePath } : {}
5644
5766
  })),
5645
5767
  producerHash,
5646
5768
  runtime: options.runtime
@@ -5699,6 +5821,7 @@ var sha256 = (bytes) => createHash8("sha256").update(bytes).digest("hex"), readP
5699
5821
  var init_buildRelease = __esm(() => {
5700
5822
  init_buildMetadata();
5701
5823
  init_releaseArtifact();
5824
+ STATIC_SCRIPT_PATTERN = /(<script\b[^>]*?\bsrc\s*=\s*["'])(\/[^"']+\.(?:js|ts))(["'][^>]*>)/giu;
5702
5825
  });
5703
5826
 
5704
5827
  // src/mobile/routeMatcher.ts
@@ -5787,21 +5910,32 @@ var init_transport = __esm(() => {
5787
5910
 
5788
5911
  // src/mobile/capacitorBundle.ts
5789
5912
  import {
5913
+ cp as cp2,
5790
5914
  copyFile as copyFile4,
5791
- mkdir as mkdir7,
5915
+ mkdir as mkdir8,
5792
5916
  mkdtemp as mkdtemp3,
5793
5917
  readFile as readFile8,
5794
5918
  rename as rename6,
5795
5919
  rm as rm5,
5796
- writeFile as writeFile6
5920
+ writeFile as writeFile7
5797
5921
  } from "fs/promises";
5798
5922
  import { existsSync as existsSync9 } from "fs";
5799
- import { basename as basename6, dirname as dirname9, extname as extname3, join as join16, resolve as resolve14 } from "path";
5800
- var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-mobile-bootstrap.js", INDEX_FILE = "index.html", CLIENT_IMPORT_PATTERN, errorHasCode = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code, shellBootstrapModule = () => {
5801
- const candidate = ["js", "ts"].map((extension) => join16(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync9);
5923
+ import { basename as basename7, dirname as dirname10, extname as extname4, join as join17, relative as relative10, resolve as resolve14 } from "path";
5924
+ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-mobile-bootstrap.js", INDEX_FILE = "index.html", CLIENT_CSS_DEPENDENCY_PATTERN, CLIENT_MARKUP_DEPENDENCY_PATTERN, CAPACITOR_CLIENT_FRAMEWORKS, CLIENT_ASSET_DIRECTORIES, errorHasCode = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code, shellBootstrapModule = () => {
5925
+ const candidate = ["js", "ts"].map((extension) => join17(import.meta.dir, `shellBootstrap.${extension}`)).find(existsSync9);
5802
5926
  if (candidate)
5803
5927
  return candidate;
5804
5928
  throw new TypeError("AbsoluteJS mobile shell bootstrap module is missing.");
5929
+ }, shellAuthModule = () => {
5930
+ const candidate = ["js", "ts"].map((extension) => join17(import.meta.dir, `shellAuth.${extension}`)).find(existsSync9);
5931
+ if (candidate)
5932
+ return candidate;
5933
+ throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
5934
+ }, shellSyncModule = () => {
5935
+ const candidate = ["js", "ts"].map((extension) => join17(import.meta.dir, `shellSync.${extension}`)).find(existsSync9);
5936
+ if (candidate)
5937
+ return candidate;
5938
+ throw new TypeError("AbsoluteJS mobile Sync shell module is missing.");
5805
5939
  }, escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;"), indexHtml = (appName) => `<!doctype html>
5806
5940
  <html>
5807
5941
  <head>
@@ -5822,11 +5956,16 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
5822
5956
  throw new TypeError("Mobile page bundle escaped the build directory.");
5823
5957
  }
5824
5958
  return asset;
5825
- }, buildShellBootstrap = async (staging) => {
5959
+ }, buildShellBootstrap = async (staging, auth, sync) => {
5826
5960
  const modulePath = shellBootstrapModule();
5827
- const entryPath = join16(staging, ".absolute-mobile-entry.ts");
5828
- await writeFile6(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
5829
- void startAbsoluteMobileShell();
5961
+ const authImport = auth ? `import { createAbsoluteMobileShellAuth } from ${JSON.stringify(shellAuthModule())};
5962
+ ` : "";
5963
+ const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
5964
+ const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
5965
+ ` : "";
5966
+ const entryPath = join17(staging, ".absolute-mobile-entry.ts");
5967
+ await writeFile7(entryPath, `import { startAbsoluteMobileShell } from ${JSON.stringify(modulePath)};
5968
+ ${authImport}${syncImport}void startAbsoluteMobileShell(${options});
5830
5969
  `);
5831
5970
  const build = await Bun.build({
5832
5971
  entrypoints: [entryPath],
@@ -5837,7 +5976,7 @@ void startAbsoluteMobileShell();
5837
5976
  if (!build.success || build.outputs.length !== 1) {
5838
5977
  throw new AggregateError(build.logs, "Failed to build the AbsoluteJS Capacitor shell.");
5839
5978
  }
5840
- await rename6(build.outputs[0]?.path ?? "", join16(staging, BOOTSTRAP_FILE));
5979
+ await rename6(build.outputs[0]?.path ?? "", join17(staging, BOOTSTRAP_FILE));
5841
5980
  await rm5(entryPath, { force: true });
5842
5981
  }, removePreviousBundle = async (backup, moved) => {
5843
5982
  if (!moved)
@@ -5865,47 +6004,93 @@ void startAbsoluteMobileShell();
5865
6004
  throw error;
5866
6005
  }
5867
6006
  }, copyClientPage = async (page, buildDirectory, staging, copiedDependencies) => {
5868
- if (page.framework !== "react") {
5869
- throw new TypeError(`Capacitor spike currently supports React pages; ${page.pageId} is ${page.framework}.`);
6007
+ if (!CAPACITOR_CLIENT_FRAMEWORKS.has(page.framework)) {
6008
+ throw new TypeError(`Capacitor client rendering does not yet support ${page.framework} page ${page.pageId}.`);
5870
6009
  }
5871
- const extension = extname3(page.bundlePath) || ".js";
6010
+ const extension = extname4(page.bundlePath) || ".js";
5872
6011
  const localBundlePath = `./pages/${page.bundleHash}${extension}`;
5873
6012
  const source = sourceAssetPath(buildDirectory, page.bundlePath);
5874
- await copyFile4(source, join16(staging, localBundlePath));
6013
+ await copyFile4(source, join17(staging, localBundlePath));
5875
6014
  await copyAbsoluteClientDependencies(source, buildDirectory, staging, copiedDependencies);
5876
- return { ...page, localBundlePath };
5877
- }, absoluteClientImports = async (sourcePath) => {
6015
+ let localStylePath;
6016
+ if (page.styleBundlePath && page.styleBundleHash) {
6017
+ const styleExtension = extname4(page.styleBundlePath) || ".css";
6018
+ localStylePath = `./styles/${page.styleBundleHash}${styleExtension}`;
6019
+ const styleSource = sourceAssetPath(buildDirectory, page.styleBundlePath);
6020
+ await mkdir8(dirname10(join17(staging, localStylePath)), {
6021
+ recursive: true
6022
+ });
6023
+ await copyFile4(styleSource, join17(staging, localStylePath));
6024
+ await copyAbsoluteClientDependencies(styleSource, buildDirectory, staging, copiedDependencies);
6025
+ }
6026
+ return {
6027
+ ...page,
6028
+ localBundlePath,
6029
+ ...localStylePath ? { localStylePath } : {}
6030
+ };
6031
+ }, absoluteClientImports = async (sourcePath, buildDirectory) => {
5878
6032
  const source = await readFile8(sourcePath, "utf8");
5879
- return [...source.matchAll(CLIENT_IMPORT_PATTERN)].flatMap((match) => {
5880
- const [specifier] = match.slice(1);
5881
- return specifier ? [specifier.split(/[?#]/u, 1)[0] ?? specifier] : [];
6033
+ const extension = extname4(sourcePath).toLowerCase();
6034
+ let scriptLoader;
6035
+ if (extension === ".tsx")
6036
+ scriptLoader = "tsx";
6037
+ else if (extension === ".ts")
6038
+ scriptLoader = "ts";
6039
+ else if (extension === ".jsx")
6040
+ scriptLoader = "jsx";
6041
+ else if ([".js", ".mjs", ".cjs"].includes(extension))
6042
+ scriptLoader = "js";
6043
+ const scriptImports = scriptLoader ? new Bun.Transpiler({ loader: scriptLoader }).scanImports(source).map(({ path }) => path) : [];
6044
+ const cssImports = extension === ".css" ? [...source.matchAll(CLIENT_CSS_DEPENDENCY_PATTERN)].flatMap((match) => match[1] ?? []) : [];
6045
+ const markupImports = extension === ".html" ? [...source.matchAll(CLIENT_MARKUP_DEPENDENCY_PATTERN)].flatMap((match) => match[1] ?? []) : [];
6046
+ return [...scriptImports, ...cssImports, ...markupImports].flatMap((specifier) => {
6047
+ if (!specifier)
6048
+ return [];
6049
+ if (!specifier.startsWith("/") && !specifier.startsWith("./") && !specifier.startsWith("../")) {
6050
+ return [];
6051
+ }
6052
+ const clean = specifier.split(/[?#]/u, 1)[0] ?? specifier;
6053
+ if (clean.startsWith("/"))
6054
+ return [clean];
6055
+ const resolved = resolve14(dirname10(sourcePath), clean);
6056
+ const root = resolve14(buildDirectory);
6057
+ const relativePath = relative10(root, resolved).replaceAll("\\", "/");
6058
+ if (relativePath === ".." || relativePath.startsWith("../")) {
6059
+ throw new TypeError(`Mobile client dependency escaped the build directory: ${specifier}`);
6060
+ }
6061
+ return [`/${relativePath}`];
5882
6062
  });
5883
6063
  }, copyAbsoluteClientDependency = async (specifier, buildDirectory, staging, copied) => {
5884
6064
  if (copied.has(specifier))
5885
6065
  return;
5886
6066
  copied.add(specifier);
5887
6067
  const source = sourceAssetPath(buildDirectory, specifier);
5888
- const destination = join16(staging, specifier.replace(/^\/+/, ""));
5889
- await mkdir7(dirname9(destination), { recursive: true });
6068
+ const destination = join17(staging, specifier.replace(/^\/+/, ""));
6069
+ await mkdir8(dirname10(destination), { recursive: true });
5890
6070
  await copyFile4(source, destination);
5891
6071
  await copyAbsoluteClientDependencies(source, buildDirectory, staging, copied);
5892
6072
  }, copyAbsoluteClientDependencies = async (sourcePath, buildDirectory, staging, copied) => {
5893
- const dependencies = await absoluteClientImports(sourcePath);
6073
+ const dependencies = await absoluteClientImports(sourcePath, buildDirectory);
5894
6074
  await Promise.all(dependencies.map((specifier) => copyAbsoluteClientDependency(specifier, buildDirectory, staging, copied)));
5895
6075
  }, materializeAbsoluteCapacitorWebBundle = async (options) => {
5896
6076
  if (!resolveAbsoluteMobileRoute(options.artifact.routes, new URL(options.config.entry, "https://absolute.invalid").pathname)) {
5897
6077
  throw new TypeError(`mobile.entry ${options.config.entry} is not a captured mobile page route.`);
5898
6078
  }
5899
6079
  const destination = options.config.bundleDirectory;
5900
- await mkdir7(dirname9(destination), { recursive: true });
5901
- const staging = await mkdtemp3(join16(dirname9(destination), `.${basename6(destination)}.stage-`));
6080
+ await mkdir8(dirname10(destination), { recursive: true });
6081
+ const staging = await mkdtemp3(join17(dirname10(destination), `.${basename7(destination)}.stage-`));
5902
6082
  try {
5903
- const pageDirectory = join16(staging, "pages");
5904
- await mkdir7(pageDirectory, { recursive: true });
6083
+ const pageDirectory = join17(staging, "pages");
6084
+ await mkdir8(pageDirectory, { recursive: true });
6085
+ await Promise.all(CLIENT_ASSET_DIRECTORIES.map((directory) => ({
6086
+ destination: join17(staging, directory),
6087
+ source: join17(options.buildDirectory, directory)
6088
+ })).filter(({ source }) => existsSync9(source)).map(({ destination: assetDestination, source }) => cp2(source, assetDestination, { recursive: true })));
5905
6089
  const copiedDependencies = new Set;
5906
6090
  const pages = await Promise.all(options.artifact.pages.map((page) => copyClientPage(page, options.buildDirectory, staging, copiedDependencies)));
5907
6091
  const manifest = {
5908
6092
  appBuild: options.artifact.appBuild,
6093
+ ...options.auth ? { auth: options.auth } : {},
5909
6094
  appId: options.config.appId,
5910
6095
  appName: options.config.appName,
5911
6096
  deepLinkHosts: options.config.deepLinkHosts,
@@ -5915,13 +6100,14 @@ void startAbsoluteMobileShell();
5915
6100
  pages,
5916
6101
  productionOrigin: options.config.productionOrigin,
5917
6102
  routes: options.artifact.routes,
5918
- runtime: options.artifact.runtime
6103
+ runtime: options.artifact.runtime,
6104
+ ...options.sync ? { sync: { socketTickets: true } } : {}
5919
6105
  };
5920
6106
  await Promise.all([
5921
- writeFile6(join16(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
6107
+ writeFile7(join17(staging, MANIFEST_FILE), `${JSON.stringify(manifest, null, "\t")}
5922
6108
  `),
5923
- writeFile6(join16(staging, INDEX_FILE), indexHtml(options.config.appName)),
5924
- buildShellBootstrap(staging)
6109
+ writeFile7(join17(staging, INDEX_FILE), indexHtml(options.config.appName)),
6110
+ buildShellBootstrap(staging, options.auth !== undefined, options.auth !== undefined && options.sync === true)
5925
6111
  ]);
5926
6112
  await installBundle(staging, destination);
5927
6113
  return manifest;
@@ -5933,7 +6119,17 @@ void startAbsoluteMobileShell();
5933
6119
  var init_capacitorBundle = __esm(() => {
5934
6120
  init_routeMatcher();
5935
6121
  init_transport();
5936
- CLIENT_IMPORT_PATTERN = /(?:\bfrom\s*|\bimport\s*\(\s*|\bimport\s*)["'](\/[^"']+)["']/gu;
6122
+ CLIENT_CSS_DEPENDENCY_PATTERN = /(?:@import\s+(?:url\(\s*)?|url\(\s*)["']?((?:\/|\.\.\/|\.\/)[^"')\s]+)["']?\s*\)?/gu;
6123
+ CLIENT_MARKUP_DEPENDENCY_PATTERN = /<(?:script\b[^>]*\bsrc|link\b[^>]*\bhref|img\b[^>]*\bsrc|source\b[^>]*\bsrcset)\s*=\s*["']((?:\/|\.\.\/|\.\/)[^"',\s]+)/giu;
6124
+ CAPACITOR_CLIENT_FRAMEWORKS = new Set([
6125
+ "angular",
6126
+ "html",
6127
+ "htmx",
6128
+ "react",
6129
+ "svelte",
6130
+ "vue"
6131
+ ]);
6132
+ CLIENT_ASSET_DIRECTORIES = ["assets", "html", "htmx", "indexes"];
5937
6133
  });
5938
6134
 
5939
6135
  // src/mobile/artifactStore.ts
@@ -5959,14 +6155,14 @@ var init_artifactStore = __esm(() => {
5959
6155
  import { createHash as createHash10 } from "crypto";
5960
6156
  import {
5961
6157
  access as access6,
5962
- mkdir as mkdir8,
6158
+ mkdir as mkdir9,
5963
6159
  mkdtemp as mkdtemp4,
5964
6160
  readFile as readFile9,
5965
6161
  rename as rename7,
5966
6162
  rm as rm6,
5967
- writeFile as writeFile7
6163
+ writeFile as writeFile8
5968
6164
  } from "fs/promises";
5969
- import { dirname as dirname10, join as join17, resolve as resolvePath2 } from "path";
6165
+ import { dirname as dirname11, join as join18, resolve as resolvePath2 } from "path";
5970
6166
  var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE = "artifact.json", BUNDLE_ID_PATTERN, isRecord7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), errorHasCode2 = (error, code) => typeof error === "object" && error !== null && Reflect.get(error, "code") === code, bundleIdFor = (currentReleaseId, releases) => {
5971
6167
  const identity = JSON.stringify({
5972
6168
  currentReleaseId,
@@ -5996,16 +6192,16 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
5996
6192
  releases
5997
6193
  };
5998
6194
  }, writeRelease = async (root, release) => {
5999
- const directory = join17(root, release.artifact.releaseId);
6000
- const producerPath = join17(directory, release.artifact.producer.module);
6001
- await mkdir8(dirname10(producerPath), { recursive: true });
6195
+ const directory = join18(root, release.artifact.releaseId);
6196
+ const producerPath = join18(directory, release.artifact.producer.module);
6197
+ await mkdir9(dirname11(producerPath), { recursive: true });
6002
6198
  await Promise.all([
6003
- writeFile7(join17(directory, ARTIFACT_FILE), `${JSON.stringify(release.artifact, null, "\t")}
6199
+ writeFile8(join18(directory, ARTIFACT_FILE), `${JSON.stringify(release.artifact, null, "\t")}
6004
6200
  `),
6005
- writeFile7(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
6201
+ writeFile8(producerPath, new Uint8Array(await release.producer.arrayBuffer()))
6006
6202
  ]);
6007
6203
  }, installImmutableBundle = async (bundlesRoot, bundleId, releases) => {
6008
- const destination = join17(bundlesRoot, bundleId);
6204
+ const destination = join18(bundlesRoot, bundleId);
6009
6205
  try {
6010
6206
  await access6(destination);
6011
6207
  return destination;
@@ -6013,7 +6209,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
6013
6209
  if (!errorHasCode2(error, "ENOENT"))
6014
6210
  throw error;
6015
6211
  }
6016
- const staging = await mkdtemp4(join17(bundlesRoot, ".stage-"));
6212
+ const staging = await mkdtemp4(join18(bundlesRoot, ".stage-"));
6017
6213
  try {
6018
6214
  await Promise.all(releases.map((release) => writeRelease(staging, release)));
6019
6215
  await rename7(staging, destination);
@@ -6042,8 +6238,8 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
6042
6238
  return release;
6043
6239
  });
6044
6240
  const root = resolvePath2(input.root);
6045
- const bundlesRoot = join17(root, BUNDLES_DIRECTORY);
6046
- await mkdir8(bundlesRoot, { recursive: true });
6241
+ const bundlesRoot = join18(root, BUNDLES_DIRECTORY);
6242
+ await mkdir9(bundlesRoot, { recursive: true });
6047
6243
  const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
6048
6244
  await installImmutableBundle(bundlesRoot, bundleId, orderedReleases);
6049
6245
  const index = {
@@ -6052,21 +6248,21 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
6052
6248
  format: ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT,
6053
6249
  releases: artifacts
6054
6250
  };
6055
- const pointerPath = join17(root, CURRENT_BUNDLE_FILE);
6056
- const temporaryPointerPath = join17(root, `.current-${crypto.randomUUID()}.json`);
6057
- await writeFile7(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
6251
+ const pointerPath = join18(root, CURRENT_BUNDLE_FILE);
6252
+ const temporaryPointerPath = join18(root, `.current-${crypto.randomUUID()}.json`);
6253
+ await writeFile8(temporaryPointerPath, `${JSON.stringify(index, null, "\t")}
6058
6254
  `, { flag: "wx" });
6059
6255
  await rename7(temporaryPointerPath, pointerPath);
6060
6256
  return index;
6061
6257
  }, readAbsoluteMobileMaterializedReleases = async (root) => {
6062
6258
  const resolvedRoot = resolvePath2(root);
6063
6259
  try {
6064
- const serialized = await readFile9(join17(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
6260
+ const serialized = await readFile9(join18(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
6065
6261
  const parsed = JSON.parse(serialized);
6066
6262
  const index = parseBundleIndex(parsed);
6067
- const bundleRoot = join17(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
6263
+ const bundleRoot = join18(resolvedRoot, BUNDLES_DIRECTORY, index.bundleId);
6068
6264
  return Promise.all(index.releases.map(async (artifact) => {
6069
- const producer = Bun.file(join17(bundleRoot, artifact.releaseId, artifact.producer.module));
6265
+ const producer = Bun.file(join18(bundleRoot, artifact.releaseId, artifact.producer.module));
6070
6266
  await verifyAbsoluteMobileCompatibilityProducer({
6071
6267
  artifact,
6072
6268
  producer
@@ -6087,7 +6283,7 @@ var init_materializedBundle = __esm(() => {
6087
6283
 
6088
6284
  // src/mobile/buildPipeline.ts
6089
6285
  import { readFile as readFile10 } from "fs/promises";
6090
- import { join as join18, resolve as resolve15 } from "path";
6286
+ import { join as join19, resolve as resolve15 } from "path";
6091
6287
  import { pathToFileURL } from "url";
6092
6288
  var isElysiaApp = (value) => typeof value === "object" && value !== null && typeof Reflect.get(value, "compile") === "function" && Array.isArray(Reflect.get(value, "routes")), isStringRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string"), serverExportName = (loaded, app) => {
6093
6289
  if (loaded.server === app)
@@ -6095,12 +6291,11 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
6095
6291
  if (loaded.app === app)
6096
6292
  return "app";
6097
6293
  return "default";
6098
- }, restoreBuildDirectory = (previous) => {
6099
- if (previous !== undefined) {
6100
- process.env.ABSOLUTE_BUILD_DIR = previous;
6101
- return;
6102
- }
6103
- delete process.env.ABSOLUTE_BUILD_DIR;
6294
+ }, restoreEnvironmentVariable = (name, previous) => {
6295
+ if (previous !== undefined)
6296
+ process.env[name] = previous;
6297
+ else
6298
+ delete process.env[name];
6104
6299
  }, requireRelease = (releases, releaseId) => {
6105
6300
  const release = releases.get(releaseId);
6106
6301
  if (!release) {
@@ -6119,9 +6314,9 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
6119
6314
  }, finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
6120
6315
  const buildDirectory = resolve15(options.buildDirectory);
6121
6316
  const mobile = normalizeAbsoluteMobileConfig(options.mobile, options.projectRoot);
6122
- const root = join18(buildDirectory, ".absolutejs", "mobile-compatibility");
6317
+ const root = join19(buildDirectory, ".absolutejs", "mobile-compatibility");
6123
6318
  const [manifestSource, previous] = await Promise.all([
6124
- readFile10(join18(buildDirectory, "manifest.json"), "utf8"),
6319
+ readFile10(join19(buildDirectory, "manifest.json"), "utf8"),
6125
6320
  readAbsoluteMobileMaterializedReleases(root)
6126
6321
  ]);
6127
6322
  const manifest = JSON.parse(manifestSource);
@@ -6129,12 +6324,20 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
6129
6324
  throw new TypeError("Invalid AbsoluteJS build manifest for mobile capture.");
6130
6325
  }
6131
6326
  const previousBuildDirectory = process.env.ABSOLUTE_BUILD_DIR;
6327
+ const previousCompiledRuntime = process.env.ABSOLUTE_COMPILED_RUNTIME;
6328
+ const previousConfigPath = process.env.ABSOLUTE_CONFIG;
6132
6329
  process.env.ABSOLUTE_BUILD_DIR = buildDirectory;
6330
+ process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
6331
+ if (options.configPath) {
6332
+ process.env.ABSOLUTE_CONFIG = resolve15(options.projectRoot, options.configPath);
6333
+ }
6133
6334
  let loaded;
6134
6335
  try {
6135
6336
  loaded = await loadServerApp(resolve15(options.producerPath));
6136
6337
  } finally {
6137
- restoreBuildDirectory(previousBuildDirectory);
6338
+ restoreEnvironmentVariable("ABSOLUTE_BUILD_DIR", previousBuildDirectory);
6339
+ restoreEnvironmentVariable("ABSOLUTE_COMPILED_RUNTIME", previousCompiledRuntime);
6340
+ restoreEnvironmentVariable("ABSOLUTE_CONFIG", previousConfigPath);
6138
6341
  }
6139
6342
  const current = await buildAbsoluteMobileCompatibilityRelease({
6140
6343
  app: loaded.app,
@@ -6146,6 +6349,11 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
6146
6349
  producerPath: resolve15(options.producerPath),
6147
6350
  runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
6148
6351
  });
6352
+ const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
6353
+ const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
6354
+ if (auth && !loaded.app.routes.some((route) => route.path === "/.well-known/openid-configuration")) {
6355
+ throw new TypeError("@absolutejs/auth is installed, but its OIDC provider is not mounted. Native authentication requires the auth oidc configuration so AbsoluteJS can provision a public PKCE client.");
6356
+ }
6149
6357
  const releasesById = new Map([current, ...previous].map((release) => [
6150
6358
  release.artifact.releaseId,
6151
6359
  release
@@ -6158,8 +6366,10 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
6158
6366
  });
6159
6367
  await materializeAbsoluteCapacitorWebBundle({
6160
6368
  artifact: current.artifact,
6369
+ ...auth ? { auth } : {},
6161
6370
  buildDirectory,
6162
- config: mobile
6371
+ config: mobile,
6372
+ ...sync ? { sync: true } : {}
6163
6373
  });
6164
6374
  return current.artifact;
6165
6375
  };
@@ -6170,13 +6380,14 @@ var init_buildPipeline = __esm(() => {
6170
6380
  init_materializedBundle();
6171
6381
  init_pageProtocol();
6172
6382
  init_releaseArtifact();
6383
+ init_nativeAuth();
6173
6384
  });
6174
6385
 
6175
6386
  // src/mobile/routeMetadataTransform.ts
6176
- import { existsSync as existsSync10, readFileSync as readFileSync10 } from "fs";
6177
- import { dirname as dirname11, extname as extname4, relative as relative10, resolve as resolve16 } from "path";
6387
+ import { existsSync as existsSync10, readFileSync as readFileSync11 } from "fs";
6388
+ import { dirname as dirname12, extname as extname5, relative as relative11, resolve as resolve16 } from "path";
6178
6389
  import ts4 from "typescript";
6179
- var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posixPath = (value) => value.replace(/\\/g, "/"), findTsconfig = (entry, projectRoot) => ts4.findConfigFile(dirname11(entry), existsSync10, "tsconfig.json") ?? ts4.findConfigFile(projectRoot, existsSync10, "tsconfig.json"), createProgram = (entry, projectRoot) => {
6390
+ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLERS, posixPath = (value) => value.replace(/\\/g, "/"), findTsconfig = (entry, projectRoot) => ts4.findConfigFile(dirname12(entry), existsSync10, "tsconfig.json") ?? ts4.findConfigFile(projectRoot, existsSync10, "tsconfig.json"), createProgram = (entry, projectRoot) => {
6180
6391
  const configPath2 = findTsconfig(entry, projectRoot);
6181
6392
  if (!configPath2) {
6182
6393
  return ts4.createProgram([entry], {
@@ -6187,7 +6398,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6187
6398
  target: ts4.ScriptTarget.ESNext
6188
6399
  });
6189
6400
  }
6190
- const parsed = ts4.parseJsonConfigFileContent(ts4.readConfigFile(configPath2, (path) => readFileSync10(path, "utf8")).config, ts4.sys, dirname11(configPath2));
6401
+ const parsed = ts4.parseJsonConfigFileContent(ts4.readConfigFile(configPath2, (path) => readFileSync11(path, "utf8")).config, ts4.sys, dirname12(configPath2));
6191
6402
  if (!parsed.fileNames.includes(entry))
6192
6403
  parsed.fileNames.push(entry);
6193
6404
  return ts4.createProgram(parsed.fileNames, parsed.options);
@@ -6288,7 +6499,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6288
6499
  const declaration = symbol?.declarations?.[0];
6289
6500
  const file = declaration?.getSourceFile().fileName ?? sourceFile.fileName;
6290
6501
  const exportedName = symbol?.name ?? expression.getText(sourceFile);
6291
- const source = posixPath(relative10(projectRoot, file));
6502
+ const source = posixPath(relative11(projectRoot, file));
6292
6503
  return `${source}#${exportedName}`;
6293
6504
  }, resolveAlias = (symbol, checker) => {
6294
6505
  if (!(symbol.flags & ts4.SymbolFlags.Alias))
@@ -6317,13 +6528,103 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6317
6528
  }
6318
6529
  const [, key] = expression.arguments;
6319
6530
  return key && ts4.isStringLiteralLike(key) ? key.text : undefined;
6531
+ }, staticString = (expression, bindings) => {
6532
+ if (ts4.isStringLiteralLike(expression))
6533
+ return expression.text;
6534
+ if (ts4.isIdentifier(expression))
6535
+ return bindings.get(expression.text);
6536
+ if (ts4.isNoSubstitutionTemplateLiteral(expression))
6537
+ return expression.text;
6538
+ if (!ts4.isTemplateExpression(expression))
6539
+ return;
6540
+ let value = expression.head.text;
6541
+ for (const span of expression.templateSpans) {
6542
+ const substitution = staticString(span.expression, bindings);
6543
+ if (substitution === undefined)
6544
+ return;
6545
+ value += substitution + span.literal.text;
6546
+ }
6547
+ return value;
6548
+ }, assetKeyWithBindings = (expression, checker, bindings = new Map) => {
6549
+ if (!expression)
6550
+ return;
6551
+ if (ts4.isCallExpression(expression) && ts4.isIdentifier(expression.expression) && expression.expression.text === "asset") {
6552
+ const [, key] = expression.arguments;
6553
+ return key ? staticString(key, bindings) : undefined;
6554
+ }
6555
+ return assetKey(expression, checker);
6556
+ }, callableObject = (call, checker) => {
6557
+ const symbol = checker.getSymbolAtLocation(call.expression);
6558
+ const resolved = symbol ? resolveAlias(symbol, checker) : undefined;
6559
+ const declaration = resolved?.valueDeclaration ?? resolved?.declarations?.[0];
6560
+ let callable;
6561
+ if (declaration && ts4.isFunctionDeclaration(declaration)) {
6562
+ callable = declaration;
6563
+ } else if (declaration && ts4.isVariableDeclaration(declaration) && declaration.initializer && (ts4.isArrowFunction(declaration.initializer) || ts4.isFunctionExpression(declaration.initializer))) {
6564
+ callable = declaration.initializer;
6565
+ }
6566
+ if (!callable)
6567
+ return;
6568
+ const bindings = new Map;
6569
+ callable.parameters.forEach((parameter, index) => {
6570
+ if (!ts4.isIdentifier(parameter.name))
6571
+ return;
6572
+ const argument = call.arguments[index];
6573
+ if (!argument)
6574
+ return;
6575
+ const value = staticString(argument, new Map);
6576
+ if (value !== undefined)
6577
+ bindings.set(parameter.name.text, value);
6578
+ });
6579
+ const { body } = callable;
6580
+ if (!body)
6581
+ return;
6582
+ const expressionBody = ts4.isParenthesizedExpression(body) ? body.expression : body;
6583
+ if (ts4.isObjectLiteralExpression(expressionBody)) {
6584
+ return { bindings, object: expressionBody };
6585
+ }
6586
+ if (ts4.isBlock(body)) {
6587
+ const returned = body.statements.find(ts4.isReturnStatement)?.expression;
6588
+ if (returned && ts4.isObjectLiteralExpression(returned)) {
6589
+ return { bindings, object: returned };
6590
+ }
6591
+ }
6592
+ return;
6593
+ }, spreadObject = (expression, checker, bindings) => {
6594
+ if (ts4.isObjectLiteralExpression(expression)) {
6595
+ return { bindings, object: expression };
6596
+ }
6597
+ if (!ts4.isCallExpression(expression))
6598
+ return;
6599
+ return callableObject(expression, checker);
6600
+ }, objectAssetKey = (object, name, checker, bindings = new Map) => {
6601
+ for (const property of [...object.properties].reverse()) {
6602
+ if (propertyName(property) === name && ts4.isShorthandPropertyAssignment(property)) {
6603
+ return assetKeyWithBindings(property.name, checker, bindings);
6604
+ }
6605
+ if (propertyName(property) === name && ts4.isPropertyAssignment(property)) {
6606
+ return assetKeyWithBindings(property.initializer, checker, bindings);
6607
+ }
6608
+ if (!ts4.isSpreadAssignment(property))
6609
+ continue;
6610
+ const nestedObject = spreadObject(property.expression, checker, bindings);
6611
+ if (!nestedObject)
6612
+ continue;
6613
+ const nested = objectAssetKey(nestedObject.object, name, checker, nestedObject.bindings);
6614
+ if (nested)
6615
+ return nested;
6616
+ }
6617
+ return;
6320
6618
  }, findPageCall = (nodes) => {
6321
6619
  let found;
6322
6620
  const visit = (candidate) => {
6323
6621
  if (found)
6324
6622
  return;
6325
- if (ts4.isCallExpression(candidate) && ts4.isIdentifier(candidate.expression) && candidate.expression.text === PAGE_HANDLER) {
6326
- found = candidate;
6623
+ if (ts4.isCallExpression(candidate) && ts4.isIdentifier(candidate.expression) && PAGE_HANDLERS.has(candidate.expression.text)) {
6624
+ const definition = PAGE_HANDLERS.get(candidate.expression.text);
6625
+ if (!definition)
6626
+ return;
6627
+ found = { definition, node: candidate };
6327
6628
  return;
6328
6629
  }
6329
6630
  ts4.forEachChild(candidate, visit);
@@ -6340,30 +6641,67 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6340
6641
  const [routePath] = node.arguments;
6341
6642
  if (!routePath || !ts4.isStringLiteralLike(routePath))
6342
6643
  return;
6343
- const pageCall = findPageCall(node.arguments.slice(1));
6644
+ const foundPageCall = findPageCall(node.arguments.slice(1));
6645
+ const pageCall = foundPageCall?.node;
6646
+ const definition = foundPageCall?.definition;
6344
6647
  const [input] = pageCall?.arguments ?? [];
6345
- if (!pageCall || !input || !ts4.isObjectLiteralExpression(input)) {
6648
+ if (!pageCall || !input) {
6346
6649
  return;
6347
6650
  }
6348
- const page = objectPropertyExpression(input, "Page");
6349
- if (!page)
6651
+ if (!definition)
6652
+ return;
6653
+ if (definition.inputKind === "static") {
6654
+ const bundleKey2 = assetKey(input, checker);
6655
+ if (!bundleKey2)
6656
+ return;
6657
+ const pageId2 = `${definition.framework}:${bundleKey2}`;
6658
+ const propsSchemaHash2 = hashAbsoluteMobilePropsSchema({
6659
+ properties: {},
6660
+ type: "object"
6661
+ });
6662
+ return {
6663
+ inputKind: "static",
6664
+ metadata: {
6665
+ bundleKey: bundleKey2,
6666
+ contract: `${definition.framework}:${pageId2}:${propsSchemaHash2}`,
6667
+ framework: definition.framework,
6668
+ pageId: pageId2,
6669
+ propsSchemaHash: propsSchemaHash2
6670
+ },
6671
+ pageCallStart: pageCall.getStart(sourceFile),
6672
+ routeCallSpan: `${node.getStart(sourceFile)}:${node.end}`
6673
+ };
6674
+ }
6675
+ if (!ts4.isObjectLiteralExpression(input) || !definition.bundleProperty) {
6676
+ return;
6677
+ }
6678
+ const page = definition.pageProperty ? objectPropertyExpression(input, definition.pageProperty) : undefined;
6679
+ const source = definition.sourceProperty ? objectAssetKey(input, definition.sourceProperty, checker) : undefined;
6680
+ if (definition.pageProperty && !page)
6350
6681
  return;
6351
- const props = objectPropertyExpression(input, "props");
6352
- const index = objectPropertyExpression(input, "index");
6353
- const bundleKey = assetKey(index, checker);
6682
+ if (definition.sourceProperty && !source)
6683
+ return;
6684
+ const props = objectPropertyExpression(input, definition.propsProperty);
6685
+ const bundleKey = objectAssetKey(input, definition.bundleProperty, checker);
6354
6686
  if (!bundleKey)
6355
6687
  return;
6356
- const pageId = resolvePageIdentity(page, sourceFile, checker, projectRoot);
6357
- const schema = serializeType(pagePropsType(page, props, checker), checker);
6688
+ const pageId = page ? resolvePageIdentity(page, sourceFile, checker, projectRoot) : `${definition.framework}:${source}`;
6689
+ let propsType;
6690
+ if (page)
6691
+ propsType = pagePropsType(page, props, checker);
6692
+ else if (props)
6693
+ propsType = checker.getTypeAtLocation(props);
6694
+ const schema = propsType ? serializeType(propsType, checker) : { properties: {}, type: "object" };
6358
6695
  const propsSchemaHash = hashAbsoluteMobilePropsSchema(schema);
6359
6696
  const metadata = {
6360
6697
  bundleKey,
6361
- contract: `react:${pageId}:${propsSchemaHash}`,
6362
- framework: "react",
6698
+ contract: `${definition.framework}:${pageId}:${propsSchemaHash}`,
6699
+ framework: definition.framework,
6363
6700
  pageId,
6364
6701
  propsSchemaHash
6365
6702
  };
6366
6703
  const result = {
6704
+ inputKind: "object",
6367
6705
  metadata,
6368
6706
  pageCallStart: pageCall.getStart(sourceFile),
6369
6707
  routeCallSpan: `${node.getStart(sourceFile)}:${node.end}`
@@ -6415,6 +6753,16 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6415
6753
  }, transformPageCall = (node, page) => {
6416
6754
  if (!page)
6417
6755
  return;
6756
+ if (page.inputKind === "static") {
6757
+ const [pagePath, existingOptions, ...rest] = node.arguments;
6758
+ if (!pagePath)
6759
+ return;
6760
+ const options = ts4.factory.createObjectLiteralExpression([
6761
+ ...existingOptions ? [ts4.factory.createSpreadAssignment(existingOptions)] : [],
6762
+ ts4.factory.createPropertyAssignment("__absoluteMobile", metadataExpression(page.metadata))
6763
+ ]);
6764
+ return ts4.factory.updateCallExpression(node, node.expression, node.typeArguments, [pagePath, options, ...rest]);
6765
+ }
6418
6766
  const [input] = node.arguments;
6419
6767
  if (!input || !ts4.isObjectLiteralExpression(input))
6420
6768
  return;
@@ -6477,7 +6825,7 @@ var ROUTE_METHODS, SOURCE_FILTER, PAGE_HANDLER = "handleReactPageRequest", posix
6477
6825
  const source = await Bun.file(path).text();
6478
6826
  return {
6479
6827
  contents: transformFile(source, path, analysis),
6480
- loader: extname4(path).endsWith("x") ? "tsx" : "ts"
6828
+ loader: extname5(path).endsWith("x") ? "tsx" : "ts"
6481
6829
  };
6482
6830
  });
6483
6831
  }
@@ -6489,10 +6837,56 @@ var init_routeMetadataTransform = __esm(() => {
6489
6837
  init_buildMetadata();
6490
6838
  ROUTE_METHODS = new Set(["get", "head"]);
6491
6839
  SOURCE_FILTER = /\.[cm]?[jt]sx?$/;
6840
+ PAGE_HANDLERS = new Map([
6841
+ [
6842
+ "handleHTMLPageRequest",
6843
+ { framework: "html", inputKind: "static", propsProperty: "props" }
6844
+ ],
6845
+ [
6846
+ "handleHTMXPageRequest",
6847
+ { framework: "htmx", inputKind: "static", propsProperty: "props" }
6848
+ ],
6849
+ [
6850
+ "handleAngularPageRequest",
6851
+ {
6852
+ bundleProperty: "indexPath",
6853
+ framework: "angular",
6854
+ propsProperty: "requestContext",
6855
+ sourceProperty: "pagePath"
6856
+ }
6857
+ ],
6858
+ [
6859
+ "handleReactPageRequest",
6860
+ {
6861
+ bundleProperty: "index",
6862
+ framework: "react",
6863
+ pageProperty: "Page",
6864
+ propsProperty: "props"
6865
+ }
6866
+ ],
6867
+ [
6868
+ "handleSveltePageRequest",
6869
+ {
6870
+ bundleProperty: "indexPath",
6871
+ framework: "svelte",
6872
+ propsProperty: "props",
6873
+ sourceProperty: "pagePath"
6874
+ }
6875
+ ],
6876
+ [
6877
+ "handleVuePageRequest",
6878
+ {
6879
+ bundleProperty: "indexPath",
6880
+ framework: "vue",
6881
+ propsProperty: "props",
6882
+ sourceProperty: "pagePath"
6883
+ }
6884
+ ]
6885
+ ]);
6492
6886
  });
6493
6887
 
6494
6888
  // src/cli/elysiaOpenApiTypeboxPlugin.ts
6495
- import { dirname as dirname12, resolve as resolve17 } from "path";
6889
+ import { dirname as dirname13, resolve as resolve17 } from "path";
6496
6890
  var OPENAPI_TYPEBOX_PREFIX = "../node_modules/typebox/", OPENAPI_DISTRIBUTION_SEGMENT = "/@elysia/openapi/dist/", createElysiaOpenApiTypeboxPlugin = () => ({
6497
6891
  name: "absolute-elysia-openapi-typebox",
6498
6892
  setup(build) {
@@ -6502,9 +6896,9 @@ var OPENAPI_TYPEBOX_PREFIX = "../node_modules/typebox/", OPENAPI_DISTRIBUTION_SE
6502
6896
  return;
6503
6897
  }
6504
6898
  const relativePath = args.path.slice(OPENAPI_TYPEBOX_PREFIX.length);
6505
- const typeboxEntry = Bun.resolveSync("typebox", dirname12(args.importer));
6899
+ const typeboxEntry = Bun.resolveSync("typebox", dirname13(args.importer));
6506
6900
  return {
6507
- path: resolve17(dirname12(typeboxEntry), "..", relativePath)
6901
+ path: resolve17(dirname13(typeboxEntry), "..", relativePath)
6508
6902
  };
6509
6903
  });
6510
6904
  }
@@ -6564,15 +6958,15 @@ __export(exports_prerender, {
6564
6958
  prerender: () => prerender,
6565
6959
  PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER
6566
6960
  });
6567
- import { mkdirSync as mkdirSync6, readFileSync as readFileSync11 } from "fs";
6568
- import { join as join19 } from "path";
6961
+ import { mkdirSync as mkdirSync6, readFileSync as readFileSync12 } from "fs";
6962
+ import { join as join20 } from "path";
6569
6963
  var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_TIMEOUT_MS = 30000, DEFAULT_FETCH_TIMEOUT_MS = 1e4, PRERENDER_BYPASS_HEADER = "X-Absolute-Prerender-Bypass", routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`, writeTimestamp = async (htmlPath) => {
6570
6964
  const metaPath = htmlPath.replace(/\.html$/, ".meta");
6571
6965
  await Bun.write(metaPath, String(Date.now()));
6572
6966
  }, readTimestamp = (htmlPath) => {
6573
6967
  const metaPath = htmlPath.replace(/\.html$/, ".meta");
6574
6968
  try {
6575
- const content = readFileSync11(metaPath, "utf-8");
6969
+ const content = readFileSync12(metaPath, "utf-8");
6576
6970
  return Number(content) || 0;
6577
6971
  } catch {
6578
6972
  return 0;
@@ -6635,7 +7029,7 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
6635
7029
  if (!isCompleteHtml(html))
6636
7030
  return false;
6637
7031
  const fileName = routeToFilename(route);
6638
- const filePath = join19(prerenderDir, fileName);
7032
+ const filePath = join20(prerenderDir, fileName);
6639
7033
  await Bun.write(filePath, html);
6640
7034
  await writeTimestamp(filePath);
6641
7035
  return true;
@@ -6665,13 +7059,13 @@ var SERVER_OUTPUT_LIMIT = 4000, STARTUP_POLL_INTERVAL_MS = 100, DEFAULT_STARTUP_
6665
7059
  return;
6666
7060
  }
6667
7061
  const fileName = routeToFilename(route);
6668
- const filePath = join19(prerenderDir, fileName);
7062
+ const filePath = join20(prerenderDir, fileName);
6669
7063
  await Bun.write(filePath, html);
6670
7064
  await writeTimestamp(filePath);
6671
7065
  result.routes.set(route, filePath);
6672
7066
  log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
6673
7067
  }, prerender = async (port, outDir, staticConfig, log) => {
6674
- const prerenderDir = join19(outDir, "_prerendered");
7068
+ const prerenderDir = join20(outDir, "_prerendered");
6675
7069
  mkdirSync6(prerenderDir, { recursive: true });
6676
7070
  const baseUrl = `http://localhost:${port}`;
6677
7071
  let routes;
@@ -7107,7 +7501,7 @@ var init_nativeRewrite = __esm(() => {
7107
7501
 
7108
7502
  // src/build/rewriteImportsPlugin.ts
7109
7503
  import { readdir as readdir3 } from "fs/promises";
7110
- import { join as join20 } from "path";
7504
+ import { join as join21 } from "path";
7111
7505
  var escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), jsRewriteImports = (content, replacements) => {
7112
7506
  let result = content;
7113
7507
  for (const [specifier, webPath] of replacements) {
@@ -7186,7 +7580,7 @@ ${content}`;
7186
7580
  const entries = await readdir3(dir);
7187
7581
  for (const entry of entries) {
7188
7582
  if (entry.endsWith(".js"))
7189
- allFiles.push(join20(dir, entry));
7583
+ allFiles.push(join21(dir, entry));
7190
7584
  }
7191
7585
  } catch {}
7192
7586
  }
@@ -7261,8 +7655,8 @@ var init_rewriteImports = __esm(() => {
7261
7655
 
7262
7656
  // src/cli/scripts/start.ts
7263
7657
  var {env: env2 } = globalThis.Bun;
7264
- import { existsSync as existsSync11, readFileSync as readFileSync12, rmSync as rmSync4 } from "fs";
7265
- import { basename as basename7, join as join21, resolve as resolve19 } from "path";
7658
+ import { existsSync as existsSync11, readFileSync as readFileSync13, rmSync as rmSync4 } from "fs";
7659
+ import { basename as basename8, join as join22, resolve as resolve19 } from "path";
7266
7660
  var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, resolvePackageVersion = (candidates) => {
7267
7661
  for (const candidate of candidates) {
7268
7662
  const version2 = readPackageVersion2(candidate);
@@ -7273,7 +7667,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
7273
7667
  return "";
7274
7668
  }, readPackageVersion2 = (candidate) => {
7275
7669
  try {
7276
- const pkg = JSON.parse(readFileSync12(candidate, "utf-8"));
7670
+ const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
7277
7671
  if (pkg.name !== "@absolutejs/absolute")
7278
7672
  return null;
7279
7673
  const ver = pkg.version;
@@ -7446,7 +7840,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
7446
7840
  }
7447
7841
  const port = Number(env2.PORT) || DEFAULT_PORT;
7448
7842
  killStaleProcesses(port);
7449
- const entryName = basename7(serverEntry).replace(/\.[^.]+$/, "");
7843
+ const entryName = basename8(serverEntry).replace(/\.[^.]+$/, "");
7450
7844
  const resolvedOutdir = resolve19(outdir ?? "dist");
7451
7845
  const absoluteVersion = resolvePackageVersion([
7452
7846
  resolve19(import.meta.dir, "..", "..", "..", "package.json"),
@@ -7455,6 +7849,8 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
7455
7849
  const buildConfig = await loadConfig(configPath2);
7456
7850
  buildConfig.buildDirectory = resolvedOutdir;
7457
7851
  buildConfig.mode = "production";
7852
+ if (buildConfig.mobile)
7853
+ installAbsoluteMobileAuthEnvironment(process.cwd(), normalizeAbsoluteMobileConfig(buildConfig.mobile, process.cwd()));
7458
7854
  const frameworks6 = [
7459
7855
  buildConfig.reactDirectory && "react",
7460
7856
  buildConfig.htmlDirectory && "html",
@@ -7492,7 +7888,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
7492
7888
  if (!build)
7493
7889
  throw new Error("Could not locate build module");
7494
7890
  await build(buildConfig);
7495
- rmSync4(join21(resolvedOutdir, "_prerendered"), {
7891
+ rmSync4(join22(resolvedOutdir, "_prerendered"), {
7496
7892
  force: true,
7497
7893
  recursive: true
7498
7894
  });
@@ -7619,6 +8015,7 @@ var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
7619
8015
  if (buildConfig.mobile) {
7620
8016
  await finalizeAbsoluteMobileCompatibilityBuild({
7621
8017
  buildDirectory: resolvedOutdir,
8018
+ ...configPath2 ? { configPath: configPath2 } : {},
7622
8019
  mobile: buildConfig.mobile,
7623
8020
  producerPath: outputPath,
7624
8021
  projectRoot: process.cwd()
@@ -7665,6 +8062,8 @@ var init_start = __esm(() => {
7665
8062
  init_bunStringRawUnicodePlugin();
7666
8063
  init_buildPipeline();
7667
8064
  init_routeMetadataTransform();
8065
+ init_nativeAuth();
8066
+ init_config();
7668
8067
  init_loadConfig();
7669
8068
  init_startupBanner();
7670
8069
  init_telemetryEvent();
@@ -7792,17 +8191,17 @@ var exports_build = {};
7792
8191
  __export(exports_build, {
7793
8192
  build: () => build
7794
8193
  });
7795
- import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync14 } from "fs";
7796
- import { join as join22, resolve as resolve21 } from "path";
8194
+ import { existsSync as existsSync13, readdirSync as readdirSync3, readFileSync as readFileSync15 } from "fs";
8195
+ import { join as join23, resolve as resolve21 } from "path";
7797
8196
  var PROFILE_TOP = 15, PROFILE_COL = 8, FRAMEWORK_KEYS, cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, printProfile = (buildDir) => {
7798
- const traceDir = join22(buildDir, ".absolute-trace");
8197
+ const traceDir = join23(buildDir, ".absolute-trace");
7799
8198
  if (!existsSync13(traceDir))
7800
8199
  return;
7801
8200
  const files = readdirSync3(traceDir).filter((file) => file.endsWith(".json")).sort();
7802
8201
  const latest = files[files.length - 1];
7803
8202
  if (latest === undefined)
7804
8203
  return;
7805
- const trace = JSON.parse(readFileSync14(join22(traceDir, latest), "utf-8"));
8204
+ const trace = JSON.parse(readFileSync15(join23(traceDir, latest), "utf-8"));
7806
8205
  const events = Array.isArray(trace.events) ? trace.events : [];
7807
8206
  if (events.length === 0)
7808
8207
  return;
@@ -7899,14 +8298,14 @@ import {
7899
8298
  lstatSync,
7900
8299
  mkdirSync as mkdirSync8,
7901
8300
  mkdtempSync,
7902
- readFileSync as readFileSync15,
8301
+ readFileSync as readFileSync16,
7903
8302
  realpathSync,
7904
8303
  renameSync as renameSync2,
7905
8304
  rmSync as rmSync5,
7906
8305
  writeFileSync as writeFileSync7
7907
8306
  } from "fs";
7908
8307
  import { tmpdir as tmpdir3 } from "os";
7909
- import { delimiter, dirname as dirname13, relative as relative11, resolve as resolve22 } from "path";
8308
+ import { delimiter, dirname as dirname14, relative as relative12, resolve as resolve22 } from "path";
7910
8309
  var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSION = 2, FLAG_NOT_FOUND = -1, CHUNKED_FLAG = "--chunked", TSCONFIG_PATTERN, ABSOLUTE_BINARY, runGit = (args, options) => {
7911
8310
  const proc = Bun.spawnSync(["git", ...args], {
7912
8311
  cwd: options.cwd,
@@ -7920,7 +8319,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
7920
8319
  }
7921
8320
  return proc.stdout.toString().trim();
7922
8321
  }, gitRoot = (cwd) => resolve22(runGit(["rev-parse", "--show-toplevel"], { cwd })), isInside3 = (parent, candidate) => {
7923
- const path = relative11(parent, candidate);
8322
+ const path = relative12(parent, candidate);
7924
8323
  return path === "" || !path.startsWith("../") && path !== "..";
7925
8324
  }, attestationPayload = (proof) => Buffer.from([
7926
8325
  "absolute-lint-proof-attestation:1",
@@ -7936,13 +8335,13 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
7936
8335
  if (isInside3(realpathSync(gitRoot(cwd)), realpathSync(path))) {
7937
8336
  throw new Error("lint proof signing key must live outside the Git working tree");
7938
8337
  }
7939
- const key = createPrivateKey(readFileSync15(path));
8338
+ const key = createPrivateKey(readFileSync16(path));
7940
8339
  if (key.asymmetricKeyType !== "ed25519") {
7941
8340
  throw new Error("lint proof signing key must be an Ed25519 private key");
7942
8341
  }
7943
8342
  return key;
7944
8343
  }, readEd25519PublicKey = (cwd, location) => {
7945
- const key = createPublicKey(readFileSync15(resolve22(cwd, location)));
8344
+ const key = createPublicKey(readFileSync16(resolve22(cwd, location)));
7946
8345
  if (key.asymmetricKeyType !== "ed25519") {
7947
8346
  throw new Error("trusted lint proof key must be an Ed25519 public key");
7948
8347
  }
@@ -7970,7 +8369,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
7970
8369
  return null;
7971
8370
  const auxiliary = gitVisibleFiles(root).filter((file) => TSCONFIG_PATTERN.test(file));
7972
8371
  const configPath2 = findEslintConfigPath(root);
7973
- const configRelative = configPath2 === null ? null : relative11(root, configPath2).replaceAll("\\", "/");
8372
+ const configRelative = configPath2 === null ? null : relative12(root, configPath2).replaceAll("\\", "/");
7974
8373
  return [
7975
8374
  ...new Set([
7976
8375
  ...resolveLintTargets(args, root),
@@ -7981,7 +8380,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
7981
8380
  }, createLintSourceTree = (cwd = process.cwd(), proofLocation = DEFAULT_PROOF_LOCATION, command = []) => {
7982
8381
  const root = gitRoot(cwd);
7983
8382
  const proofPath = resolve22(cwd, proofLocation);
7984
- const proofRelative = relative11(root, proofPath).replaceAll("\\", "/");
8383
+ const proofRelative = relative12(root, proofPath).replaceAll("\\", "/");
7985
8384
  if (proofRelative === ".." || proofRelative.startsWith("../") || proofRelative === "") {
7986
8385
  throw new Error("lint proof must live inside the Git working tree");
7987
8386
  }
@@ -8050,7 +8449,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
8050
8449
  signature: sign(null, attestationPayload(proof), privateKey).toString("base64")
8051
8450
  };
8052
8451
  }
8053
- mkdirSync8(dirname13(path), { recursive: true });
8452
+ mkdirSync8(dirname14(path), { recursive: true });
8054
8453
  writeFileSync7(temporary, `${JSON.stringify(proof, null, 2)}
8055
8454
  `);
8056
8455
  renameSync2(temporary, path);
@@ -8099,7 +8498,7 @@ var DEFAULT_PROOF_LOCATION = ".absolutejs/lint-proof.json", PROOF_CONTRACT_VERSI
8099
8498
  return { reason: `missing lint proof: ${proofLocation}`, valid: false };
8100
8499
  let proof;
8101
8500
  try {
8102
- proof = JSON.parse(readFileSync15(path, "utf-8"));
8501
+ proof = JSON.parse(readFileSync16(path, "utf-8"));
8103
8502
  } catch {
8104
8503
  return { reason: `invalid lint proof: ${proofLocation}`, valid: false };
8105
8504
  }
@@ -8210,11 +8609,11 @@ var init_lintProof = __esm(() => {
8210
8609
  });
8211
8610
 
8212
8611
  // src/build/scanConventions.ts
8213
- import { basename as basename8 } from "path";
8612
+ import { basename as basename9 } from "path";
8214
8613
  var {Glob: Glob2 } = globalThis.Bun;
8215
8614
  import { existsSync as existsSync15 } from "fs";
8216
8615
  var CONVENTION_RE, classifyFile = (file, pageFiles, defaults, pages) => {
8217
- const fileName = basename8(file);
8616
+ const fileName = basename9(file);
8218
8617
  const match = CONVENTION_RE.exec(fileName);
8219
8618
  if (!match) {
8220
8619
  pageFiles.push(file);
@@ -8259,21 +8658,13 @@ var init_scanConventions = __esm(() => {
8259
8658
  CONVENTION_RE = /^(?:(.+)\.)?(error|loading|not-found)\.[^.]+$/;
8260
8659
  });
8261
8660
 
8262
- // src/utils/stringModifiers.ts
8263
- var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toPascal = (str) => {
8264
- if (!str.includes("-") && !str.includes("_")) {
8265
- return str.charAt(0).toUpperCase() + str.slice(1);
8266
- }
8267
- return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
8268
- };
8269
-
8270
8661
  // src/cli/scripts/ls.ts
8271
8662
  var exports_ls = {};
8272
8663
  __export(exports_ls, {
8273
8664
  runLs: () => runLs
8274
8665
  });
8275
- import { existsSync as existsSync16, readFileSync as readFileSync16, statSync } from "fs";
8276
- import { basename as basename9, extname as extname5, join as join23, relative as relative12 } from "path";
8666
+ import { existsSync as existsSync16, readFileSync as readFileSync17, statSync } from "fs";
8667
+ import { basename as basename10, extname as extname6, join as join24, relative as relative13 } from "path";
8277
8668
  var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELDS, readStringField = (source, key) => {
8278
8669
  const value = Reflect.get(source, key);
8279
8670
  return typeof value === "string" ? value : undefined;
@@ -8288,24 +8679,24 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
8288
8679
  } catch {
8289
8680
  return null;
8290
8681
  }
8291
- }, relativeOrSelf = (target) => relative12(process.cwd(), target) || target, configCandidates = (raw) => isWorkspaceConfig(raw) ? Object.values(raw).map((service) => ({
8682
+ }, relativeOrSelf = (target) => relative13(process.cwd(), target) || target, configCandidates = (raw) => isWorkspaceConfig(raw) ? Object.values(raw).map((service) => ({
8292
8683
  baseDir: readStringField(service, "cwd") ?? ".",
8293
8684
  source: service
8294
8685
  })) : [{ baseDir: ".", source: raw }], specsFor = (source, baseDir) => FRAMEWORK_FIELDS.flatMap((framework) => {
8295
8686
  const dir = readStringField(source, framework.field);
8296
8687
  return dir === undefined ? [] : [
8297
8688
  {
8298
- dir: join23(baseDir, dir),
8689
+ dir: join24(baseDir, dir),
8299
8690
  label: framework.label,
8300
8691
  pattern: framework.pattern
8301
8692
  }
8302
8693
  ];
8303
8694
  }), scanFramework = async (spec) => {
8304
- const { pageFiles } = await scanConventions(join23(spec.dir, "pages"), spec.pattern);
8695
+ const { pageFiles } = await scanConventions(join24(spec.dir, "pages"), spec.pattern);
8305
8696
  if (pageFiles.length === 0)
8306
8697
  return null;
8307
8698
  const pages = pageFiles.map((file) => ({
8308
- name: basename9(file, extname5(file)),
8699
+ name: basename10(file, extname6(file)),
8309
8700
  sizeBytes: null,
8310
8701
  sourcePath: relativeOrSelf(file)
8311
8702
  }));
@@ -8325,10 +8716,10 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
8325
8716
  }, resolveDiskPath = (buildDir, value) => {
8326
8717
  if (existsSync16(value))
8327
8718
  return value;
8328
- const underBuild = join23(buildDir, value);
8719
+ const underBuild = join24(buildDir, value);
8329
8720
  if (existsSync16(underBuild))
8330
8721
  return underBuild;
8331
- return join23(process.cwd(), value);
8722
+ return join24(process.cwd(), value);
8332
8723
  }, fileSize = (diskPath) => {
8333
8724
  try {
8334
8725
  return statSync(diskPath).size;
@@ -8336,7 +8727,7 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
8336
8727
  return 0;
8337
8728
  }
8338
8729
  }, readManifestSizes = (manifestDir) => {
8339
- const manifest = JSON.parse(readFileSync16(join23(manifestDir, "manifest.json"), "utf-8"));
8730
+ const manifest = JSON.parse(readFileSync17(join24(manifestDir, "manifest.json"), "utf-8"));
8340
8731
  const sizes = new Map;
8341
8732
  Object.entries(manifest).forEach(([key, value]) => {
8342
8733
  sizes.set(key, fileSize(resolveDiskPath(manifestDir, value)));
@@ -8355,7 +8746,7 @@ var DEFAULT_BUILD_DIR = "build", LABEL_ORDER, ARTIFACT_SUFFIXES, FRAMEWORK_FIELD
8355
8746
  }))
8356
8747
  })), manifestAge = (manifestPath) => getDurationString(Date.now() - statSync(manifestPath).mtimeMs), firstBuildDir = (candidates) => candidates.map((candidate) => {
8357
8748
  const dir = readStringField(candidate.source, "buildDirectory");
8358
- return dir === undefined ? undefined : join23(candidate.baseDir, dir);
8749
+ return dir === undefined ? undefined : join24(candidate.baseDir, dir);
8359
8750
  }).find((dir) => dir !== undefined), resolveSizesDir = (args, candidates) => parseFlagValue(args, "--outdir") ?? firstBuildDir(candidates) ?? DEFAULT_BUILD_DIR, formatSize = (bytes) => {
8360
8751
  if (bytes === null || bytes === 0)
8361
8752
  return "-";
@@ -8453,7 +8844,7 @@ ${colors.dim}${frameworkCount} ${frameworkCount === 1 ? "framework" : "framework
8453
8844
  return;
8454
8845
  }
8455
8846
  const sizesDir = resolveSizesDir(args, candidates);
8456
- const manifestPath = join23(sizesDir, "manifest.json");
8847
+ const manifestPath = join24(sizesDir, "manifest.json");
8457
8848
  if (!existsSync16(manifestPath)) {
8458
8849
  printDim(`No build at ${relativeOrSelf(manifestPath)}. Run \`absolute build\` first, or pass \`--outdir <dir>\`.`);
8459
8850
  return;
@@ -9304,9 +9695,9 @@ var exports_heapDiff = {};
9304
9695
  __export(exports_heapDiff, {
9305
9696
  runHeapDiff: () => runHeapDiff
9306
9697
  });
9307
- import { existsSync as existsSync17, readFileSync as readFileSync17 } from "fs";
9698
+ import { existsSync as existsSync17, readFileSync as readFileSync18 } from "fs";
9308
9699
  var TOP = 15, STRING_TYPES, aggregate = (path) => {
9309
- const data = JSON.parse(readFileSync17(path, "utf-8"));
9700
+ const data = JSON.parse(readFileSync18(path, "utf-8"));
9310
9701
  const { nodes, strings } = data;
9311
9702
  const { node_fields: fields, node_types: nodeTypes } = data.snapshot.meta;
9312
9703
  const [typeNames] = nodeTypes;
@@ -9458,14 +9849,14 @@ import ts5 from "typescript";
9458
9849
  import {
9459
9850
  existsSync as existsSync18,
9460
9851
  mkdirSync as mkdirSync9,
9461
- readFileSync as readFileSync18,
9852
+ readFileSync as readFileSync19,
9462
9853
  statSync as statSync2,
9463
9854
  writeFileSync as writeFileSync8
9464
9855
  } from "fs";
9465
9856
  import { resolve as resolve23 } from "path";
9466
9857
  var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFrameworkRepo = (cwd) => {
9467
9858
  try {
9468
- const pkg = JSON.parse(readFileSync18(resolve23(cwd, "package.json"), "utf-8"));
9859
+ const pkg = JSON.parse(readFileSync19(resolve23(cwd, "package.json"), "utf-8"));
9469
9860
  return pkg?.name === "@absolutejs/absolute";
9470
9861
  } catch {
9471
9862
  return false;
@@ -9493,7 +9884,7 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
9493
9884
  ];
9494
9885
  for (const candidate of candidates) {
9495
9886
  try {
9496
- const { version: version2 } = JSON.parse(readFileSync18(candidate, "utf-8"));
9887
+ const { version: version2 } = JSON.parse(readFileSync19(candidate, "utf-8"));
9497
9888
  if (typeof version2 === "string")
9498
9889
  return version2;
9499
9890
  } catch {}
@@ -9513,7 +9904,7 @@ var VIRTUAL_NAME = "__absolute_type_introspect__.ts", MAX_DEPTH = 6, isFramework
9513
9904
  return resolve23(cwd, ".absolutejs", "config-schema", `${name}.json`);
9514
9905
  }, readDiskCache = (cwd, typeName, signature, specifier) => {
9515
9906
  try {
9516
- const cached = JSON.parse(readFileSync18(cacheFile(cwd, typeName, specifier), "utf-8"));
9907
+ const cached = JSON.parse(readFileSync19(cacheFile(cwd, typeName, specifier), "utf-8"));
9517
9908
  if (isRecord9(cached) && cached.signature === signature && Array.isArray(cached.fields)) {
9518
9909
  return cached.fields;
9519
9910
  }
@@ -9679,7 +10070,7 @@ var init_fromType = __esm(() => {
9679
10070
 
9680
10071
  // src/cli/config/absolute/resolveAbsoluteConfig.ts
9681
10072
  import ts6 from "typescript";
9682
- import { existsSync as existsSync19, readFileSync as readFileSync19 } from "fs";
10073
+ import { existsSync as existsSync19, readFileSync as readFileSync20 } from "fs";
9683
10074
  import { resolve as resolve24 } from "path";
9684
10075
  var CONFIG_CANDIDATES2, RUNTIME_FIELDS, findConfigPath = (cwd, override) => {
9685
10076
  if (override) {
@@ -9709,7 +10100,7 @@ var CONFIG_CANDIDATES2, RUNTIME_FIELDS, findConfigPath = (cwd, override) => {
9709
10100
  }
9710
10101
  return null;
9711
10102
  }, parseConfigObject = (configPath2) => {
9712
- const text = readFileSync19(configPath2, "utf-8");
10103
+ const text = readFileSync20(configPath2, "utf-8");
9713
10104
  return { object: findConfigObject(parseSource(configPath2, text)), text };
9714
10105
  }, evalLiteral = (node) => {
9715
10106
  if (ts6.isStringLiteralLike(node)) {
@@ -9920,7 +10311,7 @@ var init_frameworks = __esm(() => {
9920
10311
  });
9921
10312
 
9922
10313
  // src/cli/generate/context.ts
9923
- import { dirname as dirname14, isAbsolute as isAbsolute5, join as join24, relative as relative13, resolve as resolve25 } from "path";
10314
+ import { dirname as dirname15, isAbsolute as isAbsolute5, join as join25, relative as relative14, resolve as resolve25 } from "path";
9924
10315
  var asString = (value) => typeof value === "string" ? value : undefined, isRecord10 = (value) => typeof value === "object" && value !== null, resolveDir = (cwd, value) => isAbsolute5(value) ? value : resolve25(cwd, value), resolveStylesDir = (cwd, config) => {
9925
10316
  const styles = config.stylesConfig;
9926
10317
  if (typeof styles === "string")
@@ -9933,7 +10324,7 @@ var asString = (value) => typeof value === "string" ? value : undefined, isRecor
9933
10324
  return resolve25(cwd, "src/frontend/styles/indexes");
9934
10325
  }, configuredFrameworks = (project) => FRAMEWORK_KEYS2.filter((key) => project.frameworkDirs[key] !== undefined), frontendRootFor = (project, framework) => {
9935
10326
  const dir = project.frameworkDirs[framework];
9936
- return dir ? dirname14(dir) : resolve25(project.cwd, "src/frontend");
10327
+ return dir ? dirname15(dir) : resolve25(project.cwd, "src/frontend");
9937
10328
  }, resolveProject = async (cwd, configOverride) => {
9938
10329
  const loaded = await loadConfig(configOverride);
9939
10330
  const config = isRecord10(loaded) ? loaded : {};
@@ -9983,8 +10374,8 @@ var asString = (value) => typeof value === "string" ? value : undefined, isRecor
9983
10374
  message: `Multiple frameworks configured (${configured.join(", ")}). Pass --framework <name>.`,
9984
10375
  ok: false
9985
10376
  };
9986
- }, sharedDirFor = (project, framework) => join24(frontendRootFor(project, framework), "shared"), toModuleSpecifier = (fromDir, toFileNoExt) => {
9987
- const rel = relative13(fromDir, toFileNoExt).split("\\").join("/");
10377
+ }, sharedDirFor = (project, framework) => join25(frontendRootFor(project, framework), "shared"), toModuleSpecifier = (fromDir, toFileNoExt) => {
10378
+ const rel = relative14(fromDir, toFileNoExt).split("\\").join("/");
9988
10379
  return rel.startsWith(".") ? rel : `./${rel}`;
9989
10380
  };
9990
10381
  var init_context = __esm(() => {
@@ -10012,8 +10403,8 @@ var emptyOutcome = () => ({
10012
10403
 
10013
10404
  // src/cli/generate/routeWiring.ts
10014
10405
  import ts7 from "typescript";
10015
- import { existsSync as existsSync20, readFileSync as readFileSync20, readdirSync as readdirSync4, writeFileSync as writeFileSync9 } from "fs";
10016
- import { dirname as dirname15, join as join25 } from "path";
10406
+ import { existsSync as existsSync20, readFileSync as readFileSync21, readdirSync as readdirSync4, writeFileSync as writeFileSync9 } from "fs";
10407
+ import { dirname as dirname16, join as join26 } from "path";
10017
10408
  var DEFAULT_SEPARATOR = `
10018
10409
  `, BOUNDARY_USE, applyEdits = (text, edits) => {
10019
10410
  const ordered = [...edits].sort((first, second) => second.start - first.start);
@@ -10163,7 +10554,7 @@ ${newLines.join(`
10163
10554
  }, hasChain = (path) => {
10164
10555
  if (!existsSync20(path))
10165
10556
  return false;
10166
- const sourceFile = parse2(path, readFileSync20(path, "utf-8"));
10557
+ const sourceFile = parse2(path, readFileSync21(path, "utf-8"));
10167
10558
  const found = findElysiaNew(sourceFile);
10168
10559
  return found !== null;
10169
10560
  }, firstChainFile = (pluginsDir) => {
@@ -10172,14 +10563,14 @@ ${newLines.join(`
10172
10563
  for (const name of readdirSync4(pluginsDir)) {
10173
10564
  if (!name.endsWith(".ts"))
10174
10565
  continue;
10175
- const candidate = join25(pluginsDir, name);
10566
+ const candidate = join26(pluginsDir, name);
10176
10567
  if (hasChain(candidate))
10177
10568
  return candidate;
10178
10569
  }
10179
10570
  return null;
10180
10571
  }, findRoutingFile = (serverEntry) => {
10181
- const pluginsDir = join25(dirname15(serverEntry), "plugins");
10182
- const preferred = join25(pluginsDir, "pagesPlugin.ts");
10572
+ const pluginsDir = join26(dirname16(serverEntry), "plugins");
10573
+ const preferred = join26(pluginsDir, "pagesPlugin.ts");
10183
10574
  if (hasChain(preferred))
10184
10575
  return preferred;
10185
10576
  const scanned = firstChainFile(pluginsDir);
@@ -10189,7 +10580,7 @@ ${newLines.join(`
10189
10580
  return serverEntry;
10190
10581
  return null;
10191
10582
  }, buildRouteContext = (input, routingFile) => {
10192
- const specifier = `${toModuleSpecifier(dirname15(routingFile), stripExtension(input.pageFileAbs))}${input.def.pageImportExtension ?? ""}`;
10583
+ const specifier = `${toModuleSpecifier(dirname16(routingFile), stripExtension(input.pageFileAbs))}${input.def.pageImportExtension ?? ""}`;
10193
10584
  return {
10194
10585
  cssAssetKey: input.cssAssetKey,
10195
10586
  indexKey: input.indexKey,
@@ -10212,7 +10603,7 @@ ${newLines.join(`
10212
10603
  };
10213
10604
  if (!hasChain(serverEntry))
10214
10605
  return fallback;
10215
- const text = readFileSync20(serverEntry, "utf-8");
10606
+ const text = readFileSync21(serverEntry, "utf-8");
10216
10607
  const sourceFile = parse2(serverEntry, text);
10217
10608
  const newExpr = findElysiaNew(sourceFile);
10218
10609
  if (!newExpr)
@@ -10241,7 +10632,7 @@ ${newLines.join(`
10241
10632
  ${routeExpr}`
10242
10633
  };
10243
10634
  }
10244
- const text = readFileSync20(routingFile, "utf-8");
10635
+ const text = readFileSync21(routingFile, "utf-8");
10245
10636
  const sourceFile = parse2(routingFile, text);
10246
10637
  const newExpr = findElysiaNew(sourceFile);
10247
10638
  if (!newExpr) {
@@ -10271,7 +10662,7 @@ var init_routeWiring = __esm(() => {
10271
10662
 
10272
10663
  // src/cli/generate/generateApi.ts
10273
10664
  import { existsSync as existsSync21, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
10274
- import { dirname as dirname16, join as join26 } from "path";
10665
+ import { dirname as dirname17, join as join27 } from "path";
10275
10666
  var apiPluginTemplate = (pluginName, base) => `import { Elysia } from 'elysia';
10276
10667
 
10277
10668
  export const ${pluginName} = new Elysia()
@@ -10283,8 +10674,8 @@ export const ${pluginName} = new Elysia()
10283
10674
  const pluginName = `${camel}Plugin`;
10284
10675
  const base = `/api/${kebab}`;
10285
10676
  const outcome = { ...emptyOutcome(), route: base };
10286
- const pluginsDir = join26(dirname16(project.serverEntry), "plugins");
10287
- const fileAbs = join26(pluginsDir, `${pluginName}.ts`);
10677
+ const pluginsDir = join27(dirname17(project.serverEntry), "plugins");
10678
+ const fileAbs = join27(pluginsDir, `${pluginName}.ts`);
10288
10679
  if (existsSync21(fileAbs)) {
10289
10680
  outcome.notes.push(`${pluginName} already exists at ${fileAbs} \u2014 skipped.`);
10290
10681
  return outcome;
@@ -10292,7 +10683,7 @@ export const ${pluginName} = new Elysia()
10292
10683
  mkdirSync10(pluginsDir, { recursive: true });
10293
10684
  writeFileSync10(fileAbs, apiPluginTemplate(pluginName, base), "utf-8");
10294
10685
  outcome.created.push(fileAbs);
10295
- const specifier = toModuleSpecifier(dirname16(project.serverEntry), fileAbs.replace(/\.ts$/, ""));
10686
+ const specifier = toModuleSpecifier(dirname17(project.serverEntry), fileAbs.replace(/\.ts$/, ""));
10296
10687
  const wired = wirePluginUse(project.serverEntry, pluginName, specifier);
10297
10688
  if (wired.kind === "edited")
10298
10689
  outcome.updated.push(wired.routingFile);
@@ -10359,7 +10750,7 @@ var init_componentTemplates = __esm(() => {
10359
10750
 
10360
10751
  // src/cli/generate/generateComponent.ts
10361
10752
  import { existsSync as existsSync22, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
10362
- import { dirname as dirname17, join as join27 } from "path";
10753
+ import { dirname as dirname18, join as join28 } from "path";
10363
10754
  var generateComponent = (project, framework, rawName) => {
10364
10755
  const def = frameworks6[framework];
10365
10756
  const pascal = toPascalCase(rawName);
@@ -10370,12 +10761,12 @@ var generateComponent = (project, framework, rawName) => {
10370
10761
  outcome.manual = { reason: "framework directory missing", snippet: "" };
10371
10762
  return outcome;
10372
10763
  }
10373
- const fileAbs = join27(frameworkDir, "components", def.componentFile({ kebab, pascal }));
10764
+ const fileAbs = join28(frameworkDir, "components", def.componentFile({ kebab, pascal }));
10374
10765
  if (existsSync22(fileAbs)) {
10375
10766
  outcome.notes.push(`${pascal} already exists at ${fileAbs} \u2014 skipped.`);
10376
10767
  return outcome;
10377
10768
  }
10378
- mkdirSync11(dirname17(fileAbs), { recursive: true });
10769
+ mkdirSync11(dirname18(fileAbs), { recursive: true });
10379
10770
  writeFileSync11(fileAbs, componentTemplates[framework]({
10380
10771
  kebab,
10381
10772
  pascal,
@@ -10392,7 +10783,7 @@ var init_generateComponent = __esm(() => {
10392
10783
  // src/cli/generate/cssStrategy.ts
10393
10784
  import ts8 from "typescript";
10394
10785
  import { existsSync as existsSync23 } from "fs";
10395
- import { join as join28 } from "path";
10786
+ import { join as join29 } from "path";
10396
10787
  var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
10397
10788
  margin: 0 auto;
10398
10789
  max-width: 64rem;
@@ -10431,7 +10822,7 @@ var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
10431
10822
  return null;
10432
10823
  }, fileForKey = (stylesDir, assetKey2) => {
10433
10824
  const base = assetKey2.endsWith(CSS_SUFFIX) ? assetKey2.slice(0, -CSS_SUFFIX.length) : assetKey2;
10434
- return join28(stylesDir, `${toKebabCase(base)}.css`);
10825
+ return join29(stylesDir, `${toKebabCase(base)}.css`);
10435
10826
  }, planCss = (routingText, stylesDir, pascal, kebab) => {
10436
10827
  const sharedKey = detectSharedKey(routingText);
10437
10828
  if (sharedKey) {
@@ -10444,7 +10835,7 @@ var CSS_SUFFIX = "CSS", SHARED_MIN_USES = 2, DEFAULT_CSS = `main {
10444
10835
  shared: true
10445
10836
  };
10446
10837
  }
10447
- const cssFileAbs = join28(stylesDir, `${kebab}.css`);
10838
+ const cssFileAbs = join29(stylesDir, `${kebab}.css`);
10448
10839
  return {
10449
10840
  assetKey: `${pascal}${CSS_SUFFIX}`,
10450
10841
  contents: DEFAULT_CSS,
@@ -10457,8 +10848,8 @@ var init_cssStrategy = () => {};
10457
10848
 
10458
10849
  // src/cli/generate/navData.ts
10459
10850
  import ts9 from "typescript";
10460
- import { existsSync as existsSync24, mkdirSync as mkdirSync12, readFileSync as readFileSync21, writeFileSync as writeFileSync12 } from "fs";
10461
- import { dirname as dirname18 } from "path";
10851
+ import { existsSync as existsSync24, mkdirSync as mkdirSync12, readFileSync as readFileSync22, writeFileSync as writeFileSync12 } from "fs";
10852
+ import { dirname as dirname19 } from "path";
10462
10853
  var NAV_DATA_TEMPLATE = `type NavItem = {
10463
10854
  href: string;
10464
10855
  label: string;
@@ -10498,7 +10889,7 @@ export const navData: NavItem[] = [];
10498
10889
  }, readNavItems = (navDataPath) => {
10499
10890
  if (!existsSync24(navDataPath))
10500
10891
  return [];
10501
- const text = readFileSync21(navDataPath, "utf-8");
10892
+ const text = readFileSync22(navDataPath, "utf-8");
10502
10893
  const sourceFile = ts9.createSourceFile(navDataPath, text, ts9.ScriptTarget.Latest, true);
10503
10894
  const array = findNavArray(sourceFile);
10504
10895
  return array ? parseNavItems(array) : [];
@@ -10535,14 +10926,14 @@ ${indent}${entry}`;
10535
10926
  }, upsertNavItem = (navDataPath, item) => {
10536
10927
  const created = !existsSync24(navDataPath);
10537
10928
  if (created) {
10538
- mkdirSync12(dirname18(navDataPath), { recursive: true });
10929
+ mkdirSync12(dirname19(navDataPath), { recursive: true });
10539
10930
  writeFileSync12(navDataPath, NAV_DATA_TEMPLATE, "utf-8");
10540
10931
  }
10541
10932
  const existing = readNavItems(navDataPath);
10542
10933
  if (existing.some((candidate) => candidate.href === item.href)) {
10543
10934
  return { changed: created, created, items: existing };
10544
10935
  }
10545
- const text = readFileSync21(navDataPath, "utf-8");
10936
+ const text = readFileSync22(navDataPath, "utf-8");
10546
10937
  const sourceFile = ts9.createSourceFile(navDataPath, text, ts9.ScriptTarget.Latest, true);
10547
10938
  const array = findNavArray(sourceFile);
10548
10939
  if (!array)
@@ -10701,19 +11092,19 @@ var init_pageTemplates = __esm(() => {
10701
11092
  import {
10702
11093
  existsSync as existsSync25,
10703
11094
  mkdirSync as mkdirSync13,
10704
- readFileSync as readFileSync22,
11095
+ readFileSync as readFileSync23,
10705
11096
  readdirSync as readdirSync5,
10706
11097
  writeFileSync as writeFileSync13
10707
11098
  } from "fs";
10708
- import { dirname as dirname19, join as join29, relative as relative14 } from "path";
11099
+ import { dirname as dirname20, join as join30, relative as relative15 } from "path";
10709
11100
  var writeNew = (path, contents) => {
10710
- mkdirSync13(dirname19(path), { recursive: true });
11101
+ mkdirSync13(dirname20(path), { recursive: true });
10711
11102
  writeFileSync13(path, contents, "utf-8");
10712
11103
  }, toHref = (fromDir, toFile) => {
10713
- const rel = relative14(fromDir, toFile).split("\\").join("/");
11104
+ const rel = relative15(fromDir, toFile).split("\\").join("/");
10714
11105
  return rel.startsWith(".") ? rel : `./${rel}`;
10715
- }, staticPageFiles = (project) => ["html", "htmx"].map((key) => project.frameworkDirs[key]).map((dir) => dir ? join29(dir, "pages") : null).filter((pagesDir) => pagesDir !== null && existsSync25(pagesDir)).flatMap((pagesDir) => readdirSync5(pagesDir).filter((name) => name.endsWith(".html")).map((name) => join29(pagesDir, name))), resyncPage = (file, items) => {
10716
- const html = readFileSync22(file, "utf-8");
11106
+ }, staticPageFiles = (project) => ["html", "htmx"].map((key) => project.frameworkDirs[key]).map((dir) => dir ? join30(dir, "pages") : null).filter((pagesDir) => pagesDir !== null && existsSync25(pagesDir)).flatMap((pagesDir) => readdirSync5(pagesDir).filter((name) => name.endsWith(".html")).map((name) => join30(pagesDir, name))), resyncPage = (file, items) => {
11107
+ const html = readFileSync23(file, "utf-8");
10717
11108
  const synced = syncStaticNav(html, items);
10718
11109
  if (synced === null || synced === html)
10719
11110
  return false;
@@ -10740,19 +11131,19 @@ var writeNew = (path, contents) => {
10740
11131
  outcome.manual = { reason: "framework directory missing", snippet: "" };
10741
11132
  return outcome;
10742
11133
  }
10743
- const pageFileAbs = join29(frameworkDir, "pages", def.pageFile({ kebab, pascal }));
11134
+ const pageFileAbs = join30(frameworkDir, "pages", def.pageFile({ kebab, pascal }));
10744
11135
  if (existsSync25(pageFileAbs)) {
10745
11136
  outcome.notes.push(`${pascal} already exists at ${pageFileAbs} \u2014 skipped.`);
10746
11137
  return outcome;
10747
11138
  }
10748
11139
  const routingFile = findRoutingFile(project.serverEntry);
10749
- const routingText = routingFile ? readFileSync22(routingFile, "utf-8") : "";
11140
+ const routingText = routingFile ? readFileSync23(routingFile, "utf-8") : "";
10750
11141
  const css = planCss(routingText, project.stylesDir, pascal, kebab);
10751
- const navDataPath = join29(sharedDirFor(project, framework), "navData.ts");
11142
+ const navDataPath = join30(sharedDirFor(project, framework), "navData.ts");
10752
11143
  const nav = upsertNavItem(navDataPath, { href: route, label: title });
10753
- const navImportPath = toModuleSpecifier(dirname19(pageFileAbs), navDataPath.replace(/\.ts$/, ""));
11144
+ const navImportPath = toModuleSpecifier(dirname20(pageFileAbs), navDataPath.replace(/\.ts$/, ""));
10754
11145
  writeNew(pageFileAbs, pageTemplates[framework]({
10755
- cssHref: toHref(dirname19(pageFileAbs), css.cssFileAbs),
11146
+ cssHref: toHref(dirname20(pageFileAbs), css.cssFileAbs),
10756
11147
  kebab,
10757
11148
  navImportPath,
10758
11149
  navItems: nav.items,
@@ -10802,7 +11193,7 @@ var exports_generate = {};
10802
11193
  __export(exports_generate, {
10803
11194
  runGenerate: () => runGenerate
10804
11195
  });
10805
- import { relative as relative15 } from "path";
11196
+ import { relative as relative16 } from "path";
10806
11197
  var SUBCOMMANDS, write = (text) => process.stdout.write(`${text}
10807
11198
  `), fail = (message) => {
10808
11199
  process.stdout.write(`${colors.red}${message}${colors.reset}
@@ -10834,7 +11225,7 @@ var SUBCOMMANDS, write = (text) => process.stdout.write(`${text}
10834
11225
  return;
10835
11226
  write(` ${colors.dim}${label}${colors.reset}`);
10836
11227
  for (const path of paths)
10837
- write(` ${relative15(cwd, path)}`);
11228
+ write(` ${relative16(cwd, path)}`);
10838
11229
  }, printSummary = (title, outcome, cwd) => {
10839
11230
  for (const note of outcome.notes) {
10840
11231
  write(`${colors.yellow}!${colors.reset} ${note}`);
@@ -10935,7 +11326,7 @@ var init_serialize = () => {};
10935
11326
 
10936
11327
  // src/cli/config/absolute/editAbsoluteConfig.ts
10937
11328
  import ts10 from "typescript";
10938
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync14 } from "fs";
11329
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync14 } from "fs";
10939
11330
  var lineStartOffset = (text, position) => {
10940
11331
  let index = position;
10941
11332
  while (index > 0 && text[index - 1] !== `
@@ -10944,7 +11335,7 @@ var lineStartOffset = (text, position) => {
10944
11335
  return index;
10945
11336
  }, indentBefore2 = (text, position) => text.slice(lineStartOffset(text, position), position), findProperty = (object, name) => object.properties.find((property) => ts10.isPropertyAssignment(property) && (ts10.isIdentifier(property.name) || ts10.isStringLiteral(property.name)) && property.name.text === name), applyAbsoluteConfigEdit = (configPath2, request) => {
10946
11337
  try {
10947
- const text = readFileSync23(configPath2, "utf-8");
11338
+ const text = readFileSync24(configPath2, "utf-8");
10948
11339
  const sourceFile = ts10.createSourceFile(configPath2, text, ts10.ScriptTarget.Latest, true);
10949
11340
  const object = findConfigObject(sourceFile);
10950
11341
  if (!object) {
@@ -11127,14 +11518,14 @@ var init_catalog = __esm(() => {
11127
11518
  });
11128
11519
 
11129
11520
  // src/cli/integrations/addPlugin.ts
11130
- import { existsSync as existsSync26, readFileSync as readFileSync24 } from "fs";
11131
- import { join as join30 } from "path";
11521
+ import { existsSync as existsSync26, readFileSync as readFileSync25 } from "fs";
11522
+ import { join as join31 } from "path";
11132
11523
  var isRecord11 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readPackageJson = (cwd) => {
11133
- const path = join30(cwd, "package.json");
11524
+ const path = join31(cwd, "package.json");
11134
11525
  if (!existsSync26(path))
11135
11526
  return null;
11136
11527
  try {
11137
- const parsed = JSON.parse(readFileSync24(path, "utf-8"));
11528
+ const parsed = JSON.parse(readFileSync25(path, "utf-8"));
11138
11529
  return isRecord11(parsed) ? parsed : null;
11139
11530
  } catch {
11140
11531
  return null;
@@ -11626,7 +12017,7 @@ var init_authCatalog = __esm(() => {
11626
12017
 
11627
12018
  // src/cli/config/auth/resolveAuthSettings.ts
11628
12019
  import ts11 from "typescript";
11629
- import { existsSync as existsSync27, readFileSync as readFileSync25 } from "fs";
12020
+ import { existsSync as existsSync27, readFileSync as readFileSync26 } from "fs";
11630
12021
  import { resolve as resolve26 } from "path";
11631
12022
  var AUTH_PACKAGE = "@absolutejs/auth", CONFIG_CANDIDATES3, findAuthSettingsPath = (cwd, override) => {
11632
12023
  if (override) {
@@ -11656,7 +12047,7 @@ var AUTH_PACKAGE = "@absolutejs/auth", CONFIG_CANDIDATES3, findAuthSettingsPath
11656
12047
  }
11657
12048
  return null;
11658
12049
  }, parseAuthSettingsObject = (configPath2) => {
11659
- const text = readFileSync25(configPath2, "utf-8");
12050
+ const text = readFileSync26(configPath2, "utf-8");
11660
12051
  return {
11661
12052
  object: findAuthSettingsObject(parseSource2(configPath2, text)),
11662
12053
  text
@@ -11731,13 +12122,13 @@ var init_resolveAuthSettings = __esm(() => {
11731
12122
 
11732
12123
  // src/cli/config/auth/resolveAuthState.ts
11733
12124
  import ts12 from "typescript";
11734
- import { existsSync as existsSync28, readdirSync as readdirSync6, readFileSync as readFileSync26 } from "fs";
11735
- import { join as join31, relative as relative16, resolve as resolve27 } from "path";
12125
+ import { existsSync as existsSync28, readdirSync as readdirSync6, readFileSync as readFileSync27 } from "fs";
12126
+ import { join as join32, relative as relative17, resolve as resolve27 } from "path";
11736
12127
  var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutejs/absolute-auth", NPM_URL = "https://www.npmjs.com/package/@absolutejs/auth", SKIP_DIRS, MAX_FILES = 4000, SETUP_EXPORTS, isRecord12 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), readJson = (path) => {
11737
12128
  if (!existsSync28(path))
11738
12129
  return null;
11739
12130
  try {
11740
- const parsed = JSON.parse(readFileSync26(path, "utf-8"));
12131
+ const parsed = JSON.parse(readFileSync27(path, "utf-8"));
11741
12132
  return isRecord12(parsed) ? parsed : null;
11742
12133
  } catch {
11743
12134
  return null;
@@ -11746,7 +12137,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
11746
12137
  const value = record?.[key];
11747
12138
  return typeof value === "string" ? value : null;
11748
12139
  }, declaredVersionFor = (cwd) => {
11749
- const pkg = readJson(join31(cwd, "package.json"));
12140
+ const pkg = readJson(join32(cwd, "package.json"));
11750
12141
  if (!pkg)
11751
12142
  return null;
11752
12143
  for (const field of ["dependencies", "devDependencies"]) {
@@ -11758,14 +12149,14 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
11758
12149
  return version2;
11759
12150
  }
11760
12151
  return null;
11761
- }, installedVersionFor = (cwd) => stringField(readJson(join31(cwd, "node_modules", AUTH_PACKAGE2, "package.json")), "version"), SOURCE_FILE, safeReaddir = (dir) => {
12152
+ }, installedVersionFor = (cwd) => stringField(readJson(join32(cwd, "node_modules", AUTH_PACKAGE2, "package.json")), "version"), SOURCE_FILE, safeReaddir = (dir) => {
11762
12153
  try {
11763
12154
  return readdirSync6(dir, { withFileTypes: true });
11764
12155
  } catch {
11765
12156
  return [];
11766
12157
  }
11767
12158
  }, sortEntry = (dir, entry, found, dirs) => {
11768
- const full = join31(dir, entry.name);
12159
+ const full = join32(dir, entry.name);
11769
12160
  if (entry.isDirectory()) {
11770
12161
  if (SKIP_DIRS.has(entry.name) || entry.name.startsWith("."))
11771
12162
  return;
@@ -11830,7 +12221,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
11830
12221
  return { keys: new Set, providerCount: null, usesSpread: true };
11831
12222
  }, readFileOrNull = (path) => {
11832
12223
  try {
11833
- return readFileSync26(path, "utf-8");
12224
+ return readFileSync27(path, "utf-8");
11834
12225
  } catch {
11835
12226
  return null;
11836
12227
  }
@@ -11863,7 +12254,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
11863
12254
  scaffoldable: isScaffoldableFeature(feature.id)
11864
12255
  })), resolveAuthState = (cwd) => {
11865
12256
  const installedVersion = installedVersionFor(cwd);
11866
- const root = existsSync28(join31(cwd, "src")) ? join31(cwd, "src") : cwd;
12257
+ const root = existsSync28(join32(cwd, "src")) ? join32(cwd, "src") : cwd;
11867
12258
  let match = null;
11868
12259
  let setupPath = null;
11869
12260
  for (const file of candidateFiles(root)) {
@@ -11871,7 +12262,7 @@ var AUTH_PACKAGE2 = "@absolutejs/auth", REPO_URL = "https://github.com/absolutej
11871
12262
  if (found === null)
11872
12263
  continue;
11873
12264
  match = found;
11874
- setupPath = relative16(cwd, resolve27(file));
12265
+ setupPath = relative17(cwd, resolve27(file));
11875
12266
  break;
11876
12267
  }
11877
12268
  const keys = match?.keys ?? new Set;
@@ -11909,7 +12300,7 @@ var init_resolveAuthState = __esm(() => {
11909
12300
 
11910
12301
  // src/cli/config/auth/scaffoldAuthFeature.ts
11911
12302
  import { existsSync as existsSync29, writeFileSync as writeFileSync15 } from "fs";
11912
- import { dirname as dirname20, join as join32, relative as relative17, resolve as resolve28 } from "path";
12303
+ import { dirname as dirname21, join as join33, relative as relative18, resolve as resolve28 } from "path";
11913
12304
  var renderScaffold = (scaffold) => {
11914
12305
  const importNames = [...scaffold.imports, `type ${scaffold.typeName}`];
11915
12306
  const importLine = `import { ${importNames.join(", ")} } from '@absolutejs/auth';`;
@@ -11934,8 +12325,8 @@ ${body}
11934
12325
  }, targetDir = (cwd) => {
11935
12326
  const { setupPath } = resolveAuthState(cwd);
11936
12327
  if (setupPath)
11937
- return dirname20(resolve28(cwd, setupPath));
11938
- const src = join32(cwd, "src");
12328
+ return dirname21(resolve28(cwd, setupPath));
12329
+ const src = join33(cwd, "src");
11939
12330
  return existsSync29(src) ? src : cwd;
11940
12331
  }, spreadFor = (scaffold) => `import { ${scaffold.exportName} } from './${scaffold.exportName}';
11941
12332
  // add to your auth() call:
@@ -11949,8 +12340,8 @@ ${scaffold.configKey}: ${scaffold.exportName}`, failure2 = (message) => ({
11949
12340
  const scaffold = AUTH_SCAFFOLDS[id];
11950
12341
  if (!scaffold)
11951
12342
  return failure2(`Unknown auth feature "${id}".`);
11952
- const filePath = join32(targetDir(cwd), `${scaffold.exportName}.ts`);
11953
- const relPath = relative17(cwd, filePath);
12343
+ const filePath = join33(targetDir(cwd), `${scaffold.exportName}.ts`);
12344
+ const relPath = relative18(cwd, filePath);
11954
12345
  if (existsSync29(filePath)) {
11955
12346
  return {
11956
12347
  created: null,
@@ -11978,12 +12369,12 @@ var init_scaffoldAuthFeature = __esm(() => {
11978
12369
  });
11979
12370
 
11980
12371
  // src/cli/htmx/install.ts
11981
- import { existsSync as existsSync30, mkdirSync as mkdirSync14, readFileSync as readFileSync27, writeFileSync as writeFileSync16 } from "fs";
11982
- import { join as join33 } from "path";
12372
+ import { existsSync as existsSync30, mkdirSync as mkdirSync14, readFileSync as readFileSync28, writeFileSync as writeFileSync16 } from "fs";
12373
+ import { join as join34 } from "path";
11983
12374
  var VENDORED_HTMX_VERSION = "2.0.6", vendoredHtmxFile = () => [
11984
- join33(import.meta.dir, "htmx.min.js"),
11985
- join33(import.meta.dir, "htmx", "htmx.min.js"),
11986
- join33(import.meta.dir, "..", "htmx", "htmx.min.js")
12375
+ join34(import.meta.dir, "htmx.min.js"),
12376
+ join34(import.meta.dir, "htmx", "htmx.min.js"),
12377
+ join34(import.meta.dir, "..", "htmx", "htmx.min.js")
11987
12378
  ].find((path) => existsSync30(path)) ?? null, detectHtmxVersion = (content) => {
11988
12379
  const match = content.match(/version:"([0-9.]+)"/);
11989
12380
  return match ? match[1] : null;
@@ -11995,16 +12386,16 @@ var VENDORED_HTMX_VERSION = "2.0.6", vendoredHtmxFile = () => [
11995
12386
  }
11996
12387
  return response.text();
11997
12388
  }, installedHtmxVersion = (htmxDir) => {
11998
- const file = join33(htmxDir, "htmx.min.js");
12389
+ const file = join34(htmxDir, "htmx.min.js");
11999
12390
  if (!existsSync30(file))
12000
12391
  return null;
12001
- return detectHtmxVersion(readFileSync27(file, "utf-8"));
12392
+ return detectHtmxVersion(readFileSync28(file, "utf-8"));
12002
12393
  }, readVendoredHtmx = () => {
12003
12394
  const file = vendoredHtmxFile();
12004
- return file ? readFileSync27(file, "utf-8") : null;
12395
+ return file ? readFileSync28(file, "utf-8") : null;
12005
12396
  }, writeHtmx = (htmxDir, content) => {
12006
12397
  mkdirSync14(htmxDir, { recursive: true });
12007
- const file = join33(htmxDir, "htmx.min.js");
12398
+ const file = join34(htmxDir, "htmx.min.js");
12008
12399
  writeFileSync16(file, content, "utf-8");
12009
12400
  return file;
12010
12401
  };
@@ -12015,7 +12406,7 @@ var exports_add = {};
12015
12406
  __export(exports_add, {
12016
12407
  runAdd: () => runAdd
12017
12408
  });
12018
- import { dirname as dirname21, join as join34, relative as relative18 } from "path";
12409
+ import { dirname as dirname22, join as join35, relative as relative19 } from "path";
12019
12410
  var write2 = (text) => process.stdout.write(`${text}
12020
12411
  `), fail2 = (message) => {
12021
12412
  process.stdout.write(`${colors.red}${message}${colors.reset}
@@ -12026,11 +12417,11 @@ var write2 = (text) => process.stdout.write(`${text}
12026
12417
  return;
12027
12418
  write2(` ${colors.dim}${label}${colors.reset}`);
12028
12419
  for (const path of paths)
12029
- write2(` ${relative18(cwd, path)}`);
12420
+ write2(` ${relative19(cwd, path)}`);
12030
12421
  }, frontendRoot = (project, cwd) => {
12031
12422
  const [firstKey] = configuredFrameworks(project);
12032
12423
  const firstDir = firstKey ? project.frameworkDirs[firstKey] : undefined;
12033
- return firstDir ? dirname21(firstDir) : join34(cwd, "src", "frontend");
12424
+ return firstDir ? dirname22(firstDir) : join35(cwd, "src", "frontend");
12034
12425
  }, addIntegrationCli = (id, install) => {
12035
12426
  const result = addIntegration(process.cwd(), id, { install });
12036
12427
  if (!result.ok) {
@@ -12094,8 +12485,8 @@ var write2 = (text) => process.stdout.write(`${text}
12094
12485
  write2(`${colors.yellow}!${colors.reset} ${frameworks6[framework].label} is already configured \u2014 nothing to do.`);
12095
12486
  return;
12096
12487
  }
12097
- const dirAbs = join34(frontendRoot(project, cwd), framework);
12098
- const dirRel = `./${relative18(cwd, dirAbs).split("\\").join("/")}`;
12488
+ const dirAbs = join35(frontendRoot(project, cwd), framework);
12489
+ const dirRel = `./${relative19(cwd, dirAbs).split("\\").join("/")}`;
12099
12490
  let depNote = "Skipped dependency install (--no-install).";
12100
12491
  if (!noInstall) {
12101
12492
  write2(`${colors.dim}Installing ${frameworks6[framework].label} dependencies\u2026${colors.reset}`);
@@ -12164,8 +12555,8 @@ var exports_analyze = {};
12164
12555
  __export(exports_analyze, {
12165
12556
  runAnalyze: () => runAnalyze
12166
12557
  });
12167
- import { existsSync as existsSync31, readFileSync as readFileSync28, statSync as statSync3, writeFileSync as writeFileSync17 } from "fs";
12168
- import { join as join35, resolve as resolve29 } from "path";
12558
+ import { existsSync as existsSync31, readFileSync as readFileSync29, statSync as statSync3, writeFileSync as writeFileSync17 } from "fs";
12559
+ import { join as join36, resolve as resolve29 } from "path";
12169
12560
  var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_WIDTH = 16, SIZE_WIDTH = 12, CHANGE_WIDTH = 10, CATEGORY_ORDER, categoryOf = (key) => {
12170
12561
  if (key.startsWith("Island"))
12171
12562
  return "Islands";
@@ -12185,21 +12576,21 @@ var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_W
12185
12576
  return 0;
12186
12577
  }
12187
12578
  }, readSizes = (manifestDir) => {
12188
- const manifestPath = join35(manifestDir, "manifest.json");
12579
+ const manifestPath = join36(manifestDir, "manifest.json");
12189
12580
  if (!existsSync31(manifestPath))
12190
12581
  return null;
12191
- const manifest = JSON.parse(readFileSync28(manifestPath, "utf-8"));
12582
+ const manifest = JSON.parse(readFileSync29(manifestPath, "utf-8"));
12192
12583
  const sizes = {};
12193
12584
  for (const [key, value] of Object.entries(manifest)) {
12194
- sizes[key] = fileSize2(join35(manifestDir, value.replace(/^\//, "")));
12585
+ sizes[key] = fileSize2(join36(manifestDir, value.replace(/^\//, "")));
12195
12586
  }
12196
12587
  return sizes;
12197
12588
  }, readBaseline = (cwd) => {
12198
- const path = join35(cwd, BASELINE_FILE);
12589
+ const path = join36(cwd, BASELINE_FILE);
12199
12590
  if (!existsSync31(path))
12200
12591
  return null;
12201
12592
  try {
12202
- const parsed = JSON.parse(readFileSync28(path, "utf-8"));
12593
+ const parsed = JSON.parse(readFileSync29(path, "utf-8"));
12203
12594
  return parsed;
12204
12595
  } catch {
12205
12596
  return null;
@@ -12284,7 +12675,7 @@ var BASELINE_FILE = ".absolute-size-baseline.json", TOP_CHANGES = 12, CATEGORY_W
12284
12675
  return;
12285
12676
  }
12286
12677
  if (args.includes("--save")) {
12287
- writeFileSync17(join35(cwd, BASELINE_FILE), `${JSON.stringify(sizes, null, 2)}
12678
+ writeFileSync17(join36(cwd, BASELINE_FILE), `${JSON.stringify(sizes, null, 2)}
12288
12679
  `);
12289
12680
  process.stdout.write(`${colors.green}\u2713${colors.reset} Saved size baseline (${Object.keys(sizes).length} entries) to ${BASELINE_FILE}
12290
12681
  `);
@@ -12530,8 +12921,8 @@ var exports_remove = {};
12530
12921
  __export(exports_remove, {
12531
12922
  runRemove: () => runRemove
12532
12923
  });
12533
- import { existsSync as existsSync32, readFileSync as readFileSync29 } from "fs";
12534
- import { relative as relative19 } from "path";
12924
+ import { existsSync as existsSync32, readFileSync as readFileSync30 } from "fs";
12925
+ import { relative as relative20 } from "path";
12535
12926
  var write3 = (text) => process.stdout.write(`${text}
12536
12927
  `), fail3 = (message) => {
12537
12928
  process.stdout.write(`${colors.red}${message}${colors.reset}
@@ -12544,7 +12935,7 @@ var write3 = (text) => process.stdout.write(`${text}
12544
12935
  if (file === null || seen.has(file) || !existsSync32(file))
12545
12936
  return false;
12546
12937
  seen.add(file);
12547
- return readFileSync29(file, "utf-8").includes(handler);
12938
+ return readFileSync30(file, "utf-8").includes(handler);
12548
12939
  });
12549
12940
  }, runRemove = async (args) => {
12550
12941
  const [framework] = args.filter((arg) => !arg.startsWith("--"));
@@ -12580,10 +12971,10 @@ var write3 = (text) => process.stdout.write(`${text}
12580
12971
  }
12581
12972
  write3(`${colors.green}\u2713${colors.reset} Removed ${framework}Directory from absolute.config.ts
12582
12973
  `);
12583
- write3(` ${colors.dim}Kept${colors.reset} ${relative19(cwd, frameworkDir)} \u2014 delete its source manually if no longer needed.`);
12974
+ write3(` ${colors.dim}Kept${colors.reset} ${relative20(cwd, frameworkDir)} \u2014 delete its source manually if no longer needed.`);
12584
12975
  const refs = referencingFiles(project.serverEntry, HANDLER_NAME[framework]);
12585
12976
  for (const file of refs) {
12586
- write3(` ${colors.yellow}Still references${colors.reset} ${relative19(cwd, file)} (calls ${HANDLER_NAME[framework]})`);
12977
+ write3(` ${colors.yellow}Still references${colors.reset} ${relative20(cwd, file)} (calls ${HANDLER_NAME[framework]})`);
12587
12978
  }
12588
12979
  const deps = frameworkDependencyNames(framework);
12589
12980
  if (prune && deps.length > 0) {
@@ -12671,15 +13062,15 @@ __export(exports_env, {
12671
13062
  runEnv: () => runEnv,
12672
13063
  collectEnvVars: () => collectEnvVars
12673
13064
  });
12674
- import { existsSync as existsSync33, readFileSync as readFileSync30 } from "fs";
12675
- import { join as join36 } from "path";
13065
+ import { existsSync as existsSync33, readFileSync as readFileSync31 } from "fs";
13066
+ import { join as join37 } from "path";
12676
13067
  var {env: env3, Glob: Glob3 } = globalThis.Bun;
12677
- var EXTENSIONS = "ts,tsx,js,jsx,mjs,cjs,svelte,vue", STATUS_WIDTH2, keysInFile = (text) => [...text.matchAll(/getEnv\(\s*['"]([^'"]+)['"]\s*\)/g)].map((match) => match[1]).filter((key) => key !== undefined), scanPatterns = () => existsSync33(join36(process.cwd(), "src")) ? [`src/**/*.{${EXTENSIONS}}`] : [`*.{${EXTENSIONS}}`], scanEnvUsage = async () => {
13068
+ var EXTENSIONS = "ts,tsx,js,jsx,mjs,cjs,svelte,vue", STATUS_WIDTH2, keysInFile = (text) => [...text.matchAll(/getEnv\(\s*['"]([^'"]+)['"]\s*\)/g)].map((match) => match[1]).filter((key) => key !== undefined), scanPatterns = () => existsSync33(join37(process.cwd(), "src")) ? [`src/**/*.{${EXTENSIONS}}`] : [`*.{${EXTENSIONS}}`], scanEnvUsage = async () => {
12678
13069
  const scans = scanPatterns().map((pattern) => Array.fromAsync(new Glob3(pattern).scan({ cwd: process.cwd() })));
12679
13070
  const files = (await Promise.all(scans)).flat();
12680
13071
  const usage = new Map;
12681
13072
  files.forEach((file) => {
12682
- keysInFile(readFileSync30(file, "utf-8")).forEach((key) => {
13073
+ keysInFile(readFileSync31(file, "utf-8")).forEach((key) => {
12683
13074
  usage.set(key, [...usage.get(key) ?? [], file]);
12684
13075
  });
12685
13076
  });
@@ -12740,8 +13131,8 @@ __export(exports_db, {
12740
13131
  conflictClause: () => conflictClause,
12741
13132
  chunkRows: () => chunkRows
12742
13133
  });
12743
- import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync31, writeFileSync as writeFileSync18 } from "fs";
12744
- import { join as join37 } from "path";
13134
+ import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync32, writeFileSync as writeFileSync18 } from "fs";
13135
+ import { join as join38 } from "path";
12745
13136
  var {env: env4, spawn: spawn2, SQL } = globalThis.Bun;
12746
13137
  var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA_TYPES, SEED_CANDIDATES, VALUE_FLAGS, paint = (text, color) => `${color}${text}${colors.reset}`, chunkRows = (items, size) => Array.from({ length: Math.ceil(items.length / size) }, (_, idx) => items.slice(idx * size, idx * size + size)), quoteIdent = (name) => `"${name.replace(/"/g, '""')}"`, resolveUrl = (explicit) => {
12747
13138
  const found = explicit ?? URL_ENV_KEYS.map((key) => env4[key]).find((value) => typeof value === "string" && value !== "");
@@ -12851,19 +13242,19 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
12851
13242
  tables,
12852
13243
  v: BACKUP_FORMAT_VERSION
12853
13244
  };
12854
- const dir = options.out ?? join37(process.cwd(), "backups");
13245
+ const dir = options.out ?? join38(process.cwd(), "backups");
12855
13246
  mkdirSync15(dir, { recursive: true });
12856
13247
  const json = JSON.stringify(payload, (_, value) => typeof value === "bigint" ? value.toString() : value);
12857
- const file = join37(dir, `backup-${payload.at.replace(/[:.]/g, "-")}.json`);
13248
+ const file = join38(dir, `backup-${payload.at.replace(/[:.]/g, "-")}.json`);
12858
13249
  writeFileSync18(file, json);
12859
- writeFileSync18(join37(dir, "latest.json"), json);
13250
+ writeFileSync18(join38(dir, "latest.json"), json);
12860
13251
  const total = chosen.reduce((sum, name) => sum + (tables[name]?.length ?? 0), 0);
12861
13252
  console.log(paint(`\u2713 backup \u2192 ${file}`, colors.green));
12862
13253
  console.log(paint(` ${chosen.length} tables, ${total} rows`, colors.dim));
12863
13254
  }, runRestore = async (file, options) => {
12864
13255
  if (!existsSync34(file))
12865
13256
  throw new Error(`Backup not found: ${file}`);
12866
- const payload = JSON.parse(readFileSync31(file, "utf-8"));
13257
+ const payload = JSON.parse(readFileSync32(file, "utf-8"));
12867
13258
  const names = Object.keys(payload.tables).filter((name) => keepTable(name, options));
12868
13259
  const sql = new SQL(options.url);
12869
13260
  const order = dependencyOrder(names, await foreignLinks(sql));
@@ -12885,7 +13276,7 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
12885
13276
  const total = order.reduce((sum, name) => sum + (payload.tables[name]?.length ?? 0), 0);
12886
13277
  console.log(paint(`\u2713 restored ${order.length} tables, ${total} rows (idempotent upsert by primary key)`, colors.green));
12887
13278
  }, runSeed = async (entry) => {
12888
- const target = entry ?? SEED_CANDIDATES.find((candidate) => existsSync34(join37(process.cwd(), candidate)));
13279
+ const target = entry ?? SEED_CANDIDATES.find((candidate) => existsSync34(join38(process.cwd(), candidate)));
12889
13280
  if (target === undefined)
12890
13281
  throw new Error(`No seed script found (looked for ${SEED_CANDIDATES.join(", ")}). Pass a path: absolute db seed <file>.`);
12891
13282
  console.log(paint(`seeding via ${target}\u2026`, colors.cyan));
@@ -12920,7 +13311,7 @@ var BACKUP_FORMAT_VERSION = 1, RESTORE_CHUNK_ROWS = 500, URL_ENV_KEYS, JSON_DATA
12920
13311
  return;
12921
13312
  }
12922
13313
  if (sub === "restore") {
12923
- const file = positionalArgs(rest)[0] ?? join37(process.cwd(), "backups", "latest.json");
13314
+ const file = positionalArgs(rest)[0] ?? join38(process.cwd(), "backups", "latest.json");
12924
13315
  await runRestore(file, parseOptions(rest));
12925
13316
  return;
12926
13317
  }
@@ -13034,16 +13425,16 @@ var init_logs = __esm(() => {
13034
13425
  // src/cli/typeGraphCoherence.ts
13035
13426
  import {
13036
13427
  existsSync as existsSync36,
13037
- readFileSync as readFileSync32,
13428
+ readFileSync as readFileSync33,
13038
13429
  realpathSync as realpathSync2,
13039
13430
  rmSync as rmSync6,
13040
13431
  writeFileSync as writeFileSync19
13041
13432
  } from "fs";
13042
13433
  import { createRequire } from "module";
13043
- import { dirname as dirname22, join as join38, resolve as resolve30, sep as sep5 } from "path";
13434
+ import { dirname as dirname23, join as join39, resolve as resolve30, sep as sep5 } from "path";
13044
13435
  var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13045
13436
  try {
13046
- const parsed = JSON.parse(readFileSync32(path, "utf-8"));
13437
+ const parsed = JSON.parse(readFileSync33(path, "utf-8"));
13047
13438
  return isRecord9(parsed) ? parsed : null;
13048
13439
  } catch {
13049
13440
  return null;
@@ -13060,13 +13451,13 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13060
13451
  const version2 = Reflect.get(manifest, "version");
13061
13452
  return typeof version2 === "string" ? version2 : "unknown";
13062
13453
  }, packageJsonFromEntry = (entry, expectedName) => {
13063
- let directory = dirname22(entry);
13454
+ let directory = dirname23(entry);
13064
13455
  for (;; ) {
13065
- const candidate = join38(directory, "package.json");
13456
+ const candidate = join39(directory, "package.json");
13066
13457
  const manifest = readManifest(candidate);
13067
13458
  if (manifest && manifestName(manifest, "") === expectedName)
13068
13459
  return candidate;
13069
- const parent = dirname22(directory);
13460
+ const parent = dirname23(directory);
13070
13461
  if (parent === directory)
13071
13462
  return null;
13072
13463
  directory = parent;
@@ -13084,10 +13475,10 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13084
13475
  }, findInstallRoot = (cwd) => {
13085
13476
  let directory = resolve30(cwd);
13086
13477
  for (;; ) {
13087
- if (existsSync36(join38(directory, "bun.lock")) || existsSync36(join38(directory, "bun.lockb"))) {
13478
+ if (existsSync36(join39(directory, "bun.lock")) || existsSync36(join39(directory, "bun.lockb"))) {
13088
13479
  return directory;
13089
13480
  }
13090
- const parent = dirname22(directory);
13481
+ const parent = dirname23(directory);
13091
13482
  if (parent === directory)
13092
13483
  return resolve30(cwd);
13093
13484
  directory = parent;
@@ -13095,14 +13486,14 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13095
13486
  }, findProjectManifest = (cwd, installRoot) => {
13096
13487
  let directory = resolve30(cwd);
13097
13488
  for (;; ) {
13098
- const candidate = join38(directory, "package.json");
13489
+ const candidate = join39(directory, "package.json");
13099
13490
  if (existsSync36(candidate))
13100
13491
  return candidate;
13101
13492
  if (directory === installRoot)
13102
- return join38(installRoot, "package.json");
13103
- const parent = dirname22(directory);
13493
+ return join39(installRoot, "package.json");
13494
+ const parent = dirname23(directory);
13104
13495
  if (parent === directory)
13105
- return join38(installRoot, "package.json");
13496
+ return join39(installRoot, "package.json");
13106
13497
  directory = parent;
13107
13498
  }
13108
13499
  }, appendConsumer = (consumers, consumerPaths, path, manifest) => {
@@ -13140,7 +13531,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13140
13531
  appendConsumer(consumers, consumerPaths, inspection.consumer.path, inspection.consumer.manifest);
13141
13532
  }, inspectTypeGraph = (cwd) => {
13142
13533
  const installRoot = findInstallRoot(cwd);
13143
- const rootManifestPath = join38(installRoot, "package.json");
13534
+ const rootManifestPath = join39(installRoot, "package.json");
13144
13535
  const rootManifest = readManifest(rootManifestPath) ?? {};
13145
13536
  const consumers = [
13146
13537
  { manifest: rootManifest, path: rootManifestPath }
@@ -13176,7 +13567,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13176
13567
  const duplicates = duplicateTypeGraphPackages(report);
13177
13568
  if (duplicates.length === 0)
13178
13569
  return [];
13179
- const manifestPath = join38(report.installRoot, "package.json");
13570
+ const manifestPath = join39(report.installRoot, "package.json");
13180
13571
  const manifest = readManifest(manifestPath);
13181
13572
  if (!manifest)
13182
13573
  return [];
@@ -13198,7 +13589,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13198
13589
  }
13199
13590
  return changes;
13200
13591
  }, removeDuplicateTypeGraphPackages = (report) => {
13201
- const manifest = readManifest(join38(report.installRoot, "package.json")) ?? {};
13592
+ const manifest = readManifest(join39(report.installRoot, "package.json")) ?? {};
13202
13593
  const rootName = manifestName(manifest, "<workspace>");
13203
13594
  const installPrefix = `${realpathSync2(report.installRoot)}${sep5}`;
13204
13595
  const nodeModulesSegment = `${sep5}node_modules${sep5}`;
@@ -13210,7 +13601,7 @@ var DEPENDENCY_FIELDS, TYPE_GRAPH_PACKAGES, readManifest = (path) => {
13210
13601
  for (const stalePath of stalePaths) {
13211
13602
  if (!stalePath.startsWith(installPrefix) || !stalePath.includes(nodeModulesSegment))
13212
13603
  continue;
13213
- rmSync6(dirname22(stalePath), { force: true, recursive: true });
13604
+ rmSync6(dirname23(stalePath), { force: true, recursive: true });
13214
13605
  removed.push(stalePath);
13215
13606
  }
13216
13607
  return removed;
@@ -13237,10 +13628,10 @@ var exports_doctor = {};
13237
13628
  __export(exports_doctor, {
13238
13629
  runDoctor: () => runDoctor
13239
13630
  });
13240
- import { existsSync as existsSync37, mkdirSync as mkdirSync16, readFileSync as readFileSync33, writeFileSync as writeFileSync20 } from "fs";
13631
+ import { existsSync as existsSync37, mkdirSync as mkdirSync16, readFileSync as readFileSync34, writeFileSync as writeFileSync20 } from "fs";
13241
13632
  import { createRequire as createRequire2 } from "module";
13242
13633
  import { arch as arch4, platform as platform5 } from "os";
13243
- import { join as join39 } from "path";
13634
+ import { join as join40 } from "path";
13244
13635
  var FRAMEWORK_FIELDS2, projectRequire, check = (status2, label, detail) => ({
13245
13636
  detail,
13246
13637
  label,
@@ -13275,7 +13666,7 @@ var FRAMEWORK_FIELDS2, projectRequire, check = (status2, label, detail) => ({
13275
13666
  return [];
13276
13667
  const label = `${field.replace("Directory", "")} pages`;
13277
13668
  return [
13278
- existsSync37(join39(process.cwd(), dir)) ? check("ok", label, dir) : check("fail", label, `${dir} (missing)`)
13669
+ existsSync37(join40(process.cwd(), dir)) ? check("ok", label, dir) : check("fail", label, `${dir} (missing)`)
13279
13670
  ];
13280
13671
  }), envCheck = async () => {
13281
13672
  const vars = await collectEnvVars();
@@ -13337,9 +13728,9 @@ ${colors.dim}${checks.length} checks \xB7 ${colors.reset}${summary}${colors.dim}
13337
13728
  const fixes = [];
13338
13729
  for (const field of FRAMEWORK_FIELDS2) {
13339
13730
  const dir = readString2(config, field);
13340
- if (dir === undefined || existsSync37(join39(cwd, dir)))
13731
+ if (dir === undefined || existsSync37(join40(cwd, dir)))
13341
13732
  continue;
13342
- mkdirSync16(join39(cwd, dir, "pages"), { recursive: true });
13733
+ mkdirSync16(join40(cwd, dir, "pages"), { recursive: true });
13343
13734
  fixes.push(`created ${dir}/pages`);
13344
13735
  }
13345
13736
  return fixes;
@@ -13347,8 +13738,8 @@ ${colors.dim}${checks.length} checks \xB7 ${colors.reset}${summary}${colors.dim}
13347
13738
  const missing = (await collectEnvVars()).filter((entry) => !entry.set);
13348
13739
  if (missing.length === 0)
13349
13740
  return null;
13350
- const envExample = join39(cwd, ".env.example");
13351
- const existing = existsSync37(envExample) ? readFileSync33(envExample, "utf-8") : "";
13741
+ const envExample = join40(cwd, ".env.example");
13742
+ const existing = existsSync37(envExample) ? readFileSync34(envExample, "utf-8") : "";
13352
13743
  const existingKeys = new Set(existing.split(`
13353
13744
  `).map((line) => line.split("=")[0]?.trim()));
13354
13745
  const toAdd = missing.filter((entry) => !existingKeys.has(entry.key));
@@ -13418,7 +13809,7 @@ var init_doctor = __esm(() => {
13418
13809
  "htmlDirectory",
13419
13810
  "htmxDirectory"
13420
13811
  ];
13421
- projectRequire = createRequire2(join39(process.cwd(), "package.json"));
13812
+ projectRequire = createRequire2(join40(process.cwd(), "package.json"));
13422
13813
  STATUS_MARK = {
13423
13814
  fail: `${colors.red}\u2717${colors.reset}`,
13424
13815
  ok: `${colors.green}\u2713${colors.reset}`,
@@ -13807,8 +14198,8 @@ var init_sourceMetadata = __esm(() => {
13807
14198
  });
13808
14199
 
13809
14200
  // src/islands/pageMetadata.ts
13810
- import { readFileSync as readFileSync34 } from "fs";
13811
- import { dirname as dirname23, resolve as resolve31 } from "path";
14201
+ import { readFileSync as readFileSync35 } from "fs";
14202
+ import { dirname as dirname24, resolve as resolve31 } from "path";
13812
14203
  var pagePatterns, getPageDirs = (config) => [
13813
14204
  { dir: config.angularDirectory, framework: "angular" },
13814
14205
  { dir: config.emberDirectory, framework: "ember" },
@@ -13828,7 +14219,7 @@ var pagePatterns, getPageDirs = (config) => [
13828
14219
  const source = definition.buildReference?.source;
13829
14220
  if (!source)
13830
14221
  continue;
13831
- const resolvedSource = source.startsWith("file://") ? new URL(source).pathname : resolve31(dirname23(buildInfo.resolvedRegistryPath), source);
14222
+ const resolvedSource = source.startsWith("file://") ? new URL(source).pathname : resolve31(dirname24(buildInfo.resolvedRegistryPath), source);
13832
14223
  lookup.set(`${definition.framework}:${definition.component}`, resolve31(resolvedSource));
13833
14224
  }
13834
14225
  return lookup;
@@ -13844,7 +14235,7 @@ var pagePatterns, getPageDirs = (config) => [
13844
14235
  return;
13845
14236
  const files = await scanEntryPoints(resolve31(entry.dir), pattern);
13846
14237
  for (const filePath of files) {
13847
- const source = readFileSync34(filePath, "utf-8");
14238
+ const source = readFileSync35(filePath, "utf-8");
13848
14239
  const islands = extractIslandUsagesFromSource(source);
13849
14240
  pageMetadata.set(resolve31(filePath), {
13850
14241
  islands: resolveIslandUsages(islands, islandSourceLookup),
@@ -13877,8 +14268,8 @@ var exports_islands = {};
13877
14268
  __export(exports_islands, {
13878
14269
  runIslands: () => runIslands
13879
14270
  });
13880
- import { existsSync as existsSync39, readFileSync as readFileSync35, statSync as statSync5 } from "fs";
13881
- import { join as join40, relative as relative20, resolve as resolve32 } from "path";
14271
+ import { existsSync as existsSync39, readFileSync as readFileSync36, statSync as statSync5 } from "fs";
14272
+ import { join as join41, relative as relative21, resolve as resolve32 } from "path";
13882
14273
  var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.write(`${colors.dim}${message}${colors.reset}
13883
14274
  `), hostFrameworkOf = (pagePath, cwd, config) => {
13884
14275
  const resolved = resolve32(cwd, pagePath);
@@ -13896,13 +14287,13 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
13896
14287
  return 0;
13897
14288
  }
13898
14289
  }, readManifestSizes2 = (manifestDir) => {
13899
- const manifestPath = join40(manifestDir, "manifest.json");
14290
+ const manifestPath = join41(manifestDir, "manifest.json");
13900
14291
  if (!existsSync39(manifestPath))
13901
14292
  return null;
13902
- const manifest = JSON.parse(readFileSync35(manifestPath, "utf-8"));
14293
+ const manifest = JSON.parse(readFileSync36(manifestPath, "utf-8"));
13903
14294
  const sizes = new Map;
13904
14295
  for (const [key, value] of Object.entries(manifest)) {
13905
- sizes.set(key, fileSize3(join40(manifestDir, value.replace(/^\//, ""))));
14296
+ sizes.set(key, fileSize3(join41(manifestDir, value.replace(/^\//, ""))));
13906
14297
  }
13907
14298
  return sizes;
13908
14299
  }, collectIslands = async (cwd, config, sizes) => {
@@ -13919,7 +14310,7 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
13919
14310
  crossFramework: hostFramework !== null && hostFramework !== definition.framework,
13920
14311
  hostFramework,
13921
14312
  hydrate: usage2.hydrate ?? "load",
13922
- page: relative20(cwd, resolve32(cwd, usage2.page))
14313
+ page: relative21(cwd, resolve32(cwd, usage2.page))
13923
14314
  };
13924
14315
  });
13925
14316
  const key = getIslandManifestKey(definition.framework, definition.component);
@@ -13958,7 +14349,7 @@ var FRAMEWORK_DIR_KEY, FRAMEWORK_COLOR, printDim6 = (message) => process.stdout.
13958
14349
  ` ${color}\u2B21${colors.reset} ${colors.bold}${island.component}${colors.reset} ${meta}${sizeText}`
13959
14350
  ];
13960
14351
  if (island.source) {
13961
- lines.push(` ${colors.dim}${relative20(cwd, island.source)}${colors.reset}`);
14352
+ lines.push(` ${colors.dim}${relative21(cwd, island.source)}${colors.reset}`);
13962
14353
  }
13963
14354
  if (pages.length === 0) {
13964
14355
  lines.push(` ${colors.dim}(registered but not mounted on any page)${colors.reset}`);
@@ -14038,7 +14429,7 @@ var init_islands2 = __esm(() => {
14038
14429
 
14039
14430
  // src/build/externalAssetPlugin.ts
14040
14431
  import { copyFileSync as copyFileSync2, existsSync as existsSync40, mkdirSync as mkdirSync17, statSync as statSync6 } from "fs";
14041
- import { basename as basename10, dirname as dirname24, join as join41, resolve as resolve33 } from "path";
14432
+ import { basename as basename11, dirname as dirname25, join as join42, resolve as resolve33 } from "path";
14042
14433
  var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
14043
14434
  name: "absolute-external-asset",
14044
14435
  setup(bld) {
@@ -14053,7 +14444,7 @@ var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
14053
14444
  return;
14054
14445
  urlPattern.lastIndex = 0;
14055
14446
  let match;
14056
- const sourceDir = dirname24(args.path);
14447
+ const sourceDir = dirname25(args.path);
14057
14448
  while ((match = urlPattern.exec(source)) !== null) {
14058
14449
  const relPath = match[1];
14059
14450
  if (!relPath)
@@ -14063,10 +14454,10 @@ var createExternalAssetPlugin = (outDir, userSourceRoots = []) => ({
14063
14454
  continue;
14064
14455
  if (!statSync6(assetPath).isFile())
14065
14456
  continue;
14066
- const targetPath = join41(outDir, basename10(assetPath));
14457
+ const targetPath = join42(outDir, basename11(assetPath));
14067
14458
  if (existsSync40(targetPath))
14068
14459
  continue;
14069
- mkdirSync17(dirname24(targetPath), { recursive: true });
14460
+ mkdirSync17(dirname25(targetPath), { recursive: true });
14070
14461
  copyFileSync2(assetPath, targetPath);
14071
14462
  }
14072
14463
  return;
@@ -14087,7 +14478,7 @@ import {
14087
14478
  existsSync as existsSync41,
14088
14479
  mkdirSync as mkdirSync18,
14089
14480
  readdirSync as readdirSync7,
14090
- readFileSync as readFileSync36,
14481
+ readFileSync as readFileSync37,
14091
14482
  rmSync as rmSync7,
14092
14483
  statSync as statSync7,
14093
14484
  unlinkSync as unlinkSync4,
@@ -14095,11 +14486,11 @@ import {
14095
14486
  } from "fs";
14096
14487
  import { createRequire as createRequire3 } from "module";
14097
14488
  import {
14098
- basename as basename11,
14099
- dirname as dirname25,
14489
+ basename as basename12,
14490
+ dirname as dirname26,
14100
14491
  isAbsolute as isAbsolute6,
14101
- join as join42,
14102
- relative as relative21,
14492
+ join as join43,
14493
+ relative as relative22,
14103
14494
  resolve as resolve34
14104
14495
  } from "path";
14105
14496
  var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, compileBanner = (version2) => {
@@ -14114,7 +14505,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14114
14505
  const entry = pending.pop();
14115
14506
  if (!entry)
14116
14507
  continue;
14117
- const fullPath = join42(entry.parentPath, entry.name);
14508
+ const fullPath = join43(entry.parentPath, entry.name);
14118
14509
  if (entry.isDirectory())
14119
14510
  pending = pending.concat(readdirSync7(fullPath, { withFileTypes: true }));
14120
14511
  else
@@ -14122,7 +14513,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14122
14513
  }
14123
14514
  return result;
14124
14515
  }, INLINE_SOURCE_MAP_RE, rebaseInlineSourceMap = (filePath) => {
14125
- const source = readFileSync36(filePath, "utf-8");
14516
+ const source = readFileSync37(filePath, "utf-8");
14126
14517
  const match = source.match(INLINE_SOURCE_MAP_RE);
14127
14518
  const encoded = match?.[1];
14128
14519
  if (!encoded)
@@ -14133,7 +14524,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14133
14524
  if (!Array.isArray(map.sources))
14134
14525
  return;
14135
14526
  const sourceRoot = typeof map.sourceRoot === "string" ? map.sourceRoot : "";
14136
- const bundleDirectory = dirname25(filePath);
14527
+ const bundleDirectory = dirname26(filePath);
14137
14528
  map.sources = map.sources.map((entry) => {
14138
14529
  if (/^[A-Za-z][A-Za-z0-9+.-]*:/.test(entry))
14139
14530
  return entry;
@@ -14160,7 +14551,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14160
14551
  const entry = pending.pop();
14161
14552
  if (!entry)
14162
14553
  continue;
14163
- const fullPath = join42(entry.parentPath, entry.name);
14554
+ const fullPath = join43(entry.parentPath, entry.name);
14164
14555
  if (entry.isDirectory()) {
14165
14556
  if (SERVER_RUNTIME_SCAN_SKIP_DIRS.has(entry.name))
14166
14557
  continue;
@@ -14174,7 +14565,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14174
14565
  const copied = new Set;
14175
14566
  const normalizedOutdir = resolve34(outdir);
14176
14567
  const copyReference = (filePath, relPath) => {
14177
- const assetSource = resolve34(dirname25(filePath), relPath);
14568
+ const assetSource = resolve34(dirname26(filePath), relPath);
14178
14569
  if (!existsSync41(assetSource) || !statSync7(assetSource).isFile())
14179
14570
  return;
14180
14571
  const assetTarget = resolve34(normalizedOutdir, relPath.replace(/^\.\//, ""));
@@ -14183,11 +14574,11 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14183
14574
  if (copied.has(assetTarget))
14184
14575
  return;
14185
14576
  copied.add(assetTarget);
14186
- mkdirSync18(dirname25(assetTarget), { recursive: true });
14577
+ mkdirSync18(dirname26(assetTarget), { recursive: true });
14187
14578
  cpSync(assetSource, assetTarget, { force: true });
14188
14579
  };
14189
14580
  for (const filePath of collectProjectSourceFiles(process.cwd())) {
14190
- const source = readFileSync36(filePath, "utf-8");
14581
+ const source = readFileSync37(filePath, "utf-8");
14191
14582
  SERVER_RUNTIME_ASSET_RE.lastIndex = 0;
14192
14583
  let match;
14193
14584
  while ((match = SERVER_RUNTIME_ASSET_RE.exec(source)) !== null) {
@@ -14216,7 +14607,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14216
14607
  }
14217
14608
  }, readPackageVersion4 = (candidate) => {
14218
14609
  try {
14219
- const pkg = JSON.parse(readFileSync36(candidate, "utf-8"));
14610
+ const pkg = JSON.parse(readFileSync37(candidate, "utf-8"));
14220
14611
  if (pkg.name !== "@absolutejs/absolute")
14221
14612
  return null;
14222
14613
  const ver = pkg.version;
@@ -14299,7 +14690,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14299
14690
  return nativeAssetEnv;
14300
14691
  }, tryReadNodePackageJson = (packageDir) => {
14301
14692
  try {
14302
- return JSON.parse(readFileSync36(join42(packageDir, "package.json"), "utf-8"));
14693
+ return JSON.parse(readFileSync37(join43(packageDir, "package.json"), "utf-8"));
14303
14694
  } catch {
14304
14695
  return null;
14305
14696
  }
@@ -14311,13 +14702,13 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14311
14702
  if (!pkg)
14312
14703
  return;
14313
14704
  seen.add(specifier);
14314
- const destDir = join42(outdir, "node_modules", ...specifier.split("/"));
14705
+ const destDir = join43(outdir, "node_modules", ...specifier.split("/"));
14315
14706
  rmSync7(destDir, { force: true, recursive: true });
14316
14707
  cpSync(srcDir, destDir, {
14317
14708
  force: true,
14318
14709
  recursive: true,
14319
14710
  filter(source) {
14320
- const rel = relative21(srcDir, source);
14711
+ const rel = relative22(srcDir, source);
14321
14712
  const [firstSegment] = rel.split(/[\\/]/);
14322
14713
  return firstSegment !== "node_modules" && firstSegment !== ".git";
14323
14714
  }
@@ -14352,7 +14743,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14352
14743
  copyAngularRuntimePackages(buildConfig, outdir);
14353
14744
  copyChunkReferencedPackages(outdir, seen);
14354
14745
  }, collectRuntimePackageSpecifiers = (distDir) => {
14355
- const nodeModulesDir = join42(distDir, "node_modules");
14746
+ const nodeModulesDir = join43(distDir, "node_modules");
14356
14747
  if (!existsSync41(nodeModulesDir))
14357
14748
  return [];
14358
14749
  const specifiers = [];
@@ -14360,7 +14751,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14360
14751
  if (!entry.isDirectory())
14361
14752
  continue;
14362
14753
  if (entry.name.startsWith("@")) {
14363
- const scopeDir = join42(nodeModulesDir, entry.name);
14754
+ const scopeDir = join43(nodeModulesDir, entry.name);
14364
14755
  for (const scopedEntry of readdirSync7(scopeDir, {
14365
14756
  withFileTypes: true
14366
14757
  })) {
@@ -14374,7 +14765,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14374
14765
  }
14375
14766
  return specifiers.sort((firstSpecifier, secondSpecifier) => secondSpecifier.length - firstSpecifier.length);
14376
14767
  }, ensureRelativeModuleSpecifier = (fromFile, toFile) => {
14377
- const rel = relative21(dirname25(fromFile), toFile).replace(/\\/g, "/");
14768
+ const rel = relative22(dirname26(fromFile), toFile).replace(/\\/g, "/");
14378
14769
  return rel.startsWith(".") ? rel : `./${rel}`;
14379
14770
  }, pickExportEntry = (value) => {
14380
14771
  if (typeof value === "string")
@@ -14391,18 +14782,18 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14391
14782
  const packageSpecifier = packageSpecifiers.find((root) => specifier === root || specifier.startsWith(`${root}/`));
14392
14783
  if (!packageSpecifier)
14393
14784
  return null;
14394
- const packageDir = join42(distDir, "node_modules", ...packageSpecifier.split("/"));
14785
+ const packageDir = join43(distDir, "node_modules", ...packageSpecifier.split("/"));
14395
14786
  const subpath = specifier.slice(packageSpecifier.length);
14396
- const subPackageDir = subpath ? join42(packageDir, ...subpath.slice(1).split("/")) : null;
14397
- const resolvedPackageDir = subPackageDir && existsSync41(join42(subPackageDir, "package.json")) ? subPackageDir : packageDir;
14398
- const packageJsonPath = join42(resolvedPackageDir, "package.json");
14787
+ const subPackageDir = subpath ? join43(packageDir, ...subpath.slice(1).split("/")) : null;
14788
+ const resolvedPackageDir = subPackageDir && existsSync41(join43(subPackageDir, "package.json")) ? subPackageDir : packageDir;
14789
+ const packageJsonPath = join43(resolvedPackageDir, "package.json");
14399
14790
  if (!existsSync41(packageJsonPath))
14400
14791
  return null;
14401
- const pkg = JSON.parse(readFileSync36(packageJsonPath, "utf-8"));
14792
+ const pkg = JSON.parse(readFileSync37(packageJsonPath, "utf-8"));
14402
14793
  const exportKey = resolvedPackageDir !== subPackageDir && subpath ? `.${subpath}` : ".";
14403
14794
  const rootExport = pkg.exports?.[exportKey];
14404
14795
  const entry = pickExportEntry(rootExport) ?? (resolvedPackageDir === subPackageDir || !subpath ? pkg.module ?? pkg.main ?? "index.js" : `.${subpath}`);
14405
- return join42(resolvedPackageDir, entry);
14796
+ return join43(resolvedPackageDir, entry);
14406
14797
  }, RUNTIME_JS_EXTENSIONS, MODULE_SPECIFIER_RE, isRuntimeJsFile = (filePath) => RUNTIME_JS_EXTENSIONS.some((extension) => filePath.endsWith(extension)), isNodeModulesPath = (filePath) => filePath.split(/[\\/]/).includes("node_modules"), isFile = (filePath) => {
14407
14798
  try {
14408
14799
  return statSync7(filePath).isFile();
@@ -14415,16 +14806,16 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14415
14806
  const candidates = [
14416
14807
  candidate,
14417
14808
  ...RUNTIME_JS_EXTENSIONS.map((extension) => `${candidate}${extension}`),
14418
- ...RUNTIME_JS_EXTENSIONS.map((extension) => join42(candidate, `index${extension}`))
14809
+ ...RUNTIME_JS_EXTENSIONS.map((extension) => join43(candidate, `index${extension}`))
14419
14810
  ];
14420
14811
  return candidates.find((filePath) => isRuntimeJsFile(filePath) && isFile(filePath)) ?? null;
14421
14812
  }, findContainingRuntimePackageDir = (filePath) => {
14422
- let dir = dirname25(filePath);
14423
- while (dir !== dirname25(dir)) {
14424
- if (isNodeModulesPath(dir) && existsSync41(join42(dir, "package.json"))) {
14813
+ let dir = dirname26(filePath);
14814
+ while (dir !== dirname26(dir)) {
14815
+ if (isNodeModulesPath(dir) && existsSync41(join43(dir, "package.json"))) {
14425
14816
  return dir;
14426
14817
  }
14427
- dir = dirname25(dir);
14818
+ dir = dirname26(dir);
14428
14819
  }
14429
14820
  return null;
14430
14821
  }, resolvePackageImportEntryFile = (fromFile, specifier) => {
@@ -14437,13 +14828,13 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14437
14828
  const entry = pickExportEntry(pkg?.imports?.[specifier]);
14438
14829
  if (!entry)
14439
14830
  return null;
14440
- return join42(packageDir, entry);
14831
+ return join43(packageDir, entry);
14441
14832
  }, collectRuntimeRewriteRoots = (distDir) => collectFiles2(distDir).filter((filePath) => isRuntimeJsFile(filePath) && !isNodeModulesPath(filePath)), toTopLevelPackage = (specifier) => specifier.split("/").slice(0, specifier.startsWith("@") ? 2 : 1).join("/"), FRAMEWORK_PACKAGE_NAME = "@absolutejs/absolute", copyChunkReferencedPackages = (distDir, seen) => {
14442
14833
  const distRoot = resolve34(distDir);
14443
14834
  for (const filePath of collectRuntimeRewriteRoots(distDir)) {
14444
- if (resolve34(dirname25(filePath)) === distRoot)
14835
+ if (resolve34(dirname26(filePath)) === distRoot)
14445
14836
  continue;
14446
- const source = readFileSync36(filePath, "utf-8");
14837
+ const source = readFileSync37(filePath, "utf-8");
14447
14838
  for (const match of source.matchAll(MODULE_SPECIFIER_RE)) {
14448
14839
  const [, , , specifier] = match;
14449
14840
  if (!specifier || specifier.startsWith(".") || specifier.startsWith("/") || specifier.startsWith("#") || specifier.startsWith("node:") || specifier.startsWith("bun:")) {
@@ -14473,11 +14864,11 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14473
14864
  if (!filePath || seen.has(filePath))
14474
14865
  continue;
14475
14866
  seen.add(filePath);
14476
- const source = readFileSync36(filePath, "utf-8");
14867
+ const source = readFileSync37(filePath, "utf-8");
14477
14868
  const { masked, restore } = maskLiterals(source);
14478
14869
  const rewrittenMasked = masked.replace(MODULE_SPECIFIER_RE, (match, prefix, quote, specifier) => {
14479
14870
  if (typeof specifier === "string" && specifier.startsWith(".")) {
14480
- enqueue(resolveRuntimeJsFile(resolve34(dirname25(filePath), specifier)));
14871
+ enqueue(resolveRuntimeJsFile(resolve34(dirname26(filePath), specifier)));
14481
14872
  return match;
14482
14873
  }
14483
14874
  const packageImportTarget = resolveRuntimeJsFile(resolvePackageImportEntryFile(filePath, specifier) ?? "");
@@ -14498,7 +14889,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14498
14889
  }
14499
14890
  }, generateEntrypoint = (distDir, serverEntry, prerenderMap, version2, buildConfig) => {
14500
14891
  const allFiles = collectFiles2(distDir);
14501
- const serverBundleName = `${basename11(serverEntry).replace(/\.[^.]+$/, "")}.js`;
14892
+ const serverBundleName = `${basename12(serverEntry).replace(/\.[^.]+$/, "")}.js`;
14502
14893
  const embeddedSkip = new Set(["_compile_entrypoint.ts"]);
14503
14894
  const assetSkip = new Set([
14504
14895
  serverBundleName,
@@ -14506,12 +14897,12 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14506
14897
  "_compile_entrypoint.ts"
14507
14898
  ]);
14508
14899
  const embeddedFiles = allFiles.filter((file) => {
14509
- const rel = relative21(distDir, file);
14900
+ const rel = relative22(distDir, file);
14510
14901
  if (embeddedSkip.has(rel))
14511
14902
  return false;
14512
14903
  return true;
14513
14904
  });
14514
- const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(relative21(distDir, file), assetSkip));
14905
+ const clientFiles = embeddedFiles.filter((file) => shouldEmbedCompiledAsset(relative22(distDir, file), assetSkip));
14515
14906
  const imports = [];
14516
14907
  const nativeImports = [];
14517
14908
  const nativeMappings = [];
@@ -14526,14 +14917,14 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14526
14917
  nativeMappings.push(` [${JSON.stringify(asset.env)}, resolveNativeAssetPath(${varName})],`);
14527
14918
  });
14528
14919
  embeddedFiles.forEach((filePath, idx) => {
14529
- const rel = relative21(distDir, filePath).replace(/\\/g, "/");
14920
+ const rel = relative22(distDir, filePath).replace(/\\/g, "/");
14530
14921
  const varName = `__a${idx}`;
14531
14922
  embeddedVarMap.set(rel, varName);
14532
14923
  imports.push(`import ${varName} from "./${rel}" with { type: "file" };`);
14533
14924
  embeddedMappings.push(` ["${rel}", ${varName}],`);
14534
14925
  });
14535
14926
  clientFiles.forEach((filePath) => {
14536
- const rel = relative21(distDir, filePath).replace(/\\/g, "/");
14927
+ const rel = relative22(distDir, filePath).replace(/\\/g, "/");
14537
14928
  const varName = embeddedVarMap.get(rel);
14538
14929
  if (!varName)
14539
14930
  return;
@@ -14547,7 +14938,7 @@ var cliTag4 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
14547
14938
  const pageVarMap = new Map;
14548
14939
  const prerenderEntries = Array.from(prerenderMap.entries());
14549
14940
  prerenderEntries.forEach(([route, filePath]) => {
14550
- const rel = relative21(distDir, filePath).replace(/\\/g, "/");
14941
+ const rel = relative22(distDir, filePath).replace(/\\/g, "/");
14551
14942
  const varName = embeddedVarMap.get(rel);
14552
14943
  if (varName)
14553
14944
  pageVarMap.set(route, varName);
@@ -14582,6 +14973,7 @@ const RUNTIME_BUILD_ID = ${JSON.stringify(runtimeBuildId)};
14582
14973
  const RUNTIME_CONFIG_SOURCE = ${JSON.stringify(runtimeConfigSource)};
14583
14974
  const ORIGINAL_BUILD_DIR = ${JSON.stringify(resolve34(distDir))};
14584
14975
  const ORIGINAL_BUILD_DIR_NORMALIZED = ORIGINAL_BUILD_DIR.replace(/\\\\/g, "/");
14976
+ const EMBEDDED_NATIVE_AUTH_CLIENTS = ${JSON.stringify(process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV])};
14585
14977
 
14586
14978
  const resolveNativeAssetPath = (assetPath: string) => {
14587
14979
  try {
@@ -14761,6 +15153,8 @@ const resolveRuntimeFetch = async () => {
14761
15153
  process.env[envName] = assetPath;
14762
15154
  }
14763
15155
  process.env.ABSOLUTE_BUILD_DIR = runtimeDir;
15156
+ if (EMBEDDED_NATIVE_AUTH_CLIENTS)
15157
+ process.env.ABSOLUTE_AUTH_NATIVE_CLIENTS = EMBEDDED_NATIVE_AUTH_CLIENTS;
14764
15158
  process.env.ABSOLUTE_CONFIG = configPath;
14765
15159
  process.env.ABSOLUTE_COMPILED_RUNTIME = "1";
14766
15160
  process.env.ABSOLUTE_VERSION = process.env.ABSOLUTE_VERSION || "${version2}";
@@ -15004,7 +15398,7 @@ console.log(\`
15004
15398
  const configuredPrerenderPort = env5.COMPILE_PORT === undefined ? Number(env5.PORT) : Number(env5.COMPILE_PORT);
15005
15399
  const prerenderPort = configuredPrerenderPort > 0 ? configuredPrerenderPort : await findFreePort();
15006
15400
  killStaleProcesses(prerenderPort);
15007
- const entryName = basename11(serverEntry).replace(/\.[^.]+$/, "");
15401
+ const entryName = basename12(serverEntry).replace(/\.[^.]+$/, "");
15008
15402
  const resolvedOutfile = resolve34(outfile ?? "compiled-server");
15009
15403
  const absoluteVersion = resolvePackageVersion3([
15010
15404
  resolve34(import.meta.dir, "..", "..", "..", "package.json"),
@@ -15017,6 +15411,8 @@ console.log(\`
15017
15411
  const buildConfig = await loadConfig(configPath2);
15018
15412
  buildConfig.buildDirectory = resolvedOutdir;
15019
15413
  buildConfig.mode = "production";
15414
+ if (buildConfig.mobile)
15415
+ installAbsoluteMobileAuthEnvironment(process.cwd(), normalizeAbsoluteMobileConfig(buildConfig.mobile, process.cwd()));
15020
15416
  try {
15021
15417
  const build2 = await resolveBuildModule3([
15022
15418
  resolve34(import.meta.dir, "..", "..", "core", "build"),
@@ -15043,10 +15439,10 @@ console.log(\`
15043
15439
  ].filter((dir) => Boolean(dir));
15044
15440
  const islandRegistrySpec = buildConfig.islands?.registry;
15045
15441
  const islandRegistryPlugin = islandRegistrySpec ? createIslandRegistryDefinitionPlugin(await loadIslandRegistryBuildInfo(resolve34(islandRegistrySpec))) : undefined;
15046
- const serverBundleEntryDirectory = join42(resolvedOutdir, ".absolutejs-server-entry");
15442
+ const serverBundleEntryDirectory = join43(resolvedOutdir, ".absolutejs-server-entry");
15047
15443
  mkdirSync18(serverBundleEntryDirectory, { recursive: true });
15048
- const typeboxSetupEntry = join42(serverBundleEntryDirectory, "_typebox_setup.ts");
15049
- const serverBundleEntry = join42(serverBundleEntryDirectory, basename11(serverEntry));
15444
+ const typeboxSetupEntry = join43(serverBundleEntryDirectory, "_typebox_setup.ts");
15445
+ const serverBundleEntry = join43(serverBundleEntryDirectory, basename12(serverEntry));
15050
15446
  writeFileSync21(typeboxSetupEntry, `import { setupTypebox } from 'elysia';
15051
15447
  import * as compile from 'typebox/compile';
15052
15448
  import * as schema from 'typebox/schema';
@@ -15110,7 +15506,7 @@ export default server;
15110
15506
  if (scope !== "angular" || rest.length === 0)
15111
15507
  continue;
15112
15508
  const specifier = `@angular/${rest.join("/")}`;
15113
- const relPath = relative21(dirname25(outputPath), resolve34(vendorDir, file));
15509
+ const relPath = relative22(dirname26(outputPath), resolve34(vendorDir, file));
15114
15510
  angularServerVendorPaths[specifier] = relPath.startsWith(".") ? relPath : `./${relPath}`;
15115
15511
  }
15116
15512
  if (Object.keys(angularServerVendorPaths).length > 0) {
@@ -15122,7 +15518,7 @@ export default server;
15122
15518
  copyServerRuntimeAssetReferences(resolvedOutdir);
15123
15519
  const prerenderStart = performance.now();
15124
15520
  process.stdout.write(cliTag4("\x1B[36m", "Pre-rendering pages"));
15125
- rmSync7(join42(resolvedOutdir, "_prerendered"), {
15521
+ rmSync7(join43(resolvedOutdir, "_prerendered"), {
15126
15522
  force: true,
15127
15523
  recursive: true
15128
15524
  });
@@ -15143,6 +15539,7 @@ export default server;
15143
15539
  if (buildConfig.mobile) {
15144
15540
  await finalizeAbsoluteMobileCompatibilityBuild({
15145
15541
  buildDirectory: resolvedOutdir,
15542
+ ...configPath2 ? { configPath: configPath2 } : {},
15146
15543
  mobile: buildConfig.mobile,
15147
15544
  producerPath: outputPath,
15148
15545
  projectRoot: process.cwd()
@@ -15151,9 +15548,9 @@ export default server;
15151
15548
  const compileStart = performance.now();
15152
15549
  process.stdout.write(cliTag4("\x1B[36m", "Compiling standalone executable"));
15153
15550
  const entrypointCode = generateEntrypoint(resolvedOutdir, serverEntry, prerenderMap, absoluteVersion, buildConfig);
15154
- const entrypointPath = join42(resolvedOutdir, "_compile_entrypoint.ts");
15551
+ const entrypointPath = join43(resolvedOutdir, "_compile_entrypoint.ts");
15155
15552
  await Bun.write(entrypointPath, entrypointCode);
15156
- mkdirSync18(dirname25(resolvedOutfile), { recursive: true });
15553
+ mkdirSync18(dirname26(resolvedOutfile), { recursive: true });
15157
15554
  const result = await Bun.build({
15158
15555
  compile: { outfile: resolvedOutfile },
15159
15556
  define: { "process.env.NODE_ENV": '"production"' },
@@ -15182,7 +15579,7 @@ export default server;
15182
15579
  const size = (Bun.file(resolvedOutfile).size / BYTES_PER_MB).toFixed(0);
15183
15580
  const totalDuration = getDurationString(performance.now() - totalStart);
15184
15581
  console.log(cliTag4("\x1B[32m", `Compiled to ${resolvedOutfile} (${size}MB) in ${totalDuration}`));
15185
- console.log(cliTag4("\x1B[2m", `Run with: ./${basename11(resolvedOutfile)}`));
15582
+ console.log(cliTag4("\x1B[2m", `Run with: ./${basename12(resolvedOutfile)}`));
15186
15583
  sendTelemetryEvent("compile:complete", {
15187
15584
  durationMs: Math.round(performance.now() - totalStart),
15188
15585
  entry: serverEntry,
@@ -15197,6 +15594,8 @@ var init_compile = __esm(() => {
15197
15594
  init_bunStringRawUnicodePlugin();
15198
15595
  init_buildPipeline();
15199
15596
  init_routeMetadataTransform();
15597
+ init_nativeAuth();
15598
+ init_config();
15200
15599
  init_constants();
15201
15600
  init_prerender();
15202
15601
  init_getDurationString();
@@ -15234,14 +15633,14 @@ var init_compile = __esm(() => {
15234
15633
  });
15235
15634
 
15236
15635
  // src/mobile/nativeDeepLinks.ts
15237
- import { readFile as readFile11, rename as rename8, writeFile as writeFile8 } from "fs/promises";
15238
- import { join as join43 } from "path";
15636
+ import { readFile as readFile11, rename as rename8, writeFile as writeFile9 } from "fs/promises";
15637
+ import { join as join44 } from "path";
15239
15638
  var START_MARKER = "<!-- absolutejs:deep-links:start -->", END_MARKER = "<!-- absolutejs:deep-links:end -->", IOS_ENTITLEMENTS = "App/AbsoluteJS.entitlements", NOT_FOUND = -1, escapeXml = (value) => value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("'", "&apos;").replaceAll("<", "&lt;").replaceAll(">", "&gt;"), writeChangedFile = async (path, source) => {
15240
15639
  const current = await readFile11(path, "utf8");
15241
15640
  if (current === source)
15242
15641
  return false;
15243
15642
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
15244
- await writeFile8(temporary, source, { flag: "wx" });
15643
+ await writeFile9(temporary, source, { flag: "wx" });
15245
15644
  await rename8(temporary, path);
15246
15645
  return true;
15247
15646
  }, replaceManagedRegion = (source, region, insertAt) => {
@@ -15284,7 +15683,7 @@ ${hosts}
15284
15683
  ${END_MARKER}
15285
15684
  `;
15286
15685
  }, configureAndroid = async (config) => {
15287
- const path = join43(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
15686
+ const path = join44(config.nativeProjectDirectory, "android/app/src/main/AndroidManifest.xml");
15288
15687
  const source = await readFile11(path, "utf8");
15289
15688
  const mainActivity = source.indexOf('android:name=".MainActivity"');
15290
15689
  if (mainActivity === NOT_FOUND) {
@@ -15308,7 +15707,7 @@ ${hosts}
15308
15707
  </array>
15309
15708
  ${END_MARKER}
15310
15709
  `, configureIosInfo = async (config) => {
15311
- const path = join43(config.nativeProjectDirectory, "ios/App/App/Info.plist");
15710
+ const path = join44(config.nativeProjectDirectory, "ios/App/App/Info.plist");
15312
15711
  const source = await readFile11(path, "utf8");
15313
15712
  const region = config.deepLinkScheme ? iosSchemeRegion(config.deepLinkScheme) : ` ${START_MARKER}
15314
15713
  ${END_MARKER}
@@ -15330,7 +15729,7 @@ ${domains}
15330
15729
  </plist>
15331
15730
  `;
15332
15731
  }, configureIosEntitlements = async (config) => {
15333
- const path = join43(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
15732
+ const path = join44(config.nativeProjectDirectory, "ios/App/AbsoluteJS.entitlements");
15334
15733
  let current = "";
15335
15734
  try {
15336
15735
  current = await readFile11(path, "utf8");
@@ -15343,11 +15742,11 @@ ${domains}
15343
15742
  if (current === source)
15344
15743
  return false;
15345
15744
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
15346
- await writeFile8(temporary, source, { flag: "wx" });
15745
+ await writeFile9(temporary, source, { flag: "wx" });
15347
15746
  await rename8(temporary, path);
15348
15747
  return true;
15349
15748
  }, configureIosProject = async (config) => {
15350
- const path = join43(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
15749
+ const path = join44(config.nativeProjectDirectory, "ios/App/App.xcodeproj/project.pbxproj");
15351
15750
  const source = await readFile11(path, "utf8");
15352
15751
  const declarations = [
15353
15752
  ...source.matchAll(/CODE_SIGN_ENTITLEMENTS = ([^;]+);/g)
@@ -15388,11 +15787,11 @@ var init_nativeDeepLinks = () => {};
15388
15787
  // src/mobile/associationFiles.ts
15389
15788
  import {
15390
15789
  access as access7,
15391
- mkdir as mkdir9,
15790
+ mkdir as mkdir10,
15392
15791
  readFile as readFile12,
15393
15792
  rename as rename9,
15394
15793
  rm as rm7,
15395
- writeFile as writeFile9
15794
+ writeFile as writeFile10
15396
15795
  } from "fs/promises";
15397
15796
  import { resolve as resolve35 } from "path";
15398
15797
  import { Elysia } from "elysia";
@@ -15456,7 +15855,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15456
15855
  if (current === source)
15457
15856
  return false;
15458
15857
  const temporary = `${path}.${crypto.randomUUID()}.tmp`;
15459
- await writeFile9(temporary, source, { flag: "wx" });
15858
+ await writeFile10(temporary, source, { flag: "wx" });
15460
15859
  await rename9(temporary, path);
15461
15860
  return true;
15462
15861
  }, exists2 = async (path) => {
@@ -15495,7 +15894,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15495
15894
  await rm7(backup, { force: true, recursive: true });
15496
15895
  }, materializeHost = async (root, host, files) => {
15497
15896
  const directory = resolve35(root, host, ".well-known");
15498
- await mkdir9(directory, { recursive: true });
15897
+ await mkdir10(directory, { recursive: true });
15499
15898
  return Promise.all(files.map(async ([name, document]) => {
15500
15899
  const path = resolve35(directory, name);
15501
15900
  await writeAtomic(path, `${JSON.stringify(document, null, 2)}
@@ -15531,7 +15930,7 @@ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json", HTTP_OK = 200, VERI
15531
15930
  if (documents.apple) {
15532
15931
  files.push(["apple-app-site-association", documents.apple]);
15533
15932
  }
15534
- await mkdir9(temporary, { recursive: true });
15933
+ await mkdir10(temporary, { recursive: true });
15535
15934
  try {
15536
15935
  const temporaryPaths = (await Promise.all(config.deepLinkHosts.map((host) => materializeHost(temporary, host, files)))).flat();
15537
15936
  await writeAtomic(resolve35(temporary, OWNERSHIP_FILE), `${JSON.stringify({ format: 1, hosts: config.deepLinkHosts }, null, 2)}
@@ -15578,8 +15977,8 @@ var init_associationFiles = __esm(() => {
15578
15977
  });
15579
15978
 
15580
15979
  // src/mobile/androidWebView.ts
15581
- import { mkdir as mkdir10, writeFile as writeFile10 } from "fs/promises";
15582
- import { dirname as dirname26, resolve as resolve36 } from "path";
15980
+ import { mkdir as mkdir11, writeFile as writeFile11 } from "fs/promises";
15981
+ import { dirname as dirname27, resolve as resolve36 } from "path";
15583
15982
 
15584
15983
  class CdpConnection {
15585
15984
  diagnostics = [];
@@ -15851,8 +16250,8 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
15851
16250
  throw new Error("Android WebView screenshot returned no image data.");
15852
16251
  }
15853
16252
  const absolutePath = resolve36(path);
15854
- await mkdir10(dirname26(absolutePath), { recursive: true });
15855
- await writeFile10(absolutePath, Buffer.from(data, "base64"));
16253
+ await mkdir11(dirname27(absolutePath), { recursive: true });
16254
+ await writeFile11(absolutePath, Buffer.from(data, "base64"));
15856
16255
  return absolutePath;
15857
16256
  }
15858
16257
  };
@@ -15971,7 +16370,7 @@ var DEFAULT_ROUTE_TIMEOUT_MS = 30000, DEFAULT_HMR_TIMEOUT_MS = 30000, routeExpre
15971
16370
 
15972
16371
  // src/mobile/releaseDoctor.ts
15973
16372
  import { access as access8, readFile as readFile13, readdir as readdir4 } from "fs/promises";
15974
- import { extname as extname6, join as join44, relative as relative22 } from "path";
16373
+ import { extname as extname7, join as join45, relative as relative23 } from "path";
15975
16374
  var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
15976
16375
  try {
15977
16376
  await access8(path);
@@ -15982,7 +16381,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
15982
16381
  }, inspectReleaseAsset = async (path, isDirectory, isFile2) => {
15983
16382
  if (isDirectory)
15984
16383
  return findHmrAsset(path);
15985
- if (!isFile2 || !RELEASE_ASSET_EXTENSIONS.has(extname6(path)))
16384
+ if (!isFile2 || !RELEASE_ASSET_EXTENSIONS.has(extname7(path)))
15986
16385
  return;
15987
16386
  const source = await readFile13(path, "utf8");
15988
16387
  return HMR_ASSET_PATTERN.test(source) ? path : undefined;
@@ -15990,7 +16389,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
15990
16389
  if (!await pathExists5(root))
15991
16390
  return;
15992
16391
  const entries = await readdir4(root, { withFileTypes: true });
15993
- const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join44(root, entry.name), entry.isDirectory(), entry.isFile())));
16392
+ const matches = await Promise.all(entries.map((entry) => inspectReleaseAsset(join45(root, entry.name), entry.isDirectory(), entry.isFile())));
15994
16393
  return matches.find((match) => match !== undefined);
15995
16394
  }, pass = (id, detail, path) => ({ detail, id, path, status: "pass" }), fail5 = (id, detail, path, remediation) => ({
15996
16395
  detail,
@@ -16035,11 +16434,11 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16035
16434
  const hmrAsset = await findHmrAsset(publicRoot);
16036
16435
  return hmrAsset ? fail5("android.hmr-assets", "A packaged Android asset contains the development HMR client.", hmrAsset, "Rebuild the production mobile bundle and run Capacitor sync again.") : pass("android.hmr-assets", "Packaged Android assets contain no development HMR markers.", publicRoot);
16037
16436
  }, inspectAndroidRelease = async (config, projectRoot) => {
16038
- const androidRoot = join44(config.nativeProjectDirectory, "android");
16039
- const nativeConfigPath = join44(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
16040
- const manifestPath = join44(androidRoot, "app", "src", "main", "AndroidManifest.xml");
16041
- const publicRoot = join44(androidRoot, "app", "src", "main", "assets", "public");
16042
- const journalPath = join44(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
16437
+ const androidRoot = join45(config.nativeProjectDirectory, "android");
16438
+ const nativeConfigPath = join45(androidRoot, "app", "src", "main", "assets", "capacitor.config.json");
16439
+ const manifestPath = join45(androidRoot, "app", "src", "main", "AndroidManifest.xml");
16440
+ const publicRoot = join45(androidRoot, "app", "src", "main", "assets", "public");
16441
+ const journalPath = join45(projectRoot, ".absolutejs", "mobile", "dev-session", "journal.json");
16043
16442
  const checks = await Promise.all([
16044
16443
  journalReleaseCheck(journalPath, "android"),
16045
16444
  capacitorConfigReleaseCheck(nativeConfigPath),
@@ -16048,14 +16447,14 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16048
16447
  ]);
16049
16448
  return checks.map((check2) => ({
16050
16449
  ...check2,
16051
- path: check2.path ? relative22(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
16450
+ path: check2.path ? relative23(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
16052
16451
  }));
16053
16452
  }, inspectIosRelease = async (config, projectRoot) => {
16054
- const iosAppRoot = join44(config.nativeProjectDirectory, "ios", "App", "App");
16055
- const nativeConfigPath = join44(iosAppRoot, "capacitor.config.json");
16056
- const infoPath = join44(iosAppRoot, "Info.plist");
16057
- const publicRoot = join44(iosAppRoot, "public");
16058
- const journalPath = join44(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
16453
+ const iosAppRoot = join45(config.nativeProjectDirectory, "ios", "App", "App");
16454
+ const nativeConfigPath = join45(iosAppRoot, "capacitor.config.json");
16455
+ const infoPath = join45(iosAppRoot, "Info.plist");
16456
+ const publicRoot = join45(iosAppRoot, "public");
16457
+ const journalPath = join45(projectRoot, ".absolutejs", "mobile", "ios-dev-session", "journal.json");
16059
16458
  const checks = [
16060
16459
  await journalReleaseCheck(journalPath, "ios")
16061
16460
  ];
@@ -16081,7 +16480,7 @@ var HMR_ASSET_PATTERN, RELEASE_ASSET_EXTENSIONS, pathExists5 = async (path) => {
16081
16480
  checks.push(hmrAsset ? fail5("ios.hmr-assets", "A packaged iOS asset contains the development HMR client.", hmrAsset, "Rebuild the production mobile bundle and run Capacitor sync again.") : pass("ios.hmr-assets", "Packaged iOS assets contain no development HMR markers.", publicRoot));
16082
16481
  return checks.map((check2) => ({
16083
16482
  ...check2,
16084
- path: check2.path ? relative22(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
16483
+ path: check2.path ? relative23(projectRoot, check2.path).replaceAll("\\", "/") || "." : undefined
16085
16484
  }));
16086
16485
  }, inspectAbsoluteMobileRelease = async (config, projectRoot) => {
16087
16486
  const checks = config.platforms.includes("android") ? await inspectAndroidRelease(config, projectRoot) : [];
@@ -16103,15 +16502,15 @@ import { createHash as createHash12 } from "crypto";
16103
16502
  import {
16104
16503
  access as access9,
16105
16504
  copyFile as copyFile5,
16106
- mkdir as mkdir11,
16505
+ mkdir as mkdir12,
16107
16506
  mkdtemp as mkdtemp5,
16108
16507
  readFile as readFile14,
16109
16508
  rename as rename10,
16110
16509
  rm as rm8,
16111
16510
  stat as stat2,
16112
- writeFile as writeFile11
16511
+ writeFile as writeFile12
16113
16512
  } from "fs/promises";
16114
- import { dirname as dirname27, isAbsolute as isAbsolute7, join as join45, relative as relative23, resolve as resolve37, sep as sep6 } from "path";
16513
+ import { dirname as dirname28, isAbsolute as isAbsolute7, join as join46, relative as relative24, resolve as resolve37, sep as sep6 } from "path";
16115
16514
  var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), requireManifest2 = (value) => {
16116
16515
  if (!isRecord13(value) || typeof value.appBuild !== "string" || typeof value.appId !== "string" || typeof value.runtime !== "string") {
16117
16516
  throw new TypeError("Invalid embedded AbsoluteJS mobile manifest.");
@@ -16164,17 +16563,17 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16164
16563
  }, sha256File2 = async (path) => createHash12("sha256").update(await readFile14(path)).digest("hex"), safeOutputDirectory2 = (projectRoot, requested) => {
16165
16564
  const root = resolve37(projectRoot);
16166
16565
  const output = resolve37(root, requested ?? ".absolutejs/mobile/releases/android");
16167
- const projectRelative = relative23(root, output);
16566
+ const projectRelative = relative24(root, output);
16168
16567
  if (projectRelative === ".." || projectRelative.startsWith(`..${sep6}`) || isAbsolute7(projectRelative)) {
16169
16568
  throw new TypeError("mobile build --outdir must remain inside the project.");
16170
16569
  }
16171
16570
  return output;
16172
16571
  }, installRelease2 = async (artifactPath, metadata, outputRoot) => {
16173
- const releaseRoot = join45(outputRoot, metadata.releaseId);
16572
+ const releaseRoot = join46(outputRoot, metadata.releaseId);
16174
16573
  const artifactName = "app-release.aab";
16175
- const destination = join45(releaseRoot, artifactName);
16574
+ const destination = join46(releaseRoot, artifactName);
16176
16575
  if (await pathExists6(releaseRoot)) {
16177
- const existing = requireManifestIdentity(JSON.parse(await readFile14(join45(releaseRoot, "release.json"), "utf8")), metadata);
16576
+ const existing = requireManifestIdentity(JSON.parse(await readFile14(join46(releaseRoot, "release.json"), "utf8")), metadata);
16178
16577
  const [installedBytes, installedSha256] = await Promise.all([
16179
16578
  stat2(destination).then(({ size }) => size),
16180
16579
  sha256File2(destination)
@@ -16184,15 +16583,15 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16184
16583
  }
16185
16584
  return { artifactPath: destination, metadata: existing, releaseRoot };
16186
16585
  }
16187
- await mkdir11(dirname27(releaseRoot), { recursive: true });
16188
- const staging = await mkdtemp5(join45(dirname27(releaseRoot), ".android-stage-"));
16586
+ await mkdir12(dirname28(releaseRoot), { recursive: true });
16587
+ const staging = await mkdtemp5(join46(dirname28(releaseRoot), ".android-stage-"));
16189
16588
  try {
16190
- await copyFile5(artifactPath, join45(staging, artifactName));
16589
+ await copyFile5(artifactPath, join46(staging, artifactName));
16191
16590
  const complete = {
16192
16591
  ...metadata,
16193
16592
  artifact: artifactName
16194
16593
  };
16195
- await writeFile11(join45(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
16594
+ await writeFile12(join46(staging, "release.json"), `${JSON.stringify(complete, null, "\t")}
16196
16595
  `, { flag: "wx" });
16197
16596
  await rename10(staging, releaseRoot);
16198
16597
  return { artifactPath: destination, metadata: complete, releaseRoot };
@@ -16220,8 +16619,8 @@ var ABSOLUTE_ANDROID_RELEASE_FORMAT = 1, isRecord13 = (value) => typeof value ==
16220
16619
  const projectRoot = resolve37(options.projectRoot);
16221
16620
  const host = options.host ?? detectAbsoluteMobileHost();
16222
16621
  const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host);
16223
- const nativeDirectory = join45(options.config.nativeProjectDirectory, "android");
16224
- const manifest = requireManifest2(JSON.parse(await readFile14(join45(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
16622
+ const nativeDirectory = join46(options.config.nativeProjectDirectory, "android");
16623
+ const manifest = requireManifest2(JSON.parse(await readFile14(join46(options.config.bundleDirectory, "absolute-mobile-manifest.json"), "utf8")));
16225
16624
  if (manifest.appId !== options.config.appId) {
16226
16625
  throw new TypeError("Embedded mobile manifest appId does not match mobile.appId.");
16227
16626
  }
@@ -16345,7 +16744,7 @@ var init_iosConformance = __esm(() => {
16345
16744
 
16346
16745
  // src/mobile/releasePublisher.ts
16347
16746
  import { access as access10 } from "fs/promises";
16348
- import { isAbsolute as isAbsolute8, relative as relative24, resolve as resolve38, sep as sep7 } from "path";
16747
+ import { isAbsolute as isAbsolute8, relative as relative25, resolve as resolve38, sep as sep7 } from "path";
16349
16748
  import { pathToFileURL as pathToFileURL2 } from "url";
16350
16749
  var prepareAbsoluteIosRelease = async (publisher, options) => {
16351
16750
  if (typeof publisher.prepareIosRelease !== "function") {
@@ -16369,7 +16768,7 @@ var prepareAbsoluteIosRelease = async (publisher, options) => {
16369
16768
  }, isRecord14 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), isPublisher = (value) => isRecord14(value) && typeof value.publish === "function", publisherModulePath = (projectRoot, requested) => {
16370
16769
  const root = resolve38(projectRoot);
16371
16770
  const path = resolve38(root, requested);
16372
- const projectRelative = relative24(root, path);
16771
+ const projectRelative = relative25(root, path);
16373
16772
  if (projectRelative === ".." || projectRelative.startsWith(`..${sep7}`) || isAbsolute8(projectRelative)) {
16374
16773
  throw new TypeError("mobile publish --registry must remain inside the project.");
16375
16774
  }
@@ -16441,10 +16840,10 @@ var exports_mobile = {};
16441
16840
  __export(exports_mobile, {
16442
16841
  runMobile: () => runMobile
16443
16842
  });
16444
- import { access as access11, mkdir as mkdir12, writeFile as writeFile12 } from "fs/promises";
16445
- import { join as join46, resolve as resolve39 } from "path";
16843
+ import { access as access11, mkdir as mkdir13, writeFile as writeFile13 } from "fs/promises";
16844
+ import { join as join47, resolve as resolve39 } from "path";
16446
16845
  import { createInterface } from "readline/promises";
16447
- var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), CAPACITOR_PACKAGES, valueAfter = (args, flag) => {
16846
+ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value !== null && !Array.isArray(value), CAPACITOR_PACKAGES, CAPACITOR_PACKAGE_SPECS, valueAfter = (args, flag) => {
16448
16847
  const index = args.indexOf(flag);
16449
16848
  return index === NOT_FOUND2 ? undefined : args[index + 1];
16450
16849
  }, valuesAfter = (args, flag) => args.flatMap((value, index) => {
@@ -16456,7 +16855,7 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
16456
16855
  }
16457
16856
  return value;
16458
16857
  }, capacitorExecutable = async (projectRoot) => {
16459
- const executable = join46(projectRoot, "node_modules", ".bin", "cap");
16858
+ const executable = join47(projectRoot, "node_modules", ".bin", "cap");
16460
16859
  try {
16461
16860
  await access11(executable);
16462
16861
  return executable;
@@ -16517,6 +16916,15 @@ var NOT_FOUND2 = -1, isRecord15 = (value) => typeof value === "object" && value
16517
16916
  console.log(removed ? `Removed remote Mac profile ${args[1]}.` : `Remote Mac profile ${args[1]} was not found.`);
16518
16917
  }, initialize = async (args) => {
16519
16918
  const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
16919
+ try {
16920
+ await access11(join47(projectRoot, "node_modules", ".bin", "cap"));
16921
+ } catch {
16922
+ const approved = args.includes("--yes") || await confirmInstall("Capacitor and the AbsoluteJS native device adapter are missing. Install the tested mobile toolchain now?");
16923
+ if (!approved)
16924
+ throw new TypeError(`Mobile initialization requires: bun add ${CAPACITOR_PACKAGE_SPECS.join(" ")}`);
16925
+ if (!installPackages(projectRoot, CAPACITOR_PACKAGE_SPECS))
16926
+ throw new TypeError("Failed to install the AbsoluteJS mobile toolchain.");
16927
+ }
16520
16928
  const generated = await writeAbsoluteCapacitorConfig(mobile, {
16521
16929
  force: args.includes("--force"),
16522
16930
  projectRoot
@@ -16765,7 +17173,7 @@ Mobile release transport checks failed.`);
16765
17173
  const durationMs = Math.round(performance.now() - startedAt);
16766
17174
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} Android App Bundle in ${getDurationString(durationMs)}.`);
16767
17175
  console.log(`Artifact: ${release.artifactPath}`);
16768
- console.log(`Metadata: ${join46(release.releaseRoot, "release.json")}`);
17176
+ console.log(`Metadata: ${join47(release.releaseRoot, "release.json")}`);
16769
17177
  return release;
16770
17178
  } finally {
16771
17179
  sendTelemetryEvent("mobile:android-release-build", {
@@ -16864,7 +17272,7 @@ Mobile release transport checks failed.`);
16864
17272
  const durationMs = Math.round(performance.now() - startedAt);
16865
17273
  console.log(`Built ${release.metadata.signed ? "signed" : "unsigned"} iOS IPA ${release.metadata.marketingVersion}${release.metadata.buildNumber ? ` (${release.metadata.buildNumber})` : ""} in ${getDurationString(durationMs)}.`);
16866
17274
  console.log(`Artifact: ${release.artifactPath}`);
16867
- console.log(`Metadata: ${join46(release.releaseRoot, "release.json")}`);
17275
+ console.log(`Metadata: ${join47(release.releaseRoot, "release.json")}`);
16868
17276
  return release;
16869
17277
  } finally {
16870
17278
  sendTelemetryEvent("mobile:ios-release-build", {
@@ -17109,12 +17517,12 @@ Emulator setup verification:`);
17109
17517
  timeoutMs
17110
17518
  });
17111
17519
  }, writeAndroidFailureArtifacts = async (options) => {
17112
- await mkdir12(options.artifactRoot, { recursive: true });
17113
- const screenshot = options.session ? await options.session.screenshot(join46(options.artifactRoot, "android-failure.png")).catch(() => {
17520
+ await mkdir13(options.artifactRoot, { recursive: true });
17521
+ const screenshot = options.session ? await options.session.screenshot(join47(options.artifactRoot, "android-failure.png")).catch(() => {
17114
17522
  return;
17115
17523
  }) : undefined;
17116
- const diagnosticPath = join46(options.artifactRoot, "android-failure.json");
17117
- await writeFile12(diagnosticPath, `${JSON.stringify({
17524
+ const diagnosticPath = join47(options.artifactRoot, "android-failure.json");
17525
+ await writeFile13(diagnosticPath, `${JSON.stringify({
17118
17526
  diagnostics: options.session?.diagnostics ?? [],
17119
17527
  error: options.error instanceof Error ? options.error.message : String(options.error),
17120
17528
  platform: "android",
@@ -17290,8 +17698,8 @@ Emulator setup verification:`);
17290
17698
  throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
17291
17699
  return result;
17292
17700
  }, writeIosFailureArtifacts = async (options) => {
17293
- await mkdir12(options.artifactRoot, { recursive: true });
17294
- const screenshot = join46(options.artifactRoot, "ios-failure.png");
17701
+ await mkdir13(options.artifactRoot, { recursive: true });
17702
+ const screenshot = join47(options.artifactRoot, "ios-failure.png");
17295
17703
  const screenshotResult = captureCommand4([
17296
17704
  options.xcrun,
17297
17705
  "simctl",
@@ -17300,8 +17708,8 @@ Emulator setup verification:`);
17300
17708
  "screenshot",
17301
17709
  screenshot
17302
17710
  ]);
17303
- const diagnosticPath = join46(options.artifactRoot, "ios-failure.json");
17304
- await writeFile12(diagnosticPath, `${JSON.stringify({
17711
+ const diagnosticPath = join47(options.artifactRoot, "ios-failure.json");
17712
+ await writeFile13(diagnosticPath, `${JSON.stringify({
17305
17713
  appId: options.appId,
17306
17714
  error: options.error instanceof Error ? options.error.message : String(options.error),
17307
17715
  platform: "ios",
@@ -17345,8 +17753,8 @@ Emulator setup verification:`);
17345
17753
  mobile.appId
17346
17754
  ], "iOS app launch");
17347
17755
  await waitForIosHmrClient({ https, port, timeoutMs });
17348
- await mkdir12(artifactRoot, { recursive: true });
17349
- const screenshot = join46(artifactRoot, "ios-simulator.png");
17756
+ await mkdir13(artifactRoot, { recursive: true });
17757
+ const screenshot = join47(artifactRoot, "ios-simulator.png");
17350
17758
  requireCapturedIosCommand([xcrun, "simctl", "io", simulator.udid, "screenshot", screenshot], "iOS simulator screenshot");
17351
17759
  const hmrApply = await waitForRequestedIosHmr(args, instance, timeoutMs);
17352
17760
  const report = {
@@ -17446,6 +17854,7 @@ Emulator setup verification:`);
17446
17854
  throw new TypeError("Usage: absolute mobile <pair mac <name> <user@host> [--port n] [--workspace path] | remotes [--json] | unpair mac <name> | init [--no-native] [--force] | sync [ios|android] | associations [--outdir dir] [--verify] | doctor [ios|android|release] [--remote name] [--json|--fix [--yes]] | build <android|ios> [server-entry] [--outdir dir] [--web-outdir dir] [--unsigned] | publish android [server-entry] [--registry module] [--channel name] [--play-track track] [--play-status completed|draft|halted|in-progress] [--play-rollout fraction] [--play-name name] [--play-notes language=text] [--play-update-priority 0..5] [--play-hold-review] [--play-cancel-existing-review] [--outdir dir] [--web-outdir dir] [--unsigned] | publish ios [server-entry] [--registry module] [--channel name] [--testflight-group name-or-id] [--testflight-notes locale=text] [--testflight-submit-review] [--outdir dir] [--web-outdir dir] [--unsigned] | test android [--route path] [--wait-for-hmr] [--timeout ms] [--port n] [--serial id] [--artifacts dir] [--json] | test ios [--wait-for-hmr] [--timeout ms] [--port n] [--udid id] [--artifacts dir] [--json]> [--config path]");
17447
17855
  };
17448
17856
  var init_mobile = __esm(() => {
17857
+ init_dependencies();
17449
17858
  init_capacitorProject();
17450
17859
  init_config();
17451
17860
  init_nativeDeepLinks();
@@ -17470,9 +17879,26 @@ var init_mobile = __esm(() => {
17470
17879
  CAPACITOR_PACKAGES = [
17471
17880
  "@capacitor/core",
17472
17881
  "@capacitor/app",
17882
+ "@capacitor/browser",
17883
+ "@capacitor/network",
17884
+ "@capacitor/preferences",
17473
17885
  "@capacitor/cli",
17474
17886
  "@capacitor/android",
17475
- "@capacitor/ios"
17887
+ "@capacitor/ios",
17888
+ "@absolutejs/devices",
17889
+ "@absolutejs/devices-capacitor"
17890
+ ];
17891
+ CAPACITOR_PACKAGE_SPECS = [
17892
+ "@capacitor/core@8.5.0",
17893
+ "@capacitor/app@8.1.1",
17894
+ "@capacitor/browser@8.0.4",
17895
+ "@capacitor/network@8.0.1",
17896
+ "@capacitor/preferences@8.0.1",
17897
+ "@capacitor/cli@8.5.0",
17898
+ "@capacitor/android@8.5.0",
17899
+ "@capacitor/ios@8.5.0",
17900
+ "@absolutejs/devices@0.0.2",
17901
+ "@absolutejs/devices-capacitor@0.1.2"
17476
17902
  ];
17477
17903
  });
17478
17904
 
@@ -17481,9 +17907,9 @@ var exports_typecheck = {};
17481
17907
  __export(exports_typecheck, {
17482
17908
  typecheck: () => typecheck
17483
17909
  });
17484
- import { resolve as resolve40, join as join47 } from "path";
17485
- import { existsSync as existsSync42, readFileSync as readFileSync37 } from "fs";
17486
- import { mkdir as mkdir13, writeFile as writeFile13 } from "fs/promises";
17910
+ import { resolve as resolve40, join as join48 } from "path";
17911
+ import { existsSync as existsSync42, readFileSync as readFileSync38 } from "fs";
17912
+ import { mkdir as mkdir14, writeFile as writeFile14 } from "fs/promises";
17487
17913
  var isCommandService3 = (service) => service.kind === "command" || Array.isArray(service.command), resolveConfigPath = (configPath2) => resolve40(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts"), getTypecheckTargets = async (configPath2) => {
17488
17914
  if (!existsSync42(resolveConfigPath(configPath2))) {
17489
17915
  const defaultService = {};
@@ -17562,7 +17988,7 @@ Found ${errorCount} error${suffix}.`;
17562
17988
  return candidates.find((candidate) => existsSync42(candidate)) ?? candidates[0];
17563
17989
  }, ABSOLUTE_TYPECHECK_FILES, readProjectTsconfig = () => {
17564
17990
  try {
17565
- return JSON.parse(readFileSync37(resolve40("tsconfig.json"), "utf-8"));
17991
+ return JSON.parse(readFileSync38(resolve40("tsconfig.json"), "utf-8"));
17566
17992
  } catch {
17567
17993
  return {};
17568
17994
  }
@@ -17590,8 +18016,8 @@ Found ${errorCount} error${suffix}.`;
17590
18016
  console.error("\x1B[31m\u2717\x1B[0m vue-tsc is required for Vue type checking. Install it: bun add -d vue-tsc");
17591
18017
  process.exit(1);
17592
18018
  }
17593
- const vueTsconfigPath = join47(cacheDir, "tsconfig.vue-check.json");
17594
- return writeFile13(vueTsconfigPath, JSON.stringify({
18019
+ const vueTsconfigPath = join48(cacheDir, "tsconfig.vue-check.json");
18020
+ return writeFile14(vueTsconfigPath, JSON.stringify({
17595
18021
  compilerOptions: {
17596
18022
  rootDir: ".."
17597
18023
  },
@@ -17605,7 +18031,7 @@ Found ${errorCount} error${suffix}.`;
17605
18031
  resolve40(vueTsconfigPath),
17606
18032
  "--incremental",
17607
18033
  "--tsBuildInfoFile",
17608
- join47(cacheDir, "vue-tsc.tsbuildinfo"),
18034
+ join48(cacheDir, "vue-tsc.tsbuildinfo"),
17609
18035
  "--pretty"
17610
18036
  ]));
17611
18037
  }, buildAngularCheck = async (cacheDir, angularDir) => {
@@ -17614,8 +18040,8 @@ Found ${errorCount} error${suffix}.`;
17614
18040
  console.error("\x1B[31m\u2717\x1B[0m @angular/compiler-cli is required for Angular type checking. Install it: bun add -d @angular/compiler-cli");
17615
18041
  process.exit(1);
17616
18042
  }
17617
- const angularTsconfigPath = join47(cacheDir, "tsconfig.angular-check.json");
17618
- await writeFile13(angularTsconfigPath, JSON.stringify({
18043
+ const angularTsconfigPath = join48(cacheDir, "tsconfig.angular-check.json");
18044
+ await writeFile14(angularTsconfigPath, JSON.stringify({
17619
18045
  angularCompilerOptions: {
17620
18046
  strictTemplates: true
17621
18047
  },
@@ -17634,8 +18060,8 @@ Found ${errorCount} error${suffix}.`;
17634
18060
  console.error("\x1B[31m\u2717\x1B[0m typescript is required for type checking. Install it: bun add -d typescript");
17635
18061
  process.exit(1);
17636
18062
  }
17637
- const tscConfigPath = join47(cacheDir, "tsconfig.typecheck.json");
17638
- return writeFile13(tscConfigPath, JSON.stringify({
18063
+ const tscConfigPath = join48(cacheDir, "tsconfig.typecheck.json");
18064
+ return writeFile14(tscConfigPath, JSON.stringify({
17639
18065
  compilerOptions: {
17640
18066
  rootDir: ".."
17641
18067
  },
@@ -17649,7 +18075,7 @@ Found ${errorCount} error${suffix}.`;
17649
18075
  resolve40(tscConfigPath),
17650
18076
  "--incremental",
17651
18077
  "--tsBuildInfoFile",
17652
- join47(cacheDir, "tsc.tsbuildinfo"),
18078
+ join48(cacheDir, "tsc.tsbuildinfo"),
17653
18079
  "--pretty"
17654
18080
  ]));
17655
18081
  }, buildSvelteCheck = async (cacheDir, svelteDir) => {
@@ -17658,8 +18084,8 @@ Found ${errorCount} error${suffix}.`;
17658
18084
  console.error("\x1B[31m\u2717\x1B[0m svelte-check is required for Svelte type checking. Install it: bun add -d svelte-check");
17659
18085
  process.exit(1);
17660
18086
  }
17661
- const svelteTsconfigPath = join47(cacheDir, "tsconfig.svelte-check.json");
17662
- await writeFile13(svelteTsconfigPath, JSON.stringify({
18087
+ const svelteTsconfigPath = join48(cacheDir, "tsconfig.svelte-check.json");
18088
+ await writeFile14(svelteTsconfigPath, JSON.stringify({
17663
18089
  extends: resolve40("tsconfig.json"),
17664
18090
  files: ABSOLUTE_TYPECHECK_FILES,
17665
18091
  include: [`../${svelteDir}/**/*`]
@@ -17688,7 +18114,7 @@ Found ${errorCount} error${suffix}.`;
17688
18114
  ...new Set(targets.map((config) => config.angularDirectory).filter((dir) => typeof dir === "string" && dir.length > 0))
17689
18115
  ];
17690
18116
  const cacheDir = ".absolutejs";
17691
- await mkdir13(cacheDir, { recursive: true });
18117
+ await mkdir14(cacheDir, { recursive: true });
17692
18118
  const checks = [];
17693
18119
  checks.push(hasVue ? buildVueTscCheck(cacheDir) : buildTscCheck(cacheDir));
17694
18120
  for (const svelteDir of hasSvelte ? svelteDirs : []) {
@@ -17912,12 +18338,12 @@ import { spawn as nodeSpawn } from "child_process";
17912
18338
  import {
17913
18339
  createWriteStream,
17914
18340
  existsSync as existsSync5,
17915
- readFileSync as readFileSync7,
18341
+ readFileSync as readFileSync8,
17916
18342
  rmSync as rmSync2,
17917
18343
  writeFileSync as writeFileSync4
17918
18344
  } from "fs";
17919
18345
  import { tmpdir as tmpdir2 } from "os";
17920
- import { join as join12, resolve as resolve8 } from "path";
18346
+ import { join as join13, resolve as resolve8 } from "path";
17921
18347
 
17922
18348
  // src/dev/tunnel/client.ts
17923
18349
  var RECONNECT_DELAY_MS = 2000;
@@ -18403,6 +18829,7 @@ var resolveDevPort = async (requestedPort, options = {}) => {
18403
18829
 
18404
18830
  // src/cli/scripts/dev.ts
18405
18831
  init_config();
18832
+ init_nativeAuth();
18406
18833
  init_androidEmulatorController();
18407
18834
  init_emulatorDoctor();
18408
18835
  init_emulatorInstaller();
@@ -18746,6 +19173,8 @@ var dev = async (serverEntry, configPath2, options = {}) => {
18746
19173
  try {
18747
19174
  const config = await loadConfig(configPath2);
18748
19175
  mobileConfig = config?.mobile;
19176
+ if (mobileConfig)
19177
+ installAbsoluteMobileAuthEnvironment(process.cwd(), normalizeAbsoluteMobileConfig(mobileConfig, process.cwd()));
18749
19178
  resolvedDev = resolveDevConfig(config?.dev);
18750
19179
  httpsEnabled = resolvedDev.https;
18751
19180
  if (config?.buildDirectory) {
@@ -18775,7 +19204,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
18775
19204
  }
18776
19205
  }
18777
19206
  if (ready) {
18778
- const nativeDirectory = join12(normalized.nativeProjectDirectory, "android");
19207
+ const nativeDirectory = join13(normalized.nativeProjectDirectory, "android");
18779
19208
  let createNativeProject = false;
18780
19209
  if (!existsSync5(nativeDirectory)) {
18781
19210
  createNativeProject = await confirmPrompt("Create the managed Capacitor Android project now?");
@@ -18794,7 +19223,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
18794
19223
  if (!remote) {
18795
19224
  console.log(cliTag("\x1B[33m", "iOS simulator skipped. Pair a Mac with `absolute mobile pair mac <name> <user@host>`."));
18796
19225
  } else {
18797
- const nativeDirectory = join12(normalized.nativeProjectDirectory, "ios");
19226
+ const nativeDirectory = join13(normalized.nativeProjectDirectory, "ios");
18798
19227
  if (!existsSync5(nativeDirectory)) {
18799
19228
  console.log(cliTag("\x1B[33m", "The iOS project is missing. Run `absolute mobile init` before remote development."));
18800
19229
  } else {
@@ -18814,7 +19243,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
18814
19243
  }
18815
19244
  }
18816
19245
  if (ready) {
18817
- const nativeDirectory = join12(normalized.nativeProjectDirectory, "ios");
19246
+ const nativeDirectory = join13(normalized.nativeProjectDirectory, "ios");
18818
19247
  let createNativeProject = false;
18819
19248
  if (!existsSync5(nativeDirectory)) {
18820
19249
  createNativeProject = await confirmPrompt("Create the managed Capacitor iOS project now?");
@@ -19240,7 +19669,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
19240
19669
  for (const name of candidates) {
19241
19670
  let text;
19242
19671
  try {
19243
- text = readFileSync7(resolve8(process.cwd(), name), "utf8");
19672
+ text = readFileSync8(resolve8(process.cwd(), name), "utf8");
19244
19673
  } catch {
19245
19674
  continue;
19246
19675
  }
@@ -19262,7 +19691,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
19262
19691
  }
19263
19692
  return merged;
19264
19693
  };
19265
- const heapPreloadPath = join12(tmpdir2(), `absolute-heap-${process.pid}.ts`);
19694
+ const heapPreloadPath = join13(tmpdir2(), `absolute-heap-${process.pid}.ts`);
19266
19695
  let heapSnapshotEnabled = false;
19267
19696
  try {
19268
19697
  writeFileSync4(heapPreloadPath, DEV_CHILD_PRELOAD);
@@ -19392,7 +19821,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
19392
19821
  if (now - last < 100)
19393
19822
  return;
19394
19823
  recentlyHandled.set(filename, now);
19395
- scheduleServerRestart(join12(serverEntryDir, filename));
19824
+ scheduleServerRestart(join13(serverEntryDir, filename));
19396
19825
  };
19397
19826
  const recoveryScan = async () => {
19398
19827
  let entries;
@@ -19411,7 +19840,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
19411
19840
  continue;
19412
19841
  let fileStat;
19413
19842
  try {
19414
- fileStat = statSync(join12(serverEntryDir, entry.name));
19843
+ fileStat = statSync(join13(serverEntryDir, entry.name));
19415
19844
  } catch {
19416
19845
  continue;
19417
19846
  }
@@ -19773,7 +20202,7 @@ init_eslint();
19773
20202
  init_constants();
19774
20203
  init_utils();
19775
20204
  import { execSync as execSync2 } from "child_process";
19776
- import { existsSync as existsSync8, readFileSync as readFileSync9 } from "fs";
20205
+ import { existsSync as existsSync8, readFileSync as readFileSync10 } from "fs";
19777
20206
  import { arch as arch2, cpus, platform as platform3, totalmem, version } from "os";
19778
20207
  import { resolve as resolve11 } from "path";
19779
20208
  var bold = (str) => `\x1B[1m${str}\x1B[0m`;
@@ -19795,7 +20224,7 @@ var getPackageVersion = (packageName) => {
19795
20224
  const pkgPath = __require.resolve(`${packageName}/package.json`, {
19796
20225
  paths: [process.cwd()]
19797
20226
  });
19798
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
20227
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
19799
20228
  const ver = pkg.version;
19800
20229
  return ver;
19801
20230
  } catch {
@@ -19817,7 +20246,7 @@ var getAbsoluteVersion = () => {
19817
20246
  return getPackageVersion("@absolutejs/absolute");
19818
20247
  };
19819
20248
  var readPackageVersion = (pkgPath) => {
19820
- const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
20249
+ const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
19821
20250
  const ver = pkg.version;
19822
20251
  return ver;
19823
20252
  };
@@ -19919,7 +20348,7 @@ var info = () => {
19919
20348
  // src/cli/cache.ts
19920
20349
  init_constants();
19921
20350
  import { mkdir as mkdir6 } from "fs/promises";
19922
- import { join as join13 } from "path";
20351
+ import { join as join14 } from "path";
19923
20352
  var {Glob } = globalThis.Bun;
19924
20353
  var CACHE_DIR = ".absolutejs";
19925
20354
  var MAX_FILES_PER_BATCH = 200;
@@ -19971,7 +20400,7 @@ var hashFiles = async (paths) => {
19971
20400
  };
19972
20401
  var loadCache = async (tool) => {
19973
20402
  try {
19974
- const path = join13(CACHE_DIR, `${tool}.cache.json`);
20403
+ const path = join14(CACHE_DIR, `${tool}.cache.json`);
19975
20404
  const data = await Bun.file(path).json();
19976
20405
  const result = data;
19977
20406
  return result;
@@ -20018,7 +20447,7 @@ var runTool = async (adapter, args) => {
20018
20447
  };
20019
20448
  var saveCache = async (tool, data) => {
20020
20449
  await mkdir6(CACHE_DIR, { recursive: true });
20021
- const path = join13(CACHE_DIR, `${tool}.cache.json`);
20450
+ const path = join14(CACHE_DIR, `${tool}.cache.json`);
20022
20451
  await Bun.write(path, JSON.stringify(data, null, "\t"));
20023
20452
  };
20024
20453
 
@@ -20114,7 +20543,7 @@ import {
20114
20543
  existsSync as existsSync12,
20115
20544
  mkdirSync as mkdirSync7,
20116
20545
  readdirSync as readdirSync2,
20117
- readFileSync as readFileSync13,
20546
+ readFileSync as readFileSync14,
20118
20547
  unlinkSync as unlinkSync3,
20119
20548
  writeFileSync as writeFileSync6
20120
20549
  } from "fs";
@@ -20720,7 +21149,7 @@ var createWorkspaceLogSink = (appendLog) => {
20720
21149
  };
20721
21150
  var readPackageVersion3 = (candidate) => {
20722
21151
  try {
20723
- const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
21152
+ const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
20724
21153
  if (pkg.name !== "@absolutejs/absolute") {
20725
21154
  return null;
20726
21155
  }