@absolutejs/absolute 0.20.0-beta.69 → 0.20.0-beta.70
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
- package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
- package/dist/cli/index.js +359 -153
- package/dist/mobile/index.js +212 -6
- package/dist/mobile/index.js.map +4 -4
- package/dist/mobile/remoteMacAgentEntry.js +286 -233
- package/dist/src/mobile/expoDevController.d.ts +8 -0
- package/dist/src/mobile/expoNativeObservability.d.ts +1 -1
- package/package.json +8 -7
package/dist/cli/index.js
CHANGED
|
@@ -1942,6 +1942,7 @@ var init_updateRuntime = __esm(() => {
|
|
|
1942
1942
|
// src/mobile/expoNativeObservability.ts
|
|
1943
1943
|
import { join as join8 } from "path";
|
|
1944
1944
|
var HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
1945
|
+
`, XML_HEADER = `<!-- Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync. -->
|
|
1945
1946
|
`, moduleConfig, podspec, iosModule, androidBuild, androidManifest, androidModule, expoNativeObservabilityRuntimeSource, absoluteExpoNativeObservabilityFiles = (project) => new Map([
|
|
1946
1947
|
[
|
|
1947
1948
|
join8(project, "modules/absolute-mobile-observability/expo-module.config.json"),
|
|
@@ -2113,13 +2114,16 @@ android {
|
|
|
2113
2114
|
lintOptions { abortOnError false }
|
|
2114
2115
|
}
|
|
2115
2116
|
`;
|
|
2116
|
-
androidManifest = `${
|
|
2117
|
+
androidManifest = `${XML_HEADER}<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
|
2117
2118
|
`;
|
|
2118
2119
|
androidModule = `${HEADER}package expo.modules.absolutemobileobservability
|
|
2119
2120
|
|
|
2120
2121
|
import android.app.ActivityManager
|
|
2121
2122
|
import android.app.ApplicationExitInfo
|
|
2123
|
+
import android.content.pm.ApplicationInfo
|
|
2122
2124
|
import android.os.Build
|
|
2125
|
+
import android.os.Handler
|
|
2126
|
+
import android.os.Looper
|
|
2123
2127
|
import android.util.Base64
|
|
2124
2128
|
import expo.modules.kotlin.modules.Module
|
|
2125
2129
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
@@ -2138,6 +2142,7 @@ class AbsoluteMobileObservabilityModule : Module() {
|
|
|
2138
2142
|
private const val MAX_REPORTS = 8
|
|
2139
2143
|
private const val MAX_TRACE_BYTES = 32 * 1024
|
|
2140
2144
|
private const val ACKNOWLEDGED_KEY = "acknowledged"
|
|
2145
|
+
private const val CRASH_TEST_KEY = "crash-test-id"
|
|
2141
2146
|
private const val PREFERENCES = "AbsoluteMobileObservability"
|
|
2142
2147
|
}
|
|
2143
2148
|
|
|
@@ -2162,6 +2167,25 @@ class AbsoluteMobileObservabilityModule : Module() {
|
|
|
2162
2167
|
}
|
|
2163
2168
|
writeAcknowledged(acknowledged)
|
|
2164
2169
|
}
|
|
2170
|
+
|
|
2171
|
+
AsyncFunction("crashForTesting") { options: Map<String, String> ->
|
|
2172
|
+
val context = context() ?: return@AsyncFunction false
|
|
2173
|
+
if (context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE == 0) {
|
|
2174
|
+
throw IllegalStateException("Native observability crash injection requires a debuggable build.")
|
|
2175
|
+
}
|
|
2176
|
+
val testId = options["testId"]
|
|
2177
|
+
?.takeIf { it.matches(Regex("[A-Za-z0-9._:-]{1,128}")) }
|
|
2178
|
+
?: throw IllegalArgumentException("Native observability crash injection requires a valid testId.")
|
|
2179
|
+
val preferences = context.getSharedPreferences(PREFERENCES, 0)
|
|
2180
|
+
if (preferences.getString(CRASH_TEST_KEY, null) == testId) {
|
|
2181
|
+
return@AsyncFunction false
|
|
2182
|
+
}
|
|
2183
|
+
preferences.edit().putString(CRASH_TEST_KEY, testId).commit()
|
|
2184
|
+
Handler(Looper.getMainLooper()).post {
|
|
2185
|
+
throw RuntimeException("AbsoluteJS native observability acceptance crash: $testId")
|
|
2186
|
+
}
|
|
2187
|
+
true
|
|
2188
|
+
}
|
|
2165
2189
|
}
|
|
2166
2190
|
|
|
2167
2191
|
private fun context() = appContext.reactContext
|
|
@@ -2296,6 +2320,7 @@ import { ABSOLUTE_MOBILE_MANIFEST } from './webAssets';
|
|
|
2296
2320
|
|
|
2297
2321
|
type NativeObservabilityModule = {
|
|
2298
2322
|
acknowledge(options: { ids: string[] }): Promise<void>;
|
|
2323
|
+
crashForTesting(options: { testId: string }): Promise<boolean>;
|
|
2299
2324
|
pending(): Promise<{ reports: unknown[] }>;
|
|
2300
2325
|
};
|
|
2301
2326
|
type NativeReport = { details: Record<string, unknown>; id: string; kind: string; occurredAt: number; platform: 'android' | 'ios' };
|
|
@@ -2356,6 +2381,7 @@ export const startAbsoluteExpoNativeObservability = () => {
|
|
|
2356
2381
|
}
|
|
2357
2382
|
return drain();
|
|
2358
2383
|
};
|
|
2384
|
+
export const crashAbsoluteExpoNativeObservabilityForTesting = (testId: string) => native.crashForTesting({ testId });
|
|
2359
2385
|
`;
|
|
2360
2386
|
});
|
|
2361
2387
|
|
|
@@ -3792,102 +3818,11 @@ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = unde
|
|
|
3792
3818
|
`;
|
|
3793
3819
|
});
|
|
3794
3820
|
|
|
3795
|
-
// src/mobile/iosPhysicalDeviceTransport.ts
|
|
3796
|
-
import { randomUUID, X509Certificate as X509Certificate2 } from "crypto";
|
|
3797
|
-
import { createServer as createServer2 } from "http";
|
|
3798
|
-
import {
|
|
3799
|
-
connect as connectTcp,
|
|
3800
|
-
createServer as createTcpServer,
|
|
3801
|
-
isIP
|
|
3802
|
-
} from "net";
|
|
3803
|
-
import { readFile as readFile2 } from "fs/promises";
|
|
3804
|
-
var closeServer = (server) => new Promise((resolve6, reject) => {
|
|
3805
|
-
server.close((error) => {
|
|
3806
|
-
if (error)
|
|
3807
|
-
reject(error);
|
|
3808
|
-
else
|
|
3809
|
-
resolve6();
|
|
3810
|
-
});
|
|
3811
|
-
}), listen = (server, port) => new Promise((resolve6, reject) => {
|
|
3812
|
-
server.once("error", reject);
|
|
3813
|
-
server.listen(port, "0.0.0.0", () => {
|
|
3814
|
-
server.off("error", reject);
|
|
3815
|
-
const address = server.address();
|
|
3816
|
-
if (!address || typeof address === "string") {
|
|
3817
|
-
reject(new Error("Could not determine the iOS device helper port."));
|
|
3818
|
-
return;
|
|
3819
|
-
}
|
|
3820
|
-
resolve6(address.port);
|
|
3821
|
-
});
|
|
3822
|
-
}), findEphemeralPort = async () => {
|
|
3823
|
-
const probe = createTcpServer();
|
|
3824
|
-
const port = await new Promise((resolve6, reject) => {
|
|
3825
|
-
probe.once("error", reject);
|
|
3826
|
-
probe.listen(0, "127.0.0.1", () => {
|
|
3827
|
-
const address = probe.address();
|
|
3828
|
-
if (!address || typeof address === "string") {
|
|
3829
|
-
reject(new Error("Could not allocate the iOS CA enrollment port."));
|
|
3830
|
-
return;
|
|
3831
|
-
}
|
|
3832
|
-
resolve6(address.port);
|
|
3833
|
-
});
|
|
3834
|
-
});
|
|
3835
|
-
await closeServer(probe);
|
|
3836
|
-
return port;
|
|
3837
|
-
}, normalizeAbsoluteIosDeviceHost = (value) => {
|
|
3838
|
-
const normalized = value.trim();
|
|
3839
|
-
if (!normalized || normalized.length > 253 || /[\0\s/?#]/u.test(normalized))
|
|
3840
|
-
throw new TypeError("Physical iOS development requires a valid LAN host.");
|
|
3841
|
-
return normalized;
|
|
3842
|
-
}, normalizeAbsoluteIosDeviceIdentifier = (value) => {
|
|
3843
|
-
const normalized = value.trim();
|
|
3844
|
-
if (!normalized || normalized.length > 256 || /[\0\r\n]/u.test(normalized))
|
|
3845
|
-
throw new TypeError("--ios-device requires a valid Xcode device identifier or name.");
|
|
3846
|
-
return normalized;
|
|
3847
|
-
}, urlForHost = (protocol, host2, port) => {
|
|
3848
|
-
const url = new URL(`${protocol}://localhost:${port}`);
|
|
3849
|
-
const normalizedHost = normalizeAbsoluteIosDeviceHost(host2);
|
|
3850
|
-
url.hostname = isIP(normalizedHost) === 6 ? `[${normalizedHost}]` : normalizedHost;
|
|
3851
|
-
return url;
|
|
3852
|
-
}, startAbsoluteIosCaEnrollmentServer = async (options) => {
|
|
3853
|
-
const certificate = new X509Certificate2(await readFile2(options.certificateAuthorityPath));
|
|
3854
|
-
const certificateBytes = certificate.raw;
|
|
3855
|
-
const token = randomUUID().replaceAll("-", "");
|
|
3856
|
-
const certificatePath = `/${token}/absolutejs-development-ca.cer`;
|
|
3857
|
-
const server = createServer2((request, response) => {
|
|
3858
|
-
if (request.method !== "GET" || request.url !== certificatePath) {
|
|
3859
|
-
response.writeHead(404, {
|
|
3860
|
-
"Cache-Control": "no-store",
|
|
3861
|
-
"Content-Type": "text/plain; charset=utf-8"
|
|
3862
|
-
});
|
|
3863
|
-
response.end("Not found.");
|
|
3864
|
-
return;
|
|
3865
|
-
}
|
|
3866
|
-
response.writeHead(200, {
|
|
3867
|
-
"Cache-Control": "no-store",
|
|
3868
|
-
"Content-Disposition": 'attachment; filename="absolutejs-development-ca.cer"',
|
|
3869
|
-
"Content-Length": String(certificateBytes.byteLength),
|
|
3870
|
-
"Content-Type": "application/x-x509-ca-cert",
|
|
3871
|
-
"X-Content-Type-Options": "nosniff"
|
|
3872
|
-
});
|
|
3873
|
-
response.end(certificateBytes);
|
|
3874
|
-
});
|
|
3875
|
-
const port = await findEphemeralPort();
|
|
3876
|
-
await listen(server, port);
|
|
3877
|
-
const url = urlForHost("http", options.displayHost, port);
|
|
3878
|
-
url.pathname = certificatePath;
|
|
3879
|
-
return {
|
|
3880
|
-
url: url.href,
|
|
3881
|
-
close: () => closeServer(server)
|
|
3882
|
-
};
|
|
3883
|
-
};
|
|
3884
|
-
var init_iosPhysicalDeviceTransport = () => {};
|
|
3885
|
-
|
|
3886
3821
|
// src/cli/utils.ts
|
|
3887
3822
|
var {$: $2 } = globalThis.Bun;
|
|
3888
3823
|
import { execSync } from "child_process";
|
|
3889
3824
|
import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
|
|
3890
|
-
import { createServer as
|
|
3825
|
+
import { createServer as createServer2 } from "net";
|
|
3891
3826
|
import { resolve as resolve6 } from "path";
|
|
3892
3827
|
var COMPOSE_PATH = "db/docker-compose.db.yml", DEFAULT_SERVER_ENTRY = "src/backend/server.ts", isWSLEnvironment = () => {
|
|
3893
3828
|
try {
|
|
@@ -3901,7 +3836,7 @@ var COMPOSE_PATH = "db/docker-compose.db.yml", DEFAULT_SERVER_ENTRY = "src/backe
|
|
|
3901
3836
|
process.kill(pid, "SIGTERM");
|
|
3902
3837
|
} catch {}
|
|
3903
3838
|
}, findFreePort = () => new Promise((_resolve, reject) => {
|
|
3904
|
-
const server =
|
|
3839
|
+
const server = createServer2();
|
|
3905
3840
|
server.unref();
|
|
3906
3841
|
server.once("error", reject);
|
|
3907
3842
|
server.listen(0, "127.0.0.1", () => {
|
|
@@ -4023,9 +3958,9 @@ var init_utils = __esm(() => {
|
|
|
4023
3958
|
});
|
|
4024
3959
|
|
|
4025
3960
|
// src/mobile/emulatorDoctor.ts
|
|
4026
|
-
import { access as
|
|
3961
|
+
import { access as access2 } from "fs/promises";
|
|
4027
3962
|
import { homedir as homedir3 } from "os";
|
|
4028
|
-
import { join as
|
|
3963
|
+
import { join as join10 } from "path";
|
|
4029
3964
|
var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command) => {
|
|
4030
3965
|
try {
|
|
4031
3966
|
const result = Bun.spawnSync(command, {
|
|
@@ -4070,18 +4005,18 @@ var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command)
|
|
|
4070
4005
|
}
|
|
4071
4006
|
}, absoluteManagedAndroidSdkRoot = (host2, env = process.env) => {
|
|
4072
4007
|
if (host2 === "windows") {
|
|
4073
|
-
return
|
|
4008
|
+
return join10(env.LOCALAPPDATA ?? join10(homedir3(), "AppData", "Local"), "AbsoluteJS", "Android", "Sdk");
|
|
4074
4009
|
}
|
|
4075
4010
|
if (host2 === "wsl") {
|
|
4076
4011
|
const localAppData = windowsLocalAppDataFromWsl();
|
|
4077
4012
|
if (localAppData) {
|
|
4078
|
-
return
|
|
4013
|
+
return join10(localAppData, "AbsoluteJS", "Android", "Sdk");
|
|
4079
4014
|
}
|
|
4080
4015
|
}
|
|
4081
|
-
return
|
|
4016
|
+
return join10(homedir3(), ".absolutejs", "android-sdk");
|
|
4082
4017
|
}, pathExists = async (path) => {
|
|
4083
4018
|
try {
|
|
4084
|
-
await
|
|
4019
|
+
await access2(path);
|
|
4085
4020
|
return true;
|
|
4086
4021
|
} catch {
|
|
4087
4022
|
return false;
|
|
@@ -4131,7 +4066,7 @@ var ABSOLUTE_ANDROID_AVD_NAME = "AbsoluteJS_API_36", captureCommand = (command)
|
|
|
4131
4066
|
const capture = input.capture ?? captureCommand;
|
|
4132
4067
|
const androidRoot = input.androidRoot === null ? undefined : input.androidRoot ?? env.ANDROID_HOME ?? env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host2, env);
|
|
4133
4068
|
const windowsAndroidTools = host2 === "windows" || host2 === "wsl";
|
|
4134
|
-
const android = (segments) => androidRoot ?
|
|
4069
|
+
const android = (segments) => androidRoot ? join10(androidRoot, ...segments) : undefined;
|
|
4135
4070
|
const paths = (values) => values.filter((value) => Boolean(value));
|
|
4136
4071
|
const adb = await findExecutable("adb", paths([
|
|
4137
4072
|
android(["platform-tools", windowsAndroidTools ? "adb.exe" : "adb"])
|
|
@@ -4236,6 +4171,97 @@ var init_emulatorDoctor = __esm(() => {
|
|
|
4236
4171
|
init_utils();
|
|
4237
4172
|
});
|
|
4238
4173
|
|
|
4174
|
+
// src/mobile/iosPhysicalDeviceTransport.ts
|
|
4175
|
+
import { randomUUID, X509Certificate as X509Certificate2 } from "crypto";
|
|
4176
|
+
import { createServer as createServer3 } from "http";
|
|
4177
|
+
import {
|
|
4178
|
+
connect as connectTcp,
|
|
4179
|
+
createServer as createTcpServer,
|
|
4180
|
+
isIP
|
|
4181
|
+
} from "net";
|
|
4182
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
4183
|
+
var closeServer = (server) => new Promise((resolve7, reject) => {
|
|
4184
|
+
server.close((error) => {
|
|
4185
|
+
if (error)
|
|
4186
|
+
reject(error);
|
|
4187
|
+
else
|
|
4188
|
+
resolve7();
|
|
4189
|
+
});
|
|
4190
|
+
}), listen = (server, port) => new Promise((resolve7, reject) => {
|
|
4191
|
+
server.once("error", reject);
|
|
4192
|
+
server.listen(port, "0.0.0.0", () => {
|
|
4193
|
+
server.off("error", reject);
|
|
4194
|
+
const address = server.address();
|
|
4195
|
+
if (!address || typeof address === "string") {
|
|
4196
|
+
reject(new Error("Could not determine the iOS device helper port."));
|
|
4197
|
+
return;
|
|
4198
|
+
}
|
|
4199
|
+
resolve7(address.port);
|
|
4200
|
+
});
|
|
4201
|
+
}), findEphemeralPort = async () => {
|
|
4202
|
+
const probe = createTcpServer();
|
|
4203
|
+
const port = await new Promise((resolve7, reject) => {
|
|
4204
|
+
probe.once("error", reject);
|
|
4205
|
+
probe.listen(0, "127.0.0.1", () => {
|
|
4206
|
+
const address = probe.address();
|
|
4207
|
+
if (!address || typeof address === "string") {
|
|
4208
|
+
reject(new Error("Could not allocate the iOS CA enrollment port."));
|
|
4209
|
+
return;
|
|
4210
|
+
}
|
|
4211
|
+
resolve7(address.port);
|
|
4212
|
+
});
|
|
4213
|
+
});
|
|
4214
|
+
await closeServer(probe);
|
|
4215
|
+
return port;
|
|
4216
|
+
}, normalizeAbsoluteIosDeviceHost = (value) => {
|
|
4217
|
+
const normalized = value.trim();
|
|
4218
|
+
if (!normalized || normalized.length > 253 || /[\0\s/?#]/u.test(normalized))
|
|
4219
|
+
throw new TypeError("Physical iOS development requires a valid LAN host.");
|
|
4220
|
+
return normalized;
|
|
4221
|
+
}, normalizeAbsoluteIosDeviceIdentifier = (value) => {
|
|
4222
|
+
const normalized = value.trim();
|
|
4223
|
+
if (!normalized || normalized.length > 256 || /[\0\r\n]/u.test(normalized))
|
|
4224
|
+
throw new TypeError("--ios-device requires a valid Xcode device identifier or name.");
|
|
4225
|
+
return normalized;
|
|
4226
|
+
}, urlForHost = (protocol, host2, port) => {
|
|
4227
|
+
const url = new URL(`${protocol}://localhost:${port}`);
|
|
4228
|
+
const normalizedHost = normalizeAbsoluteIosDeviceHost(host2);
|
|
4229
|
+
url.hostname = isIP(normalizedHost) === 6 ? `[${normalizedHost}]` : normalizedHost;
|
|
4230
|
+
return url;
|
|
4231
|
+
}, startAbsoluteIosCaEnrollmentServer = async (options) => {
|
|
4232
|
+
const certificate = new X509Certificate2(await readFile2(options.certificateAuthorityPath));
|
|
4233
|
+
const certificateBytes = certificate.raw;
|
|
4234
|
+
const token = randomUUID().replaceAll("-", "");
|
|
4235
|
+
const certificatePath = `/${token}/absolutejs-development-ca.cer`;
|
|
4236
|
+
const server = createServer3((request, response) => {
|
|
4237
|
+
if (request.method !== "GET" || request.url !== certificatePath) {
|
|
4238
|
+
response.writeHead(404, {
|
|
4239
|
+
"Cache-Control": "no-store",
|
|
4240
|
+
"Content-Type": "text/plain; charset=utf-8"
|
|
4241
|
+
});
|
|
4242
|
+
response.end("Not found.");
|
|
4243
|
+
return;
|
|
4244
|
+
}
|
|
4245
|
+
response.writeHead(200, {
|
|
4246
|
+
"Cache-Control": "no-store",
|
|
4247
|
+
"Content-Disposition": 'attachment; filename="absolutejs-development-ca.cer"',
|
|
4248
|
+
"Content-Length": String(certificateBytes.byteLength),
|
|
4249
|
+
"Content-Type": "application/x-x509-ca-cert",
|
|
4250
|
+
"X-Content-Type-Options": "nosniff"
|
|
4251
|
+
});
|
|
4252
|
+
response.end(certificateBytes);
|
|
4253
|
+
});
|
|
4254
|
+
const port = await findEphemeralPort();
|
|
4255
|
+
await listen(server, port);
|
|
4256
|
+
const url = urlForHost("http", options.displayHost, port);
|
|
4257
|
+
url.pathname = certificatePath;
|
|
4258
|
+
return {
|
|
4259
|
+
url: url.href,
|
|
4260
|
+
close: () => closeServer(server)
|
|
4261
|
+
};
|
|
4262
|
+
};
|
|
4263
|
+
var init_iosPhysicalDeviceTransport = () => {};
|
|
4264
|
+
|
|
4239
4265
|
// src/mobile/capacitorProject.ts
|
|
4240
4266
|
import { access as access4, readFile as readFile3, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
4241
4267
|
import { relative as relative3, resolve as resolve7 } from "path";
|
|
@@ -4340,7 +4366,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, ANDROID_CAPTU
|
|
|
4340
4366
|
forwardCommandOutput(subprocess.stderr, process.stderr)
|
|
4341
4367
|
]);
|
|
4342
4368
|
return exitCode;
|
|
4343
|
-
},
|
|
4369
|
+
}, captureCommand3 = (command, options = {}) => {
|
|
4344
4370
|
try {
|
|
4345
4371
|
const result = Bun.spawnSync(command, {
|
|
4346
4372
|
cwd: options.cwd,
|
|
@@ -4776,7 +4802,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, ANDROID_CAPTU
|
|
|
4776
4802
|
return poll();
|
|
4777
4803
|
};
|
|
4778
4804
|
return poll();
|
|
4779
|
-
},
|
|
4805
|
+
}, windowsPathFromWsl2 = (path, capture) => {
|
|
4780
4806
|
const result = capture(["wslpath", "-w", path]);
|
|
4781
4807
|
if (result.exitCode !== 0 || !result.stdout.trim()) {
|
|
4782
4808
|
throw new Error(`Could not translate WSL path for Windows: ${path}`);
|
|
@@ -4791,7 +4817,7 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, ANDROID_CAPTU
|
|
|
4791
4817
|
const source = resolve8(project.nativeDirectory, sourcePath);
|
|
4792
4818
|
dependencies.push({
|
|
4793
4819
|
name,
|
|
4794
|
-
windowsSource:
|
|
4820
|
+
windowsSource: windowsPathFromWsl2(source, capture)
|
|
4795
4821
|
});
|
|
4796
4822
|
return `project('${projectName}').projectDir = new File('./.absolutejs-dependencies/${name}')`;
|
|
4797
4823
|
});
|
|
@@ -4845,16 +4871,16 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, ANDROID_CAPTU
|
|
|
4845
4871
|
return join12(nativeDirectory, "app", "build", "outputs", "apk", "release", "app-release-unsigned.apk");
|
|
4846
4872
|
}, buildAbsoluteAndroidGradleArtifact = async (options) => {
|
|
4847
4873
|
const { project, task } = options;
|
|
4848
|
-
const capture = options.capture ??
|
|
4874
|
+
const capture = options.capture ?? captureCommand3;
|
|
4849
4875
|
const run = options.run ?? runCommand;
|
|
4850
4876
|
const env = options.env ?? process.env;
|
|
4851
4877
|
const gradleArguments = options.gradleArguments ?? [];
|
|
4852
4878
|
if (project.host === "wsl") {
|
|
4853
|
-
const windowsSource =
|
|
4879
|
+
const windowsSource = windowsPathFromWsl2(project.nativeDirectory, capture);
|
|
4854
4880
|
const buildId = Bun.hash(project.projectRoot).toString(HASH_RADIX);
|
|
4855
4881
|
const managedBuildDirectory = resolve8(project.androidRoot, "..", "..", "Builds", `${project.config.appId}-${buildId}`);
|
|
4856
|
-
const windowsDirectory =
|
|
4857
|
-
const windowsAndroidRoot =
|
|
4882
|
+
const windowsDirectory = windowsPathFromWsl2(managedBuildDirectory, capture);
|
|
4883
|
+
const windowsAndroidRoot = windowsPathFromWsl2(project.androidRoot, capture);
|
|
4858
4884
|
const { dependencies, rewrittenSettings } = await mirroredCapacitorDependencies(project, capture);
|
|
4859
4885
|
await requireSuccess([
|
|
4860
4886
|
"powershell.exe",
|
|
@@ -5126,12 +5152,12 @@ var ANDROID_BOOT_TIMEOUT_MS = 180000, ANDROID_BOOT_POLL_MS = 1000, ANDROID_CAPTU
|
|
|
5126
5152
|
phaseStartedAt = now;
|
|
5127
5153
|
options.onStateChange?.(next);
|
|
5128
5154
|
};
|
|
5129
|
-
const capture = options.capture ??
|
|
5155
|
+
const capture = options.capture ?? captureCommand3;
|
|
5130
5156
|
const run = options.run ?? runCommand;
|
|
5131
5157
|
const sleep = options.sleep ?? Bun.sleep;
|
|
5132
5158
|
const spawn2 = options.spawn ?? spawnCommand;
|
|
5133
5159
|
const log = options.log ?? console.log;
|
|
5134
|
-
const androidHome = project.host === "wsl" ?
|
|
5160
|
+
const androidHome = project.host === "wsl" ? windowsPathFromWsl2(project.androidRoot, capture) : project.androidRoot;
|
|
5135
5161
|
const env = {
|
|
5136
5162
|
...process.env,
|
|
5137
5163
|
ANDROID_HOME: androidHome
|
|
@@ -6880,7 +6906,7 @@ import {
|
|
|
6880
6906
|
join as join16,
|
|
6881
6907
|
posix,
|
|
6882
6908
|
relative as relative7,
|
|
6883
|
-
resolve as
|
|
6909
|
+
resolve as resolvePath2,
|
|
6884
6910
|
sep as sep5
|
|
6885
6911
|
} from "path";
|
|
6886
6912
|
var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TIMEOUT_MS = 2000, REMOTE_RELEASE_LEASE_HEARTBEAT_MS = 15000, REMOTE_RELEASE_LEASE_STALE_SECONDS = 120, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join16(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
|
|
@@ -7054,16 +7080,16 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
|
|
|
7054
7080
|
}
|
|
7055
7081
|
await saveStore(store, profilePath);
|
|
7056
7082
|
return true;
|
|
7057
|
-
}, projectIdentity = (projectRoot, appId) => createHash8("sha256").update(`${
|
|
7083
|
+
}, projectIdentity = (projectRoot, appId) => createHash8("sha256").update(`${resolvePath2(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20), createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
|
|
7058
7084
|
if (config.engine !== "expo")
|
|
7059
7085
|
throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
|
|
7060
7086
|
return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
|
|
7061
7087
|
}, createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
|
|
7062
|
-
cap: join16(
|
|
7088
|
+
cap: join16(resolvePath2(projectRoot), "node_modules", ".bin", "cap"),
|
|
7063
7089
|
config,
|
|
7064
7090
|
nativeDirectory: join16(config.nativeProjectDirectory, "ios"),
|
|
7065
7091
|
profile,
|
|
7066
|
-
projectRoot:
|
|
7092
|
+
projectRoot: resolvePath2(projectRoot),
|
|
7067
7093
|
remote: true,
|
|
7068
7094
|
remoteProjectRoot: posix.join(profile.workspaceRoot, "projects", projectIdentity(projectRoot, config.appId), "current"),
|
|
7069
7095
|
xcodebuild: "remote:xcodebuild",
|
|
@@ -7230,7 +7256,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
|
|
|
7230
7256
|
const source = await sourceCandidates.reduce(async (found, candidate) => await found ?? (await Bun.file(candidate).exists() ? candidate : undefined), Promise.resolve(undefined));
|
|
7231
7257
|
if (!source)
|
|
7232
7258
|
throw new Error("The AbsoluteJS installation does not contain its remote Mac agent artifact.");
|
|
7233
|
-
const outdir = join16(
|
|
7259
|
+
const outdir = join16(resolvePath2(projectRoot), ".absolutejs", "mobile", "remote-agent");
|
|
7234
7260
|
await mkdir6(outdir, { recursive: true });
|
|
7235
7261
|
const result = await Bun.build({
|
|
7236
7262
|
entrypoints: [source],
|
|
@@ -7918,7 +7944,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TI
|
|
|
7918
7944
|
},
|
|
7919
7945
|
screenshot: async (destination) => {
|
|
7920
7946
|
const result = await request("screenshot");
|
|
7921
|
-
const target =
|
|
7947
|
+
const target = resolvePath2(options.project.projectRoot, destination);
|
|
7922
7948
|
const targetRelative = relative7(options.project.projectRoot, target);
|
|
7923
7949
|
if (targetRelative.startsWith("..") || isAbsolute4(targetRelative))
|
|
7924
7950
|
throw new Error("iOS screenshot must remain inside the project.");
|
|
@@ -10299,7 +10325,7 @@ import {
|
|
|
10299
10325
|
rm as rm8,
|
|
10300
10326
|
writeFile as writeFile9
|
|
10301
10327
|
} from "fs/promises";
|
|
10302
|
-
import { dirname as dirname13, join as join23, resolve as
|
|
10328
|
+
import { dirname as dirname13, join as join23, resolve as resolvePath4 } from "path";
|
|
10303
10329
|
var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "current.json", BUNDLES_DIRECTORY = "bundles", ARTIFACT_FILE = "artifact.json", BUNDLE_ID_PATTERN, isRecord8 = (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) => {
|
|
10304
10330
|
const identity = JSON.stringify({
|
|
10305
10331
|
currentReleaseId,
|
|
@@ -10374,7 +10400,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
10374
10400
|
}
|
|
10375
10401
|
return release;
|
|
10376
10402
|
});
|
|
10377
|
-
const root =
|
|
10403
|
+
const root = resolvePath4(input.root);
|
|
10378
10404
|
const bundlesRoot = join23(root, BUNDLES_DIRECTORY);
|
|
10379
10405
|
await mkdir10(bundlesRoot, { recursive: true });
|
|
10380
10406
|
const bundleId = bundleIdFor(input.currentReleaseId, artifacts);
|
|
@@ -10392,7 +10418,7 @@ var ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT = 1, CURRENT_BUNDLE_FILE = "curre
|
|
|
10392
10418
|
await rename8(temporaryPointerPath, pointerPath);
|
|
10393
10419
|
return index;
|
|
10394
10420
|
}, readAbsoluteMobileMaterializedReleases = async (root) => {
|
|
10395
|
-
const resolvedRoot =
|
|
10421
|
+
const resolvedRoot = resolvePath4(root);
|
|
10396
10422
|
try {
|
|
10397
10423
|
const serialized = await readFile11(join23(resolvedRoot, CURRENT_BUNDLE_FILE), "utf8");
|
|
10398
10424
|
const parsed = JSON.parse(serialized);
|
|
@@ -21703,7 +21729,7 @@ class CdpConnection {
|
|
|
21703
21729
|
pending.resolve(message.result);
|
|
21704
21730
|
}
|
|
21705
21731
|
}
|
|
21706
|
-
var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POLL_MS = 200,
|
|
21732
|
+
var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POLL_MS = 200, captureCommand4 = (command) => {
|
|
21707
21733
|
const result = Bun.spawnSync(command, {
|
|
21708
21734
|
stderr: "pipe",
|
|
21709
21735
|
stdin: "ignore",
|
|
@@ -21903,7 +21929,7 @@ var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POL
|
|
|
21903
21929
|
return;
|
|
21904
21930
|
});
|
|
21905
21931
|
}, Promise.resolve(undefined)), attachAbsoluteAndroidWebView = async (options) => {
|
|
21906
|
-
const capture = options.capture ??
|
|
21932
|
+
const capture = options.capture ?? captureCommand4;
|
|
21907
21933
|
const fetcher = options.fetch ?? fetch;
|
|
21908
21934
|
const deadline = Date.now() + (options.timeoutMs ?? WEBVIEW_ATTACH_TIMEOUT_MS);
|
|
21909
21935
|
let lastError;
|
|
@@ -42516,7 +42542,7 @@ AbsoluteJS can configure ${installPlatform} emulation:`);
|
|
|
42516
42542
|
console.log(`
|
|
42517
42543
|
Emulator setup verification:`);
|
|
42518
42544
|
printDoctorChecks(result.checks.filter((check2) => check2.platform === "host" || check2.platform === installPlatform));
|
|
42519
|
-
},
|
|
42545
|
+
}, captureCommand5 = (command) => {
|
|
42520
42546
|
const result = Bun.spawnSync(command, {
|
|
42521
42547
|
stderr: "pipe",
|
|
42522
42548
|
stdin: "ignore",
|
|
@@ -42562,7 +42588,7 @@ Emulator setup verification:`);
|
|
|
42562
42588
|
}
|
|
42563
42589
|
return adb;
|
|
42564
42590
|
}, selectAndroidSerial = (adb, explicitSerial) => {
|
|
42565
|
-
const devices =
|
|
42591
|
+
const devices = captureCommand5([adb, "devices"]);
|
|
42566
42592
|
if (devices.exitCode !== 0) {
|
|
42567
42593
|
throw new Error(`Could not list Android targets: ${devices.stderr.trim() || devices.stdout.trim()}`);
|
|
42568
42594
|
}
|
|
@@ -42832,10 +42858,10 @@ Emulator setup verification:`);
|
|
|
42832
42858
|
remote: false,
|
|
42833
42859
|
xcodeVersion: requireCapturedCommand(["/usr/bin/xcodebuild", "-version"], "Xcode version inspection").stdout.trim(),
|
|
42834
42860
|
xcrun: "/usr/bin/xcrun",
|
|
42835
|
-
capture: async (command) =>
|
|
42861
|
+
capture: async (command) => captureCommand5(command)
|
|
42836
42862
|
};
|
|
42837
42863
|
}, selectIosSimulator = (xcrun, explicitUdid) => {
|
|
42838
|
-
const result =
|
|
42864
|
+
const result = captureCommand5([
|
|
42839
42865
|
xcrun,
|
|
42840
42866
|
"simctl",
|
|
42841
42867
|
"list",
|
|
@@ -42857,14 +42883,14 @@ Emulator setup verification:`);
|
|
|
42857
42883
|
throw new TypeError("No ready AbsoluteJS iOS simulator was found. Start `bun dev` and wait for the iOS target to become ready.");
|
|
42858
42884
|
return selected;
|
|
42859
42885
|
}, requireCapturedCommand = (command, label) => {
|
|
42860
|
-
const result =
|
|
42886
|
+
const result = captureCommand5(command);
|
|
42861
42887
|
if (result.exitCode !== 0)
|
|
42862
42888
|
throw new Error(`${label} failed: ${result.stderr.trim() || result.stdout.trim() || `status ${result.exitCode}`}`);
|
|
42863
42889
|
return result;
|
|
42864
42890
|
}, writeIosFailureArtifacts = async (options) => {
|
|
42865
42891
|
await mkdir21(options.artifactRoot, { recursive: true });
|
|
42866
42892
|
const screenshot = join61(options.artifactRoot, "ios-failure.png");
|
|
42867
|
-
const screenshotResult =
|
|
42893
|
+
const screenshotResult = captureCommand5([
|
|
42868
42894
|
options.xcrun,
|
|
42869
42895
|
"simctl",
|
|
42870
42896
|
"io",
|
|
@@ -43806,7 +43832,7 @@ import {
|
|
|
43806
43832
|
writeFileSync as writeFileSync4
|
|
43807
43833
|
} from "fs";
|
|
43808
43834
|
import { tmpdir as tmpdir2 } from "os";
|
|
43809
|
-
import { join as join18, resolve as
|
|
43835
|
+
import { join as join18, resolve as resolvePath3 } from "path";
|
|
43810
43836
|
|
|
43811
43837
|
// src/dev/tunnel/client.ts
|
|
43812
43838
|
var RECONNECT_DELAY_MS = 2000;
|
|
@@ -44313,14 +44339,164 @@ init_config();
|
|
|
44313
44339
|
init_expoProject();
|
|
44314
44340
|
|
|
44315
44341
|
// src/mobile/expoDevController.ts
|
|
44342
|
+
init_emulatorDoctor();
|
|
44316
44343
|
init_iosPhysicalDeviceTransport();
|
|
44317
44344
|
import { spawn } from "child_process";
|
|
44318
|
-
import { access as
|
|
44319
|
-
import { join as
|
|
44345
|
+
import { access as access3 } from "fs/promises";
|
|
44346
|
+
import { join as join11, resolve as resolvePath } from "path";
|
|
44320
44347
|
var METRO_READY_TIMEOUT_MS = 60000;
|
|
44321
44348
|
var PROCESS_CLOSE_TIMEOUT_MS = 2000;
|
|
44349
|
+
var preserveWindowsSubstRealpaths = `
|
|
44350
|
+
const fs = require('node:fs');
|
|
44351
|
+
const path = require('node:path');
|
|
44352
|
+
const physicalRoot = process.env.ABSOLUTE_EXPO_PHYSICAL_ROOT;
|
|
44353
|
+
const mappedRoot = process.env.ABSOLUTE_EXPO_MAPPED_ROOT;
|
|
44354
|
+
const remap = (value) => {
|
|
44355
|
+
if (typeof value !== 'string' || !physicalRoot || !mappedRoot) return value;
|
|
44356
|
+
const normalizedValue = path.resolve(value);
|
|
44357
|
+
const normalizedRoot = path.resolve(physicalRoot);
|
|
44358
|
+
if (normalizedValue.toLowerCase() === normalizedRoot.toLowerCase()) return mappedRoot;
|
|
44359
|
+
const prefix = normalizedRoot.endsWith(path.sep) ? normalizedRoot : normalizedRoot + path.sep;
|
|
44360
|
+
return normalizedValue.toLowerCase().startsWith(prefix.toLowerCase())
|
|
44361
|
+
? path.join(mappedRoot, normalizedValue.slice(prefix.length))
|
|
44362
|
+
: value;
|
|
44363
|
+
};
|
|
44364
|
+
const realpath = fs.realpath.bind(fs);
|
|
44365
|
+
const realpathSync = fs.realpathSync.bind(fs);
|
|
44366
|
+
const realpathNative = fs.realpathSync.native?.bind(fs.realpathSync);
|
|
44367
|
+
fs.realpath = (value, options, callback) => {
|
|
44368
|
+
const done = typeof options === 'function' ? options : callback;
|
|
44369
|
+
const encoding = typeof options === 'function' ? undefined : options;
|
|
44370
|
+
return realpath(value, encoding, (error, result) => done(error, remap(result)));
|
|
44371
|
+
};
|
|
44372
|
+
fs.realpathSync = (value, options) => remap(realpathSync(value, options));
|
|
44373
|
+
if (realpathNative) fs.realpathSync.native = (value, options) => remap(realpathNative(value, options));
|
|
44374
|
+
const promiseRealpath = fs.promises.realpath.bind(fs.promises);
|
|
44375
|
+
fs.promises.realpath = async (value, options) => remap(await promiseRealpath(value, options));
|
|
44376
|
+
`;
|
|
44377
|
+
var expoDevelopmentClientScheme = (appId) => `exp+${appId.toLowerCase().replaceAll(/[^a-z0-9]+/gu, "-")}`;
|
|
44378
|
+
var expoDevelopmentClientUrl = (appId, host2, port) => `${expoDevelopmentClientScheme(appId)}://expo-development-client/?url=${encodeURIComponent(`http://${host2}:${port}`)}`;
|
|
44379
|
+
var captureCommand2 = (command) => {
|
|
44380
|
+
const result = Bun.spawnSync(command, {
|
|
44381
|
+
stderr: "ignore",
|
|
44382
|
+
stdout: "pipe"
|
|
44383
|
+
});
|
|
44384
|
+
return { exitCode: result.exitCode, stdout: result.stdout.toString() };
|
|
44385
|
+
};
|
|
44386
|
+
var windowsPathFromWsl = (path, capture) => {
|
|
44387
|
+
const result = capture(["wslpath", "-w", path]);
|
|
44388
|
+
if (result.exitCode !== 0 || !result.stdout.trim()) {
|
|
44389
|
+
throw new Error(`Could not translate WSL path for Windows: ${path}`);
|
|
44390
|
+
}
|
|
44391
|
+
return result.stdout.trim();
|
|
44392
|
+
};
|
|
44393
|
+
var connectLocalExpoAndroid = (adb, appId, metroPort, capture, preferredDevice) => {
|
|
44394
|
+
const devices = capture([adb, "devices"]);
|
|
44395
|
+
if (devices.exitCode !== 0)
|
|
44396
|
+
throw new Error("Could not inspect devices after the Expo Android build.");
|
|
44397
|
+
const ready = devices.stdout.split(/\r?\n/u).flatMap((line) => {
|
|
44398
|
+
const match = /^(\S+)\s+device$/u.exec(line.trim());
|
|
44399
|
+
return match?.[1] ? [match[1]] : [];
|
|
44400
|
+
});
|
|
44401
|
+
const serial = preferredDevice ? ready.find((value) => value === preferredDevice) : ready.find((value) => value.startsWith("emulator-")) ?? ready[0];
|
|
44402
|
+
if (!serial)
|
|
44403
|
+
throw new Error(preferredDevice ? "The selected Expo Android device is not connected after build." : "Expo Android build completed but no ready device was found.");
|
|
44404
|
+
const run = (args, message) => {
|
|
44405
|
+
if (capture([adb, "-s", serial, ...args]).exitCode !== 0)
|
|
44406
|
+
throw new Error(message);
|
|
44407
|
+
};
|
|
44408
|
+
run(["reverse", `tcp:${metroPort}`, `tcp:${metroPort}`], "Expo Android Metro forwarding failed.");
|
|
44409
|
+
run(["shell", "am", "force-stop", appId], "Expo Android development-client reset failed.");
|
|
44410
|
+
run([
|
|
44411
|
+
"shell",
|
|
44412
|
+
"am",
|
|
44413
|
+
"start",
|
|
44414
|
+
"-W",
|
|
44415
|
+
"-a",
|
|
44416
|
+
"android.intent.action.VIEW",
|
|
44417
|
+
"-d",
|
|
44418
|
+
expoDevelopmentClientUrl(appId, "localhost", metroPort),
|
|
44419
|
+
appId
|
|
44420
|
+
], "Expo Android development-client launch failed.");
|
|
44421
|
+
return serial;
|
|
44422
|
+
};
|
|
44423
|
+
var encodedWindowsExpoAndroidCommand = (project, androidRoot, appId, args, capture, metroPort, preferredDevice) => {
|
|
44424
|
+
const windowsSource = windowsPathFromWsl(project, capture);
|
|
44425
|
+
const buildId = Bun.hash(resolvePath(project)).toString(16);
|
|
44426
|
+
const buildDirectory = resolvePath(androidRoot, "..", "..", "ExpoBuilds", buildId.slice(0, 10));
|
|
44427
|
+
const windowsDirectory = windowsPathFromWsl(buildDirectory, capture);
|
|
44428
|
+
const windowsAndroidRoot = windowsPathFromWsl(androidRoot, capture);
|
|
44429
|
+
const encode = (value) => Buffer.from(value, "utf8").toString("base64");
|
|
44430
|
+
const developmentScheme = expoDevelopmentClientScheme(appId);
|
|
44431
|
+
const realpathHook = encode(preserveWindowsSubstRealpaths);
|
|
44432
|
+
const mappedBuild = [
|
|
44433
|
+
"$mappedProject = Join-Path ($drive + '\\') (Split-Path -Leaf $directory)",
|
|
44434
|
+
"Set-Location $mappedProject",
|
|
44435
|
+
"$hook = Join-Path $mappedProject '.absolutejs-preserve-subst.cjs'",
|
|
44436
|
+
`[IO.File]::WriteAllText($hook, [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${realpathHook}')))`,
|
|
44437
|
+
"$env:ABSOLUTE_EXPO_PHYSICAL_ROOT = $directory",
|
|
44438
|
+
"$env:ABSOLUTE_EXPO_MAPPED_ROOT = $mappedProject",
|
|
44439
|
+
'$env:NODE_OPTIONS = "--require=$hook"',
|
|
44440
|
+
"$autolinkingCache = Join-Path $mappedProject 'android\\build\\generated\\autolinking'",
|
|
44441
|
+
"if ([IO.Directory]::Exists($autolinkingCache)) { [IO.Directory]::Delete($autolinkingCache, $true) }",
|
|
44442
|
+
"$expo = Join-Path $mappedProject 'node_modules\\.bin\\expo.exe'",
|
|
44443
|
+
"& $expo @expoArguments",
|
|
44444
|
+
"if ($LASTEXITCODE -ne 0) { throw 'Expo Android native build failed.' }",
|
|
44445
|
+
"$adb = Join-Path $androidHome 'platform-tools\\adb.exe'",
|
|
44446
|
+
"$readyDevices = @(& $adb devices) | Where-Object { $_ -match '\\tdevice$' } | ForEach-Object { ($_ -split '\\s+')[0] }",
|
|
44447
|
+
...preferredDevice ? [
|
|
44448
|
+
`$serial = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(preferredDevice)}'))`,
|
|
44449
|
+
"if ($readyDevices -notcontains $serial) { throw 'The selected Expo Android device is not connected after build.' }"
|
|
44450
|
+
] : [
|
|
44451
|
+
"$serial = $readyDevices | Where-Object { $_ -like 'emulator-*' } | Select-Object -First 1",
|
|
44452
|
+
"if (-not $serial) { $serial = $readyDevices | Select-Object -First 1 }"
|
|
44453
|
+
],
|
|
44454
|
+
"if (-not $serial) { throw 'Expo Android build completed but no ready device was found.' }",
|
|
44455
|
+
`& $adb -s $serial reverse 'tcp:${metroPort}' 'tcp:${metroPort}'`,
|
|
44456
|
+
"if ($LASTEXITCODE -ne 0) { throw 'Expo Android Metro forwarding failed.' }",
|
|
44457
|
+
`& $adb -s $serial shell am force-stop '${appId}'`,
|
|
44458
|
+
"if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client reset failed.' }",
|
|
44459
|
+
`$developmentUrl = '${developmentScheme}://expo-development-client/?url=' + [Uri]::EscapeDataString('http://localhost:${metroPort}')`,
|
|
44460
|
+
`& $adb -s $serial shell am start -W -a android.intent.action.VIEW -d $developmentUrl '${appId}'`,
|
|
44461
|
+
"if ($LASTEXITCODE -ne 0) { throw 'Expo Android development-client launch failed.' }"
|
|
44462
|
+
].join("; ");
|
|
44463
|
+
const source = [
|
|
44464
|
+
"$ErrorActionPreference = 'Stop'",
|
|
44465
|
+
"$ProgressPreference = 'SilentlyContinue'",
|
|
44466
|
+
`$source = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(windowsSource)}'))`,
|
|
44467
|
+
`$directory = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(windowsDirectory)}'))`,
|
|
44468
|
+
`$androidHome = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(windowsAndroidRoot)}'))`,
|
|
44469
|
+
`$expoArguments = @([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encode(JSON.stringify(args))}')) | ConvertFrom-Json)`,
|
|
44470
|
+
"$env:ANDROID_HOME = $androidHome",
|
|
44471
|
+
"$env:ANDROID_SDK_ROOT = $androidHome",
|
|
44472
|
+
"$env:NODE_ENV = 'development'",
|
|
44473
|
+
...preferredDevice ? [] : ["$env:ORG_GRADLE_PROJECT_reactNativeArchitectures = 'x86_64'"],
|
|
44474
|
+
"New-Item -ItemType Directory -Force -Path $directory | Out-Null",
|
|
44475
|
+
"& 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",
|
|
44476
|
+
"$copyExit = $LASTEXITCODE",
|
|
44477
|
+
"if ($copyExit -ge 8) { exit $copyExit }",
|
|
44478
|
+
"Set-Location $directory",
|
|
44479
|
+
"$bun = (Get-Command bun.exe -ErrorAction Stop).Source",
|
|
44480
|
+
"& $bun install",
|
|
44481
|
+
"if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }",
|
|
44482
|
+
"$drive = @('Z:', 'Y:', 'X:', 'W:', 'V:', 'U:', 'T:') | Where-Object { -not (Test-Path ($_ + '\\')) } | Select-Object -First 1",
|
|
44483
|
+
"if (-not $drive) { throw 'AbsoluteJS could not reserve a temporary drive letter for the Expo Android build.' }",
|
|
44484
|
+
"$mirrorRoot = Split-Path -Parent $directory",
|
|
44485
|
+
"& subst.exe $drive $mirrorRoot",
|
|
44486
|
+
"if ($LASTEXITCODE -ne 0) { throw 'AbsoluteJS could not create the short Expo Android build path.' }",
|
|
44487
|
+
`try { ${mappedBuild} } finally { Set-Location ($env:SystemDrive + '\\'); & subst.exe $drive /D | Out-Null }`,
|
|
44488
|
+
"exit 0"
|
|
44489
|
+
].join("; ");
|
|
44490
|
+
return [
|
|
44491
|
+
"powershell.exe",
|
|
44492
|
+
"-NoProfile",
|
|
44493
|
+
"-EncodedCommand",
|
|
44494
|
+
Buffer.from(source, "utf16le").toString("base64")
|
|
44495
|
+
];
|
|
44496
|
+
};
|
|
44322
44497
|
var commandEnvironment = (options) => ({
|
|
44323
44498
|
ABSOLUTE_EXPO_DEVELOPMENT: "1",
|
|
44499
|
+
NODE_ENV: "development",
|
|
44324
44500
|
...options.certificateAuthorityPath ? {
|
|
44325
44501
|
ABSOLUTE_EXPO_DEVELOPMENT_CA_PATH: options.certificateAuthorityPath
|
|
44326
44502
|
} : {},
|
|
@@ -44329,9 +44505,9 @@ var commandEnvironment = (options) => ({
|
|
|
44329
44505
|
...options.metroHost ? { REACT_NATIVE_PACKAGER_HOSTNAME: options.metroHost } : {}
|
|
44330
44506
|
});
|
|
44331
44507
|
var absoluteExpoExecutable = async (project) => {
|
|
44332
|
-
const executable =
|
|
44508
|
+
const executable = join11(project, "node_modules", ".bin", "expo");
|
|
44333
44509
|
try {
|
|
44334
|
-
await
|
|
44510
|
+
await access3(executable);
|
|
44335
44511
|
return executable;
|
|
44336
44512
|
} catch {
|
|
44337
44513
|
throw new TypeError("Expo dependencies are not installed in the generated shell. Run `absolute mobile init --yes`.");
|
|
@@ -44375,8 +44551,6 @@ var planAbsoluteExpoDevSession = (config, options) => {
|
|
|
44375
44551
|
args: [
|
|
44376
44552
|
`run:${platform2}`,
|
|
44377
44553
|
"--no-bundler",
|
|
44378
|
-
"--port",
|
|
44379
|
-
String(options.metroPort),
|
|
44380
44554
|
...device ? ["--device", device] : []
|
|
44381
44555
|
],
|
|
44382
44556
|
env,
|
|
@@ -44425,18 +44599,18 @@ var stopProcess = async (process2) => {
|
|
|
44425
44599
|
return;
|
|
44426
44600
|
process2.kill("SIGTERM");
|
|
44427
44601
|
await Promise.race([
|
|
44428
|
-
new Promise((
|
|
44429
|
-
new Promise((
|
|
44602
|
+
new Promise((resolve7) => process2.once("exit", () => resolve7())),
|
|
44603
|
+
new Promise((resolve7) => setTimeout(resolve7, PROCESS_CLOSE_TIMEOUT_MS))
|
|
44430
44604
|
]);
|
|
44431
44605
|
if (process2.exitCode === null)
|
|
44432
44606
|
process2.kill("SIGKILL");
|
|
44433
44607
|
};
|
|
44434
|
-
var waitForExit = (process2) => new Promise((
|
|
44608
|
+
var waitForExit = (process2) => new Promise((resolve7) => {
|
|
44435
44609
|
if (process2.exitCode !== null) {
|
|
44436
|
-
|
|
44610
|
+
resolve7(process2.exitCode);
|
|
44437
44611
|
return;
|
|
44438
44612
|
}
|
|
44439
|
-
process2.once("exit", (code) =>
|
|
44613
|
+
process2.once("exit", (code) => resolve7(code ?? 1));
|
|
44440
44614
|
});
|
|
44441
44615
|
var runUtilityCommand = async (run, command, args, options) => {
|
|
44442
44616
|
const child = run(command, args, {
|
|
@@ -44457,6 +44631,8 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44457
44631
|
const plan = planAbsoluteExpoDevSession(options.config, options);
|
|
44458
44632
|
const executable = options.executable ?? await absoluteExpoExecutable(plan.project);
|
|
44459
44633
|
const run = options.spawnProcess ?? spawn;
|
|
44634
|
+
const host2 = options.host ?? detectAbsoluteMobileHost();
|
|
44635
|
+
const capture = options.capture ?? captureCommand2;
|
|
44460
44636
|
const log = options.log ?? (() => {
|
|
44461
44637
|
return;
|
|
44462
44638
|
});
|
|
@@ -44516,9 +44692,9 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44516
44692
|
}) : undefined;
|
|
44517
44693
|
let metroReady = false;
|
|
44518
44694
|
let resolveMetro;
|
|
44519
|
-
const metroPromise = new Promise((
|
|
44695
|
+
const metroPromise = new Promise((resolve7, reject) => {
|
|
44520
44696
|
if (!metro) {
|
|
44521
|
-
|
|
44697
|
+
resolve7();
|
|
44522
44698
|
return;
|
|
44523
44699
|
}
|
|
44524
44700
|
const timeout = setTimeout(() => {
|
|
@@ -44526,7 +44702,7 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44526
44702
|
}, METRO_READY_TIMEOUT_MS);
|
|
44527
44703
|
resolveMetro = () => {
|
|
44528
44704
|
clearTimeout(timeout);
|
|
44529
|
-
|
|
44705
|
+
resolve7();
|
|
44530
44706
|
};
|
|
44531
44707
|
metro.once("exit", (code) => {
|
|
44532
44708
|
if (!metroReady) {
|
|
@@ -44558,7 +44734,14 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44558
44734
|
const state = platform2 === "android" ? "building-android" : "building-ios";
|
|
44559
44735
|
setState(state);
|
|
44560
44736
|
const started = performance.now();
|
|
44561
|
-
const
|
|
44737
|
+
const invocation = platform2 === "android" && host2 === "wsl" ? encodedWindowsExpoAndroidCommand(plan.project, options.androidRoot ?? absoluteManagedAndroidSdkRoot(host2), options.config.appId, command.args, capture, options.metroPort, options.androidDevice) : [executable, ...command.args];
|
|
44738
|
+
if (platform2 === "android" && host2 === "wsl") {
|
|
44739
|
+
log("[android] Mirroring native inputs to the Windows host for accelerated Expo build and launch.");
|
|
44740
|
+
}
|
|
44741
|
+
const [nativeExecutable, ...nativeArguments] = invocation;
|
|
44742
|
+
if (!nativeExecutable)
|
|
44743
|
+
throw new Error("Expo native build command is empty.");
|
|
44744
|
+
const child = run(nativeExecutable, nativeArguments, {
|
|
44562
44745
|
cwd: plan.project,
|
|
44563
44746
|
env: { ...process.env, ...command.env },
|
|
44564
44747
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -44576,6 +44759,12 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44576
44759
|
if (exitCode !== 0) {
|
|
44577
44760
|
throw new Error(`Expo ${platform2} development build exited with status ${exitCode}.`);
|
|
44578
44761
|
}
|
|
44762
|
+
if (platform2 === "android" && host2 !== "wsl") {
|
|
44763
|
+
const androidRoot = options.androidRoot ?? process.env.ANDROID_HOME ?? process.env.ANDROID_SDK_ROOT ?? absoluteManagedAndroidSdkRoot(host2);
|
|
44764
|
+
const adb = options.androidAdb ?? join11(androidRoot, "platform-tools", host2 === "windows" ? "adb.exe" : "adb");
|
|
44765
|
+
connectLocalExpoAndroid(adb, options.config.appId, options.metroPort, capture, options.androidDevice);
|
|
44766
|
+
log("Connected the Expo Android development client to Metro.");
|
|
44767
|
+
}
|
|
44579
44768
|
if (platform2 === "ios" && options.certificateAuthorityPath && options.iosOrigin && new URL(options.iosOrigin).protocol === "https:" && !options.iosDevice) {
|
|
44580
44769
|
setState("enrolling-trust");
|
|
44581
44770
|
const trustStarted = performance.now();
|
|
@@ -44600,6 +44789,23 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
44600
44789
|
log("Installed the AbsoluteJS development CA into the Expo iOS Simulator and relaunched the app.");
|
|
44601
44790
|
publishTiming("enrolling-trust", performance.now() - trustStarted);
|
|
44602
44791
|
}
|
|
44792
|
+
if (platform2 === "ios" && !options.iosDevice) {
|
|
44793
|
+
const utilityOptions = {
|
|
44794
|
+
cwd: plan.project,
|
|
44795
|
+
signal: options.signal,
|
|
44796
|
+
log: (line) => line && log(`[ios-connect] ${line}`)
|
|
44797
|
+
};
|
|
44798
|
+
await runUtilityCommand(run, "xcrun", ["simctl", "terminate", "booted", options.config.appId], utilityOptions);
|
|
44799
|
+
const connectExit = await runUtilityCommand(run, "xcrun", [
|
|
44800
|
+
"simctl",
|
|
44801
|
+
"openurl",
|
|
44802
|
+
"booted",
|
|
44803
|
+
expoDevelopmentClientUrl(options.config.appId, options.metroHost ?? "localhost", options.metroPort)
|
|
44804
|
+
], utilityOptions);
|
|
44805
|
+
if (connectExit !== 0)
|
|
44806
|
+
throw new Error(`Expo iOS Simulator Metro connection exited with status ${connectExit}.`);
|
|
44807
|
+
log("Connected the Expo iOS Simulator development client to Metro.");
|
|
44808
|
+
}
|
|
44603
44809
|
const durationMs = performance.now() - started;
|
|
44604
44810
|
timings[state] = durationMs;
|
|
44605
44811
|
options.onPhaseTiming?.({ durationMs, phase: state });
|
|
@@ -44890,8 +45096,8 @@ var iosLogTag = (entry) => {
|
|
|
44890
45096
|
var DEFAULT_PORT_RANGE = 10;
|
|
44891
45097
|
var RESTART_PARK_POLL_MS = 20;
|
|
44892
45098
|
var NODE_API_IMPORT_ERROR = "To load Node-API modules, use require() or process.dlopen instead of import.";
|
|
44893
|
-
var sourceServerBootstrap =
|
|
44894
|
-
var serverBootstrap = existsSync6(sourceServerBootstrap) ? sourceServerBootstrap :
|
|
45099
|
+
var sourceServerBootstrap = resolvePath3(import.meta.dir, "../../dev/serverBootstrap.ts");
|
|
45100
|
+
var serverBootstrap = existsSync6(sourceServerBootstrap) ? sourceServerBootstrap : resolvePath3(import.meta.dir, "../dev/serverBootstrap.js");
|
|
44895
45101
|
var formatServerBootDiagnostic = (output, serverEntry) => {
|
|
44896
45102
|
if (!output.includes(NODE_API_IMPORT_ERROR))
|
|
44897
45103
|
return null;
|
|
@@ -45019,7 +45225,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45019
45225
|
let httpsEnabled = false;
|
|
45020
45226
|
let devCertificateAuthorityPath = null;
|
|
45021
45227
|
let resolvedDev;
|
|
45022
|
-
let buildDirectory =
|
|
45228
|
+
let buildDirectory = resolvePath3(process.cwd(), "build");
|
|
45023
45229
|
let mobileConfig;
|
|
45024
45230
|
let normalizedMobileConfig;
|
|
45025
45231
|
let iosPhysicalServerHost;
|
|
@@ -45035,7 +45241,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45035
45241
|
resolvedDev = resolveDevConfig(config?.dev);
|
|
45036
45242
|
httpsEnabled = resolvedDev.https;
|
|
45037
45243
|
if (config?.buildDirectory) {
|
|
45038
|
-
buildDirectory =
|
|
45244
|
+
buildDirectory = resolvePath3(process.cwd(), config.buildDirectory);
|
|
45039
45245
|
}
|
|
45040
45246
|
} catch {
|
|
45041
45247
|
resolvedDev = resolveDevConfig(undefined);
|
|
@@ -45280,7 +45486,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45280
45486
|
instanceLog.write(text2.replace(ANSI_LOG_REGEX, ""));
|
|
45281
45487
|
} catch {}
|
|
45282
45488
|
};
|
|
45283
|
-
const usesDocker = existsSync6(
|
|
45489
|
+
const usesDocker = existsSync6(resolvePath3(COMPOSE_PATH));
|
|
45284
45490
|
const scripts = usesDocker ? await readDbScripts() : null;
|
|
45285
45491
|
if (scripts)
|
|
45286
45492
|
await startDatabase(scripts);
|
|
@@ -45790,7 +45996,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45790
45996
|
};
|
|
45791
45997
|
let lastBuildDirectoryWarned;
|
|
45792
45998
|
const refreshDevConfigForSpawn = async () => {
|
|
45793
|
-
const cfgPath =
|
|
45999
|
+
const cfgPath = resolvePath3(configPath2 ?? process.env.ABSOLUTE_CONFIG ?? "absolute.config.ts");
|
|
45794
46000
|
let cfg;
|
|
45795
46001
|
try {
|
|
45796
46002
|
const mod = await import(`${cfgPath}?t=${Date.now()}`);
|
|
@@ -45805,7 +46011,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45805
46011
|
if (options.androidDevice && ["localhost", "127.0.0.1", "::1"].includes(refreshedDevConfig.host)) {
|
|
45806
46012
|
refreshedDevConfig.host = "0.0.0.0";
|
|
45807
46013
|
}
|
|
45808
|
-
const desiredBuildDir = cfg?.buildDirectory ?
|
|
46014
|
+
const desiredBuildDir = cfg?.buildDirectory ? resolvePath3(process.cwd(), cfg.buildDirectory) : resolvePath3(process.cwd(), "build");
|
|
45809
46015
|
if (desiredBuildDir !== buildDirectory && desiredBuildDir !== lastBuildDirectoryWarned) {
|
|
45810
46016
|
lastBuildDirectoryWarned = desiredBuildDir;
|
|
45811
46017
|
console.log(cliTag("\x1B[33m", `buildDirectory changed in config (${buildDirectory} \u2192 ${desiredBuildDir}) \u2014 restart \`absolute dev\` to apply (the parent CLI holds a directory lock at the original path).`));
|
|
@@ -45837,7 +46043,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45837
46043
|
for (const name of candidates) {
|
|
45838
46044
|
let text2;
|
|
45839
46045
|
try {
|
|
45840
|
-
text2 = readFileSync11(
|
|
46046
|
+
text2 = readFileSync11(resolvePath3(process.cwd(), name), "utf8");
|
|
45841
46047
|
} catch {
|
|
45842
46048
|
continue;
|
|
45843
46049
|
}
|
|
@@ -45890,7 +46096,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45890
46096
|
ABSOLUTE_HOST: resolvedDev.host,
|
|
45891
46097
|
ABSOLUTE_INSTANCE_MANAGED: "1",
|
|
45892
46098
|
ABSOLUTE_PORT: String(port),
|
|
45893
|
-
ABSOLUTE_SERVER_ENTRY:
|
|
46099
|
+
ABSOLUTE_SERVER_ENTRY: resolvePath3(serverEntry),
|
|
45894
46100
|
...mobileConfig ? { ABSOLUTE_MOBILE_PREVIEW: "1" } : {},
|
|
45895
46101
|
FORCE_COLOR: "1",
|
|
45896
46102
|
NODE_ENV: "development",
|
|
@@ -45959,7 +46165,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
45959
46165
|
try {
|
|
45960
46166
|
const { watch: watch3 } = await import("fs");
|
|
45961
46167
|
const { dirname: dirname9 } = await import("path");
|
|
45962
|
-
const absServerEntry =
|
|
46168
|
+
const absServerEntry = resolvePath3(serverEntry);
|
|
45963
46169
|
const serverEntryDir = dirname9(absServerEntry);
|
|
45964
46170
|
const ROOT_RESTART_DENY = new Set([
|
|
45965
46171
|
"build",
|