@absolutejs/absolute 0.20.0-beta.92 → 0.20.0-beta.93
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/changelog.json +28 -0
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/build/buildWorker.js +10 -1
- package/dist/build.js +16 -7
- package/dist/build.js.map +9 -8
- package/dist/cli/{compile-vf61bv90.js → compile-wkfd88w7.js} +5 -5
- package/dist/cli/{dev-perzmh2w.js → dev-01zcxngn.js} +83 -11
- package/dist/cli/{expoDevController-tr63cg78.js → expoDevController-k15hftqn.js} +25 -1
- package/dist/cli/expoNativeWatcher-rmc95bak.js +138 -0
- package/dist/cli/{expoProject-djc0vk7g.js → expoProject-mmm3s62b.js} +1 -1
- package/dist/cli/{index-fn44wefq.js → index-3sdvzrv2.js} +37 -28
- package/dist/cli/index-bw4ktfnz.js +11 -0
- package/dist/cli/{index-751czk1b.js → index-kh44yx23.js} +1 -1
- package/dist/cli/{index-gxkmg2ss.js → index-v5knwk7v.js} +1 -1
- package/dist/cli/{index-8zrnvazp.js → index-wqhbxtyp.js} +21 -12
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-yk7qr9qg.js → mobile-pbe1a667.js} +20 -12
- package/dist/cli/{remoteMacProtocol-vw931n0a.js → remoteMacProtocol-kqvkp0qd.js} +2 -1
- package/dist/cli/{start-ef7tgbmf.js → start-dw5crgp7.js} +3 -3
- package/dist/dev/client/handlers/svelte.ts +11 -15
- package/dist/dev/serverBootstrap.js +10 -1
- package/dist/index.js +17 -8
- package/dist/index.js.map +11 -10
- package/dist/mobile/index.js +343 -162
- package/dist/mobile/index.js.map +9 -7
- package/dist/mobile/mobilePreviewClient.ts +1 -1
- package/dist/mobile/remoteMacAgentEntry.js +77 -68
- package/dist/src/dev/clientManager.d.ts +2 -2
- package/dist/src/mobile/androidConformance.d.ts +4 -1
- package/dist/src/mobile/expoDevController.d.ts +2 -6
- package/dist/src/mobile/expoNativeWatcher.d.ts +21 -0
- package/dist/src/mobile/index.d.ts +1 -0
- package/dist/src/mobile/remoteMacProtocol.d.ts +1 -4
- package/dist/src/utils/unrefTimer.d.ts +5 -0
- package/package.json +4 -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-
|
|
18
|
+
} from "./index-kh44yx23.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-
|
|
39
|
+
import"./index-wqhbxtyp.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
|
|
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-
|
|
1286
|
-
import("./expoDevController-
|
|
1289
|
+
import("./expoProject-mmm3s62b.js"),
|
|
1290
|
+
import("./expoDevController-k15hftqn.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-
|
|
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
|
|
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)
|
|
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
|
-
|
|
2881
|
-
ppidWatcher.unref();
|
|
2953
|
+
unrefTimer(ppidWatcher);
|
|
2882
2954
|
printHint();
|
|
2883
2955
|
const HEALTHY_CHILD_UPTIME_MS = 1e4;
|
|
2884
2956
|
const MAX_CONSECUTIVE_CRASHES = 5;
|
|
@@ -717,18 +717,42 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
717
717
|
publishTiming("starting-metro", performance.now() - metroStarted);
|
|
718
718
|
await runNativeCommands(nativeCommands);
|
|
719
719
|
setState("ready");
|
|
720
|
-
|
|
720
|
+
let closed = false;
|
|
721
|
+
let rebuildQueue = Promise.resolve();
|
|
722
|
+
const session = {
|
|
721
723
|
metroPort: plan.metroPort,
|
|
722
724
|
platforms: options.platforms,
|
|
723
725
|
timings,
|
|
724
726
|
close: async () => {
|
|
727
|
+
if (closed)
|
|
728
|
+
return;
|
|
729
|
+
closed = true;
|
|
725
730
|
options.signal?.removeEventListener("abort", abort);
|
|
731
|
+
await rebuildQueue;
|
|
726
732
|
if (metro)
|
|
727
733
|
await stopProcess(metro);
|
|
728
734
|
await closeEnrollmentServer();
|
|
729
735
|
setState("closed");
|
|
736
|
+
},
|
|
737
|
+
rebuild: () => {
|
|
738
|
+
const rebuild = rebuildQueue.then(async () => {
|
|
739
|
+
if (closed)
|
|
740
|
+
throw new Error("The Expo development session is closed.");
|
|
741
|
+
if (prepareCommand)
|
|
742
|
+
await runPrepareCommand(prepareCommand);
|
|
743
|
+
await runNativeCommands(nativeCommands);
|
|
744
|
+
setState("ready");
|
|
745
|
+
return session;
|
|
746
|
+
});
|
|
747
|
+
rebuildQueue = rebuild.then(() => {
|
|
748
|
+
return;
|
|
749
|
+
}, () => {
|
|
750
|
+
return;
|
|
751
|
+
});
|
|
752
|
+
return rebuild;
|
|
730
753
|
}
|
|
731
754
|
};
|
|
755
|
+
return session;
|
|
732
756
|
} catch (error) {
|
|
733
757
|
options.signal?.removeEventListener("abort", abort);
|
|
734
758
|
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
|
+
};
|
|
@@ -3,6 +3,9 @@ import {
|
|
|
3
3
|
installAbsoluteIosRelease,
|
|
4
4
|
requireAbsoluteIosReleaseMetadata
|
|
5
5
|
} from "./index-qxnptvwn.js";
|
|
6
|
+
import {
|
|
7
|
+
unrefTimer
|
|
8
|
+
} from "./index-bw4ktfnz.js";
|
|
6
9
|
|
|
7
10
|
// src/mobile/remoteMacProtocol.ts
|
|
8
11
|
import { createHash, randomUUID } from "crypto";
|
|
@@ -311,6 +314,29 @@ var acquireAbsoluteRemoteMacReleaseLease = async (project, options = {}) => {
|
|
|
311
314
|
release: () => runOwned(`rm -rf ${shellQuote(path)}`)
|
|
312
315
|
};
|
|
313
316
|
};
|
|
317
|
+
var cleanAbsoluteRemoteMacWorkspace = async (profile, transport) => {
|
|
318
|
+
const root = profile.workspaceRoot;
|
|
319
|
+
const projects = posix.join(root, "projects");
|
|
320
|
+
const script = [
|
|
321
|
+
"set -eu",
|
|
322
|
+
`mkdir -p ${shellQuote(root)}`,
|
|
323
|
+
`project_staging=$(find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
|
|
324
|
+
`mobile_staging=$(find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
|
|
325
|
+
`count=$((project_staging+mobile_staging))`,
|
|
326
|
+
`find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
|
|
327
|
+
`find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
|
|
328
|
+
`printf '%s\\n' "$count"`
|
|
329
|
+
].join("; ");
|
|
330
|
+
const result = await (transport?.capture ?? defaultTransport.capture)([
|
|
331
|
+
...absoluteRemoteMacSshBase(profile),
|
|
332
|
+
"/bin/sh -lc",
|
|
333
|
+
shellQuote(script)
|
|
334
|
+
]);
|
|
335
|
+
const removed = Number(requireRemoteSuccess(result, "Remote Mac workspace cleanup"));
|
|
336
|
+
if (!Number.isSafeInteger(removed) || removed < 0)
|
|
337
|
+
throw new TypeError("Remote Mac returned an invalid cleanup result.");
|
|
338
|
+
return { profile: profile.name, removed, workspaceRoot: root };
|
|
339
|
+
};
|
|
314
340
|
var inspectAbsoluteRemoteMacWorkspace = async (profile, transport) => {
|
|
315
341
|
const root = profile.workspaceRoot;
|
|
316
342
|
const script = [
|
|
@@ -339,29 +365,6 @@ var inspectAbsoluteRemoteMacWorkspace = async (profile, transport) => {
|
|
|
339
365
|
workspaceRoot: root
|
|
340
366
|
};
|
|
341
367
|
};
|
|
342
|
-
var cleanAbsoluteRemoteMacWorkspace = async (profile, transport) => {
|
|
343
|
-
const root = profile.workspaceRoot;
|
|
344
|
-
const projects = posix.join(root, "projects");
|
|
345
|
-
const script = [
|
|
346
|
-
"set -eu",
|
|
347
|
-
`mkdir -p ${shellQuote(root)}`,
|
|
348
|
-
`project_staging=$(find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
|
|
349
|
-
`mobile_staging=$(find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -print 2>/dev/null | wc -l | tr -d ' ')`,
|
|
350
|
-
`count=$((project_staging+mobile_staging))`,
|
|
351
|
-
`find ${shellQuote(projects)} -mindepth 2 -maxdepth 2 -type d \\( -name '.incoming-*' -o -name '.previous' -o -name '.release-lease.stale-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
|
|
352
|
-
`find ${shellQuote(projects)} -type d \\( -path '*/current/.absolutejs/mobile/.ios-build-*' -o -path '*/current/.absolutejs/mobile/.ios-stage-*' -o -path '*/current/.absolutejs/mobile/*.incoming-*' \\) -mtime +0 -prune -exec rm -rf {} + 2>/dev/null || true`,
|
|
353
|
-
`printf '%s\\n' "$count"`
|
|
354
|
-
].join("; ");
|
|
355
|
-
const result = await (transport?.capture ?? defaultTransport.capture)([
|
|
356
|
-
...absoluteRemoteMacSshBase(profile),
|
|
357
|
-
"/bin/sh -lc",
|
|
358
|
-
shellQuote(script)
|
|
359
|
-
]);
|
|
360
|
-
const removed = Number(requireRemoteSuccess(result, "Remote Mac workspace cleanup"));
|
|
361
|
-
if (!Number.isSafeInteger(removed) || removed < 0)
|
|
362
|
-
throw new TypeError("Remote Mac returned an invalid cleanup result.");
|
|
363
|
-
return { profile: profile.name, removed, workspaceRoot: root };
|
|
364
|
-
};
|
|
365
368
|
var installAbsoluteRemoteMacAgent = async (project) => {
|
|
366
369
|
const artifact = await materializeAbsoluteRemoteMacAgent(project.projectRoot);
|
|
367
370
|
const directory = posix.join(project.profile.workspaceRoot, "agents", `protocol-${ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION}`, artifact.sha256);
|
|
@@ -707,7 +710,7 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
|
|
|
707
710
|
heartbeat = undefined;
|
|
708
711
|
});
|
|
709
712
|
}, REMOTE_RELEASE_LEASE_HEARTBEAT_MS);
|
|
710
|
-
heartbeatTimer
|
|
713
|
+
unrefTimer(heartbeatTimer);
|
|
711
714
|
try {
|
|
712
715
|
const syncStartedAt = performance.now();
|
|
713
716
|
if (options.syncProject)
|
|
@@ -850,7 +853,7 @@ var buildAbsoluteRemoteIosRelease = async (options) => {
|
|
|
850
853
|
}
|
|
851
854
|
};
|
|
852
855
|
var startAbsoluteRemoteExpoIosDevSession = async (options) => {
|
|
853
|
-
|
|
856
|
+
let session = await startAbsoluteRemoteDevSession({
|
|
854
857
|
certificateAuthorityPath: options.certificateAuthorityPath,
|
|
855
858
|
deviceIdentifier: options.deviceIdentifier,
|
|
856
859
|
https: options.https,
|
|
@@ -866,12 +869,18 @@ var startAbsoluteRemoteExpoIosDevSession = async (options) => {
|
|
|
866
869
|
syncProject: options.syncProject,
|
|
867
870
|
transport: options.transport
|
|
868
871
|
});
|
|
869
|
-
|
|
872
|
+
const expoSession = {
|
|
870
873
|
close: session.close,
|
|
871
874
|
metroPort: options.metroPort,
|
|
872
875
|
platforms: ["ios"],
|
|
873
|
-
timings: session.timings
|
|
876
|
+
timings: session.timings,
|
|
877
|
+
rebuild: async () => {
|
|
878
|
+
session = await session.rebuild();
|
|
879
|
+
expoSession.timings = session.timings;
|
|
880
|
+
return expoSession;
|
|
881
|
+
}
|
|
874
882
|
};
|
|
883
|
+
return expoSession;
|
|
875
884
|
};
|
|
876
885
|
var startAbsoluteRemoteIosDevSession = (options) => startAbsoluteRemoteDevSession(options);
|
|
877
886
|
var startAbsoluteRemoteDevSession = async (options) => {
|
|
@@ -1138,4 +1147,4 @@ var startAbsoluteRemoteDevSession = async (options) => {
|
|
|
1138
1147
|
return makeSession();
|
|
1139
1148
|
};
|
|
1140
1149
|
|
|
1141
|
-
export { ABSOLUTE_REMOTE_MAC_EVENT_PREFIX, ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION, validateAbsoluteRemoteMacProfileName, validateAbsoluteSshDestination, absoluteRemoteMacSshBase, captureAbsoluteRemoteMacCommand, getAbsoluteRemoteMacProfile, inspectAbsoluteRemoteMac, inspectAbsoluteRemoteMacLanHost, listAbsoluteRemoteMacProfiles, pairAbsoluteRemoteMac, removeAbsoluteRemoteMacProfile, createAbsoluteRemoteExpoIosDevProject, createAbsoluteRemoteIosDevProject, acquireAbsoluteRemoteMacReleaseLease,
|
|
1150
|
+
export { ABSOLUTE_REMOTE_MAC_EVENT_PREFIX, ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION, validateAbsoluteRemoteMacProfileName, validateAbsoluteSshDestination, absoluteRemoteMacSshBase, captureAbsoluteRemoteMacCommand, getAbsoluteRemoteMacProfile, inspectAbsoluteRemoteMac, inspectAbsoluteRemoteMacLanHost, listAbsoluteRemoteMacProfiles, pairAbsoluteRemoteMac, removeAbsoluteRemoteMacProfile, createAbsoluteRemoteExpoIosDevProject, createAbsoluteRemoteIosDevProject, acquireAbsoluteRemoteMacReleaseLease, cleanAbsoluteRemoteMacWorkspace, inspectAbsoluteRemoteMacWorkspace, installAbsoluteRemoteMacAgent, materializeAbsoluteRemoteMacAgent, absoluteRemoteProjectSyncCommands, syncAbsoluteRemoteMacProject, absoluteRemoteReleaseInputSyncCommands, syncAbsoluteRemoteMacReleaseInputs, buildAbsoluteRemoteIosRelease, startAbsoluteRemoteExpoIosDevSession, startAbsoluteRemoteIosDevSession };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/utils/unrefTimer.ts
|
|
3
|
+
var unrefTimer = (timer) => {
|
|
4
|
+
if (timer === null || typeof timer !== "object" && typeof timer !== "function")
|
|
5
|
+
return;
|
|
6
|
+
const unref = Reflect.get(timer, "unref");
|
|
7
|
+
if (typeof unref === "function")
|
|
8
|
+
Reflect.apply(unref, timer, []);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export { unrefTimer };
|
|
@@ -1493,7 +1493,7 @@ var packageDependencies = (plan) => Object.fromEntries(plan.requiredPackages.map
|
|
|
1493
1493
|
var expoPackage = (auth, sync, devices, updates) => ({
|
|
1494
1494
|
dependencies: {
|
|
1495
1495
|
"@absolutejs/devices": "0.7.0",
|
|
1496
|
-
"@absolutejs/devices-expo": "0.0.
|
|
1496
|
+
"@absolutejs/devices-expo": "0.0.3",
|
|
1497
1497
|
...auth ? {
|
|
1498
1498
|
"@absolutejs/auth": ABSOLUTE_EXPO_AUTH_CORE_VERSION,
|
|
1499
1499
|
[ABSOLUTE_EXPO_AUTH_PACKAGE]: ABSOLUTE_EXPO_AUTH_VERSION
|
|
@@ -2100,7 +2100,7 @@ var webHostSource = (config, auth, sync) => {
|
|
|
2100
2100
|
const nativeRoutePatterns = nativeRoutes.map((route) => route.split("/").filter(Boolean));
|
|
2101
2101
|
return `${EXPO_GENERATED_HEADER}import * as Linking from 'expo-linking';
|
|
2102
2102
|
import { router, usePathname } from 'expo-router';
|
|
2103
|
-
import { useEffect, useRef, useState } from 'react';
|
|
2103
|
+
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
2104
2104
|
import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
|
|
2105
2105
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
2106
2106
|
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
|
|
@@ -2255,17 +2255,21 @@ const authStatus = async () => {
|
|
|
2255
2255
|
return { principal: principal ? { namespace: principal.namespace } : null, user };` : "throw new Error('Expo Auth is not configured.');"}
|
|
2256
2256
|
};
|
|
2257
2257
|
|
|
2258
|
-
export
|
|
2259
|
-
|
|
2258
|
+
export type AbsoluteWebHostProps = { path?: string };
|
|
2259
|
+
|
|
2260
|
+
export function AbsoluteWebHost({ path }: AbsoluteWebHostProps = {}) {
|
|
2261
|
+
const routerPathname = usePathname() || '/';
|
|
2262
|
+
const pathname = path?.startsWith('/') && !path.startsWith('//') ? path : routerPathname;
|
|
2260
2263
|
const safeAreaInsets = useSafeAreaInsets();
|
|
2261
2264
|
const webView = useRef<WebView>(null);
|
|
2262
2265
|
const devicesBridge = useRef<{ close(): void | Promise<void>; request(method: string, params: Record<string, unknown>): Promise<unknown> } | undefined>(undefined);
|
|
2263
2266
|
const syncBridge = useRef<{ close(): void | Promise<void>; request(method: string, params: Record<string, unknown>): Promise<unknown> } | undefined>(undefined);
|
|
2264
2267
|
const [indexUri, setIndexUri] = useState<string>();
|
|
2265
|
-
const
|
|
2268
|
+
const canGoBack = useRef(false);
|
|
2266
2269
|
const [runtimeReady, setRuntimeReady] = useState(!AUTH_ENABLED && !SYNC_ENABLED);
|
|
2267
2270
|
const [devicesReady, setDevicesReady] = useState(false);
|
|
2268
2271
|
const activeWebPath = useRef(pathname);
|
|
2272
|
+
const webSource = useMemo(() => indexUri ? { uri: indexUri } : undefined, [indexUri]);
|
|
2269
2273
|
|
|
2270
2274
|
useEffect(() => {
|
|
2271
2275
|
if (!AUTH_ENABLED && !SYNC_ENABLED) return;
|
|
@@ -2323,7 +2327,7 @@ export function AbsoluteWebHost() {
|
|
|
2323
2327
|
if (!active) return;
|
|
2324
2328
|
respond({ event, format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload });
|
|
2325
2329
|
}).then(host => {
|
|
2326
|
-
if (!active) return void host.close();
|
|
2330
|
+
if (!active) return void Promise.resolve(host.close()).catch(() => undefined);
|
|
2327
2331
|
devicesBridge.current = host;
|
|
2328
2332
|
setDevicesReady(true);
|
|
2329
2333
|
});
|
|
@@ -2331,7 +2335,7 @@ export function AbsoluteWebHost() {
|
|
|
2331
2335
|
active = false;
|
|
2332
2336
|
const host = devicesBridge.current;
|
|
2333
2337
|
devicesBridge.current = undefined;
|
|
2334
|
-
void host
|
|
2338
|
+
if (host) void Promise.resolve(host.close()).catch(() => undefined);
|
|
2335
2339
|
};
|
|
2336
2340
|
}, []);
|
|
2337
2341
|
const hasOrigin = (source: string, origin: string) => {
|
|
@@ -2351,7 +2355,7 @@ export function AbsoluteWebHost() {
|
|
|
2351
2355
|
return;
|
|
2352
2356
|
}
|
|
2353
2357
|
if (message.kind === 'event' && message.event === 'back-unhandled') {
|
|
2354
|
-
if (canGoBack) webView.current?.goBack();
|
|
2358
|
+
if (canGoBack.current) webView.current?.goBack();
|
|
2355
2359
|
else BackHandler.exitApp();
|
|
2356
2360
|
return;
|
|
2357
2361
|
}
|
|
@@ -2385,22 +2389,27 @@ export function AbsoluteWebHost() {
|
|
|
2385
2389
|
}
|
|
2386
2390
|
};
|
|
2387
2391
|
|
|
2388
|
-
if (!
|
|
2392
|
+
if (!webSource || !runtimeReady || !devicesReady) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
2389
2393
|
return <WebView
|
|
2390
2394
|
allowFileAccess
|
|
2391
2395
|
allowFileAccessFromFileURLs
|
|
2392
2396
|
allowUniversalAccessFromFileURLs={false}
|
|
2393
|
-
allowingReadAccessToURL={
|
|
2397
|
+
allowingReadAccessToURL={webSource.uri.slice(0, webSource.uri.lastIndexOf('/') + 1)}
|
|
2394
2398
|
injectedJavaScriptBeforeContentLoaded={bridgeBootstrap(pathname, safeAreaInsets)}
|
|
2395
2399
|
onMessage={onMessage}
|
|
2396
|
-
onNavigationStateChange={state =>
|
|
2400
|
+
onNavigationStateChange={state => {
|
|
2401
|
+
canGoBack.current = state.canGoBack;
|
|
2402
|
+
if (!DEV_ORIGIN || !hasOrigin(state.url, DEV_ORIGIN)) return;
|
|
2403
|
+
const route = new URL(state.url);
|
|
2404
|
+
activeWebPath.current = route.pathname + route.search + route.hash;
|
|
2405
|
+
}}
|
|
2397
2406
|
onShouldStartLoadWithRequest={request => {
|
|
2398
2407
|
if (request.url.startsWith('file:') || hasOrigin(request.url, PRODUCTION_ORIGIN) || DEV_ORIGIN && hasOrigin(request.url, DEV_ORIGIN)) return true;
|
|
2399
2408
|
void Linking.openURL(request.url);
|
|
2400
2409
|
return false;
|
|
2401
2410
|
}}
|
|
2402
2411
|
ref={webView}
|
|
2403
|
-
source={
|
|
2412
|
+
source={webSource}
|
|
2404
2413
|
style={styles.web}
|
|
2405
2414
|
/>;
|
|
2406
2415
|
}
|