@absolutejs/absolute 0.20.0-beta.92 → 0.20.0-beta.94

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 (39) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/changelog.json +48 -0
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  4. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  5. package/dist/build/buildWorker.js +10 -1
  6. package/dist/build.js +16 -7
  7. package/dist/build.js.map +9 -8
  8. package/dist/cli/{compile-vf61bv90.js → compile-qg75ewma.js} +5 -5
  9. package/dist/cli/{dev-perzmh2w.js → dev-sm9px53g.js} +83 -11
  10. package/dist/cli/{expoDevController-tr63cg78.js → expoDevController-a0jk8d43.js} +31 -2
  11. package/dist/cli/expoNativeWatcher-rmc95bak.js +138 -0
  12. package/dist/cli/{expoProject-djc0vk7g.js → expoProject-h38entbj.js} +1 -1
  13. package/dist/cli/{index-8zrnvazp.js → index-0t1cxstr.js} +261 -48
  14. package/dist/cli/{index-fn44wefq.js → index-3sdvzrv2.js} +37 -28
  15. package/dist/cli/{index-gxkmg2ss.js → index-51yyq29s.js} +1 -1
  16. package/dist/cli/index-bw4ktfnz.js +11 -0
  17. package/dist/cli/{index-751czk1b.js → index-d8va9b7v.js} +1 -1
  18. package/dist/cli/index.js +5 -5
  19. package/dist/cli/{mobile-yk7qr9qg.js → mobile-dev4mjsa.js} +20 -12
  20. package/dist/cli/{remoteMacProtocol-vw931n0a.js → remoteMacProtocol-kqvkp0qd.js} +2 -1
  21. package/dist/cli/{start-ef7tgbmf.js → start-0ddnh0y4.js} +3 -3
  22. package/dist/dev/client/handlers/svelte.ts +11 -15
  23. package/dist/dev/serverBootstrap.js +10 -1
  24. package/dist/index.js +17 -8
  25. package/dist/index.js.map +11 -10
  26. package/dist/mobile/index.js +599 -208
  27. package/dist/mobile/index.js.map +11 -8
  28. package/dist/mobile/mobilePreviewClient.ts +1 -1
  29. package/dist/mobile/remoteMacAgentEntry.js +354 -188
  30. package/dist/src/dev/clientManager.d.ts +2 -2
  31. package/dist/src/mobile/androidConformance.d.ts +4 -1
  32. package/dist/src/mobile/expoActivityResultRecovery.d.ts +1 -0
  33. package/dist/src/mobile/expoBridge.d.ts +2 -2
  34. package/dist/src/mobile/expoDevController.d.ts +2 -6
  35. package/dist/src/mobile/expoNativeWatcher.d.ts +21 -0
  36. package/dist/src/mobile/index.d.ts +1 -0
  37. package/dist/src/mobile/remoteMacProtocol.d.ts +1 -4
  38. package/dist/src/utils/unrefTimer.d.ts +5 -0
  39. package/package.json +5 -2
@@ -2,6 +2,9 @@
2
2
  import {
3
3
  isRecord
4
4
  } from "./index-v1k46q3x.js";
5
+ import {
6
+ prerenderWithServer
7
+ } from "./index-9q8yn5ax.js";
5
8
  import {
6
9
  maskLiterals
7
10
  } from "./index-me8nczrw.js";
@@ -12,7 +15,7 @@ import {
12
15
  createIslandRegistryDefinitionPlugin,
13
16
  finalizeAbsoluteMobileCompatibilityBuild,
14
17
  resolveServerBundleExternals
15
- } from "./index-751czk1b.js";
18
+ } from "./index-d8va9b7v.js";
16
19
  import {
17
20
  loadIslandRegistryBuildInfo
18
21
  } from "./index-bzs19w3r.js";
