@absolutejs/absolute 0.20.0-beta.43 → 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 +275 -161
- 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 +552 -423
- package/dist/mobile/index.js.map +9 -9
- package/dist/mobile/remoteMacAgentEntry.js +115 -37
- 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/nativeAuth.d.ts +3 -0
- 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";
|
|
@@ -5178,13 +5284,13 @@ var init_remoteMacProtocol = __esm(() => {
|
|
|
5178
5284
|
// src/dev/devCert.ts
|
|
5179
5285
|
var exports_devCert = {};
|
|
5180
5286
|
__export(exports_devCert, {
|
|
5181
|
-
|
|
5182
|
-
normalizeDevCertificateHosts: () => normalizeDevCertificateHosts,
|
|
5183
|
-
loadDevCert: () => loadDevCert,
|
|
5184
|
-
hasMkcert: () => hasMkcert,
|
|
5185
|
-
hasCert: () => hasCert,
|
|
5287
|
+
ensureDevCert: () => ensureDevCert,
|
|
5186
5288
|
getDevCertificateAuthorityPath: () => getDevCertificateAuthorityPath,
|
|
5187
|
-
|
|
5289
|
+
hasCert: () => hasCert,
|
|
5290
|
+
hasMkcert: () => hasMkcert,
|
|
5291
|
+
loadDevCert: () => loadDevCert,
|
|
5292
|
+
normalizeDevCertificateHosts: () => normalizeDevCertificateHosts,
|
|
5293
|
+
setupMkcert: () => setupMkcert
|
|
5188
5294
|
});
|
|
5189
5295
|
import {
|
|
5190
5296
|
copyFileSync,
|
|
@@ -5492,13 +5598,13 @@ var init_devCert = __esm(() => {
|
|
|
5492
5598
|
// src/cli/scripts/eslintChunked.ts
|
|
5493
5599
|
var exports_eslintChunked = {};
|
|
5494
5600
|
__export(exports_eslintChunked, {
|
|
5495
|
-
|
|
5496
|
-
ruleSummary: () => ruleSummary,
|
|
5497
|
-
resolveLintTargets: () => resolveLintTargets,
|
|
5498
|
-
parseChunkedArgs: () => parseChunkedArgs,
|
|
5499
|
-
gitVisibleFiles: () => gitVisibleFiles,
|
|
5601
|
+
eslintChunked: () => eslintChunked,
|
|
5500
5602
|
gitChangedFiles: () => gitChangedFiles,
|
|
5501
|
-
|
|
5603
|
+
gitVisibleFiles: () => gitVisibleFiles,
|
|
5604
|
+
parseChunkedArgs: () => parseChunkedArgs,
|
|
5605
|
+
resolveLintTargets: () => resolveLintTargets,
|
|
5606
|
+
ruleSummary: () => ruleSummary,
|
|
5607
|
+
upstreamRef: () => upstreamRef
|
|
5502
5608
|
});
|
|
5503
5609
|
import { existsSync as existsSync6 } from "fs";
|
|
5504
5610
|
import { relative as relative7, resolve as resolve9 } from "path";
|
|
@@ -7144,6 +7250,11 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
7144
7250
|
if (candidate)
|
|
7145
7251
|
return candidate;
|
|
7146
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.");
|
|
7147
7258
|
}, shellSyncModule = () => {
|
|
7148
7259
|
const candidate = ["js", "ts"].map((extension) => join19(import.meta.dir, `shellSync.${extension}`)).find(existsSync9);
|
|
7149
7260
|
if (candidate)
|
|
@@ -7217,9 +7328,10 @@ var MANIFEST_FILE = "absolute-mobile-manifest.json", BOOTSTRAP_FILE = "absolute-
|
|
|
7217
7328
|
const capacitor = engine !== "expo";
|
|
7218
7329
|
const shellCapabilities = capacitor ? deviceCapabilities.capabilities : [];
|
|
7219
7330
|
const modulePath = shellBootstrapModule();
|
|
7220
|
-
const
|
|
7331
|
+
const authFactory = capacitor ? "createAbsoluteMobileShellAuth" : "createAbsoluteExpoShellAuth";
|
|
7332
|
+
const authImport = auth ? `import { ${authFactory} } from ${JSON.stringify(capacitor ? shellAuthModule() : shellExpoAuthModule())};
|
|
7221
7333
|
` : "";
|
|
7222
|
-
const options = auth ? `{ createAuth:
|
|
7334
|
+
const options = auth ? `{ createAuth: ${authFactory}${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
|
|
7223
7335
|
const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
|
|
7224
7336
|
` : "";
|
|
7225
7337
|
const pushIndex = shellCapabilities.indexOf("pushNotifications");
|
|
@@ -7241,7 +7353,7 @@ const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absolu
|
|
|
7241
7353
|
const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
|
|
7242
7354
|
const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
|
|
7243
7355
|
const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : "installAbsoluteExpoWebDeviceAdapter();";
|
|
7244
|
-
let shellOptions = "{ createFetch: createAbsoluteExpoBridgeFetch }";
|
|
7356
|
+
let shellOptions = auth ? options : "{ createFetch: createAbsoluteExpoBridgeFetch }";
|
|
7245
7357
|
if (capacitor)
|
|
7246
7358
|
shellOptions = options;
|
|
7247
7359
|
if (push) {
|
|
@@ -8327,10 +8439,10 @@ var isElysiaApp = (value) => typeof value === "object" && value !== null && type
|
|
|
8327
8439
|
runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
|
|
8328
8440
|
});
|
|
8329
8441
|
const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
|
|
8330
|
-
if (mobile.engine === "expo" && auth) {
|
|
8331
|
-
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.");
|
|
8332
|
-
}
|
|
8333
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
|
+
}
|
|
8334
8446
|
const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
|
|
8335
8447
|
const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
|
|
8336
8448
|
const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
|
|
@@ -8956,12 +9068,12 @@ var init_serverBundleExternals = __esm(() => {
|
|
|
8956
9068
|
// src/core/prerender.ts
|
|
8957
9069
|
var exports_prerender = {};
|
|
8958
9070
|
__export(exports_prerender, {
|
|
8959
|
-
|
|
8960
|
-
rerenderRoute: () => rerenderRoute,
|
|
8961
|
-
readTimestamp: () => readTimestamp,
|
|
8962
|
-
prerenderWithServer: () => prerenderWithServer,
|
|
9071
|
+
PRERENDER_BYPASS_HEADER: () => PRERENDER_BYPASS_HEADER,
|
|
8963
9072
|
prerender: () => prerender,
|
|
8964
|
-
|
|
9073
|
+
prerenderWithServer: () => prerenderWithServer,
|
|
9074
|
+
readTimestamp: () => readTimestamp,
|
|
9075
|
+
rerenderRoute: () => rerenderRoute,
|
|
9076
|
+
routeToFilename: () => routeToFilename
|
|
8965
9077
|
});
|
|
8966
9078
|
import { mkdirSync as mkdirSync6, readFileSync as readFileSync14 } from "fs";
|
|
8967
9079
|
import { join as join24 } from "path";
|
|
@@ -9621,8 +9733,8 @@ var init_rewriteImportsPlugin = __esm(() => {
|
|
|
9621
9733
|
// src/build/rewriteImports.ts
|
|
9622
9734
|
var exports_rewriteImports = {};
|
|
9623
9735
|
__export(exports_rewriteImports, {
|
|
9624
|
-
|
|
9625
|
-
|
|
9736
|
+
rewriteImports: () => rewriteImports,
|
|
9737
|
+
rewriteVendorDirectories: () => rewriteVendorDirectories2
|
|
9626
9738
|
});
|
|
9627
9739
|
var rewriteImports = async (outputPaths, vendorPaths) => {
|
|
9628
9740
|
const jsFiles = outputPaths.filter((path) => path.endsWith(".js"));
|
|
@@ -10285,11 +10397,11 @@ var init_build = __esm(() => {
|
|
|
10285
10397
|
// src/cli/scripts/lintProof.ts
|
|
10286
10398
|
var exports_lintProof = {};
|
|
10287
10399
|
__export(exports_lintProof, {
|
|
10288
|
-
|
|
10289
|
-
verifyLintProof: () => verifyLintProof,
|
|
10290
|
-
runLintProof: () => runLintProof,
|
|
10400
|
+
createLintProof: () => createLintProof,
|
|
10291
10401
|
createLintSourceTree: () => createLintSourceTree,
|
|
10292
|
-
|
|
10402
|
+
runLintProof: () => runLintProof,
|
|
10403
|
+
verifyLintProof: () => verifyLintProof,
|
|
10404
|
+
writeLintProof: () => writeLintProof
|
|
10293
10405
|
});
|
|
10294
10406
|
import {
|
|
10295
10407
|
createHash as createHash12,
|
|
@@ -15063,9 +15175,9 @@ var init_htmx = __esm(() => {
|
|
|
15063
15175
|
// src/cli/scripts/env.ts
|
|
15064
15176
|
var exports_env = {};
|
|
15065
15177
|
__export(exports_env, {
|
|
15066
|
-
|
|
15178
|
+
collectEnvVars: () => collectEnvVars,
|
|
15067
15179
|
runEnv: () => runEnv,
|
|
15068
|
-
|
|
15180
|
+
scanEnvUsage: () => scanEnvUsage
|
|
15069
15181
|
});
|
|
15070
15182
|
import { existsSync as existsSync33, readFileSync as readFileSync33 } from "fs";
|
|
15071
15183
|
import { join as join41 } from "path";
|
|
@@ -15129,12 +15241,12 @@ var init_env = __esm(() => {
|
|
|
15129
15241
|
// src/cli/scripts/db.ts
|
|
15130
15242
|
var exports_db = {};
|
|
15131
15243
|
__export(exports_db, {
|
|
15132
|
-
|
|
15133
|
-
quoteIdent: () => quoteIdent,
|
|
15134
|
-
encodeValue: () => encodeValue,
|
|
15135
|
-
dependencyOrder: () => dependencyOrder,
|
|
15244
|
+
chunkRows: () => chunkRows,
|
|
15136
15245
|
conflictClause: () => conflictClause,
|
|
15137
|
-
|
|
15246
|
+
dependencyOrder: () => dependencyOrder,
|
|
15247
|
+
encodeValue: () => encodeValue,
|
|
15248
|
+
quoteIdent: () => quoteIdent,
|
|
15249
|
+
runDb: () => runDb
|
|
15138
15250
|
});
|
|
15139
15251
|
import { existsSync as existsSync34, mkdirSync as mkdirSync15, readFileSync as readFileSync34, writeFileSync as writeFileSync18 } from "fs";
|
|
15140
15252
|
import { join as join42 } from "path";
|
|
@@ -16474,8 +16586,8 @@ var init_externalAssetPlugin = () => {};
|
|
|
16474
16586
|
// src/cli/scripts/compile.ts
|
|
16475
16587
|
var exports_compile = {};
|
|
16476
16588
|
__export(exports_compile, {
|
|
16477
|
-
|
|
16478
|
-
|
|
16589
|
+
compile: () => compile,
|
|
16590
|
+
shouldEmbedCompiledAsset: () => shouldEmbedCompiledAsset
|
|
16479
16591
|
});
|
|
16480
16592
|
var {env: env5 } = globalThis.Bun;
|
|
16481
16593
|
import {
|
|
@@ -18434,12 +18546,38 @@ import { mkdir as mkdir12, writeFile as writeFile14 } from "fs/promises";
|
|
|
18434
18546
|
import { dirname as dirname29, resolve as resolve38 } from "path";
|
|
18435
18547
|
|
|
18436
18548
|
class CdpConnection {
|
|
18437
|
-
|
|
18438
|
-
|
|
18439
|
-
#
|
|
18440
|
-
#nextId = 1;
|
|
18441
|
-
#pending = new Map;
|
|
18549
|
+
#closed;
|
|
18550
|
+
#nextId;
|
|
18551
|
+
#pending;
|
|
18442
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
|
+
};
|
|
18443
18581
|
this.socket = socket;
|
|
18444
18582
|
socket.addEventListener("message", (event) => {
|
|
18445
18583
|
this.onMessage(event.data);
|
|
@@ -18518,30 +18656,6 @@ class CdpConnection {
|
|
|
18518
18656
|
}
|
|
18519
18657
|
pending.resolve(message.result);
|
|
18520
18658
|
}
|
|
18521
|
-
command = (method, params = {}, timeoutMs = CDP_COMMAND_TIMEOUT_MS) => {
|
|
18522
|
-
if (this.#closed) {
|
|
18523
|
-
return Promise.reject(new Error("Android WebView debugger is closed."));
|
|
18524
|
-
}
|
|
18525
|
-
const id = this.#nextId++;
|
|
18526
|
-
return new Promise((_resolve, reject) => {
|
|
18527
|
-
const timer = setTimeout(() => {
|
|
18528
|
-
this.#pending.delete(id);
|
|
18529
|
-
reject(new Error(`CDP ${method} timed out after ${timeoutMs}ms.`));
|
|
18530
|
-
}, timeoutMs);
|
|
18531
|
-
this.#pending.set(id, {
|
|
18532
|
-
reject,
|
|
18533
|
-
resolve: _resolve,
|
|
18534
|
-
timer
|
|
18535
|
-
});
|
|
18536
|
-
this.socket.send(JSON.stringify({ id, method, params }));
|
|
18537
|
-
});
|
|
18538
|
-
};
|
|
18539
|
-
close = async () => {
|
|
18540
|
-
if (this.#closed)
|
|
18541
|
-
return;
|
|
18542
|
-
this.#closed = true;
|
|
18543
|
-
this.socket.close();
|
|
18544
|
-
};
|
|
18545
18659
|
}
|
|
18546
18660
|
var CDP_COMMAND_TIMEOUT_MS = 1e4, WEBVIEW_ATTACH_TIMEOUT_MS = 30000, WEBVIEW_POLL_MS = 200, captureCommand3 = (command) => {
|
|
18547
18661
|
const result = Bun.spawnSync(command, {
|
|
@@ -21019,7 +21133,7 @@ var NOT_FOUND4 = -1, isRecord15 = (value) => typeof value === "object" && value
|
|
|
21019
21133
|
}, initialize = async (args) => {
|
|
21020
21134
|
const { mobile, projectRoot } = await loadMobile(valueAfter(args, "--config"));
|
|
21021
21135
|
if (mobile.engine === "expo") {
|
|
21022
|
-
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.");
|
|
21023
21137
|
const generated2 = await writeAbsoluteExpoProject(mobile, {
|
|
21024
21138
|
force: args.includes("--force"),
|
|
21025
21139
|
projectRoot
|
|
@@ -23455,7 +23569,7 @@ init_expoProject();
|
|
|
23455
23569
|
init_iosPhysicalDeviceTransport();
|
|
23456
23570
|
import { spawn } from "child_process";
|
|
23457
23571
|
import { access as access2 } from "fs/promises";
|
|
23458
|
-
import { join as
|
|
23572
|
+
import { join as join7 } from "path";
|
|
23459
23573
|
var METRO_READY_TIMEOUT_MS = 60000;
|
|
23460
23574
|
var PROCESS_CLOSE_TIMEOUT_MS = 2000;
|
|
23461
23575
|
var commandEnvironment = (options) => ({
|
|
@@ -23468,7 +23582,7 @@ var commandEnvironment = (options) => ({
|
|
|
23468
23582
|
...options.metroHost ? { REACT_NATIVE_PACKAGER_HOSTNAME: options.metroHost } : {}
|
|
23469
23583
|
});
|
|
23470
23584
|
var absoluteExpoExecutable = async (project) => {
|
|
23471
|
-
const executable =
|
|
23585
|
+
const executable = join7(project, "node_modules", ".bin", "expo");
|
|
23472
23586
|
try {
|
|
23473
23587
|
await access2(executable);
|
|
23474
23588
|
return executable;
|