@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.
- package/CHANGELOG.md +24 -0
- package/changelog.json +48 -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-qg75ewma.js} +5 -5
- package/dist/cli/{dev-perzmh2w.js → dev-sm9px53g.js} +83 -11
- package/dist/cli/{expoDevController-tr63cg78.js → expoDevController-a0jk8d43.js} +31 -2
- package/dist/cli/expoNativeWatcher-rmc95bak.js +138 -0
- package/dist/cli/{expoProject-djc0vk7g.js → expoProject-h38entbj.js} +1 -1
- package/dist/cli/{index-8zrnvazp.js → index-0t1cxstr.js} +261 -48
- package/dist/cli/{index-fn44wefq.js → index-3sdvzrv2.js} +37 -28
- package/dist/cli/{index-gxkmg2ss.js → index-51yyq29s.js} +1 -1
- package/dist/cli/index-bw4ktfnz.js +11 -0
- package/dist/cli/{index-751czk1b.js → index-d8va9b7v.js} +1 -1
- package/dist/cli/index.js +5 -5
- package/dist/cli/{mobile-yk7qr9qg.js → mobile-dev4mjsa.js} +20 -12
- package/dist/cli/{remoteMacProtocol-vw931n0a.js → remoteMacProtocol-kqvkp0qd.js} +2 -1
- package/dist/cli/{start-ef7tgbmf.js → start-0ddnh0y4.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 +599 -208
- package/dist/mobile/index.js.map +11 -8
- package/dist/mobile/mobilePreviewClient.ts +1 -1
- package/dist/mobile/remoteMacAgentEntry.js +354 -188
- package/dist/src/dev/clientManager.d.ts +2 -2
- package/dist/src/mobile/androidConformance.d.ts +4 -1
- package/dist/src/mobile/expoActivityResultRecovery.d.ts +1 -0
- package/dist/src/mobile/expoBridge.d.ts +2 -2
- 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 +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-
|
|
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-
|
|
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
|
|
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-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-
|
|
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;
|
|
@@ -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
|
-
|
|
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
|
+
};
|