@absolutejs/absolute 0.20.0-beta.42 → 0.20.0-beta.44
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/browser.js +378 -361
- package/dist/angular/browser.js.map +2 -2
- package/dist/angular/components/core/streamingSlotRegistrar.js +7 -7
- package/dist/angular/components/core/streamingSlotRegistry.js +4 -4
- package/dist/angular/index.js +300 -294
- package/dist/angular/index.js.map +2 -2
- package/dist/angular/server.js +54 -50
- package/dist/angular/server.js.map +2 -2
- package/dist/build.js +199 -203
- package/dist/build.js.map +2 -2
- package/dist/cli/config/client.js +12 -12
- package/dist/cli/config/server.js +1096 -1090
- package/dist/cli/index.js +595 -256
- package/dist/client/index.js +29 -25
- package/dist/client/index.js.map +2 -2
- package/dist/core/streamingSlotRegistrar.js +15 -13
- package/dist/core/streamingSlotRegistrar.js.map +2 -2
- package/dist/core/streamingSlotRegistry.js +11 -9
- package/dist/core/streamingSlotRegistry.js.map +2 -2
- package/dist/image-client/imageClient.js +7 -7
- package/dist/index.js +782 -732
- package/dist/index.js.map +6 -5
- package/dist/islands/browser.js +11 -9
- package/dist/islands/browser.js.map +2 -2
- package/dist/islands/index.js +39 -35
- package/dist/islands/index.js.map +2 -2
- package/dist/mobile/browser.js +23 -22
- package/dist/mobile/browser.js.map +2 -2
- package/dist/mobile/index.js +724 -488
- package/dist/mobile/index.js.map +12 -12
- package/dist/mobile/remoteMacAgentEntry.js +413 -14
- package/dist/mobile/shellBootstrap.js +0 -1
- package/dist/mobile/shellExpoAuth.js +184 -0
- package/dist/mobile/shellExpoDevices.js +4 -5
- package/dist/mobile/shellSync.js +4 -4
- package/dist/react/browser.js +17 -15
- package/dist/react/browser.js.map +2 -2
- package/dist/react/components/browser/index.js +107 -107
- package/dist/react/components/index.js +118 -116
- package/dist/react/components/index.js.map +2 -2
- package/dist/react/hooks/index.js +11 -9
- package/dist/react/hooks/index.js.map +2 -2
- package/dist/react/index.js +53 -49
- package/dist/react/index.js.map +2 -2
- package/dist/react/jsxDevRuntimeCompat.js +11 -9
- package/dist/react/jsxDevRuntimeCompat.js.map +2 -2
- package/dist/react/jsxRuntimeCompat.js +11 -9
- package/dist/react/jsxRuntimeCompat.js.map +2 -2
- package/dist/react/router/browser.js +9 -7
- package/dist/react/router/browser.js.map +2 -2
- package/dist/react/router/index.js +9 -7
- package/dist/react/router/index.js.map +2 -2
- package/dist/react/server.js +12 -10
- package/dist/react/server.js.map +2 -2
- package/dist/src/mobile/devDeviceAdapter.d.ts +1 -1
- package/dist/src/mobile/expoBridge.d.ts +12 -12
- package/dist/src/mobile/expoDevController.d.ts +8 -4
- package/dist/src/mobile/nativeAuth.d.ts +3 -0
- package/dist/src/mobile/remoteMacProtocol.d.ts +27 -0
- package/dist/src/mobile/remoteMacWire.d.ts +1 -1
- package/dist/src/mobile/shellExpoAuth.d.ts +12 -0
- package/dist/svelte/browser.js +12 -10
- package/dist/svelte/browser.js.map +2 -2
- package/dist/svelte/index.js +47 -43
- package/dist/svelte/index.js.map +2 -2
- package/dist/svelte/server.js +29 -27
- package/dist/svelte/server.js.map +2 -2
- package/dist/vue/browser.js +14 -12
- package/dist/vue/browser.js.map +2 -2
- package/dist/vue/components/Image.js +9 -7
- package/dist/vue/components/Image.js.map +2 -2
- package/dist/vue/components/index.js +11 -9
- package/dist/vue/components/index.js.map +2 -2
- package/dist/vue/index.js +52 -48
- package/dist/vue/index.js.map +2 -2
- package/dist/vue/server.js +14 -12
- package/dist/vue/server.js.map +2 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -847,6 +847,50 @@ var init_config = __esm(() => {
|
|
|
847
847
|
HOSTNAME_PATTERN = /^(?=.{1,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\.(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?))*$/;
|
|
848
848
|
});
|
|
849
849
|
|
|
850
|
+
// src/mobile/nativeAuth.ts
|
|
851
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
852
|
+
import { join as join5 } from "path";
|
|
853
|
+
var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth", ABSOLUTE_EXPO_AUTH_CORE_VERSION = "0.75.6", ABSOLUTE_EXPO_AUTH_PACKAGE = "@absolutejs/auth-expo", ABSOLUTE_EXPO_AUTH_VERSION = "0.0.2", ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS", ABSOLUTE_NATIVE_AUTH_SCOPES, ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync", readPackageManifest = (projectRoot) => {
|
|
854
|
+
try {
|
|
855
|
+
return JSON.parse(readFileSync5(join5(projectRoot, "package.json"), "utf8"));
|
|
856
|
+
} catch {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
}, packageManifestHas = (manifest, packageName) => {
|
|
860
|
+
if (typeof manifest !== "object" || manifest === null)
|
|
861
|
+
return false;
|
|
862
|
+
return [
|
|
863
|
+
Reflect.get(manifest, "dependencies"),
|
|
864
|
+
Reflect.get(manifest, "devDependencies"),
|
|
865
|
+
Reflect.get(manifest, "optionalDependencies"),
|
|
866
|
+
Reflect.get(manifest, "peerDependencies")
|
|
867
|
+
].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
|
|
868
|
+
}, createAbsoluteMobileAuthManifest = (config) => {
|
|
869
|
+
const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
|
|
870
|
+
return {
|
|
871
|
+
clientId: `absolutejs-native:${config.appId}`,
|
|
872
|
+
issuer: config.productionOrigin,
|
|
873
|
+
redirectUri: `${scheme}://auth/callback`,
|
|
874
|
+
scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
|
|
875
|
+
};
|
|
876
|
+
}, installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
|
|
877
|
+
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
878
|
+
const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
|
|
879
|
+
if (serialized === undefined)
|
|
880
|
+
delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
|
|
881
|
+
else
|
|
882
|
+
process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
|
|
883
|
+
return auth;
|
|
884
|
+
}, projectUsesAbsoluteAuth = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_AUTH_PACKAGE), projectUsesAbsoluteSync = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_SYNC_PACKAGE), resolveAbsoluteMobileAuthManifest = (projectRoot, config) => projectUsesAbsoluteAuth(projectRoot) ? createAbsoluteMobileAuthManifest(config) : undefined, serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefined ? undefined : JSON.stringify([
|
|
885
|
+
{
|
|
886
|
+
...auth,
|
|
887
|
+
name: `${config.appName} native app`
|
|
888
|
+
}
|
|
889
|
+
]);
|
|
890
|
+
var init_nativeAuth = __esm(() => {
|
|
891
|
+
ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
|
|
892
|
+
});
|
|
893
|
+
|
|
850
894
|
// src/mobile/expoProject.ts
|
|
851
895
|
import {
|
|
852
896
|
access,
|
|
@@ -860,7 +904,7 @@ import {
|
|
|
860
904
|
writeFile
|
|
861
905
|
} from "fs/promises";
|
|
862
906
|
import { createHash } from "crypto";
|
|
863
|
-
import { basename as basename2, dirname as dirname3, join as
|
|
907
|
+
import { basename as basename2, dirname as dirname3, join as join6, relative, resolve as resolve3 } from "path";
|
|
864
908
|
var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts, then run absolute mobile sync.
|
|
865
909
|
`, EXPO_ASSET_EXTENSION = ".absasset", EXPO_PROJECT_MARKER = ".absolutejs-expo-project", exists = async (path) => {
|
|
866
910
|
try {
|
|
@@ -879,8 +923,12 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
879
923
|
throw new TypeError(`Expo native route ${route} contains an unsupported segment ${segment}.`);
|
|
880
924
|
}
|
|
881
925
|
return segment;
|
|
882
|
-
}), routeFile = (project, route) =>
|
|
926
|
+
}), routeFile = (project, route) => join6(project, "app", ...routeSegments(route), "index.tsx"), expoPackage = (auth) => ({
|
|
883
927
|
dependencies: {
|
|
928
|
+
...auth ? {
|
|
929
|
+
"@absolutejs/auth": ABSOLUTE_EXPO_AUTH_CORE_VERSION,
|
|
930
|
+
[ABSOLUTE_EXPO_AUTH_PACKAGE]: ABSOLUTE_EXPO_AUTH_VERSION
|
|
931
|
+
} : {},
|
|
884
932
|
expo: "~57.0.9",
|
|
885
933
|
"expo-asset": "~57.0.15",
|
|
886
934
|
"expo-constants": "~57.0.16",
|
|
@@ -889,6 +937,10 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
889
937
|
"expo-haptics": "~57.0.2",
|
|
890
938
|
"expo-linking": "~57.0.8",
|
|
891
939
|
"expo-router": "~57.0.17",
|
|
940
|
+
...auth ? {
|
|
941
|
+
"expo-secure-store": "~57.0.2",
|
|
942
|
+
"expo-web-browser": "~57.0.2"
|
|
943
|
+
} : {},
|
|
892
944
|
react: "19.2.3",
|
|
893
945
|
"react-native": "0.86.3",
|
|
894
946
|
"react-native-safe-area-context": "~5.7.0",
|
|
@@ -908,7 +960,7 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
908
960
|
start: "expo start --dev-client"
|
|
909
961
|
},
|
|
910
962
|
version: "0.0.0"
|
|
911
|
-
}), expoAppConfig = (config) => ({
|
|
963
|
+
}), expoAppConfig = (config, auth) => ({
|
|
912
964
|
expo: {
|
|
913
965
|
android: {
|
|
914
966
|
intentFilters: config.deepLinkHosts.map((host) => ({
|
|
@@ -928,7 +980,8 @@ var EXPO_GENERATED_HEADER = `// Generated by AbsoluteJS. Edit absolute.config.ts
|
|
|
928
980
|
name: config.appName,
|
|
929
981
|
plugins: [
|
|
930
982
|
"expo-router",
|
|
931
|
-
["expo-dev-client", { launchMode: "most-recent" }]
|
|
983
|
+
["expo-dev-client", { launchMode: "most-recent" }],
|
|
984
|
+
...auth ? ["expo-secure-store"] : []
|
|
932
985
|
],
|
|
933
986
|
runtimeVersion: { policy: "appVersion" },
|
|
934
987
|
scheme: config.deepLinkScheme,
|
|
@@ -949,7 +1002,48 @@ config.resolver.nodeModulesPaths = [
|
|
|
949
1002
|
config.watchFolders = [appRoot];
|
|
950
1003
|
|
|
951
1004
|
module.exports = config;
|
|
952
|
-
`, layoutSource
|
|
1005
|
+
`, layoutSource = (auth) => `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
|
|
1006
|
+
${auth ? `import { useEffect } from 'react';
|
|
1007
|
+
import { startAbsoluteExpoAuth } from '../src/generated/AbsoluteAuth';` : ""}
|
|
1008
|
+
|
|
1009
|
+
export default function AbsoluteLayout() {
|
|
1010
|
+
${auth ? `useEffect(() => {
|
|
1011
|
+
void startAbsoluteExpoAuth();
|
|
1012
|
+
}, []);` : ""}
|
|
1013
|
+
return <Stack screenOptions={{ headerShown: false }} />;
|
|
1014
|
+
}
|
|
1015
|
+
`, nativeDiagnosticSource, authRuntimeSource = (auth, appId) => {
|
|
1016
|
+
const storageIdentity = createHash("sha256").update(appId).digest("hex").slice(0, 24);
|
|
1017
|
+
return `${EXPO_GENERATED_HEADER}import { createAbsoluteExpoAuthClient } from '@absolutejs/auth-expo';
|
|
1018
|
+
import { createMobileAuthTransport, installAuthClientRuntimeTransport } from '@absolutejs/auth/client/mobile';
|
|
1019
|
+
|
|
1020
|
+
export const absoluteExpoAuth = createAbsoluteExpoAuthClient({
|
|
1021
|
+
allowedOrigins: [${JSON.stringify(auth.issuer)}],
|
|
1022
|
+
clientId: ${JSON.stringify(auth.clientId)},
|
|
1023
|
+
issuer: ${JSON.stringify(auth.issuer)},
|
|
1024
|
+
redirectUri: ${JSON.stringify(auth.redirectUri)},
|
|
1025
|
+
resource: ${JSON.stringify(auth.issuer)},
|
|
1026
|
+
scopes: ${JSON.stringify(auth.scopes)},
|
|
1027
|
+
storagePrefix: ${JSON.stringify(`absolutejs.auth.${storageIdentity}`)}
|
|
1028
|
+
});
|
|
1029
|
+
installAuthClientRuntimeTransport(createMobileAuthTransport(absoluteExpoAuth, { baseUrl: ${JSON.stringify(auth.issuer)} }));
|
|
1030
|
+
|
|
1031
|
+
let currentPrincipal: Awaited<ReturnType<typeof absoluteExpoAuth.principal>> = null;
|
|
1032
|
+
absoluteExpoAuth.onPrincipalChange(principal => {
|
|
1033
|
+
currentPrincipal = principal;
|
|
1034
|
+
});
|
|
1035
|
+
export const getAbsoluteExpoAuthPrincipal = () => currentPrincipal;
|
|
1036
|
+
|
|
1037
|
+
let startPromise: Promise<void> | undefined;
|
|
1038
|
+
export const startAbsoluteExpoAuth = () => {
|
|
1039
|
+
startPromise ??= absoluteExpoAuth.start().then(async () => {
|
|
1040
|
+
await absoluteExpoAuth.principal();
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
return startPromise;
|
|
1044
|
+
};
|
|
1045
|
+
`;
|
|
1046
|
+
}, webHostSource = (config, auth) => {
|
|
953
1047
|
const nativeRoutes = [
|
|
954
1048
|
"/__absolute/native",
|
|
955
1049
|
...Object.keys(config.expoNativeRoutes)
|
|
@@ -961,8 +1055,9 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
961
1055
|
import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
|
|
962
1056
|
import { WebView, type WebViewMessageEvent } from 'react-native-webview';
|
|
963
1057
|
import { materializeAbsoluteWebBundle } from './webAssets';
|
|
1058
|
+
${auth ? "import { absoluteExpoAuth, getAbsoluteExpoAuthPrincipal, startAbsoluteExpoAuth } from './AbsoluteAuth';" : ""}
|
|
964
1059
|
|
|
965
|
-
const BRIDGE_FORMAT =
|
|
1060
|
+
const BRIDGE_FORMAT = 2;
|
|
966
1061
|
const MAX_MESSAGE_BYTES = 64 * 1024;
|
|
967
1062
|
const MAX_HTTP_BODY_BYTES = 48 * 1024;
|
|
968
1063
|
const NATIVE_ROUTES = new Set(${JSON.stringify(nativeRoutes)});
|
|
@@ -971,6 +1066,7 @@ const DEV_ORIGIN = Platform.OS === 'android'
|
|
|
971
1066
|
? process.env.EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN
|
|
972
1067
|
: process.env.EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN;
|
|
973
1068
|
const HMR_TARGET = Platform.OS === 'android' ? 'expo-android' : 'expo-ios';
|
|
1069
|
+
const AUTH_ENABLED = ${auth ? "true" : "false"};
|
|
974
1070
|
|
|
975
1071
|
const bridgeBootstrap = (path: string) => {
|
|
976
1072
|
const initialPath = DEV_ORIGIN
|
|
@@ -978,6 +1074,7 @@ const bridgeBootstrap = (path: string) => {
|
|
|
978
1074
|
: JSON.stringify(path);
|
|
979
1075
|
return \`(() => {
|
|
980
1076
|
const pending = new Map();
|
|
1077
|
+
const listeners = new Map();
|
|
981
1078
|
let sequence = 0;
|
|
982
1079
|
let currentPath = \${initialPath};
|
|
983
1080
|
const send = value => {
|
|
@@ -987,6 +1084,10 @@ const bridgeBootstrap = (path: string) => {
|
|
|
987
1084
|
};
|
|
988
1085
|
globalThis.__absoluteExpoReceive = source => {
|
|
989
1086
|
const message = JSON.parse(source);
|
|
1087
|
+
if (message.kind === 'event') {
|
|
1088
|
+
for (const listener of listeners.get(message.event) || []) listener(message.payload || {});
|
|
1089
|
+
return;
|
|
1090
|
+
}
|
|
990
1091
|
const operation = pending.get(message.id);
|
|
991
1092
|
if (!operation) return;
|
|
992
1093
|
pending.delete(message.id);
|
|
@@ -994,9 +1095,18 @@ const bridgeBootstrap = (path: string) => {
|
|
|
994
1095
|
message.error ? operation.reject(new Error(message.error.message)) : operation.resolve(message.result);
|
|
995
1096
|
};
|
|
996
1097
|
globalThis.__absoluteExpoBridge = {
|
|
1098
|
+
on(event, listener) {
|
|
1099
|
+
const values = listeners.get(event) || new Set();
|
|
1100
|
+
values.add(listener);
|
|
1101
|
+
listeners.set(event, values);
|
|
1102
|
+
return () => {
|
|
1103
|
+
values.delete(listener);
|
|
1104
|
+
if (values.size === 0) listeners.delete(event);
|
|
1105
|
+
};
|
|
1106
|
+
},
|
|
997
1107
|
request(method, params) {
|
|
998
1108
|
const id = 'web_' + Date.now().toString(36) + '_' + (++sequence).toString(36);
|
|
999
|
-
send({ format:
|
|
1109
|
+
send({ format: 2, id, kind: 'request', method, params, path: currentPath });
|
|
1000
1110
|
return new Promise((resolve, reject) => {
|
|
1001
1111
|
const timer = setTimeout(() => {
|
|
1002
1112
|
pending.delete(id);
|
|
@@ -1007,7 +1117,7 @@ const bridgeBootstrap = (path: string) => {
|
|
|
1007
1117
|
},
|
|
1008
1118
|
setPath(path) {
|
|
1009
1119
|
currentPath = path;
|
|
1010
|
-
send({ format:
|
|
1120
|
+
send({ format: 2, kind: 'event', event: 'navigation', path });
|
|
1011
1121
|
}
|
|
1012
1122
|
};
|
|
1013
1123
|
if (\${DEV_ORIGIN ? 'true' : 'false'}) {
|
|
@@ -1015,7 +1125,7 @@ const bridgeBootstrap = (path: string) => {
|
|
|
1015
1125
|
const path = location.pathname + location.search + location.hash;
|
|
1016
1126
|
if (path === currentPath) return;
|
|
1017
1127
|
currentPath = path;
|
|
1018
|
-
send({ format:
|
|
1128
|
+
send({ format: 2, kind: 'event', event: 'navigation', path });
|
|
1019
1129
|
};
|
|
1020
1130
|
for (const method of ['pushState', 'replaceState']) {
|
|
1021
1131
|
const original = history[method];
|
|
@@ -1034,9 +1144,9 @@ const bridgeBootstrap = (path: string) => {
|
|
|
1034
1144
|
const url = new URL(anchor.href, location.href);
|
|
1035
1145
|
if (!${JSON.stringify(nativeRoutes)}.includes(url.pathname)) return;
|
|
1036
1146
|
event.preventDefault();
|
|
1037
|
-
send({ format:
|
|
1147
|
+
send({ format: 2, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
|
|
1038
1148
|
}, true);
|
|
1039
|
-
send({ format:
|
|
1149
|
+
send({ format: 2, kind: 'event', event: 'ready', path: currentPath });
|
|
1040
1150
|
})(); true;\`;
|
|
1041
1151
|
};
|
|
1042
1152
|
|
|
@@ -1052,16 +1162,16 @@ const impact = async (params: Record<string, unknown>) => {
|
|
|
1052
1162
|
};
|
|
1053
1163
|
|
|
1054
1164
|
const bridgeFetch = async (params: Record<string, unknown>) => {
|
|
1055
|
-
if (params.method !== 'GET' || typeof params.url !== 'string' || typeof params.headers !== 'object' || params.headers === null || Array.isArray(params.headers)) throw new Error('Expo bridge HTTP request is invalid.');
|
|
1165
|
+
if (typeof params.method !== 'string' || !['DELETE', 'GET', 'PATCH', 'POST', 'PUT'].includes(params.method) || typeof params.url !== 'string' || typeof params.headers !== 'object' || params.headers === null || Array.isArray(params.headers) || params.body !== undefined && typeof params.body !== 'string') throw new Error('Expo bridge HTTP request is invalid.');
|
|
1056
1166
|
const url = new URL(params.url);
|
|
1057
1167
|
if (url.origin !== PRODUCTION_ORIGIN || url.username || url.password) throw new Error('Expo bridge HTTP request left productionOrigin.');
|
|
1058
1168
|
const headers = new Headers();
|
|
1059
1169
|
for (const [name, value] of Object.entries(params.headers as Record<string, unknown>)) {
|
|
1060
1170
|
const normalized = name.toLowerCase();
|
|
1061
|
-
if (typeof value !== 'string' || (normalized !== 'accept' && !normalized.startsWith('x-absolute-mobile-'))) throw new Error('Expo bridge HTTP header is not allowed.');
|
|
1171
|
+
if (typeof value !== 'string' || (normalized !== 'accept' && normalized !== 'content-type' && !normalized.startsWith('x-absolute-mobile-'))) throw new Error('Expo bridge HTTP header is not allowed.');
|
|
1062
1172
|
headers.set(normalized, value);
|
|
1063
1173
|
}
|
|
1064
|
-
const response = await fetch(url, { headers, method:
|
|
1174
|
+
const response = await ${auth ? "absoluteExpoAuth.fetchOptional" : "fetch"}(url, { ...(typeof params.body === 'string' ? { body: params.body } : {}), headers, method: params.method, redirect: 'manual' });
|
|
1065
1175
|
if (new URL(response.url || url.href).origin !== PRODUCTION_ORIGIN || response.status >= 300 && response.status < 400) throw new Error('Expo bridge HTTP redirects are not allowed.');
|
|
1066
1176
|
const body = await response.text();
|
|
1067
1177
|
if (new TextEncoder().encode(body).byteLength > MAX_HTTP_BODY_BYTES) throw new Error('Expo bridge HTTP response exceeds 48 KiB.');
|
|
@@ -1073,13 +1183,32 @@ const bridgeFetch = async (params: Record<string, unknown>) => {
|
|
|
1073
1183
|
return { body, headers: responseHeaders, status: response.status };
|
|
1074
1184
|
};
|
|
1075
1185
|
|
|
1186
|
+
const authStatus = async () => {
|
|
1187
|
+
${auth ? `const user = await absoluteExpoAuth.status();
|
|
1188
|
+
const principal = getAbsoluteExpoAuthPrincipal();
|
|
1189
|
+
return { principal: principal ? { namespace: principal.namespace } : null, user };` : "throw new Error('Expo Auth is not configured.');"}
|
|
1190
|
+
};
|
|
1191
|
+
|
|
1076
1192
|
export function AbsoluteWebHost() {
|
|
1077
1193
|
const pathname = usePathname() || '/';
|
|
1078
1194
|
const webView = useRef<WebView>(null);
|
|
1079
1195
|
const [indexUri, setIndexUri] = useState<string>();
|
|
1080
1196
|
const [canGoBack, setCanGoBack] = useState(false);
|
|
1197
|
+
const [authReady, setAuthReady] = useState(!AUTH_ENABLED);
|
|
1081
1198
|
const activeWebPath = useRef(pathname);
|
|
1082
1199
|
|
|
1200
|
+
useEffect(() => {
|
|
1201
|
+
if (!AUTH_ENABLED) return;
|
|
1202
|
+
let active = true;
|
|
1203
|
+
${auth ? `const stop = absoluteExpoAuth.onPrincipalChange(principal => {
|
|
1204
|
+
if (!active) return;
|
|
1205
|
+
const source = JSON.stringify({ event: 'auth.principal', format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload: { principal: principal ? { namespace: principal.namespace } : null } });
|
|
1206
|
+
webView.current?.injectJavaScript(\`globalThis.__absoluteExpoReceive(\${JSON.stringify(source)}); true;\`);
|
|
1207
|
+
});
|
|
1208
|
+
void startAbsoluteExpoAuth().then(() => { if (active) setAuthReady(true); });
|
|
1209
|
+
return () => { active = false; stop(); };` : ""}
|
|
1210
|
+
}, []);
|
|
1211
|
+
|
|
1083
1212
|
useEffect(() => {
|
|
1084
1213
|
if (DEV_ORIGIN) {
|
|
1085
1214
|
const target = new URL(pathname, DEV_ORIGIN);
|
|
@@ -1129,6 +1258,16 @@ export function AbsoluteWebHost() {
|
|
|
1129
1258
|
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: null });
|
|
1130
1259
|
} else if (message.method === 'http.fetch') {
|
|
1131
1260
|
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await bridgeFetch(message.params as Record<string, unknown>) });
|
|
1261
|
+
} else if (message.method === 'auth.signIn') {
|
|
1262
|
+
${auth ? `const params = message.params as Record<string, unknown>;
|
|
1263
|
+
if (typeof params.email !== 'string' || typeof params.signup !== 'boolean') throw new Error('Expo Auth sign-in params are invalid.');
|
|
1264
|
+
await absoluteExpoAuth.signIn({ authorizationParameters: { login_hint: params.email, ...(params.signup ? { screen_hint: 'signup' } : {}) } });
|
|
1265
|
+
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await authStatus() });` : "throw new Error('Expo Auth is not configured.');"}
|
|
1266
|
+
} else if (message.method === 'auth.signOut') {
|
|
1267
|
+
${auth ? `await absoluteExpoAuth.signOut();
|
|
1268
|
+
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: null });` : "throw new Error('Expo Auth is not configured.');"}
|
|
1269
|
+
} else if (message.method === 'auth.status') {
|
|
1270
|
+
respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await authStatus() });
|
|
1132
1271
|
} else {
|
|
1133
1272
|
throw new Error('Expo bridge method is not allowed.');
|
|
1134
1273
|
}
|
|
@@ -1137,7 +1276,7 @@ export function AbsoluteWebHost() {
|
|
|
1137
1276
|
}
|
|
1138
1277
|
};
|
|
1139
1278
|
|
|
1140
|
-
if (!indexUri) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
1279
|
+
if (!indexUri || !authReady) return <View style={styles.loading}><ActivityIndicator /></View>;
|
|
1141
1280
|
return <WebView
|
|
1142
1281
|
allowFileAccess
|
|
1143
1282
|
allowFileAccessFromFileURLs
|
|
@@ -1160,9 +1299,17 @@ export function AbsoluteWebHost() {
|
|
|
1160
1299
|
const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, justifyContent: 'center' }, web: { flex: 1 } });
|
|
1161
1300
|
`;
|
|
1162
1301
|
}, webRouteSource, catchAllRouteSource, nativeWrapperSource = (wrapper, module) => `${EXPO_GENERATED_HEADER}export { default } from ${JSON.stringify(portableRelative(dirname3(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
|
|
1163
|
-
`, expoTsConfig = (projectRoot, project) => ({
|
|
1302
|
+
`, expoTsConfig = (projectRoot, project, auth) => ({
|
|
1164
1303
|
compilerOptions: {
|
|
1165
1304
|
paths: {
|
|
1305
|
+
...auth ? {
|
|
1306
|
+
"@absolutejs/auth": [
|
|
1307
|
+
"./node_modules/@absolutejs/auth/dist/index.d.ts"
|
|
1308
|
+
],
|
|
1309
|
+
"@absolutejs/auth/*": [
|
|
1310
|
+
"./node_modules/@absolutejs/auth/dist/*"
|
|
1311
|
+
]
|
|
1312
|
+
} : {},
|
|
1166
1313
|
"*": [
|
|
1167
1314
|
"./node_modules/*",
|
|
1168
1315
|
`${portableRelative(project, projectRoot)}/node_modules/*`
|
|
@@ -1193,6 +1340,7 @@ const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, jus
|
|
|
1193
1340
|
throw new TypeError("Expo project generation requires mobile.engine: expo.");
|
|
1194
1341
|
const projectRoot = resolve3(options.projectRoot);
|
|
1195
1342
|
const project = config.nativeProjectDirectory;
|
|
1343
|
+
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
1196
1344
|
const routeModules = Object.entries(config.expoNativeRoutes);
|
|
1197
1345
|
const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
|
|
1198
1346
|
exists: await exists(module),
|
|
@@ -1203,7 +1351,7 @@ const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, jus
|
|
|
1203
1351
|
if (missing) {
|
|
1204
1352
|
throw new TypeError(`Expo native route ${missing.route} references missing module ${missing.module}.`);
|
|
1205
1353
|
}
|
|
1206
|
-
const marker =
|
|
1354
|
+
const marker = join6(project, EXPO_PROJECT_MARKER);
|
|
1207
1355
|
if (await exists(project) && !await exists(marker)) {
|
|
1208
1356
|
const entries = await readdir(project);
|
|
1209
1357
|
if (entries.length > 0 && !options.force) {
|
|
@@ -1213,47 +1361,54 @@ const styles = StyleSheet.create({ loading: { alignItems: 'center', flex: 1, jus
|
|
|
1213
1361
|
await mkdir(project, { recursive: true });
|
|
1214
1362
|
await writeFile(marker, `format=1
|
|
1215
1363
|
`);
|
|
1364
|
+
const authEnabled = Boolean(auth);
|
|
1216
1365
|
const files = new Map([
|
|
1217
1366
|
[
|
|
1218
|
-
|
|
1367
|
+
join6(project, ".gitignore"),
|
|
1219
1368
|
`.expo/
|
|
1220
1369
|
android/
|
|
1221
1370
|
ios/
|
|
1222
1371
|
node_modules/
|
|
1223
1372
|
`
|
|
1224
1373
|
],
|
|
1225
|
-
[join5(project, "app.json"), jsonSource(expoAppConfig(config))],
|
|
1226
|
-
[join5(project, "app.config.js"), expoDynamicAppConfig],
|
|
1227
|
-
[join5(project, "package.json"), jsonSource(expoPackage())],
|
|
1228
|
-
[join5(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
1229
1374
|
[
|
|
1230
|
-
|
|
1375
|
+
join6(project, "app.json"),
|
|
1376
|
+
jsonSource(expoAppConfig(config, authEnabled))
|
|
1377
|
+
],
|
|
1378
|
+
[join6(project, "app.config.js"), expoDynamicAppConfig],
|
|
1379
|
+
[join6(project, "package.json"), jsonSource(expoPackage(authEnabled))],
|
|
1380
|
+
[join6(project, "metro.config.js"), metroConfig(projectRoot)],
|
|
1381
|
+
[
|
|
1382
|
+
join6(project, "plugins", "withAbsoluteDevelopmentCa.js"),
|
|
1231
1383
|
expoDevelopmentCaPlugin
|
|
1232
1384
|
],
|
|
1233
1385
|
[
|
|
1234
|
-
|
|
1235
|
-
jsonSource(expoTsConfig(projectRoot, project))
|
|
1386
|
+
join6(project, "tsconfig.json"),
|
|
1387
|
+
jsonSource(expoTsConfig(projectRoot, project, authEnabled))
|
|
1236
1388
|
],
|
|
1237
|
-
[
|
|
1389
|
+
[join6(project, "app", "_layout.tsx"), layoutSource(authEnabled)],
|
|
1238
1390
|
[
|
|
1239
|
-
|
|
1391
|
+
join6(project, "app", "__absolute", "native", "index.tsx"),
|
|
1240
1392
|
nativeDiagnosticSource
|
|
1241
1393
|
],
|
|
1242
1394
|
[
|
|
1243
|
-
|
|
1244
|
-
webHostSource(config)
|
|
1395
|
+
join6(project, "src", "generated", "AbsoluteWebHost.tsx"),
|
|
1396
|
+
webHostSource(config, auth)
|
|
1245
1397
|
]
|
|
1246
1398
|
]);
|
|
1247
|
-
|
|
1399
|
+
if (auth) {
|
|
1400
|
+
files.set(join6(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
|
|
1401
|
+
}
|
|
1402
|
+
const webAssetsPath = join6(project, "src", "generated", "webAssets.ts");
|
|
1248
1403
|
if (!await exists(webAssetsPath)) {
|
|
1249
1404
|
files.set(webAssetsPath, emptyWebAssetsSource);
|
|
1250
1405
|
}
|
|
1251
1406
|
if (!config.expoNativeRoutes["/"]) {
|
|
1252
|
-
files.set(
|
|
1407
|
+
files.set(join6(project, "app", "index.tsx"), webRouteSource);
|
|
1253
1408
|
}
|
|
1254
|
-
files.set(
|
|
1409
|
+
files.set(join6(project, "app", "[...absolute].tsx"), catchAllRouteSource);
|
|
1255
1410
|
for (const [route, module] of routeModules) {
|
|
1256
|
-
const wrapper = route === "/" ?
|
|
1411
|
+
const wrapper = route === "/" ? join6(project, "app", "index.tsx") : routeFile(project, route);
|
|
1257
1412
|
files.set(wrapper, nativeWrapperSource(wrapper, module));
|
|
1258
1413
|
}
|
|
1259
1414
|
const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
|
|
@@ -1262,7 +1417,7 @@ node_modules/
|
|
|
1262
1417
|
}, walkFiles = async (root, directory = root) => {
|
|
1263
1418
|
const entries = await readdir(directory, { withFileTypes: true });
|
|
1264
1419
|
const nested = await Promise.all(entries.map((entry) => {
|
|
1265
|
-
const path =
|
|
1420
|
+
const path = join6(directory, entry.name);
|
|
1266
1421
|
if (entry.isDirectory())
|
|
1267
1422
|
return walkFiles(root, path);
|
|
1268
1423
|
if (entry.isFile())
|
|
@@ -1323,11 +1478,11 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
1323
1478
|
`, syncAbsoluteExpoWebAssets = async (config) => {
|
|
1324
1479
|
if (config.engine !== "expo")
|
|
1325
1480
|
throw new TypeError("Expo asset sync requires mobile.engine: expo.");
|
|
1326
|
-
const marker =
|
|
1481
|
+
const marker = join6(config.nativeProjectDirectory, EXPO_PROJECT_MARKER);
|
|
1327
1482
|
if (!await exists(marker)) {
|
|
1328
1483
|
throw new TypeError("Expo asset sync requires an AbsoluteJS-managed Expo project. Run mobile init first.");
|
|
1329
1484
|
}
|
|
1330
|
-
const manifestPath =
|
|
1485
|
+
const manifestPath = join6(config.bundleDirectory, "absolute-mobile-manifest.json");
|
|
1331
1486
|
const manifest = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
1332
1487
|
const appBuild = typeof manifest === "object" && manifest !== null && typeof Reflect.get(manifest, "appBuild") === "string" ? String(Reflect.get(manifest, "appBuild")) : undefined;
|
|
1333
1488
|
if (!appBuild)
|
|
@@ -1342,16 +1497,16 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
1342
1497
|
bundleHash.update("\x00");
|
|
1343
1498
|
});
|
|
1344
1499
|
const bundleId = `amexpo_${bundleHash.digest("hex")}`;
|
|
1345
|
-
const destination =
|
|
1500
|
+
const destination = join6(config.nativeProjectDirectory, "assets", "absolute");
|
|
1346
1501
|
await mkdir(dirname3(destination), { recursive: true });
|
|
1347
|
-
const staging = await mkdtemp(
|
|
1502
|
+
const staging = await mkdtemp(join6(dirname3(destination), `.${basename2(destination)}.stage-`));
|
|
1348
1503
|
let assets;
|
|
1349
1504
|
try {
|
|
1350
1505
|
assets = await Promise.all(files.map(async (source, index) => {
|
|
1351
1506
|
const name = `${String(index).padStart(6, "0")}${EXPO_ASSET_EXTENSION}`;
|
|
1352
|
-
await cp(source,
|
|
1507
|
+
await cp(source, join6(staging, name));
|
|
1353
1508
|
return {
|
|
1354
|
-
asset: portableRelative(
|
|
1509
|
+
asset: portableRelative(join6(config.nativeProjectDirectory, "src", "generated"), join6(destination, name)),
|
|
1355
1510
|
path: relative(config.bundleDirectory, source).replaceAll("\\", "/")
|
|
1356
1511
|
};
|
|
1357
1512
|
}));
|
|
@@ -1360,11 +1515,12 @@ export const materializeAbsoluteWebBundle = async () => {
|
|
|
1360
1515
|
await rm(staging, { force: true, recursive: true });
|
|
1361
1516
|
throw error;
|
|
1362
1517
|
}
|
|
1363
|
-
const generated =
|
|
1518
|
+
const generated = join6(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
|
|
1364
1519
|
await writeManagedFile(generated, assetModuleSource(assets, bundleId), true);
|
|
1365
1520
|
return { appBuild, assets: assets.length, bundleId, path: destination };
|
|
1366
1521
|
};
|
|
1367
1522
|
var init_expoProject = __esm(() => {
|
|
1523
|
+
init_nativeAuth();
|
|
1368
1524
|
expoDynamicAppConfig = `${EXPO_GENERATED_HEADER}const config = require('./app.json');
|
|
1369
1525
|
|
|
1370
1526
|
if (process.env.ABSOLUTE_EXPO_DEVELOPMENT === '1' && process.env.ABSOLUTE_EXPO_DEVELOPMENT_CA_PATH) {
|
|
@@ -1415,12 +1571,6 @@ const withAbsoluteDevelopmentCa = config => {
|
|
|
1415
1571
|
};
|
|
1416
1572
|
|
|
1417
1573
|
module.exports = withAbsoluteDevelopmentCa;
|
|
1418
|
-
`;
|
|
1419
|
-
layoutSource = `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
|
|
1420
|
-
|
|
1421
|
-
export default function AbsoluteLayout() {
|
|
1422
|
-
return <Stack screenOptions={{ headerShown: false }} />;
|
|
1423
|
-
}
|
|
1424
1574
|
`;
|
|
1425
1575
|
nativeDiagnosticSource = `${EXPO_GENERATED_HEADER}import * as Haptics from 'expo-haptics';
|
|
1426
1576
|
import { Link } from 'expo-router';
|
|
@@ -1558,50 +1708,6 @@ var closeServer = (server) => new Promise((resolve4, reject) => {
|
|
|
1558
1708
|
};
|
|
1559
1709
|
var init_iosPhysicalDeviceTransport = () => {};
|
|
1560
1710
|
|
|
1561
|
-
// src/mobile/nativeAuth.ts
|
|
1562
|
-
import { readFileSync as readFileSync5 } from "fs";
|
|
1563
|
-
import { join as join7 } from "path";
|
|
1564
|
-
var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth", ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS", ABSOLUTE_NATIVE_AUTH_SCOPES, ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync", readPackageManifest = (projectRoot) => {
|
|
1565
|
-
try {
|
|
1566
|
-
return JSON.parse(readFileSync5(join7(projectRoot, "package.json"), "utf8"));
|
|
1567
|
-
} catch {
|
|
1568
|
-
return;
|
|
1569
|
-
}
|
|
1570
|
-
}, packageManifestHas = (manifest, packageName) => {
|
|
1571
|
-
if (typeof manifest !== "object" || manifest === null)
|
|
1572
|
-
return false;
|
|
1573
|
-
return [
|
|
1574
|
-
Reflect.get(manifest, "dependencies"),
|
|
1575
|
-
Reflect.get(manifest, "devDependencies"),
|
|
1576
|
-
Reflect.get(manifest, "optionalDependencies"),
|
|
1577
|
-
Reflect.get(manifest, "peerDependencies")
|
|
1578
|
-
].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
|
|
1579
|
-
}, createAbsoluteMobileAuthManifest = (config) => {
|
|
1580
|
-
const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
|
|
1581
|
-
return {
|
|
1582
|
-
clientId: `absolutejs-native:${config.appId}`,
|
|
1583
|
-
issuer: config.productionOrigin,
|
|
1584
|
-
redirectUri: `${scheme}://auth/callback`,
|
|
1585
|
-
scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
|
|
1586
|
-
};
|
|
1587
|
-
}, installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
|
|
1588
|
-
const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
|
|
1589
|
-
const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
|
|
1590
|
-
if (serialized === undefined)
|
|
1591
|
-
delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
|
|
1592
|
-
else
|
|
1593
|
-
process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
|
|
1594
|
-
return auth;
|
|
1595
|
-
}, projectUsesAbsoluteAuth = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_AUTH_PACKAGE), projectUsesAbsoluteSync = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_SYNC_PACKAGE), resolveAbsoluteMobileAuthManifest = (projectRoot, config) => projectUsesAbsoluteAuth(projectRoot) ? createAbsoluteMobileAuthManifest(config) : undefined, serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefined ? undefined : JSON.stringify([
|
|
1596
|
-
{
|
|
1597
|
-
...auth,
|
|
1598
|
-
name: `${config.appName} native app`
|
|
1599
|
-
}
|
|
1600
|
-
]);
|
|
1601
|
-
var init_nativeAuth = __esm(() => {
|
|
1602
|
-
ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
|
|
1603
|
-
});
|
|
1604
|
-
|
|
1605
1711
|
// src/cli/utils.ts
|
|
1606
1712
|
var {$: $2 } = globalThis.Bun;
|
|
1607
1713
|
import { execSync } from "child_process";
|
|
@@ -4488,7 +4594,7 @@ var init_iosSimulatorController = __esm(() => {
|
|
|
4488
4594
|
});
|
|
4489
4595
|
|
|
4490
4596
|
// src/mobile/remoteMacWire.ts
|
|
4491
|
-
var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION =
|
|
4597
|
+
var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t", ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 2;
|
|
4492
4598
|
|
|
4493
4599
|
// src/mobile/remoteMacProtocol.ts
|
|
4494
4600
|
import { createHash as createHash6, randomUUID as randomUUID4 } from "crypto";
|
|
@@ -4504,7 +4610,7 @@ import {
|
|
|
4504
4610
|
resolve as resolvePath,
|
|
4505
4611
|
sep as sep4
|
|
4506
4612
|
} from "path";
|
|
4507
|
-
var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join13(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
|
|
4613
|
+
var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, REMOTE_SESSION_CLOSE_TIMEOUT_MS = 2000, PROFILE_NAME, SSH_DESTINATION, defaultProfilePath = () => join13(homedir4(), ".absolutejs", "mobile", "remote-macs.json"), emptyStore = () => ({
|
|
4508
4614
|
format: PROFILE_FORMAT,
|
|
4509
4615
|
profiles: {}
|
|
4510
4616
|
}), loadStore = async (path = defaultProfilePath()) => {
|
|
@@ -4675,7 +4781,11 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4675
4781
|
}
|
|
4676
4782
|
await saveStore(store, profilePath);
|
|
4677
4783
|
return true;
|
|
4678
|
-
}, projectIdentity = (projectRoot, appId) => createHash6("sha256").update(`${resolvePath(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20),
|
|
4784
|
+
}, projectIdentity = (projectRoot, appId) => createHash6("sha256").update(`${resolvePath(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20), createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
|
|
4785
|
+
if (config.engine !== "expo")
|
|
4786
|
+
throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
|
|
4787
|
+
return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
|
|
4788
|
+
}, createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
|
|
4679
4789
|
cap: join13(resolvePath(projectRoot), "node_modules", ".bin", "cap"),
|
|
4680
4790
|
config,
|
|
4681
4791
|
nativeDirectory: join13(config.nativeProjectDirectory, "ios"),
|
|
@@ -4762,6 +4872,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4762
4872
|
appId: project.config.appId,
|
|
4763
4873
|
appName: project.config.appName,
|
|
4764
4874
|
bundleDirectory: portableRelativePath(project.projectRoot, project.config.bundleDirectory),
|
|
4875
|
+
engine: project.config.engine,
|
|
4765
4876
|
...project.config.deepLinkScheme || project.config.deepLinkHosts.length > 1 || project.config.appleAppIdPrefix ? {
|
|
4766
4877
|
deepLinks: {
|
|
4767
4878
|
...project.config.deepLinkScheme ? { scheme: project.config.deepLinkScheme } : {},
|
|
@@ -4774,6 +4885,16 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4774
4885
|
}
|
|
4775
4886
|
} : {},
|
|
4776
4887
|
entry: project.config.entry,
|
|
4888
|
+
...project.config.engine === "expo" ? {
|
|
4889
|
+
expo: { sdkVersion: project.config.expoSdkVersion ?? 57 },
|
|
4890
|
+
routes: {
|
|
4891
|
+
default: "web",
|
|
4892
|
+
native: Object.fromEntries(Object.entries(project.config.expoNativeRoutes).map(([route, module]) => [
|
|
4893
|
+
route,
|
|
4894
|
+
portableRelativePath(project.projectRoot, module)
|
|
4895
|
+
]))
|
|
4896
|
+
}
|
|
4897
|
+
} : {},
|
|
4777
4898
|
...project.config.iosVersion ? { ios: { version: project.config.iosVersion } } : {},
|
|
4778
4899
|
nativeProject: {
|
|
4779
4900
|
directory: portableRelativePath(project.projectRoot, project.config.nativeProjectDirectory),
|
|
@@ -4861,7 +4982,30 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4861
4982
|
} finally {
|
|
4862
4983
|
reader.releaseLock();
|
|
4863
4984
|
}
|
|
4864
|
-
},
|
|
4985
|
+
}, startAbsoluteRemoteExpoIosDevSession = async (options) => {
|
|
4986
|
+
const session = await startAbsoluteRemoteDevSession({
|
|
4987
|
+
certificateAuthorityPath: options.certificateAuthorityPath,
|
|
4988
|
+
deviceIdentifier: options.deviceIdentifier,
|
|
4989
|
+
https: options.https,
|
|
4990
|
+
installAgent: options.installAgent,
|
|
4991
|
+
log: options.log,
|
|
4992
|
+
metroPort: options.metroPort,
|
|
4993
|
+
onExpoPhaseTiming: options.onPhaseTiming,
|
|
4994
|
+
onExpoStateChange: options.onStateChange,
|
|
4995
|
+
port: options.port,
|
|
4996
|
+
project: options.project,
|
|
4997
|
+
serverHost: options.serverHost,
|
|
4998
|
+
signal: options.signal,
|
|
4999
|
+
syncProject: options.syncProject,
|
|
5000
|
+
transport: options.transport
|
|
5001
|
+
});
|
|
5002
|
+
return {
|
|
5003
|
+
close: session.close,
|
|
5004
|
+
metroPort: options.metroPort,
|
|
5005
|
+
platforms: ["ios"],
|
|
5006
|
+
timings: session.timings
|
|
5007
|
+
};
|
|
5008
|
+
}, startAbsoluteRemoteIosDevSession = (options) => startAbsoluteRemoteDevSession(options), startAbsoluteRemoteDevSession = async (options) => {
|
|
4865
5009
|
const startedAt = performance.now();
|
|
4866
5010
|
const transport = options.transport ?? defaultTransport;
|
|
4867
5011
|
const installAgent = options.installAgent ?? installAbsoluteRemoteMacAgent;
|
|
@@ -4875,9 +5019,22 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4875
5019
|
const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
|
|
4876
5020
|
const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile8(options.certificateAuthorityPath)).toString("base64url") : undefined;
|
|
4877
5021
|
const physicalDevice = options.deviceIdentifier !== undefined;
|
|
4878
|
-
|
|
4879
|
-
if (
|
|
4880
|
-
|
|
5022
|
+
const expo = options.project.config.engine === "expo";
|
|
5023
|
+
if (expo && options.metroPort === undefined)
|
|
5024
|
+
throw new TypeError("Remote Expo execution requires a Metro port.");
|
|
5025
|
+
if (options.metroPort === options.port)
|
|
5026
|
+
throw new TypeError("Expo Metro and AbsoluteJS must use different ports.");
|
|
5027
|
+
const translatedRelayPort = (sourcePort) => sourcePort <= 49151 ? sourcePort + 16384 : sourcePort - 16384;
|
|
5028
|
+
const occupiedRemotePorts = new Set([options.port, options.metroPort].filter((value) => value !== undefined));
|
|
5029
|
+
const reserveRelayPort = (sourcePort) => {
|
|
5030
|
+
let candidate = translatedRelayPort(sourcePort);
|
|
5031
|
+
while (occupiedRemotePorts.has(candidate))
|
|
5032
|
+
candidate = candidate === 65535 ? 1024 : candidate + 1;
|
|
5033
|
+
occupiedRemotePorts.add(candidate);
|
|
5034
|
+
return candidate;
|
|
5035
|
+
};
|
|
5036
|
+
const relayPort = physicalDevice ? reserveRelayPort(options.port) : undefined;
|
|
5037
|
+
const metroRelayPort = physicalDevice && options.metroPort !== undefined ? reserveRelayPort(options.metroPort) : undefined;
|
|
4881
5038
|
if (physicalDevice && !options.serverHost)
|
|
4882
5039
|
throw new Error("Remote physical iOS development requires the Remote Mac LAN host.");
|
|
4883
5040
|
const remoteCommand = [
|
|
@@ -4890,6 +5047,7 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4890
5047
|
String(options.port),
|
|
4891
5048
|
"--mobile-config",
|
|
4892
5049
|
shellQuote(encodedConfig),
|
|
5050
|
+
...expo && options.metroPort !== undefined ? ["--metro-port", String(options.metroPort)] : [],
|
|
4893
5051
|
...encodedCertificateAuthority ? [
|
|
4894
5052
|
"--certificate-authority",
|
|
4895
5053
|
shellQuote(encodedCertificateAuthority)
|
|
@@ -4901,7 +5059,8 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4901
5059
|
"--server-host",
|
|
4902
5060
|
shellQuote(options.serverHost ?? ""),
|
|
4903
5061
|
"--relay-port",
|
|
4904
|
-
String(relayPort)
|
|
5062
|
+
String(relayPort),
|
|
5063
|
+
...expo && metroRelayPort !== undefined ? ["--metro-relay-port", String(metroRelayPort)] : []
|
|
4905
5064
|
] : []
|
|
4906
5065
|
].join(" ");
|
|
4907
5066
|
const command = [
|
|
@@ -4910,6 +5069,10 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4910
5069
|
"ExitOnForwardFailure=yes",
|
|
4911
5070
|
"-R",
|
|
4912
5071
|
physicalDevice ? `127.0.0.1:${relayPort}:127.0.0.1:${options.port}` : `${options.port}:127.0.0.1:${options.port}`,
|
|
5072
|
+
...expo && options.metroPort !== undefined ? [
|
|
5073
|
+
"-R",
|
|
5074
|
+
physicalDevice ? `127.0.0.1:${metroRelayPort}:127.0.0.1:${options.metroPort}` : `${options.metroPort}:127.0.0.1:${options.metroPort}`
|
|
5075
|
+
] : [],
|
|
4913
5076
|
"/bin/sh -lc",
|
|
4914
5077
|
shellQuote(remoteCommand)
|
|
4915
5078
|
];
|
|
@@ -4935,11 +5098,19 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4935
5098
|
if (event.type === "native-log")
|
|
4936
5099
|
options.nativeLog?.(event.entry);
|
|
4937
5100
|
if (event.type === "state") {
|
|
4938
|
-
(
|
|
4939
|
-
|
|
5101
|
+
if (expo)
|
|
5102
|
+
options.onExpoStateChange?.(event.state);
|
|
5103
|
+
else {
|
|
5104
|
+
state = event.state;
|
|
5105
|
+
options.onStateChange?.(state);
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
5108
|
+
if (event.type === "timing") {
|
|
5109
|
+
if (expo)
|
|
5110
|
+
options.onExpoPhaseTiming?.(event);
|
|
5111
|
+
else
|
|
5112
|
+
options.onPhaseTiming?.(event);
|
|
4940
5113
|
}
|
|
4941
|
-
if (event.type === "timing")
|
|
4942
|
-
options.onPhaseTiming?.(event);
|
|
4943
5114
|
if (event.type === "ready") {
|
|
4944
5115
|
ready = event;
|
|
4945
5116
|
resolveReady();
|
|
@@ -4981,9 +5152,26 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4981
5152
|
pending.clear();
|
|
4982
5153
|
return;
|
|
4983
5154
|
});
|
|
4984
|
-
|
|
5155
|
+
try {
|
|
5156
|
+
await readyPromise;
|
|
5157
|
+
} catch (error) {
|
|
5158
|
+
process2.stdin.end();
|
|
5159
|
+
process2.kill();
|
|
5160
|
+
await process2.exited.catch(() => {
|
|
5161
|
+
return;
|
|
5162
|
+
});
|
|
5163
|
+
throw error;
|
|
5164
|
+
}
|
|
4985
5165
|
if (!ready)
|
|
4986
5166
|
throw fatal ?? new Error("Remote Mac did not become ready.");
|
|
5167
|
+
if (ready.engine !== options.project.config.engine) {
|
|
5168
|
+
process2.stdin.end();
|
|
5169
|
+
process2.kill();
|
|
5170
|
+
await process2.exited.catch(() => {
|
|
5171
|
+
return;
|
|
5172
|
+
});
|
|
5173
|
+
throw new Error("Remote Mac executor returned the wrong mobile engine.");
|
|
5174
|
+
}
|
|
4987
5175
|
const totalDuration = performance.now() - startedAt;
|
|
4988
5176
|
let currentReady = {
|
|
4989
5177
|
...ready,
|
|
@@ -4995,11 +5183,11 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
4995
5183
|
total: totalDuration
|
|
4996
5184
|
}
|
|
4997
5185
|
};
|
|
4998
|
-
options.log?.(`Remote Mac connected (${options.project.profile.name}); agent ${agent.uploaded ? "uploaded" : "cache hit"}, project synced, and iOS ready in ${totalDuration.toFixed(2)}ms.`);
|
|
5186
|
+
options.log?.(`Remote Mac connected (${options.project.profile.name}); agent ${agent.uploaded ? "uploaded" : "cache hit"}, project synced, and ${expo ? "Expo " : ""}iOS ready in ${totalDuration.toFixed(2)}ms.`);
|
|
4999
5187
|
const request = (commandName) => {
|
|
5000
5188
|
const id = randomUUID4();
|
|
5001
5189
|
const response = new Promise((resolve9, reject) => pending.set(id, { reject, resolve: resolve9 }));
|
|
5002
|
-
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v:
|
|
5190
|
+
process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
|
|
5003
5191
|
`);
|
|
5004
5192
|
const flush = async () => {
|
|
5005
5193
|
for (let attempt = 0;attempt < REMOTE_STDIN_FLUSH_ATTEMPTS; attempt++) {
|
|
@@ -5018,13 +5206,24 @@ var PROFILE_FORMAT = 1, REMOTE_STDIN_FLUSH_ATTEMPTS = 3, PROFILE_NAME, SSH_DESTI
|
|
|
5018
5206
|
if (closed)
|
|
5019
5207
|
return;
|
|
5020
5208
|
closed = true;
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5209
|
+
const timeout = () => new Promise((resolve9) => setTimeout(() => resolve9("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
|
|
5210
|
+
await Promise.race([
|
|
5211
|
+
request("close").catch(() => {
|
|
5212
|
+
return;
|
|
5213
|
+
}),
|
|
5214
|
+
timeout()
|
|
5215
|
+
]);
|
|
5024
5216
|
process2.stdin.end();
|
|
5025
|
-
await
|
|
5026
|
-
|
|
5027
|
-
|
|
5217
|
+
const exit = await Promise.race([
|
|
5218
|
+
process2.exited.then(() => "exited").catch(() => "exited"),
|
|
5219
|
+
timeout()
|
|
5220
|
+
]);
|
|
5221
|
+
if (exit === "timeout") {
|
|
5222
|
+
process2.kill();
|
|
5223
|
+
await process2.exited.catch(() => {
|
|
5224
|
+
return;
|
|
5225
|
+
});
|
|
5226
|
+
}
|
|
5028
5227
|
};
|
|
5029
5228
|
const makeSession = () => ({
|
|
5030
5229
|
close,
|
|
@@ -5085,13 +5284,13 @@ var init_remoteMacProtocol = __esm(() => {
|
|
|
5085
5284
|
// src/dev/devCert.ts
|
|
5086
5285
|
var exports_devCert = {};
|
|
5087
5286
|
__export(exports_devCert, {
|
|
5088
|
-
|
|
5089
|
-
normalizeDevCertificateHosts: () => normalizeDevCertificateHosts,
|
|
5090
|
-
loadDevCert: () => loadDevCert,
|
|
5091
|
-
hasMkcert: () => hasMkcert,
|
|
5092
|
-
hasCert: () => hasCert,
|
|
5287
|
+
ensureDevCert: () => ensureDevCert,
|
|
5093
5288
|
getDevCertificateAuthorityPath: () => getDevCertificateAuthorityPath,
|
|
5094
|
-
|
|
5289
|
+
hasCert: () => hasCert,
|
|
5290
|
+
hasMkcert: () => hasMkcert,
|
|
5291
|
+
loadDevCert: () => loadDevCert,
|
|
5292
|
+
normalizeDevCertificateHosts: () => normalizeDevCertificateHosts,
|
|
5293
|
+
setupMkcert: () => setupMkcert
|
|
5095
5294
|
});
|
|
5096
5295
|
import {
|
|
5097
5296
|
copyFileSync,
|
|
@@ -5399,13 +5598,13 @@ var init_devCert = __esm(() => {
|
|
|
5399
5598
|
// src/cli/scripts/eslintChunked.ts
|
|
5400
5599
|
var exports_eslintChunked = {};
|
|
5401
5600
|
__export(exports_eslintChunked, {
|
|
5402
|
-
|
|
5403
|
-
ruleSummary: () => ruleSummary,
|
|
5404
|
-
resolveLintTargets: () => resolveLintTargets,
|
|
5405
|
-
parseChunkedArgs: () => parseChunkedArgs,
|
|
5406
|
-
gitVisibleFiles: () => gitVisibleFiles,
|
|
5601
|
+
eslintChunked: () => eslintChunked,
|
|
5407
5602
|
gitChangedFiles: () => gitChangedFiles,
|
|
5408
|
-
|
|
5603
|
+
gitVisibleFiles: () => gitVisibleFiles,
|
|
5604
|
+
parseChunkedArgs: () => parseChunkedArgs,
|
|
5605
|
+
resolveLintTargets: () => resolveLintTargets,
|
|
5606
|
+
ruleSummary: () => ruleSummary,
|
|
5607
|
+
upstreamRef: () => upstreamRef
|
|
5409
5608
|
});
|
|
5410
5609
|
import { existsSync as existsSync6 } from "fs";
|
|
5411
5610
|
import { relative as relative7, resolve as resolve9 } from "path";
|
|
@@ -7051,6 +7250,11 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
7051
7250
|
if (candidate)
|
|
7052
7251
|
return candidate;
|
|
7053
7252
|
throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
|
|
7253
|
+
}, shellExpoAuthModule = () => {
|
|
7254
|
+
const candidate = ["js", "ts"].map((extension) => join19(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync9);
|
|
7255
|
+
if (candidate)
|
|
7256
|
+
return candidate;
|
|
7257
|
+
throw new TypeError("AbsoluteJS Expo auth bridge module is missing.");
|
|
7054
7258
|
}, shellSyncModule = () => {
|
|
7055
7259
|
const candidate = ["js", "ts"].map((extension) => join19(import.meta.dir, `shellSync.${extension}`)).find(existsSync9);
|
|
7056
7260
|
if (candidate)
|
|
@@ -7124,9 +7328,10 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
7124
7328
|
const capacitor = engine !== "expo";
|
|
7125
7329
|
const shellCapabilities = capacitor ? deviceCapabilities.capabilities : [];
|
|
7126
7330
|
const modulePath = shellBootstrapModule();
|
|
7127
|
-
const
|
|
7331
|
+
const authFactory = capacitor ? "createAbsoluteMobileShellAuth" : "createAbsoluteExpoShellAuth";
|
|
7332
|
+
const authImport = auth ? `import { ${authFactory} } from ${JSON.stringify(capacitor ? shellAuthModule() : shellExpoAuthModule())};
|
|
7128
7333
|
` : "";
|
|
7129
|
-
const options = auth ? `{ createAuth:
|
|
7334
|
+
const options = auth ? `{ createAuth: ${authFactory}${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
|
|
7130
7335
|
const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
|
|
7131
7336
|
` : "";
|
|
7132
7337
|
const pushIndex = shellCapabilities.indexOf("pushNotifications");
|
|
@@ -7148,7 +7353,7 @@ const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absolu
|
|
|
7148
7353
|
const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
|
|
7149
7354
|
const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
|
|
7150
7355
|
const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : "installAbsoluteExpoWebDeviceAdapter();";
|
|
7151
|
-
let shellOptions = "{ createFetch: createAbsoluteExpoBridgeFetch }";
|
|
7356
|
+
let shellOptions = auth ? options : "{ createFetch: createAbsoluteExpoBridgeFetch }";
|
|
7152
7357
|
if (capacitor)
|
|
7153
7358
|
shellOptions = options;
|
|
7154
7359
|
if (push) {
|
|
@@ -8234,10 +8439,10 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
8234
8439
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
8235
8440
|
});
|
|
8236
8441
|
const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
|
|
8237
|
-
if (mobile.engine === "expo" && auth) {
|
|
8238
|
-
throw new TypeError("Expo mobile Auth is not released yet. The experimental Expo shell cannot safely substitute Capacitor credentials; remove engine: 'expo' or wait for @absolutejs/auth-expo.");
|
|
8239
|
-
}
|
|
8240
8442
|
const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
|
|
8443
|
+
if (mobile.engine === "expo" && sync) {
|
|
8444
|
+
throw new TypeError("Expo mobile Sync is not released yet. Auth and authenticated HTTP are available, but @absolutejs/sync requires @absolutejs/sync-expo for shared durable state.");
|
|
8445
|
+
}
|
|
8241
8446
|
const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
|
|
8242
8447
|
const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
|
|
8243
8448
|
const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
|
|
@@ -8863,12 +9068,12 @@ var init_serverBundleExternals = __esm(() => {
|
|
|
8863
9068
|
// src/core/prerender.ts
|
|
8864
9069
|
var exports_prerender = {};
|
|
8865
9070
|
__export(exports_prerender, {
|
|
8866
|
-
|
|
8867
|
-
rerenderRoute: () => rerenderRoute,
|
|
8868
|
-
readTimestamp: () => readTimestamp,
|
|
8869
|
-
prerenderWithServer: () => prerenderWithServer,
|
|
9071
|
+
PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER,
|
|
8870
9072
|
prerender: () => prerender,
|
|
8871
|
-
|
|
9073
|
+
prerenderWithServer: () => prerenderWithServer,
|
|
9074
|
+
readTimestamp: () => readTimestamp,
|
|
9075
|
+
rerenderRoute: () => rerenderRoute,
|
|
9076
|
+
routeToFilename: () => routeToFilename
|
|
8872
9077
|
});
|
|
8873
9078
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync14 } from "fs";
|
|
8874
9079
|
import { join as join24 } from "path";
|
|
@@ -9528,8 +9733,8 @@ var init_rewriteImportsPlugin = __esm(() => {
|
|
|
9528
9733
|
// src/build/rewriteImports.ts
|
|
9529
9734
|
var exports_rewriteImports = {};
|
|
9530
9735
|
__export(exports_rewriteImports, {
|
|
9531
|
-
|
|
9532
|
-
|
|
9736
|
+
rewriteImports: () => rewriteImports,
|
|
9737
|
+
rewriteVendorDirectories: () => rewriteVendorDirectories2
|
|
9533
9738
|
});
|
|
9534
9739
|
var rewriteImports = async (outputPaths, vendorPaths) => {
|
|
9535
9740
|
const jsFiles = outputPaths.filter((path) => path.endsWith(".js"));
|
|
@@ -10192,11 +10397,11 @@ var init_build = __esm(() => {
|
|
|
10192
10397
|
// src/cli/scripts/lintProof.ts
|
|
10193
10398
|
var exports_lintProof = {};
|
|
10194
10399
|
__export(exports_lintProof, {
|
|
10195
|
-
|
|
10196
|
-
verifyLintProof: () => verifyLintProof,
|
|
10197
|
-
runLintProof: () => runLintProof,
|
|
10400
|
+
createLintProof: () => createLintProof,
|
|
10198
10401
|
createLintSourceTree: () => createLintSourceTree,
|
|
10199
|
-
|
|
10402
|
+
runLintProof: () => runLintProof,
|
|
10403
|
+
verifyLintProof: () => verifyLintProof,
|
|
10404
|
+
writeLintProof: () => writeLintProof
|
|
10200
10405
|
});
|
|
10201
10406
|
import {
|
|
10202
10407
|
createHash as createHash12,
|
|
@@ -14970,9 +15175,9 @@ var init_htmx = __esm(() => {
|
|
|
14970
15175
|
// src/cli/scripts/env.ts
|
|
14971
15176
|
var exports_env = {};
|
|
14972
15177
|
__export(exports_env, {
|
|
14973
|
-
|
|
15178
|
+
collectEnvVars: () => collectEnvVars,
|
|
14974
15179
|
runEnv: () => runEnv,
|
|
14975
|
-
|
|
15180
|
+
scanEnvUsage: () => scanEnvUsage
|
|
14976
15181
|
});
|
|
14977
15182
|
import { existsSync as existsSync33, readFileSync as readFileSync33 } from "fs";
|
|
14978
15183
|
import { join as join41 } from "path";
|
|
@@ -15036,12 +15241,12 @@ var init_env = __esm(() => {
|
|
|
15036
15241
|
// src/cli/scripts/db.ts
|
|
15037
15242
|
var exports_db = {};
|
|
15038
15243
|
__export(exports_db, {
|
|
15039
|
-
|
|
15040
|
-
quoteIdent: () => quoteIdent,
|
|
15041
|
-
encodeValue: () => encodeValue,
|
|
15042
|
-
dependencyOrder: () => dependencyOrder,
|
|
15244
|
+
chunkRows: () => chunkRows,
|
|
15043
15245
|
conflictClause: () => conflictClause,
|
|
15044
|
-
|
|
15246
|
+
dependencyOrder: () => dependencyOrder,
|
|
15247
|
+
encodeValue: () => encodeValue,
|
|
15248
|
+
quoteIdent: () => quoteIdent,
|
|
15249
|
+
runDb: () => runDb
|
|
15045
15250
|
});
|
|
15046
15251
|
import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync34, writeFileSync as writeFileSync18 } from "fs";
|
|
15047
15252
|
import { join as join42 } from "path";
|
|
@@ -16381,8 +16586,8 @@ var init_externalAssetPlugin = () => {};
|
|
|
16381
16586
|
// src/cli/scripts/compile.ts
|
|
16382
16587
|
var exports_compile = {};
|
|
16383
16588
|
__export(exports_compile, {
|
|
16384
|
-
|
|
16385
|
-
|
|
16589
|
+
compile: () => compile,
|
|
16590
|
+
shouldEmbedCompiledAsset: () => shouldEmbedCompiledAsset
|
|
16386
16591
|
});
|
|
16387
16592
|
var {env: env5 } = globalThis.Bun;
|
|
16388
16593
|
import {
|
|
@@ -18341,12 +18546,38 @@ import { mkdir as mkdir12, writeFile as writeFile14 } from "fs/promises";
|
|
|
18341
18546
|
import { dirname as dirname29, resolve as resolve38 } from "path";
|
|
18342
18547
|
|
|
18343
18548
|
class CdpConnection {
|
|
18344
|
-
|
|
18345
|
-
|
|
18346
|
-
#
|
|
18347
|
-
#nextId = 1;
|
|
18348
|
-
#pending = new Map;
|
|
18549
|
+
#closed;
|
|
18550
|
+
#nextId;
|
|
18551
|
+
#pending;
|
|
18349
18552
|
constructor(socket) {
|
|
18553
|
+
this.diagnostics = [];
|
|
18554
|
+
this.#closed = false;
|
|
18555
|
+
this.#nextId = 1;
|
|
18556
|
+
this.#pending = new Map;
|
|
18557
|
+
this.command = (method, params = {}, timeoutMs = CDP_COMMAND_TIMEOUT_MS) => {
|
|
18558
|
+
if (this.#closed) {
|
|
18559
|
+
return Promise.reject(new Error("Android WebView debugger is closed."));
|
|
18560
|
+
}
|
|
18561
|
+
const id = this.#nextId++;
|
|
18562
|
+
return new Promise((_resolve, reject) => {
|
|
18563
|
+
const timer = setTimeout(() => {
|
|
18564
|
+
this.#pending.delete(id);
|
|
18565
|
+
reject(new Error(`CDP ${method} timed out after ${timeoutMs}ms.`));
|
|
18566
|
+
}, timeoutMs);
|
|
18567
|
+
this.#pending.set(id, {
|
|
18568
|
+
reject,
|
|
18569
|
+
resolve: _resolve,
|
|
18570
|
+
timer
|
|
18571
|
+
});
|
|
18572
|
+
this.socket.send(JSON.stringify({ id, method, params }));
|
|
18573
|
+
});
|
|
18574
|
+
};
|
|
18575
|
+
this.close = async () => {
|
|
18576
|
+
if (this.#closed)
|
|
18577
|
+
return;
|
|
18578
|
+
this.#closed = true;
|
|
18579
|
+
this.socket.close();
|
|
18580
|
+
};
|
|
18350
18581
|
this.socket = socket;
|
|
18351
18582
|
socket.addEventListener("message", (event) => {
|
|
18352
18583
|
this.onMessage(event.data);
|
|
@@ -18425,30 +18656,6 @@ class CdpConnection {
|
|
|
18425
18656
|
}
|
|
18426
18657
|
pending.resolve(message.result);
|
|
18427
18658
|
}
|
|
18428
|
-
command = (method, params = {}, timeoutMs = CDP_COMMAND_TIMEOUT_MS) => {
|
|
18429
|
-
if (this.#closed) {
|
|
18430
|
-
return Promise.reject(new Error("Android WebView debugger is closed."));
|
|
18431
|
-
}
|
|
18432
|
-
const id = this.#nextId++;
|
|
18433
|
-
return new Promise((_resolve, reject) => {
|
|
18434
|
-
const timer = setTimeout(() => {
|
|
18435
|
-
this.#pending.delete(id);
|
|
18436
|
-
reject(new Error(`CDP ${method} timed out after ${timeoutMs}ms.`));
|
|
18437
|
-
}, timeoutMs);
|
|
18438
|
-
this.#pending.set(id, {
|
|
18439
|
-
reject,
|
|
18440
|
-
resolve: _resolve,
|
|
18441
|
-
timer
|
|
18442
|
-
});
|
|
18443
|
-
this.socket.send(JSON.stringify({ id, method, params }));
|
|
18444
|
-
});
|
|
18445
|
-
};
|
|
18446
|
-
close = async () => {
|
|
18447
|
-
if (this.#closed)
|
|
18448
|
-
return;
|
|
18449
|
-
this.#closed = true;
|
|
18450
|
-
this.socket.close();
|
|
18451
|
-
};
|
|
18452
18659
|
}
|
|
18453
18660
|
var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POLL_MS = 200, captureCommand3 = (command) => {
|
|
18454
18661
|
const result = Bun.spawnSync(command, {
|
|
@@ -20926,7 +21133,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
20926
21133
|
}, initialize = async (args) => {
|
|
20927
21134
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
20928
21135
|
if (mobile.engine === "expo") {
|
|
20929
|
-
console.warn("Experimental: Expo Auth
|
|
21136
|
+
console.warn("Experimental: Expo Auth and authenticated HTTP are available; Sync, release publishing, and physical-device acceptance are not complete.");
|
|
20930
21137
|
const generated2 = await writeAbsoluteExpoProject(mobile, {
|
|
20931
21138
|
force: args.includes("--force"),
|
|
20932
21139
|
projectRoot
|
|
@@ -23362,7 +23569,7 @@ init_expoProject();
|
|
|
23362
23569
|
init_iosPhysicalDeviceTransport();
|
|
23363
23570
|
import { spawn } from "child_process";
|
|
23364
23571
|
import { access as access2 } from "fs/promises";
|
|
23365
|
-
import { join as
|
|
23572
|
+
import { join as join7 } from "path";
|
|
23366
23573
|
var METRO_READY_TIMEOUT_MS = 60000;
|
|
23367
23574
|
var PROCESS_CLOSE_TIMEOUT_MS = 2000;
|
|
23368
23575
|
var commandEnvironment = (options) => ({
|
|
@@ -23371,10 +23578,11 @@ var commandEnvironment = (options) => ({
|
|
|
23371
23578
|
ABSOLUTE_EXPO_DEVELOPMENT_CA_PATH: options.certificateAuthorityPath
|
|
23372
23579
|
} : {},
|
|
23373
23580
|
...options.androidOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN: options.androidOrigin } : {},
|
|
23374
|
-
...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {}
|
|
23581
|
+
...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {},
|
|
23582
|
+
...options.metroHost ? { REACT_NATIVE_PACKAGER_HOSTNAME: options.metroHost } : {}
|
|
23375
23583
|
});
|
|
23376
23584
|
var absoluteExpoExecutable = async (project) => {
|
|
23377
|
-
const executable =
|
|
23585
|
+
const executable = join7(project, "node_modules", ".bin", "expo");
|
|
23378
23586
|
try {
|
|
23379
23587
|
await access2(executable);
|
|
23380
23588
|
return executable;
|
|
@@ -23385,8 +23593,8 @@ var absoluteExpoExecutable = async (project) => {
|
|
|
23385
23593
|
var planAbsoluteExpoDevSession = (config, options) => {
|
|
23386
23594
|
if (config.engine !== "expo")
|
|
23387
23595
|
throw new TypeError("The Expo development controller requires Expo.");
|
|
23388
|
-
if (options.platforms.length === 0)
|
|
23389
|
-
throw new TypeError("Expo
|
|
23596
|
+
if (options.platforms.length === 0 && options.metro === "external")
|
|
23597
|
+
throw new TypeError("External Expo execution requires a target platform.");
|
|
23390
23598
|
const secureOrigin = [options.androidOrigin, options.iosOrigin].some((origin) => origin && new URL(origin).protocol === "https:");
|
|
23391
23599
|
if (secureOrigin && !options.certificateAuthorityPath)
|
|
23392
23600
|
throw new TypeError("Expo HTTPS development requires the AbsoluteJS development CA certificate.");
|
|
@@ -23403,7 +23611,7 @@ var planAbsoluteExpoDevSession = (config, options) => {
|
|
|
23403
23611
|
env,
|
|
23404
23612
|
role: "metro"
|
|
23405
23613
|
};
|
|
23406
|
-
const prepare = {
|
|
23614
|
+
const prepare = options.platforms.length === 0 ? undefined : {
|
|
23407
23615
|
args: [
|
|
23408
23616
|
"prebuild",
|
|
23409
23617
|
"--clean",
|
|
@@ -23431,7 +23639,11 @@ var planAbsoluteExpoDevSession = (config, options) => {
|
|
|
23431
23639
|
return command;
|
|
23432
23640
|
});
|
|
23433
23641
|
return {
|
|
23434
|
-
commands: [
|
|
23642
|
+
commands: [
|
|
23643
|
+
...prepare ? [prepare] : [],
|
|
23644
|
+
...options.metro === "external" ? [] : [metro],
|
|
23645
|
+
...native
|
|
23646
|
+
],
|
|
23435
23647
|
metroPort: options.metroPort,
|
|
23436
23648
|
project: config.nativeProjectDirectory
|
|
23437
23649
|
};
|
|
@@ -23520,47 +23732,48 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23520
23732
|
const prepareCommand = plan.commands.find((command) => command.role === "native-prepare");
|
|
23521
23733
|
const metroCommand = plan.commands.find((command) => command.role === "metro");
|
|
23522
23734
|
const nativeCommands = plan.commands.filter((command) => command.role === "native-build");
|
|
23523
|
-
|
|
23524
|
-
|
|
23525
|
-
|
|
23526
|
-
|
|
23527
|
-
|
|
23528
|
-
|
|
23529
|
-
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23533
|
-
|
|
23534
|
-
|
|
23535
|
-
|
|
23536
|
-
|
|
23537
|
-
|
|
23538
|
-
|
|
23539
|
-
|
|
23540
|
-
|
|
23541
|
-
|
|
23542
|
-
|
|
23543
|
-
|
|
23544
|
-
|
|
23545
|
-
|
|
23546
|
-
|
|
23547
|
-
|
|
23548
|
-
|
|
23549
|
-
|
|
23550
|
-
|
|
23551
|
-
|
|
23552
|
-
phase: "preparing-native"
|
|
23553
|
-
});
|
|
23554
|
-
setState("starting-metro");
|
|
23735
|
+
const runPrepareCommand = async (command) => {
|
|
23736
|
+
setState("preparing-native");
|
|
23737
|
+
const prepareStarted = performance.now();
|
|
23738
|
+
const prepareProcess = run(executable, command.args, {
|
|
23739
|
+
cwd: plan.project,
|
|
23740
|
+
env: { ...process.env, ...command.env },
|
|
23741
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
23742
|
+
});
|
|
23743
|
+
forwardLines(prepareProcess, (line) => {
|
|
23744
|
+
if (line)
|
|
23745
|
+
log(`[prebuild] ${line}`);
|
|
23746
|
+
});
|
|
23747
|
+
const abortPrepare = () => void stopProcess(prepareProcess);
|
|
23748
|
+
options.signal?.addEventListener("abort", abortPrepare, { once: true });
|
|
23749
|
+
const prepareExit = await waitForExit(prepareProcess);
|
|
23750
|
+
options.signal?.removeEventListener("abort", abortPrepare);
|
|
23751
|
+
if (options.signal?.aborted)
|
|
23752
|
+
throw abortError();
|
|
23753
|
+
if (prepareExit !== 0) {
|
|
23754
|
+
setState("failed");
|
|
23755
|
+
throw new Error(`Expo native preparation exited with status ${prepareExit}.`);
|
|
23756
|
+
}
|
|
23757
|
+
publishTiming("preparing-native", performance.now() - prepareStarted);
|
|
23758
|
+
};
|
|
23759
|
+
if (prepareCommand)
|
|
23760
|
+
await runPrepareCommand(prepareCommand);
|
|
23761
|
+
const managedMetro = metroCommand !== undefined;
|
|
23762
|
+
if (managedMetro)
|
|
23763
|
+
setState("starting-metro");
|
|
23555
23764
|
const metroStarted = performance.now();
|
|
23556
|
-
const metro = run(executable, metroCommand.args, {
|
|
23765
|
+
const metro = metroCommand ? run(executable, metroCommand.args, {
|
|
23557
23766
|
cwd: plan.project,
|
|
23558
23767
|
env: { ...process.env, ...metroCommand.env },
|
|
23559
23768
|
stdio: ["ignore", "pipe", "pipe"]
|
|
23560
|
-
});
|
|
23769
|
+
}) : undefined;
|
|
23561
23770
|
let metroReady = false;
|
|
23562
23771
|
let resolveMetro;
|
|
23563
23772
|
const metroPromise = new Promise((resolve4, reject) => {
|
|
23773
|
+
if (!metro) {
|
|
23774
|
+
resolve4();
|
|
23775
|
+
return;
|
|
23776
|
+
}
|
|
23564
23777
|
const timeout = setTimeout(() => {
|
|
23565
23778
|
reject(new Error("Expo Metro did not become ready within 60 seconds."));
|
|
23566
23779
|
}, METRO_READY_TIMEOUT_MS);
|
|
@@ -23575,15 +23788,19 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23575
23788
|
}
|
|
23576
23789
|
});
|
|
23577
23790
|
});
|
|
23578
|
-
|
|
23579
|
-
|
|
23580
|
-
|
|
23581
|
-
|
|
23582
|
-
metroReady
|
|
23583
|
-
|
|
23584
|
-
|
|
23585
|
-
|
|
23586
|
-
|
|
23791
|
+
if (metro)
|
|
23792
|
+
forwardLines(metro, (line) => {
|
|
23793
|
+
if (line)
|
|
23794
|
+
log(`[metro] ${line}`);
|
|
23795
|
+
if (!metroReady && /(?:Waiting on|Metro waiting on|Dev server ready)/iu.test(line)) {
|
|
23796
|
+
metroReady = true;
|
|
23797
|
+
resolveMetro?.();
|
|
23798
|
+
}
|
|
23799
|
+
});
|
|
23800
|
+
const abort = () => {
|
|
23801
|
+
if (metro)
|
|
23802
|
+
stopProcess(metro);
|
|
23803
|
+
};
|
|
23587
23804
|
options.signal?.addEventListener("abort", abort, { once: true });
|
|
23588
23805
|
const runNativeCommand = async (command) => {
|
|
23589
23806
|
if (options.signal?.aborted)
|
|
@@ -23664,12 +23881,8 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23664
23881
|
try {
|
|
23665
23882
|
await startPhysicalIosEnrollment();
|
|
23666
23883
|
await metroPromise;
|
|
23667
|
-
|
|
23668
|
-
|
|
23669
|
-
options.onPhaseTiming?.({
|
|
23670
|
-
durationMs: metroMs,
|
|
23671
|
-
phase: "starting-metro"
|
|
23672
|
-
});
|
|
23884
|
+
if (managedMetro)
|
|
23885
|
+
publishTiming("starting-metro", performance.now() - metroStarted);
|
|
23673
23886
|
await runNativeCommands(nativeCommands);
|
|
23674
23887
|
setState("ready");
|
|
23675
23888
|
return {
|
|
@@ -23678,14 +23891,16 @@ var startAbsoluteExpoDevSession = async (options) => {
|
|
|
23678
23891
|
timings,
|
|
23679
23892
|
close: async () => {
|
|
23680
23893
|
options.signal?.removeEventListener("abort", abort);
|
|
23681
|
-
|
|
23894
|
+
if (metro)
|
|
23895
|
+
await stopProcess(metro);
|
|
23682
23896
|
await closeEnrollmentServer();
|
|
23683
23897
|
setState("closed");
|
|
23684
23898
|
}
|
|
23685
23899
|
};
|
|
23686
23900
|
} catch (error) {
|
|
23687
23901
|
options.signal?.removeEventListener("abort", abort);
|
|
23688
|
-
|
|
23902
|
+
if (metro)
|
|
23903
|
+
await stopProcess(metro);
|
|
23689
23904
|
await closeEnrollmentServer();
|
|
23690
23905
|
setState("failed");
|
|
23691
23906
|
throw error;
|
|
@@ -24092,9 +24307,6 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24092
24307
|
throw new TypeError("--ios-device requires ios in mobile.platforms.");
|
|
24093
24308
|
}
|
|
24094
24309
|
if (options.iosDevice) {
|
|
24095
|
-
if (mobileConfig?.engine === "expo" && detectAbsoluteMobileHost() !== "macos") {
|
|
24096
|
-
throw new Error("Expo physical iOS development currently requires local macOS; Expo Remote Mac execution is the next adapter milestone.");
|
|
24097
|
-
}
|
|
24098
24310
|
if (detectAbsoluteMobileHost() === "macos")
|
|
24099
24311
|
iosPhysicalServerHost = mobileReachableHost(resolvedDev.host);
|
|
24100
24312
|
else {
|
|
@@ -24138,6 +24350,7 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24138
24350
|
}
|
|
24139
24351
|
}
|
|
24140
24352
|
const platforms = [];
|
|
24353
|
+
let remoteIos;
|
|
24141
24354
|
if (normalized.platforms.includes("android")) {
|
|
24142
24355
|
const target = options.androidDevice ? "device" : "emulator";
|
|
24143
24356
|
let ready = androidToolchainReady(await inspectAbsoluteMobileToolchain(), target);
|
|
@@ -24153,7 +24366,14 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24153
24366
|
}
|
|
24154
24367
|
if (normalized.platforms.includes("ios")) {
|
|
24155
24368
|
if (detectAbsoluteMobileHost() !== "macos") {
|
|
24156
|
-
|
|
24369
|
+
const remote = selectedRemoteMacProfile ?? await getAbsoluteRemoteMacProfile();
|
|
24370
|
+
if (!remote) {
|
|
24371
|
+
console.log(cliTag("\x1B[33m", "Expo iOS target skipped. Pair a Mac with `absolute mobile pair mac <name> <user@host>`."));
|
|
24372
|
+
} else {
|
|
24373
|
+
selectedRemoteMacProfile = remote;
|
|
24374
|
+
remoteIos = createAbsoluteRemoteExpoIosDevProject(normalized, process.cwd(), remote);
|
|
24375
|
+
console.log(cliTag("\x1B[35m", `Using remote Mac ${remote.name} for Expo iOS development.`));
|
|
24376
|
+
}
|
|
24157
24377
|
} else {
|
|
24158
24378
|
const target = options.iosDevice ? "device" : "simulator";
|
|
24159
24379
|
let ready = iosToolchainReady(await inspectAbsoluteMobileToolchain(), target);
|
|
@@ -24168,13 +24388,17 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24168
24388
|
platforms.push("ios");
|
|
24169
24389
|
}
|
|
24170
24390
|
}
|
|
24171
|
-
if (platforms.length > 0) {
|
|
24391
|
+
if (platforms.length > 0 || remoteIos) {
|
|
24172
24392
|
expoDevProject = {
|
|
24173
24393
|
executable: await absoluteExpoExecutable(generated.path),
|
|
24174
24394
|
mobile: normalized,
|
|
24175
|
-
platforms
|
|
24395
|
+
platforms,
|
|
24396
|
+
...remoteIos ? { remoteIos } : {}
|
|
24176
24397
|
};
|
|
24177
|
-
console.log(cliTag("\x1B[35m", `Expo development build queued for ${
|
|
24398
|
+
console.log(cliTag("\x1B[35m", `Expo development build queued for ${[
|
|
24399
|
+
...platforms,
|
|
24400
|
+
...remoteIos ? ["ios (Remote Mac)"] : []
|
|
24401
|
+
].join(" + ")}; Metro and native launch will start with the Bun server.`));
|
|
24178
24402
|
}
|
|
24179
24403
|
} else if (normalized.platforms.includes("android")) {
|
|
24180
24404
|
const androidTarget = options.androidDevice ? "device" : "emulator";
|
|
@@ -24601,54 +24825,166 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
24601
24825
|
return;
|
|
24602
24826
|
}
|
|
24603
24827
|
const androidHost = options.androidDevice ? mobileReachableHost(resolvedDev.host) : "10.0.2.2";
|
|
24604
|
-
const iosHost = options.iosDevice ? mobileReachableHost(resolvedDev.host) : "localhost";
|
|
24605
|
-
|
|
24606
|
-
|
|
24607
|
-
|
|
24828
|
+
const iosHost = options.iosDevice ? iosPhysicalServerHost ?? mobileReachableHost(resolvedDev.host) : "localhost";
|
|
24829
|
+
const androidOrigin = project.platforms.includes("android") ? absoluteDevOrigin(androidHost) : undefined;
|
|
24830
|
+
const iosOrigin = project.platforms.includes("ios") || project.remoteIos ? absoluteDevOrigin(iosHost) : undefined;
|
|
24831
|
+
let metroSession;
|
|
24832
|
+
let localNativeSession;
|
|
24833
|
+
let remoteSession;
|
|
24834
|
+
const metroStart = startAbsoluteExpoDevSession({
|
|
24835
|
+
androidOrigin,
|
|
24608
24836
|
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24609
24837
|
config: project.mobile,
|
|
24610
24838
|
executable: project.executable,
|
|
24611
|
-
|
|
24612
|
-
iosOrigin: project.platforms.includes("ios") ? absoluteDevOrigin(iosHost) : undefined,
|
|
24839
|
+
iosOrigin,
|
|
24613
24840
|
metroPort: expoMetroPort,
|
|
24614
|
-
platforms:
|
|
24841
|
+
platforms: [],
|
|
24615
24842
|
signal: expoDevAbort.signal,
|
|
24616
24843
|
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo ${message}`)),
|
|
24617
24844
|
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24618
24845
|
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24619
24846
|
durationMs: Math.round(durationMs),
|
|
24847
|
+
host: detectAbsoluteMobileHost(),
|
|
24620
24848
|
phase,
|
|
24621
24849
|
platform: expoTelemetryPlatform(phase),
|
|
24622
24850
|
provider: "expo"
|
|
24623
24851
|
});
|
|
24624
24852
|
},
|
|
24625
24853
|
onStateChange: (state) => {
|
|
24626
|
-
expoDevState = state;
|
|
24627
24854
|
if (state === "ready" || state === "closed")
|
|
24628
24855
|
return;
|
|
24856
|
+
expoDevState = state;
|
|
24629
24857
|
printNativeOutput(cliTag("\x1B[35m", `Expo development: ${state}.`));
|
|
24630
24858
|
}
|
|
24631
|
-
}).then(
|
|
24859
|
+
}).then((session) => {
|
|
24860
|
+
metroSession = session;
|
|
24861
|
+
return session;
|
|
24862
|
+
});
|
|
24863
|
+
const localNativeStart = metroStart.then(async () => {
|
|
24864
|
+
if (project.platforms.length === 0)
|
|
24865
|
+
return;
|
|
24866
|
+
const session = await startAbsoluteExpoDevSession({
|
|
24867
|
+
androidDevice: options.androidDevice,
|
|
24868
|
+
androidOrigin,
|
|
24869
|
+
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24870
|
+
config: project.mobile,
|
|
24871
|
+
executable: project.executable,
|
|
24872
|
+
iosDevice: options.iosDevice,
|
|
24873
|
+
iosOrigin,
|
|
24874
|
+
metro: "external",
|
|
24875
|
+
metroPort: expoMetroPort,
|
|
24876
|
+
platforms: project.platforms,
|
|
24877
|
+
signal: expoDevAbort.signal,
|
|
24878
|
+
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo ${message}`)),
|
|
24879
|
+
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24880
|
+
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24881
|
+
durationMs: Math.round(durationMs),
|
|
24882
|
+
host: detectAbsoluteMobileHost(),
|
|
24883
|
+
phase,
|
|
24884
|
+
platform: expoTelemetryPlatform(phase),
|
|
24885
|
+
provider: "expo"
|
|
24886
|
+
});
|
|
24887
|
+
},
|
|
24888
|
+
onStateChange: (state) => {
|
|
24889
|
+
if (state === "ready" || state === "closed")
|
|
24890
|
+
return;
|
|
24891
|
+
expoDevState = state;
|
|
24892
|
+
printNativeOutput(cliTag("\x1B[35m", `Expo development: ${state}.`));
|
|
24893
|
+
}
|
|
24894
|
+
});
|
|
24895
|
+
localNativeSession = session;
|
|
24896
|
+
return session;
|
|
24897
|
+
});
|
|
24898
|
+
const remoteIosProject = project.remoteIos;
|
|
24899
|
+
const remoteStart = remoteIosProject ? metroStart.then(async () => {
|
|
24900
|
+
const session = await startAbsoluteRemoteExpoIosDevSession({
|
|
24901
|
+
certificateAuthorityPath: devCertificateAuthorityPath ?? undefined,
|
|
24902
|
+
deviceIdentifier: options.iosDevice,
|
|
24903
|
+
https: httpsEnabled,
|
|
24904
|
+
metroPort: expoMetroPort,
|
|
24905
|
+
port,
|
|
24906
|
+
project: remoteIosProject,
|
|
24907
|
+
serverHost: options.iosDevice ? iosPhysicalServerHost : undefined,
|
|
24908
|
+
signal: expoDevAbort.signal,
|
|
24909
|
+
log: (message) => printNativeOutput(cliTag("\x1B[35m", `Expo [remote-ios] ${message}`)),
|
|
24910
|
+
onPhaseTiming: ({ durationMs, phase }) => {
|
|
24911
|
+
sendTelemetryEvent("mobile:expo-dev-phase", {
|
|
24912
|
+
durationMs: Math.round(durationMs),
|
|
24913
|
+
host: "remote-macos",
|
|
24914
|
+
phase,
|
|
24915
|
+
platform: expoTelemetryPlatform(phase),
|
|
24916
|
+
provider: "expo"
|
|
24917
|
+
});
|
|
24918
|
+
},
|
|
24919
|
+
onStateChange: (state) => {
|
|
24920
|
+
if (state === "ready" || state === "closed")
|
|
24921
|
+
return;
|
|
24922
|
+
expoDevState = state;
|
|
24923
|
+
printNativeOutput(cliTag("\x1B[35m", `Expo Remote Mac iOS: ${state}.`));
|
|
24924
|
+
}
|
|
24925
|
+
});
|
|
24926
|
+
remoteSession = session;
|
|
24927
|
+
return session;
|
|
24928
|
+
}) : Promise.resolve(undefined);
|
|
24929
|
+
expoDevStart = Promise.all([metroStart, localNativeStart, remoteStart]).then(async ([metro, localNative, remote]) => {
|
|
24930
|
+
const session = {
|
|
24931
|
+
metroPort: metro.metroPort,
|
|
24932
|
+
platforms: [
|
|
24933
|
+
...new Set([
|
|
24934
|
+
...localNative?.platforms ?? [],
|
|
24935
|
+
...remote?.platforms ?? []
|
|
24936
|
+
])
|
|
24937
|
+
],
|
|
24938
|
+
timings: {
|
|
24939
|
+
...metro.timings,
|
|
24940
|
+
...localNative?.timings,
|
|
24941
|
+
...remote?.timings
|
|
24942
|
+
},
|
|
24943
|
+
close: async () => {
|
|
24944
|
+
await Promise.all([
|
|
24945
|
+
metro.close(),
|
|
24946
|
+
localNative?.close(),
|
|
24947
|
+
remote?.close()
|
|
24948
|
+
]);
|
|
24949
|
+
}
|
|
24950
|
+
};
|
|
24632
24951
|
if (cleaning) {
|
|
24633
24952
|
await session.close();
|
|
24634
24953
|
} else {
|
|
24635
24954
|
expoDevSession = session;
|
|
24955
|
+
expoDevState = "ready";
|
|
24636
24956
|
sendTelemetryEvent("mobile:expo-dev-ready", {
|
|
24637
24957
|
metroPort: session.metroPort,
|
|
24638
24958
|
platforms: session.platforms,
|
|
24639
24959
|
provider: "expo",
|
|
24960
|
+
remoteIos: project.remoteIos !== undefined,
|
|
24640
24961
|
timings: session.timings
|
|
24641
24962
|
});
|
|
24642
24963
|
printNativeOutput(cliTag("\x1B[35m", `Expo ${session.platforms.join(" + ")} connected; native Fast Refresh uses Metro on ${session.metroPort}, and AbsoluteJS pages use HMR on ${port}.`));
|
|
24643
24964
|
}
|
|
24644
24965
|
}).catch((error) => {
|
|
24966
|
+
expoDevAbort.abort();
|
|
24967
|
+
Promise.all([
|
|
24968
|
+
metroSession?.close().catch(() => {
|
|
24969
|
+
return;
|
|
24970
|
+
}),
|
|
24971
|
+
localNativeSession?.close().catch(() => {
|
|
24972
|
+
return;
|
|
24973
|
+
}),
|
|
24974
|
+
remoteSession?.close().catch(() => {
|
|
24975
|
+
return;
|
|
24976
|
+
})
|
|
24977
|
+
]);
|
|
24645
24978
|
expoDevState = "failed";
|
|
24646
24979
|
if (cleaning && error instanceof Error && error.name === "AbortError") {
|
|
24647
24980
|
return;
|
|
24648
24981
|
}
|
|
24649
24982
|
sendTelemetryEvent("mobile:expo-dev-failed", {
|
|
24650
24983
|
phase: expoDevState,
|
|
24651
|
-
platforms:
|
|
24984
|
+
platforms: [
|
|
24985
|
+
...project.platforms,
|
|
24986
|
+
...project.remoteIos ? ["ios"] : []
|
|
24987
|
+
],
|
|
24652
24988
|
provider: "expo"
|
|
24653
24989
|
});
|
|
24654
24990
|
console.error(cliTag("\x1B[31m", `Expo development failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
@@ -25186,7 +25522,10 @@ var dev = async (serverEntry, configPath2, options = {}) => {
|
|
|
25186
25522
|
console.log(cliTag("\x1B[35m", `iOS target: ${target}; HMR port ${port}.`));
|
|
25187
25523
|
}
|
|
25188
25524
|
if (expoDevProject) {
|
|
25189
|
-
console.log(cliTag("\x1B[35m", `Expo targets: ${
|
|
25525
|
+
console.log(cliTag("\x1B[35m", `Expo targets: ${[
|
|
25526
|
+
...expoDevProject.platforms,
|
|
25527
|
+
...expoDevProject.remoteIos ? ["ios (Remote Mac)"] : []
|
|
25528
|
+
].join(", ")}; state ${expoDevState}; Metro ${expoMetroPort ?? "not allocated"}; AbsoluteJS HMR ${port}.`));
|
|
25190
25529
|
}
|
|
25191
25530
|
},
|
|
25192
25531
|
relaunchDevice: async () => {
|