@@ -26,9 +29,6 @@ import {
26
29
  import {
27
30
  loadConfig
28
31
  } from "./index-06cmrcdq.js";
29
- import {
30
- prerenderWithServer
31
- } from "./index-9q8yn5ax.js";
32
32
  import {
33
33
  sendTelemetryEvent
34
34
  } from "./index-9kwmb3c0.js";
@@ -36,7 +36,7 @@ import"./index-w5vswatm.js";
36
36
  import {
37
37
  normalizeAbsoluteMobileConfig
38
38
  } from "./index-rd2hbttb.js";
39
- import"./index-8zrnvazp.js";
39
+ import"./index-0t1cxstr.js";
40
40
  import {
41
41
  ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
42
42
  installAbsoluteMobileAuthEnvironment
@@ -25,6 +25,9 @@ import {
25
25
  import {
26
26
  loadConfig
27
27
  } from "./index-06cmrcdq.js";
28
+ import {
29
+ unrefTimer
30
+ } from "./index-bw4ktfnz.js";
28
31
  import {
29
32
  bootTimelineChildEnv,
30
33
  markBoot
@@ -906,7 +909,7 @@ var startEarlyListener = (options) => {
906
909
  if (attempts >= BIND_RETRY_LIMIT)
907
910
  return;
908
911
  retryTimer = setTimeout(tryBind, BIND_RETRY_INTERVAL_MS);
909
- retryTimer.unref();
912
+ unrefTimer(retryTimer);
910
913
  } finally {
911
914
  bindingPlaceholder = false;
912
915
  }
@@ -1279,23 +1282,26 @@ var loadAbsoluteMobileDevModules = async () => {
1279
1282
  androidNativeWatcher,
1280
1283
  iosSimulatorController,
1281
1284
  remoteMacProtocol,
1282
- iosNativeWatcher
1285
+ iosNativeWatcher,
1286
+ expoNativeWatcher
1283
1287
  ] = await Promise.all([
1284
1288
  import("./config-vy04mqce.js"),
1285
- import("./expoProject-djc0vk7g.js"),
1286
- import("./expoDevController-tr63cg78.js"),
1289
+ import("./expoProject-h38entbj.js"),
1290
+ import("./expoDevController-a0jk8d43.js"),
1287
1291
  import("./nativeAuth-zx4tsb1f.js"),
1288
1292
  import("./androidEmulatorController-nybhzc6c.js"),
1289
1293
  import("./emulatorDoctor-y2nqmaha.js"),
1290
1294
  import("./emulatorInstaller-3shdna4g.js"),
1291
1295
  import("./androidNativeWatcher-2930tb8c.js"),
1292
1296
  import("./iosSimulatorController-dr98a0p9.js"),
1293
- import("./remoteMacProtocol-vw931n0a.js"),
1294
- import("./iosNativeWatcher-3k715hq0.js")
1297
+ import("./remoteMacProtocol-kqvkp0qd.js"),
1298
+ import("./iosNativeWatcher-3k715hq0.js"),
1299
+ import("./expoNativeWatcher-rmc95bak.js")
1295
1300
  ]);
1296
1301
  return {
1297
1302
  absoluteExpoExecutable: expoDevController.absoluteExpoExecutable,
1298
1303
  createAbsoluteAndroidNativeWatcher: androidNativeWatcher.createAbsoluteAndroidNativeWatcher,
1304
+ createAbsoluteExpoNativeWatcher: expoNativeWatcher.createAbsoluteExpoNativeWatcher,
1299
1305
  createAbsoluteIosNativeWatcher: iosNativeWatcher.createAbsoluteIosNativeWatcher,
1300
1306
  createAbsoluteRemoteExpoIosDevProject: remoteMacProtocol.createAbsoluteRemoteExpoIosDevProject,
1301
1307
  createAbsoluteRemoteIosDevProject: remoteMacProtocol.createAbsoluteRemoteIosDevProject,
@@ -1613,6 +1619,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
1613
1619
  if (platforms.length > 0 || remoteIos) {
1614
1620
  expoDevProject = {
1615
1621
  executable: await mobile.absoluteExpoExecutable(generated.path),
1622
+ expoProjectDirectory: generated.path,
1616
1623
  mobile: normalized,
1617
1624
  platforms,
1618
1625
  ...remoteIos ? { remoteIos } : {}
@@ -1821,6 +1828,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
1821
1828
  let iosDevStart = null;
1822
1829
  let iosNativeWatcher = null;
1823
1830
  let expoDevSession = null;
1831
+ let expoNativeWatcher = null;
1824
1832
  let expoDevStart = null;
1825
1833
  let expoDevState = "waiting-for-server";
1826
1834
  const expoDevAbort = new AbortController;
@@ -2094,6 +2102,55 @@ var dev = async (serverEntry, configPath, options = {}) => {
2094
2102
  return "ios";
2095
2103
  return "shared";
2096
2104
  };
2105
+ const ensureExpoNativeWatcher = async (project) => {
2106
+ if (expoNativeWatcher)
2107
+ return;
2108
+ const mobile = requireMobileDev();
2109
+ expoNativeWatcher = await mobile.createAbsoluteExpoNativeWatcher({
2110
+ expoProjectDirectory: project.expoProjectDirectory,
2111
+ projectRoot: process.cwd(),
2112
+ signal: expoDevAbort.signal,
2113
+ onChange: async (change) => {
2114
+ if (cleaning)
2115
+ return;
2116
+ const startedAt = performance.now();
2117
+ printNativeOutput(cliTag("\x1B[35m", `Expo native inputs changed (${change.paths.length} path${change.paths.length === 1 ? "" : "s"}); regenerating and rebuilding\u2026`));
2118
+ const current = expoDevSession;
2119
+ if (!current)
2120
+ return;
2121
+ if (change.rootInputChanged)
2122
+ await mobile.writeAbsoluteExpoProject(project.mobile, {
2123
+ projectRoot: process.cwd()
2124
+ });
2125
+ const replacement = await current.rebuild();
2126
+ if (cleaning)
2127
+ return;
2128
+ expoDevSession = replacement;
2129
+ expoDevState = "ready";
2130
+ const durationMs = performance.now() - startedAt;
2131
+ sendTelemetryEvent("mobile:native-rebuild", {
2132
+ durationMs: Math.round(durationMs),
2133
+ host: mobile.detectAbsoluteMobileHost(),
2134
+ platforms: replacement.platforms,
2135
+ provider: "expo",
2136
+ rootInputChanged: change.rootInputChanged,
2137
+ success: true,
2138
+ timings: replacement.timings
2139
+ });
2140
+ printNativeOutput(cliTag("\x1B[35m", `Expo native rebuild completed in ${Math.round(durationMs)}ms; Metro stayed live on ${replacement.metroPort}.`));
2141
+ },
2142
+ onError: (error) => {
2143
+ expoDevState = "failed";
2144
+ sendTelemetryEvent("mobile:native-rebuild", {
2145
+ host: mobile.detectAbsoluteMobileHost(),
2146
+ platforms: project.platforms,
2147
+ provider: "expo",
2148
+ success: false
2149
+ });
2150
+ printNativeOutput(cliTag("\x1B[31m", `Expo native rebuild failed: ${error instanceof Error ? error.message : String(error)}`));
2151
+ }
2152
+ });
2153
+ };
2097
2154
  const startExpoDev = () => {
2098
2155
  const project = expoDevProject;
2099
2156
  if (!project || expoMetroPort === undefined || expoDevStart || expoDevSession) {
@@ -2222,6 +2279,19 @@ var dev = async (serverEntry, configPath, options = {}) => {
2222
2279
  localNative?.close(),
2223
2280
  remote?.close()
2224
2281
  ]);
2282
+ },
2283
+ rebuild: async () => {
2284
+ const [, nextLocal, nextRemote] = await Promise.all([
2285
+ metro.rebuild(),
2286
+ localNative?.rebuild(),
2287
+ remote?.rebuild()
2288
+ ]);
2289
+ session.timings = {
2290
+ ...metro.timings,
2291
+ ...nextLocal?.timings,
2292
+ ...nextRemote?.timings
2293
+ };
2294
+ return session;
2225
2295
  }
2226
2296
  };
2227
2297
  if (cleaning) {
@@ -2229,6 +2299,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2229
2299
  } else {
2230
2300
  expoDevSession = session;
2231
2301
  expoDevState = "ready";
2302
+ await ensureExpoNativeWatcher(project);
2232
2303
  sendTelemetryEvent("mobile:expo-dev-ready", {
2233
2304
  metroPort: session.metroPort,
2234
2305
  platforms: session.platforms,
@@ -2654,7 +2725,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2654
2725
  const killTimer = setTimeout(() => {
2655
2726
  signalChildTree(proc, "SIGKILL");
2656
2727
  }, FORCE_KILL_GRACE_MS);
2657
- killTimer.unref();
2728
+ unrefTimer(killTimer);
2658
2729
  });
2659
2730
  const cleanup = async (exitCode = 0) => {
2660
2731
  if (cleaning)
@@ -2673,6 +2744,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2673
2744
  iosDevAbort.abort();
2674
2745
  iosNativeWatcher?.close();
2675
2746
  expoDevAbort.abort();
2747
+ expoNativeWatcher?.close();
2676
2748
  if (expoDevStart)
2677
2749
  await expoDevStart.catch(() => {
2678
2750
  return;
@@ -2703,9 +2775,10 @@ var dev = async (serverEntry, configPath, options = {}) => {
2703
2775
  return;
2704
2776
  }
2705
2777
  serverProcess.once("exit", () => _resolve());
2706
- setTimeout(() => {
2778
+ const forceKillTimer = setTimeout(() => {
2707
2779
  killChildTree("SIGKILL");
2708
- }, 2000).unref();
2780
+ }, 2000);
2781
+ unrefTimer(forceKillTimer);
2709
2782
  });
2710
2783
  if (scripts)
2711
2784
  await stopDatabase(scripts);
@@ -2877,8 +2950,7 @@ var dev = async (serverEntry, configPath, options = {}) => {
2877
2950
  cleanup(0);
2878
2951
  }
2879
2952
  }, 1000);
2880
- if (typeof ppidWatcher.unref === "function")
2881
- ppidWatcher.unref();
2953
+ unrefTimer(ppidWatcher);
2882
2954
  printHint();
2883
2955
  const HEALTHY_CHILD_UPTIME_MS = 1e4;
2884
2956
  const MAX_CONSECUTIVE_CRASHES = 5;
@@ -208,10 +208,15 @@ var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, captu
208
208
  `$env:NODE_ENV = '${mode === "development" ? "development" : "production"}'`,
209
209
  ...preferredDevice ? [] : ["$env:ORG_GRADLE_PROJECT_reactNativeArchitectures = 'x86_64'"],
210
210
  "New-Item -ItemType Directory -Force -Path $directory | Out-Null",
211
- "& robocopy.exe $source $directory /MIR /XD node_modules .expo .git .gradle .cxx .kotlin build /XF bun.lock bun.lockb .absolutejs-preserve-subst.cjs /NFL /NDL /NJH /NJS /NP",
211
+ "& robocopy.exe $source $directory /MIR /XD node_modules .expo .git .gradle .cxx .kotlin build /XF bun.lock bun.lockb .absolutejs-preserve-subst.cjs .absolutejs-source-lock.sha256 /NFL /NDL /NJH /NJS /NP",
212
212
  "$copyExit = $LASTEXITCODE",
213
213
  "if ($copyExit -ge 8) { exit $copyExit }",
214
214
  "Set-Location $directory",
215
+ "$sourceLock = @('bun.lock', 'bun.lockb') | ForEach-Object { Join-Path $source $_ } | Where-Object { Test-Path $_ } | Select-Object -First 1",
216
+ "$sourceLockHash = if ($sourceLock) { (Get-FileHash $sourceLock -Algorithm SHA256).Hash } else { 'none' }",
217
+ "$lockMarker = Join-Path $directory '.absolutejs-source-lock.sha256'",
218
+ "$priorLockHash = if (Test-Path $lockMarker) { (Get-Content $lockMarker -Raw).Trim() } else { '' }",
219
+ "if ($priorLockHash -ne $sourceLockHash) { Remove-Item (Join-Path $directory 'bun.lock'), (Join-Path $directory 'bun.lockb') -Force -ErrorAction SilentlyContinue; Set-Content $lockMarker $sourceLockHash -NoNewline }",
215
220
  "$bun = (Get-Command bun.exe -ErrorAction Stop).Source",
216
221
  "& $bun install",
217
222
  "if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }",
@@ -717,18 +722,42 @@ var startAbsoluteExpoDevSession = async (options) => {
717
722
  publishTiming("starting-metro", performance.now() - metroStarted);
718
723
  await runNativeCommands(nativeCommands);
719
724
  setState("ready");
720
- return {
725
+ let closed = false;
726
+ let rebuildQueue = Promise.resolve();
727
+ const session = {
721
728
  metroPort: plan.metroPort,
722
729
  platforms: options.platforms,
723
730
  timings,
724
731
  close: async () => {
732
+ if (closed)
733
+ return;
734
+ closed = true;
725
735
  options.signal?.removeEventListener("abort", abort);
736
+ await rebuildQueue;
726
737
  if (metro)
727
738
  await stopProcess(metro);
728
739
  await closeEnrollmentServer();
729
740
  setState("closed");
741
+ },
742
+ rebuild: () => {
743
+ const rebuild = rebuildQueue.then(async () => {
744
+ if (closed)
745
+ throw new Error("The Expo development session is closed.");
746
+ if (prepareCommand)
747
+ await runPrepareCommand(prepareCommand);
748
+ await runNativeCommands(nativeCommands);
749
+ setState("ready");
750
+ return session;
751
+ });
752
+ rebuildQueue = rebuild.then(() => {
753
+ return;
754
+ }, () => {
755
+ return;
756
+ });
757
+ return rebuild;
730
758
  }
731
759
  };
760
+ return session;
732
761
  } catch (error) {
733
762
  options.signal?.removeEventListener("abort", abort);
734
763
  if (metro)
@@ -0,0 +1,138 @@
1
+ // @bun
2
+ import"./index-mywsk201.js";
3
+
4
+ // src/mobile/expoNativeWatcher.ts
5
+ import { watch } from "fs";
6
+ import { access, readdir, readFile } from "fs/promises";
7
+ import { basename, join, relative } from "path";
8
+ import { createHash } from "crypto";
9
+ var NATIVE_CHANGE_DEBOUNCE_MS = 500;
10
+ var ROOT_NATIVE_INPUTS = new Set([
11
+ "absolute.config.js",
12
+ "absolute.config.mjs",
13
+ "absolute.config.ts",
14
+ "absolutejs.config.js",
15
+ "absolutejs.config.mjs",
16
+ "absolutejs.config.ts",
17
+ "bun.lock",
18
+ "bun.lockb",
19
+ "package.json"
20
+ ]);
21
+ var EXPO_NATIVE_DIRECTORIES = ["modules", "plugins"];
22
+ var exists = async (path) => access(path).then(() => true, () => false);
23
+ var filesIn = async (directory, prefix) => {
24
+ if (!await exists(directory))
25
+ return [];
26
+ const entries = await readdir(directory, { withFileTypes: true });
27
+ const nested = await Promise.all(entries.map((entry) => {
28
+ const path = join(directory, entry.name);
29
+ const name = `${prefix}/${entry.name}`;
30
+ if (entry.isDirectory())
31
+ return filesIn(path, name);
32
+ return Promise.resolve(entry.isFile() ? [{ name, path }] : []);
33
+ }));
34
+ return nested.flat().sort((left, right) => left.name.localeCompare(right.name));
35
+ };
36
+ var fingerprintAbsoluteExpoNativeInputs = async (options) => {
37
+ const hash = createHash("sha256");
38
+ const rootFiles = await Promise.all([...ROOT_NATIVE_INPUTS].sort().map(async (name) => {
39
+ const path = join(options.projectRoot, name);
40
+ return await exists(path) ? [{ name: `root/${name}`, path }] : [];
41
+ }));
42
+ const nativeFiles = await Promise.all(EXPO_NATIVE_DIRECTORIES.map((name) => filesIn(join(options.expoProjectDirectory, name), name)));
43
+ const files = [...rootFiles.flat(), ...nativeFiles.flat()].sort((left, right) => left.name.localeCompare(right.name));
44
+ const contents = await Promise.all(files.map(({ path }) => readFile(path)));
45
+ files.forEach(({ name }, index) => {
46
+ hash.update(name);
47
+ hash.update(contents[index] ?? Buffer.alloc(0));
48
+ });
49
+ return hash.digest("hex");
50
+ };
51
+ var isAbsoluteExpoNativeRootInput = (path) => ROOT_NATIVE_INPUTS.has(basename(path));
52
+ var createAbsoluteExpoNativeWatcher = async (options) => {
53
+ let fingerprint = await fingerprintAbsoluteExpoNativeInputs(options);
54
+ let closed = false;
55
+ let running = false;
56
+ let timer;
57
+ let rootInputChanged = false;
58
+ const changedPaths = new Set;
59
+ const watchers = [];
60
+ const debounceMs = options.debounceMs ?? NATIVE_CHANGE_DEBOUNCE_MS;
61
+ const close = () => {
62
+ if (closed)
63
+ return;
64
+ closed = true;
65
+ if (timer)
66
+ clearTimeout(timer);
67
+ watchers.forEach((watcher) => watcher.close());
68
+ options.signal?.removeEventListener("abort", close);
69
+ };
70
+ const schedule = () => {
71
+ if (closed || running)
72
+ return;
73
+ if (timer)
74
+ clearTimeout(timer);
75
+ timer = setTimeout(() => void flush(), debounceMs);
76
+ };
77
+ const record = (path, root) => {
78
+ if (closed)
79
+ return;
80
+ changedPaths.add(path);
81
+ rootInputChanged ||= root;
82
+ schedule();
83
+ };
84
+ const flush = async () => {
85
+ timer = undefined;
86
+ if (closed || running || changedPaths.size === 0)
87
+ return;
88
+ running = true;
89
+ const paths = [...changedPaths].sort();
90
+ const rootChanged = rootInputChanged;
91
+ changedPaths.clear();
92
+ rootInputChanged = false;
93
+ try {
94
+ const next = await fingerprintAbsoluteExpoNativeInputs(options);
95
+ if (next === fingerprint)
96
+ return;
97
+ await options.onChange({
98
+ afterFingerprint: next,
99
+ beforeFingerprint: fingerprint,
100
+ paths,
101
+ rootInputChanged: rootChanged
102
+ });
103
+ fingerprint = await fingerprintAbsoluteExpoNativeInputs(options);
104
+ } catch (error) {
105
+ options.onError?.(error);
106
+ } finally {
107
+ running = false;
108
+ if (changedPaths.size > 0)
109
+ schedule();
110
+ }
111
+ };
112
+ const nativeDirectories = (await Promise.all(EXPO_NATIVE_DIRECTORIES.map(async (name) => {
113
+ const directory = join(options.expoProjectDirectory, name);
114
+ return await exists(directory) ? [directory] : [];
115
+ }))).flat();
116
+ nativeDirectories.forEach((directory) => {
117
+ watchers.push(watch(directory, { recursive: true }, (_event, filename) => {
118
+ if (!filename)
119
+ return;
120
+ record(relative(options.expoProjectDirectory, join(directory, String(filename))), false);
121
+ }));
122
+ });
123
+ watchers.push(watch(options.projectRoot, (_event, filename) => {
124
+ if (!filename)
125
+ return;
126
+ const path = String(filename);
127
+ if (isAbsoluteExpoNativeRootInput(path))
128
+ record(path, true);
129
+ }));
130
+ watchers.forEach((watcher) => watcher.on("error", (error) => options.onError?.(error)));
131
+ options.signal?.addEventListener("abort", close, { once: true });
132
+ return { close };
133
+ };
134
+ export {
135
+ createAbsoluteExpoNativeWatcher,
136
+ fingerprintAbsoluteExpoNativeInputs,
137
+ isAbsoluteExpoNativeRootInput
138
+ };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  syncAbsoluteExpoWebAssets,
4
4
  writeAbsoluteExpoProject
5
- } from "./index-8zrnvazp.js";
5
+ } from "./index-0t1cxstr.js";
6
6
  import"./index-ar4gz15x.js";
7
7
  import"./index-mywsk201.js";
8
8
  export {