@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.
Files changed (78) hide show
  1. package/dist/angular/browser.js +378 -361
  2. package/dist/angular/browser.js.map +2 -2
  3. package/dist/angular/components/core/streamingSlotRegistrar.js +7 -7
  4. package/dist/angular/components/core/streamingSlotRegistry.js +4 -4
  5. package/dist/angular/index.js +300 -294
  6. package/dist/angular/index.js.map +2 -2
  7. package/dist/angular/server.js +54 -50
  8. package/dist/angular/server.js.map +2 -2
  9. package/dist/build.js +199 -203
  10. package/dist/build.js.map +2 -2
  11. package/dist/cli/config/client.js +12 -12
  12. package/dist/cli/config/server.js +1096 -1090
  13. package/dist/cli/index.js +595 -256
  14. package/dist/client/index.js +29 -25
  15. package/dist/client/index.js.map +2 -2
  16. package/dist/core/streamingSlotRegistrar.js +15 -13
  17. package/dist/core/streamingSlotRegistrar.js.map +2 -2
  18. package/dist/core/streamingSlotRegistry.js +11 -9
  19. package/dist/core/streamingSlotRegistry.js.map +2 -2
  20. package/dist/image-client/imageClient.js +7 -7
  21. package/dist/index.js +782 -732
  22. package/dist/index.js.map +6 -5
  23. package/dist/islands/browser.js +11 -9
  24. package/dist/islands/browser.js.map +2 -2
  25. package/dist/islands/index.js +39 -35
  26. package/dist/islands/index.js.map +2 -2
  27. package/dist/mobile/browser.js +23 -22
  28. package/dist/mobile/browser.js.map +2 -2
  29. package/dist/mobile/index.js +724 -488
  30. package/dist/mobile/index.js.map +12 -12
  31. package/dist/mobile/remoteMacAgentEntry.js +413 -14
  32. package/dist/mobile/shellBootstrap.js +0 -1
  33. package/dist/mobile/shellExpoAuth.js +184 -0
  34. package/dist/mobile/shellExpoDevices.js +4 -5
  35. package/dist/mobile/shellSync.js +4 -4
  36. package/dist/react/browser.js +17 -15
  37. package/dist/react/browser.js.map +2 -2
  38. package/dist/react/components/browser/index.js +107 -107
  39. package/dist/react/components/index.js +118 -116
  40. package/dist/react/components/index.js.map +2 -2
  41. package/dist/react/hooks/index.js +11 -9
  42. package/dist/react/hooks/index.js.map +2 -2
  43. package/dist/react/index.js +53 -49
  44. package/dist/react/index.js.map +2 -2
  45. package/dist/react/jsxDevRuntimeCompat.js +11 -9
  46. package/dist/react/jsxDevRuntimeCompat.js.map +2 -2
  47. package/dist/react/jsxRuntimeCompat.js +11 -9
  48. package/dist/react/jsxRuntimeCompat.js.map +2 -2
  49. package/dist/react/router/browser.js +9 -7
  50. package/dist/react/router/browser.js.map +2 -2
  51. package/dist/react/router/index.js +9 -7
  52. package/dist/react/router/index.js.map +2 -2
  53. package/dist/react/server.js +12 -10
  54. package/dist/react/server.js.map +2 -2
  55. package/dist/src/mobile/devDeviceAdapter.d.ts +1 -1
  56. package/dist/src/mobile/expoBridge.d.ts +12 -12
  57. package/dist/src/mobile/expoDevController.d.ts +8 -4
  58. package/dist/src/mobile/nativeAuth.d.ts +3 -0
  59. package/dist/src/mobile/remoteMacProtocol.d.ts +27 -0
  60. package/dist/src/mobile/remoteMacWire.d.ts +1 -1
  61. package/dist/src/mobile/shellExpoAuth.d.ts +12 -0
  62. package/dist/svelte/browser.js +12 -10
  63. package/dist/svelte/browser.js.map +2 -2
  64. package/dist/svelte/index.js +47 -43
  65. package/dist/svelte/index.js.map +2 -2
  66. package/dist/svelte/server.js +29 -27
  67. package/dist/svelte/server.js.map +2 -2
  68. package/dist/vue/browser.js +14 -12
  69. package/dist/vue/browser.js.map +2 -2
  70. package/dist/vue/components/Image.js +9 -7
  71. package/dist/vue/components/Image.js.map +2 -2
  72. package/dist/vue/components/index.js +11 -9
  73. package/dist/vue/components/index.js.map +2 -2
  74. package/dist/vue/index.js +52 -48
  75. package/dist/vue/index.js.map +2 -2
  76. package/dist/vue/server.js +14 -12
  77. package/dist/vue/server.js.map +2 -2
  78. package/package.json +1 -1
@@ -19,12 +19,14 @@ var __toESM = (mod, isNodeMode, target) => {
19
19
  }
20
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
21
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
- for (let key of __getOwnPropNames(mod))
23
- if (!__hasOwnProp.call(to, key))
24
- __defProp(to, key, {
25
- get: __accessProp.bind(mod, key),
26
- enumerable: true
27
- });
22
+ if (mod && typeof mod === "object" || typeof mod === "function") {
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ }
28
30
  if (canCache)
29
31
  cache.set(mod, to);
30
32
  return to;
@@ -163,6 +165,137 @@ var init_startupBanner = __esm(() => {
163
165
  ];
164
166
  });
165
167
 
168
+ // src/mobile/config.ts
169
+ import { resolve as resolve6 } from "path";
170
+ var APP_ID_PATTERN, SCHEME_PATTERN, APPLE_APP_ID_PREFIX_PATTERN, CERTIFICATE_FINGERPRINT_PATTERN, HOSTNAME_PATTERN, resolveProjectPath = (projectRoot, value, field2) => {
171
+ const root = resolve6(projectRoot);
172
+ const path = resolve6(root, value);
173
+ if (path !== root && !path.startsWith(`${root}/`)) {
174
+ throw new TypeError(`${field2} must remain inside the project root.`);
175
+ }
176
+ return path;
177
+ }, requireText = (value, field2) => {
178
+ const normalized = value.trim();
179
+ if (!normalized)
180
+ throw new TypeError(`${field2} must not be empty.`);
181
+ return normalized;
182
+ }, normalizeEntry = (entry) => {
183
+ const normalized = requireText(entry ?? "/", "mobile.entry");
184
+ if (!normalized.startsWith("/") || normalized.startsWith("//")) {
185
+ throw new TypeError("mobile.entry must be an absolute application path.");
186
+ }
187
+ return normalized;
188
+ }, normalizeProductionOrigin = (value) => {
189
+ const parsed = new URL(requireText(value, "mobile.server.productionOrigin"));
190
+ const isLoopbackHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]");
191
+ if (parsed.protocol !== "https:" && !isLoopbackHttp) {
192
+ throw new TypeError("mobile.server.productionOrigin must use HTTPS, except for a loopback development origin.");
193
+ }
194
+ if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
195
+ throw new TypeError("mobile.server.productionOrigin must be an origin without credentials, path, query, or hash.");
196
+ }
197
+ return parsed.origin;
198
+ }, normalizePlatforms = (platforms) => {
199
+ const normalized = [
200
+ ...new Set(platforms ?? ["ios", "android"])
201
+ ];
202
+ if (normalized.length === 0) {
203
+ throw new TypeError("mobile.platforms must contain at least one platform.");
204
+ }
205
+ return normalized;
206
+ }, normalizeHosts = (hosts, productionOrigin) => {
207
+ const normalizeHostname = (host) => {
208
+ const value = requireText(host, "mobile.deepLinks.hosts").toLowerCase();
209
+ if (!HOSTNAME_PATTERN.test(value)) {
210
+ throw new TypeError("mobile.deepLinks.hosts entries must be valid hostnames without ports, wildcards, or paths.");
211
+ }
212
+ return value;
213
+ };
214
+ const productionHostname = new URL(productionOrigin).hostname;
215
+ const normalized = new Set(productionHostname === "[::1]" ? [] : [normalizeHostname(productionHostname)]);
216
+ for (const host of hosts ?? []) {
217
+ normalized.add(normalizeHostname(host));
218
+ }
219
+ return [...normalized].sort();
220
+ }, normalizeAppleAppIdPrefix = (value) => {
221
+ if (value === undefined)
222
+ return;
223
+ const normalized = requireText(value, "mobile.deepLinks.apple.appIdPrefix").toUpperCase();
224
+ if (!APPLE_APP_ID_PREFIX_PATTERN.test(normalized)) {
225
+ throw new TypeError("mobile.deepLinks.apple.appIdPrefix must contain ten letters or digits.");
226
+ }
227
+ return normalized;
228
+ }, normalizeIosVersion = (value) => {
229
+ if (value === undefined)
230
+ return;
231
+ const normalized = requireText(value, "mobile.ios.version");
232
+ if (!/^\d+(?:\.\d+){0,2}$/u.test(normalized)) {
233
+ throw new TypeError("mobile.ios.version must contain one to three dot-separated integer components, for example 1.4.0.");
234
+ }
235
+ return normalized;
236
+ }, normalizeCertificateFingerprints = (values) => [
237
+ ...new Set((values ?? []).map((value) => requireText(value, "mobile.deepLinks.android.sha256CertificateFingerprints").replaceAll(":", "").toUpperCase()).map((value) => {
238
+ if (!CERTIFICATE_FINGERPRINT_PATTERN.test(value)) {
239
+ throw new TypeError("mobile.deepLinks.android.sha256CertificateFingerprints entries must be SHA-256 certificate fingerprints.");
240
+ }
241
+ return value.match(/.{2}/g)?.join(":") ?? value;
242
+ }))
243
+ ].sort(), normalizeExpoNativeRoutes = (config, projectRoot) => {
244
+ if (config.engine !== "expo")
245
+ return {};
246
+ const routes = config.routes?.native ?? {};
247
+ const normalized = {};
248
+ for (const [route, module] of Object.entries(routes)) {
249
+ const path = normalizeEntry(route);
250
+ if (path.includes("?") || path.includes("#") || path !== "/" && path.endsWith("/")) {
251
+ throw new TypeError(`mobile.routes.native route ${path} must be a canonical path without a query, fragment, or trailing slash.`);
252
+ }
253
+ if (path === "/__absolute/native") {
254
+ throw new TypeError("mobile.routes.native reserves /__absolute/native for the Expo diagnostic screen.");
255
+ }
256
+ if (path.includes("*") || path.includes(":")) {
257
+ throw new TypeError(`mobile.routes.native route ${path} must be static during the Expo experiment; parameters and wildcards are not supported yet.`);
258
+ }
259
+ normalized[path] = resolveProjectPath(projectRoot, requireText(module, `mobile.routes.native[${path}]`), `mobile.routes.native[${path}]`);
260
+ }
261
+ return Object.fromEntries(Object.entries(normalized).sort(([left], [right]) => left.localeCompare(right)));
262
+ }, normalizeAbsoluteMobileConfig = (config, projectRoot) => {
263
+ const appId = requireText(config.appId, "mobile.appId");
264
+ if (!APP_ID_PATTERN.test(appId)) {
265
+ throw new TypeError("mobile.appId must use reverse-domain notation, for example com.example.app.");
266
+ }
267
+ const productionOrigin = normalizeProductionOrigin(config.server.productionOrigin);
268
+ const deepLinkScheme = (config.deepLinks?.scheme ?? appId).trim().toLowerCase();
269
+ if (deepLinkScheme && !SCHEME_PATTERN.test(deepLinkScheme)) {
270
+ throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
271
+ }
272
+ return {
273
+ androidCertificateFingerprints: normalizeCertificateFingerprints(config.deepLinks?.android?.sha256CertificateFingerprints),
274
+ appId,
275
+ appleAppIdPrefix: normalizeAppleAppIdPrefix(config.deepLinks?.apple?.appIdPrefix),
276
+ appName: requireText(config.appName, "mobile.appName"),
277
+ bundleDirectory: resolveProjectPath(projectRoot, config.bundleDirectory ?? ".absolutejs/mobile/web", "mobile.bundleDirectory"),
278
+ deepLinkHosts: normalizeHosts(config.deepLinks?.hosts, productionOrigin),
279
+ deepLinkScheme,
280
+ engine: config.engine ?? "capacitor",
281
+ entry: normalizeEntry(config.entry),
282
+ expoNativeRoutes: normalizeExpoNativeRoutes(config, projectRoot),
283
+ ...config.engine === "expo" ? { expoSdkVersion: config.expo?.sdkVersion ?? 57 } : {},
284
+ iosVersion: normalizeIosVersion(config.ios?.version),
285
+ nativeProjectDirectory: resolveProjectPath(projectRoot, config.nativeProject?.directory ?? (config.engine === "expo" ? ".absolutejs/mobile/expo" : "mobile"), "mobile.nativeProject.directory"),
286
+ platforms: normalizePlatforms(config.platforms),
287
+ productionOrigin,
288
+ pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile")
289
+ };
290
+ };
291
+ var init_config = __esm(() => {
292
+ APP_ID_PATTERN = /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)+$/;
293
+ SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*$/;
294
+ APPLE_APP_ID_PREFIX_PATTERN = /^[A-Z0-9]{10}$/;
295
+ CERTIFICATE_FINGERPRINT_PATTERN = /^[0-9A-F]{64}$/;
296
+ 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])?))*$/;
297
+ });
298
+
166
299
  // src/utils/stringModifiers.ts
167
300
  var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-9\-_]+/g, "").replace(/[-_]{2,}/g, "-"), toKebab = (str) => normalizeSlug(str).replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase(), toPascal = (str) => {
168
301
  if (!str.includes("-") && !str.includes("_")) {
@@ -171,6 +304,50 @@ var normalizeSlug = (str) => str.trim().replace(/\s+/g, "-").replace(/[^A-Za-z0-
171
304
  return normalizeSlug(str).split(/[-_]/).filter(Boolean).map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1).toLowerCase()).join("");
172
305
  };
173
306
 
307
+ // src/mobile/nativeAuth.ts
308
+ import { readFileSync as readFileSync2 } from "fs";
309
+ import { join as join11 } from "path";
310
+ 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) => {
311
+ try {
312
+ return JSON.parse(readFileSync2(join11(projectRoot, "package.json"), "utf8"));
313
+ } catch {
314
+ return;
315
+ }
316
+ }, packageManifestHas = (manifest, packageName) => {
317
+ if (typeof manifest !== "object" || manifest === null)
318
+ return false;
319
+ return [
320
+ Reflect.get(manifest, "dependencies"),
321
+ Reflect.get(manifest, "devDependencies"),
322
+ Reflect.get(manifest, "optionalDependencies"),
323
+ Reflect.get(manifest, "peerDependencies")
324
+ ].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
325
+ }, createAbsoluteMobileAuthManifest = (config) => {
326
+ const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
327
+ return {
328
+ clientId: `absolutejs-native:${config.appId}`,
329
+ issuer: config.productionOrigin,
330
+ redirectUri: `${scheme}://auth/callback`,
331
+ scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
332
+ };
333
+ }, installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
334
+ const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
335
+ const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
336
+ if (serialized === undefined)
337
+ delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
338
+ else
339
+ process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
340
+ return auth;
341
+ }, 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([
342
+ {
343
+ ...auth,
344
+ name: `${config.appName} native app`
345
+ }
346
+ ]);
347
+ var init_nativeAuth = __esm(() => {
348
+ ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
349
+ });
350
+
174
351
  // node_modules/@absolutejs/sync/dist/client/index.js
175
352
  var RUNTIME_TRANSPORT, host, isRegistry = (value) => typeof value === "object" && value !== null && Array.isArray(Reflect.get(value, "installations")) && Array.isArray(Reflect.get(value, "clients")), registry, SyncLocalDataPolicyError, SyncLocalStoreSchemaError, positiveVersion = (value, label) => {
176
353
  if (!Number.isSafeInteger(value) || value < 1)
@@ -3788,11 +3965,12 @@ import {
3788
3965
 
3789
3966
  // src/mobile/remoteMacWire.ts
3790
3967
  var ABSOLUTE_REMOTE_MAC_EVENT_PREFIX = "ABSOLUTE_REMOTE_MAC\t";
3791
- var ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 1;
3968
+ var ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION = 2;
3792
3969
 
3793
3970
  // src/mobile/remoteMacProtocol.ts
3794
3971
  var PROFILE_FORMAT = 1;
3795
3972
  var REMOTE_STDIN_FLUSH_ATTEMPTS = 3;
3973
+ var REMOTE_SESSION_CLOSE_TIMEOUT_MS = 2000;
3796
3974
  var PROFILE_NAME = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/u;
3797
3975
  var SSH_DESTINATION = /^(?:[A-Za-z0-9._-]+@)?[A-Za-z0-9._:-]+$/u;
3798
3976
  var defaultProfilePath = () => join7(homedir2(), ".absolutejs", "mobile", "remote-macs.json");
@@ -3994,6 +4172,11 @@ var removeAbsoluteRemoteMacProfile = async (name, profilePath) => {
3994
4172
  return true;
3995
4173
  };
3996
4174
  var projectIdentity = (projectRoot, appId) => createHash7("sha256").update(`${resolvePath2(projectRoot)}\x00${appId}`).digest("hex").slice(0, 20);
4175
+ var createAbsoluteRemoteExpoIosDevProject = (config, projectRoot, profile) => {
4176
+ if (config.engine !== "expo")
4177
+ throw new TypeError("Remote Expo execution requires mobile.engine: expo.");
4178
+ return createAbsoluteRemoteIosDevProject(config, projectRoot, profile);
4179
+ };
3997
4180
  var createAbsoluteRemoteIosDevProject = (config, projectRoot, profile) => ({
3998
4181
  cap: join7(resolvePath2(projectRoot), "node_modules", ".bin", "cap"),
3999
4182
  config,
@@ -4085,6 +4268,7 @@ var portableMobileConfig = (project) => ({
4085
4268
  appId: project.config.appId,
4086
4269
  appName: project.config.appName,
4087
4270
  bundleDirectory: portableRelativePath(project.projectRoot, project.config.bundleDirectory),
4271
+ engine: project.config.engine,
4088
4272
  ...project.config.deepLinkScheme || project.config.deepLinkHosts.length > 1 || project.config.appleAppIdPrefix ? {
4089
4273
  deepLinks: {
4090
4274
  ...project.config.deepLinkScheme ? { scheme: project.config.deepLinkScheme } : {},
@@ -4097,6 +4281,16 @@ var portableMobileConfig = (project) => ({
4097
4281
  }
4098
4282
  } : {},
4099
4283
  entry: project.config.entry,
4284
+ ...project.config.engine === "expo" ? {
4285
+ expo: { sdkVersion: project.config.expoSdkVersion ?? 57 },
4286
+ routes: {
4287
+ default: "web",
4288
+ native: Object.fromEntries(Object.entries(project.config.expoNativeRoutes).map(([route, module]) => [
4289
+ route,
4290
+ portableRelativePath(project.projectRoot, module)
4291
+ ]))
4292
+ }
4293
+ } : {},
4100
4294
  ...project.config.iosVersion ? { ios: { version: project.config.iosVersion } } : {},
4101
4295
  nativeProject: {
4102
4296
  directory: portableRelativePath(project.projectRoot, project.config.nativeProjectDirectory),
@@ -4188,7 +4382,32 @@ var consumeLines2 = async (stream, onLine) => {
4188
4382
  reader.releaseLock();
4189
4383
  }
4190
4384
  };
4191
- var startAbsoluteRemoteIosDevSession = async (options) => {
4385
+ var startAbsoluteRemoteExpoIosDevSession = async (options) => {
4386
+ const session = await startAbsoluteRemoteDevSession({
4387
+ certificateAuthorityPath: options.certificateAuthorityPath,
4388
+ deviceIdentifier: options.deviceIdentifier,
4389
+ https: options.https,
4390
+ installAgent: options.installAgent,
4391
+ log: options.log,
4392
+ metroPort: options.metroPort,
4393
+ onExpoPhaseTiming: options.onPhaseTiming,
4394
+ onExpoStateChange: options.onStateChange,
4395
+ port: options.port,
4396
+ project: options.project,
4397
+ serverHost: options.serverHost,
4398
+ signal: options.signal,
4399
+ syncProject: options.syncProject,
4400
+ transport: options.transport
4401
+ });
4402
+ return {
4403
+ close: session.close,
4404
+ metroPort: options.metroPort,
4405
+ platforms: ["ios"],
4406
+ timings: session.timings
4407
+ };
4408
+ };
4409
+ var startAbsoluteRemoteIosDevSession = (options) => startAbsoluteRemoteDevSession(options);
4410
+ var startAbsoluteRemoteDevSession = async (options) => {
4192
4411
  const startedAt = performance.now();
4193
4412
  const transport = options.transport ?? defaultTransport;
4194
4413
  const installAgent = options.installAgent ?? installAbsoluteRemoteMacAgent;
@@ -4202,9 +4421,22 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4202
4421
  const encodedConfig = Buffer.from(JSON.stringify(portableMobileConfig(options.project))).toString("base64url");
4203
4422
  const encodedCertificateAuthority = options.certificateAuthorityPath ? (await readFile9(options.certificateAuthorityPath)).toString("base64url") : undefined;
4204
4423
  const physicalDevice = options.deviceIdentifier !== undefined;
4205
- let relayPort;
4206
- if (physicalDevice)
4207
- relayPort = options.port <= 49151 ? options.port + 16384 : options.port - 16384;
4424
+ const expo = options.project.config.engine === "expo";
4425
+ if (expo && options.metroPort === undefined)
4426
+ throw new TypeError("Remote Expo execution requires a Metro port.");
4427
+ if (options.metroPort === options.port)
4428
+ throw new TypeError("Expo Metro and AbsoluteJS must use different ports.");
4429
+ const translatedRelayPort = (sourcePort) => sourcePort <= 49151 ? sourcePort + 16384 : sourcePort - 16384;
4430
+ const occupiedRemotePorts = new Set([options.port, options.metroPort].filter((value) => value !== undefined));
4431
+ const reserveRelayPort = (sourcePort) => {
4432
+ let candidate = translatedRelayPort(sourcePort);
4433
+ while (occupiedRemotePorts.has(candidate))
4434
+ candidate = candidate === 65535 ? 1024 : candidate + 1;
4435
+ occupiedRemotePorts.add(candidate);
4436
+ return candidate;
4437
+ };
4438
+ const relayPort = physicalDevice ? reserveRelayPort(options.port) : undefined;
4439
+ const metroRelayPort = physicalDevice && options.metroPort !== undefined ? reserveRelayPort(options.metroPort) : undefined;
4208
4440
  if (physicalDevice && !options.serverHost)
4209
4441
  throw new Error("Remote physical iOS development requires the Remote Mac LAN host.");
4210
4442
  const remoteCommand = [
@@ -4217,6 +4449,7 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4217
4449
  String(options.port),
4218
4450
  "--mobile-config",
4219
4451
  shellQuote(encodedConfig),
4452
+ ...expo && options.metroPort !== undefined ? ["--metro-port", String(options.metroPort)] : [],
4220
4453
  ...encodedCertificateAuthority ? [
4221
4454
  "--certificate-authority",
4222
4455
  shellQuote(encodedCertificateAuthority)
@@ -4228,7 +4461,8 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4228
4461
  "--server-host",
4229
4462
  shellQuote(options.serverHost ?? ""),
4230
4463
  "--relay-port",
4231
- String(relayPort)
4464
+ String(relayPort),
4465
+ ...expo && metroRelayPort !== undefined ? ["--metro-relay-port", String(metroRelayPort)] : []
4232
4466
  ] : []
4233
4467
  ].join(" ");
4234
4468
  const command = [
@@ -4237,6 +4471,10 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4237
4471
  "ExitOnForwardFailure=yes",
4238
4472
  "-R",
4239
4473
  physicalDevice ? `127.0.0.1:${relayPort}:127.0.0.1:${options.port}` : `${options.port}:127.0.0.1:${options.port}`,
4474
+ ...expo && options.metroPort !== undefined ? [
4475
+ "-R",
4476
+ physicalDevice ? `127.0.0.1:${metroRelayPort}:127.0.0.1:${options.metroPort}` : `${options.metroPort}:127.0.0.1:${options.metroPort}`
4477
+ ] : [],
4240
4478
  "/bin/sh -lc",
4241
4479
  shellQuote(remoteCommand)
4242
4480
  ];
@@ -4262,11 +4500,19 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4262
4500
  if (event.type === "native-log")
4263
4501
  options.nativeLog?.(event.entry);
4264
4502
  if (event.type === "state") {
4265
- ({ state } = event);
4266
- options.onStateChange?.(state);
4503
+ if (expo)
4504
+ options.onExpoStateChange?.(event.state);
4505
+ else {
4506
+ state = event.state;
4507
+ options.onStateChange?.(state);
4508
+ }
4509
+ }
4510
+ if (event.type === "timing") {
4511
+ if (expo)
4512
+ options.onExpoPhaseTiming?.(event);
4513
+ else
4514
+ options.onPhaseTiming?.(event);
4267
4515
  }
4268
- if (event.type === "timing")
4269
- options.onPhaseTiming?.(event);
4270
4516
  if (event.type === "ready") {
4271
4517
  ready = event;
4272
4518
  resolveReady();
@@ -4308,9 +4554,26 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4308
4554
  pending.clear();
4309
4555
  return;
4310
4556
  });
4311
- await readyPromise;
4557
+ try {
4558
+ await readyPromise;
4559
+ } catch (error) {
4560
+ process2.stdin.end();
4561
+ process2.kill();
4562
+ await process2.exited.catch(() => {
4563
+ return;
4564
+ });
4565
+ throw error;
4566
+ }
4312
4567
  if (!ready)
4313
4568
  throw fatal ?? new Error("Remote Mac did not become ready.");
4569
+ if (ready.engine !== options.project.config.engine) {
4570
+ process2.stdin.end();
4571
+ process2.kill();
4572
+ await process2.exited.catch(() => {
4573
+ return;
4574
+ });
4575
+ throw new Error("Remote Mac executor returned the wrong mobile engine.");
4576
+ }
4314
4577
  const totalDuration = performance.now() - startedAt;
4315
4578
  let currentReady = {
4316
4579
  ...ready,
@@ -4322,11 +4585,11 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4322
4585
  total: totalDuration
4323
4586
  }
4324
4587
  };
4325
- 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.`);
4588
+ 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.`);
4326
4589
  const request = (commandName) => {
4327
4590
  const id = randomUUID4();
4328
4591
  const response = new Promise((resolve6, reject) => pending.set(id, { reject, resolve: resolve6 }));
4329
- process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: 1 })}
4592
+ process2.stdin.write(`${JSON.stringify({ command: commandName, id, v: ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION })}
4330
4593
  `);
4331
4594
  const flush = async () => {
4332
4595
  for (let attempt = 0;attempt < REMOTE_STDIN_FLUSH_ATTEMPTS; attempt++) {
@@ -4345,13 +4608,24 @@ var startAbsoluteRemoteIosDevSession = async (options) => {
4345
4608
  if (closed)
4346
4609
  return;
4347
4610
  closed = true;
4348
- await request("close").catch(() => {
4349
- return;
4350
- });
4611
+ const timeout = () => new Promise((resolve6) => setTimeout(() => resolve6("timeout"), REMOTE_SESSION_CLOSE_TIMEOUT_MS));
4612
+ await Promise.race([
4613
+ request("close").catch(() => {
4614
+ return;
4615
+ }),
4616
+ timeout()
4617
+ ]);
4351
4618
  process2.stdin.end();
4352
- await process2.exited.catch(() => {
4353
- return;
4354
- });
4619
+ const exit = await Promise.race([
4620
+ process2.exited.then(() => "exited").catch(() => "exited"),
4621
+ timeout()
4622
+ ]);
4623
+ if (exit === "timeout") {
4624
+ process2.kill();
4625
+ await process2.exited.catch(() => {
4626
+ return;
4627
+ });
4628
+ }
4355
4629
  };
4356
4630
  const makeSession = () => ({
4357
4631
  close,
@@ -4435,6 +4709,7 @@ var testAbsoluteIosPhysicalDevice = async (options) => {
4435
4709
  };
4436
4710
  };
4437
4711
  // src/mobile/associationFiles.ts
4712
+ init_config();
4438
4713
  import {
4439
4714
  access as access7,
4440
4715
  mkdir as mkdir7,
@@ -4445,183 +4720,42 @@ import {
4445
4720
  } from "fs/promises";
4446
4721
  import { resolve as resolve7 } from "path";
4447
4722
  import { Elysia } from "elysia";
4448
-
4449
- // src/mobile/config.ts
4450
- import { resolve as resolve6 } from "path";
4451
- var APP_ID_PATTERN = /^[A-Za-z][\w]*(?:\.[A-Za-z][\w]*)+$/;
4452
- var SCHEME_PATTERN = /^[a-z][a-z0-9+.-]*$/;
4453
- var APPLE_APP_ID_PREFIX_PATTERN = /^[A-Z0-9]{10}$/;
4454
- var CERTIFICATE_FINGERPRINT_PATTERN = /^[0-9A-F]{64}$/;
4455
- var 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])?))*$/;
4456
- var resolveProjectPath = (projectRoot, value, field2) => {
4457
- const root = resolve6(projectRoot);
4458
- const path = resolve6(root, value);
4459
- if (path !== root && !path.startsWith(`${root}/`)) {
4460
- throw new TypeError(`${field2} must remain inside the project root.`);
4461
- }
4462
- return path;
4463
- };
4464
- var requireText = (value, field2) => {
4465
- const normalized = value.trim();
4466
- if (!normalized)
4467
- throw new TypeError(`${field2} must not be empty.`);
4468
- return normalized;
4723
+ var JSON_HEADERS = {
4724
+ "cache-control": "public, max-age=300, must-revalidate",
4725
+ "content-type": "application/json; charset=utf-8"
4469
4726
  };
4470
- var normalizeEntry = (entry) => {
4471
- const normalized = requireText(entry ?? "/", "mobile.entry");
4472
- if (!normalized.startsWith("/") || normalized.startsWith("//")) {
4473
- throw new TypeError("mobile.entry must be an absolute application path.");
4727
+ var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json";
4728
+ var HTTP_OK = 200;
4729
+ var VERIFY_TIMEOUT_MS = 1e4;
4730
+ var ANDROID_ASSOCIATION_PATH = "/.well-known/assetlinks.json";
4731
+ var APPLE_ASSOCIATION_PATH = "/.well-known/apple-app-site-association";
4732
+ var missingIdentity = (field2, platform) => new TypeError(`${field2} is required to publish ${platform} deep-link association files.`);
4733
+ var createAppleDocument = (config, requireAll) => {
4734
+ if (!config.platforms.includes("ios"))
4735
+ return;
4736
+ if (!config.appleAppIdPrefix && requireAll) {
4737
+ throw missingIdentity("mobile.deepLinks.apple.appIdPrefix", "iOS");
4474
4738
  }
4475
- return normalized;
4739
+ if (!config.appleAppIdPrefix)
4740
+ return;
4741
+ return {
4742
+ applinks: {
4743
+ details: [
4744
+ {
4745
+ appIDs: [
4746
+ `${config.appleAppIdPrefix}.${config.appId}`
4747
+ ],
4748
+ components: [{ "/": "/*" }]
4749
+ }
4750
+ ]
4751
+ }
4752
+ };
4476
4753
  };
4477
- var normalizeProductionOrigin = (value) => {
4478
- const parsed = new URL(requireText(value, "mobile.server.productionOrigin"));
4479
- const isLoopbackHttp = parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]");
4480
- if (parsed.protocol !== "https:" && !isLoopbackHttp) {
4481
- throw new TypeError("mobile.server.productionOrigin must use HTTPS, except for a loopback development origin.");
4482
- }
4483
- if (parsed.username || parsed.password || parsed.pathname !== "/" || parsed.search || parsed.hash) {
4484
- throw new TypeError("mobile.server.productionOrigin must be an origin without credentials, path, query, or hash.");
4485
- }
4486
- return parsed.origin;
4487
- };
4488
- var normalizePlatforms = (platforms) => {
4489
- const normalized = [
4490
- ...new Set(platforms ?? ["ios", "android"])
4491
- ];
4492
- if (normalized.length === 0) {
4493
- throw new TypeError("mobile.platforms must contain at least one platform.");
4494
- }
4495
- return normalized;
4496
- };
4497
- var normalizeHosts = (hosts, productionOrigin) => {
4498
- const normalizeHostname = (host) => {
4499
- const value = requireText(host, "mobile.deepLinks.hosts").toLowerCase();
4500
- if (!HOSTNAME_PATTERN.test(value)) {
4501
- throw new TypeError("mobile.deepLinks.hosts entries must be valid hostnames without ports, wildcards, or paths.");
4502
- }
4503
- return value;
4504
- };
4505
- const productionHostname = new URL(productionOrigin).hostname;
4506
- const normalized = new Set(productionHostname === "[::1]" ? [] : [normalizeHostname(productionHostname)]);
4507
- for (const host of hosts ?? []) {
4508
- normalized.add(normalizeHostname(host));
4509
- }
4510
- return [...normalized].sort();
4511
- };
4512
- var normalizeAppleAppIdPrefix = (value) => {
4513
- if (value === undefined)
4514
- return;
4515
- const normalized = requireText(value, "mobile.deepLinks.apple.appIdPrefix").toUpperCase();
4516
- if (!APPLE_APP_ID_PREFIX_PATTERN.test(normalized)) {
4517
- throw new TypeError("mobile.deepLinks.apple.appIdPrefix must contain ten letters or digits.");
4518
- }
4519
- return normalized;
4520
- };
4521
- var normalizeIosVersion = (value) => {
4522
- if (value === undefined)
4523
- return;
4524
- const normalized = requireText(value, "mobile.ios.version");
4525
- if (!/^\d+(?:\.\d+){0,2}$/u.test(normalized)) {
4526
- throw new TypeError("mobile.ios.version must contain one to three dot-separated integer components, for example 1.4.0.");
4527
- }
4528
- return normalized;
4529
- };
4530
- var normalizeCertificateFingerprints = (values) => [
4531
- ...new Set((values ?? []).map((value) => requireText(value, "mobile.deepLinks.android.sha256CertificateFingerprints").replaceAll(":", "").toUpperCase()).map((value) => {
4532
- if (!CERTIFICATE_FINGERPRINT_PATTERN.test(value)) {
4533
- throw new TypeError("mobile.deepLinks.android.sha256CertificateFingerprints entries must be SHA-256 certificate fingerprints.");
4534
- }
4535
- return value.match(/.{2}/g)?.join(":") ?? value;
4536
- }))
4537
- ].sort();
4538
- var normalizeExpoNativeRoutes = (config, projectRoot) => {
4539
- if (config.engine !== "expo")
4540
- return {};
4541
- const routes = config.routes?.native ?? {};
4542
- const normalized = {};
4543
- for (const [route, module] of Object.entries(routes)) {
4544
- const path = normalizeEntry(route);
4545
- if (path.includes("?") || path.includes("#") || path !== "/" && path.endsWith("/")) {
4546
- throw new TypeError(`mobile.routes.native route ${path} must be a canonical path without a query, fragment, or trailing slash.`);
4547
- }
4548
- if (path === "/__absolute/native") {
4549
- throw new TypeError("mobile.routes.native reserves /__absolute/native for the Expo diagnostic screen.");
4550
- }
4551
- if (path.includes("*") || path.includes(":")) {
4552
- throw new TypeError(`mobile.routes.native route ${path} must be static during the Expo experiment; parameters and wildcards are not supported yet.`);
4553
- }
4554
- normalized[path] = resolveProjectPath(projectRoot, requireText(module, `mobile.routes.native[${path}]`), `mobile.routes.native[${path}]`);
4555
- }
4556
- return Object.fromEntries(Object.entries(normalized).sort(([left], [right]) => left.localeCompare(right)));
4557
- };
4558
- var normalizeAbsoluteMobileConfig = (config, projectRoot) => {
4559
- const appId = requireText(config.appId, "mobile.appId");
4560
- if (!APP_ID_PATTERN.test(appId)) {
4561
- throw new TypeError("mobile.appId must use reverse-domain notation, for example com.example.app.");
4562
- }
4563
- const productionOrigin = normalizeProductionOrigin(config.server.productionOrigin);
4564
- const deepLinkScheme = (config.deepLinks?.scheme ?? appId).trim().toLowerCase();
4565
- if (deepLinkScheme && !SCHEME_PATTERN.test(deepLinkScheme)) {
4566
- throw new TypeError("mobile.deepLinks.scheme is not a valid URL scheme.");
4567
- }
4568
- return {
4569
- androidCertificateFingerprints: normalizeCertificateFingerprints(config.deepLinks?.android?.sha256CertificateFingerprints),
4570
- appId,
4571
- appleAppIdPrefix: normalizeAppleAppIdPrefix(config.deepLinks?.apple?.appIdPrefix),
4572
- appName: requireText(config.appName, "mobile.appName"),
4573
- bundleDirectory: resolveProjectPath(projectRoot, config.bundleDirectory ?? ".absolutejs/mobile/web", "mobile.bundleDirectory"),
4574
- deepLinkHosts: normalizeHosts(config.deepLinks?.hosts, productionOrigin),
4575
- deepLinkScheme,
4576
- engine: config.engine ?? "capacitor",
4577
- entry: normalizeEntry(config.entry),
4578
- expoNativeRoutes: normalizeExpoNativeRoutes(config, projectRoot),
4579
- ...config.engine === "expo" ? { expoSdkVersion: config.expo?.sdkVersion ?? 57 } : {},
4580
- iosVersion: normalizeIosVersion(config.ios?.version),
4581
- nativeProjectDirectory: resolveProjectPath(projectRoot, config.nativeProject?.directory ?? (config.engine === "expo" ? ".absolutejs/mobile/expo" : "mobile"), "mobile.nativeProject.directory"),
4582
- platforms: normalizePlatforms(config.platforms),
4583
- productionOrigin,
4584
- pushAndroidGoogleServicesFile: resolveProjectPath(projectRoot, config.pushNotifications?.android?.googleServicesFile ?? "google-services.json", "mobile.pushNotifications.android.googleServicesFile")
4585
- };
4586
- };
4587
-
4588
- // src/mobile/associationFiles.ts
4589
- var JSON_HEADERS = {
4590
- "cache-control": "public, max-age=300, must-revalidate",
4591
- "content-type": "application/json; charset=utf-8"
4592
- };
4593
- var OWNERSHIP_FILE = ".absolutejs-mobile-associations.json";
4594
- var HTTP_OK = 200;
4595
- var VERIFY_TIMEOUT_MS = 1e4;
4596
- var ANDROID_ASSOCIATION_PATH = "/.well-known/assetlinks.json";
4597
- var APPLE_ASSOCIATION_PATH = "/.well-known/apple-app-site-association";
4598
- var missingIdentity = (field2, platform) => new TypeError(`${field2} is required to publish ${platform} deep-link association files.`);
4599
- var createAppleDocument = (config, requireAll) => {
4600
- if (!config.platforms.includes("ios"))
4601
- return;
4602
- if (!config.appleAppIdPrefix && requireAll) {
4603
- throw missingIdentity("mobile.deepLinks.apple.appIdPrefix", "iOS");
4604
- }
4605
- if (!config.appleAppIdPrefix)
4606
- return;
4607
- return {
4608
- applinks: {
4609
- details: [
4610
- {
4611
- appIDs: [
4612
- `${config.appleAppIdPrefix}.${config.appId}`
4613
- ],
4614
- components: [{ "/": "/*" }]
4615
- }
4616
- ]
4617
- }
4618
- };
4619
- };
4620
- var createAndroidDocument = (config, requireAll) => {
4621
- if (!config.platforms.includes("android"))
4622
- return;
4623
- if (config.androidCertificateFingerprints.length === 0 && requireAll) {
4624
- throw missingIdentity("mobile.deepLinks.android.sha256CertificateFingerprints", "Android");
4754
+ var createAndroidDocument = (config, requireAll) => {
4755
+ if (!config.platforms.includes("android"))
4756
+ return;
4757
+ if (config.androidCertificateFingerprints.length === 0 && requireAll) {
4758
+ throw missingIdentity("mobile.deepLinks.android.sha256CertificateFingerprints", "Android");
4625
4759
  }
4626
4760
  if (config.androidCertificateFingerprints.length === 0)
4627
4761
  return;
@@ -5259,7 +5393,6 @@ var finalizeAbsoluteMobilePage = (input) => {
5259
5393
 
5260
5394
  // src/mobile/client.ts
5261
5395
  class AbsoluteMobilePageProtocolError extends Error {
5262
- code;
5263
5396
  constructor(code, message) {
5264
5397
  super(message);
5265
5398
  this.name = "AbsoluteMobilePageProtocolError";
@@ -5470,6 +5603,12 @@ var shellAuthModule = () => {
5470
5603
  return candidate;
5471
5604
  throw new TypeError("AbsoluteJS mobile auth shell module is missing.");
5472
5605
  };
5606
+ var shellExpoAuthModule = () => {
5607
+ const candidate = ["js", "ts"].map((extension) => join9(import.meta.dir, `shellExpoAuth.${extension}`)).find(existsSync2);
5608
+ if (candidate)
5609
+ return candidate;
5610
+ throw new TypeError("AbsoluteJS Expo auth bridge module is missing.");
5611
+ };
5473
5612
  var shellSyncModule = () => {
5474
5613
  const candidate = ["js", "ts"].map((extension) => join9(import.meta.dir, `shellSync.${extension}`)).find(existsSync2);
5475
5614
  if (candidate)
@@ -5552,9 +5691,10 @@ var buildShellBootstrap = async (staging, auth, sync, storagePrefix, engine, dev
5552
5691
  const capacitor = engine !== "expo";
5553
5692
  const shellCapabilities = capacitor ? deviceCapabilities.capabilities : [];
5554
5693
  const modulePath = shellBootstrapModule();
5555
- const authImport = auth ? `import { createAbsoluteMobileShellAuth } from ${JSON.stringify(shellAuthModule())};
5694
+ const authFactory = capacitor ? "createAbsoluteMobileShellAuth" : "createAbsoluteExpoShellAuth";
5695
+ const authImport = auth ? `import { ${authFactory} } from ${JSON.stringify(capacitor ? shellAuthModule() : shellExpoAuthModule())};
5556
5696
  ` : "";
5557
- const options = auth ? `{ createAuth: createAbsoluteMobileShellAuth${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
5697
+ const options = auth ? `{ createAuth: ${authFactory}${sync ? ", installSync: installAbsoluteMobileShellSync" : ""} }` : "";
5558
5698
  const syncImport = sync ? `import { installAbsoluteMobileShellSync } from ${JSON.stringify(shellSyncModule())};
5559
5699
  ` : "";
5560
5700
  const pushIndex = shellCapabilities.indexOf("pushNotifications");
@@ -5576,7 +5716,7 @@ const absoluteMobilePushCapability = absoluteDeviceCapability${pushIndex}(absolu
5576
5716
  const baseAdapterModule = capacitor ? await resolveProjectImport(projectRoot, "@absolutejs/devices-capacitor") : shellExpoDevicesModule();
5577
5717
  const adapterImport = capacitor ? `import { installCapacitorDeviceAdapterIfNative } from ${JSON.stringify(baseAdapterModule)};` : `import { createAbsoluteExpoBridgeFetch, installAbsoluteExpoWebDeviceAdapter } from ${JSON.stringify(baseAdapterModule)};`;
5578
5718
  const adapterInstall = capacitor ? `installCapacitorDeviceAdapterIfNative({ storagePrefix: ${JSON.stringify(storagePrefix)}${capabilityOptions ? `, ${capabilityOptions}` : ""} });` : "installAbsoluteExpoWebDeviceAdapter();";
5579
- let shellOptions = "{ createFetch: createAbsoluteExpoBridgeFetch }";
5719
+ let shellOptions = auth ? options : "{ createFetch: createAbsoluteExpoBridgeFetch }";
5580
5720
  if (capacitor)
5581
5721
  shellOptions = options;
5582
5722
  if (push) {
@@ -5760,6 +5900,9 @@ var materializeAbsoluteCapacitorWebBundle = async (options) => {
5760
5900
  }
5761
5901
  };
5762
5902
 
5903
+ // src/mobile/buildPipeline.ts
5904
+ init_config();
5905
+
5763
5906
  // src/mobile/materializedBundle.ts
5764
5907
  import { createHash as createHash9 } from "crypto";
5765
5908
  import {
@@ -5937,63 +6080,13 @@ var readAbsoluteMobileMaterializedReleases = async (root) => {
5937
6080
  }
5938
6081
  };
5939
6082
 
5940
- // src/mobile/nativeAuth.ts
5941
- import { readFileSync as readFileSync2 } from "fs";
5942
- import { join as join11 } from "path";
5943
- var ABSOLUTE_AUTH_PACKAGE = "@absolutejs/auth";
5944
- var ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV = "ABSOLUTE_AUTH_NATIVE_CLIENTS";
5945
- var ABSOLUTE_NATIVE_AUTH_SCOPES = ["openid", "profile"];
5946
- var ABSOLUTE_SYNC_PACKAGE = "@absolutejs/sync";
5947
- var readPackageManifest = (projectRoot) => {
5948
- try {
5949
- return JSON.parse(readFileSync2(join11(projectRoot, "package.json"), "utf8"));
5950
- } catch {
5951
- return;
5952
- }
5953
- };
5954
- var packageManifestHas = (manifest, packageName) => {
5955
- if (typeof manifest !== "object" || manifest === null)
5956
- return false;
5957
- return [
5958
- Reflect.get(manifest, "dependencies"),
5959
- Reflect.get(manifest, "devDependencies"),
5960
- Reflect.get(manifest, "optionalDependencies"),
5961
- Reflect.get(manifest, "peerDependencies")
5962
- ].some((dependencies) => typeof dependencies === "object" && dependencies !== null && Object.hasOwn(dependencies, packageName));
5963
- };
5964
- var createAbsoluteMobileAuthManifest = (config) => {
5965
- const scheme = config.deepLinkScheme ?? config.appId.toLowerCase();
5966
- return {
5967
- clientId: `absolutejs-native:${config.appId}`,
5968
- issuer: config.productionOrigin,
5969
- redirectUri: `${scheme}://auth/callback`,
5970
- scopes: [...ABSOLUTE_NATIVE_AUTH_SCOPES]
5971
- };
5972
- };
5973
- var installAbsoluteMobileAuthEnvironment = (projectRoot, config) => {
5974
- const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
5975
- const serialized = serializeAbsoluteMobileAuthEnvironment(config, auth);
5976
- if (serialized === undefined)
5977
- delete process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV];
5978
- else
5979
- process.env[ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV] = serialized;
5980
- return auth;
5981
- };
5982
- var projectUsesAbsoluteAuth = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_AUTH_PACKAGE);
5983
- var projectUsesAbsoluteSync = (projectRoot) => packageManifestHas(readPackageManifest(projectRoot), ABSOLUTE_SYNC_PACKAGE);
5984
- var resolveAbsoluteMobileAuthManifest = (projectRoot, config) => projectUsesAbsoluteAuth(projectRoot) ? createAbsoluteMobileAuthManifest(config) : undefined;
5985
- var serializeAbsoluteMobileAuthEnvironment = (config, auth) => auth === undefined ? undefined : JSON.stringify([
5986
- {
5987
- ...auth,
5988
- name: `${config.appName} native app`
5989
- }
5990
- ]);
5991
-
5992
6083
  // src/mobile/buildPipeline.ts
6084
+ init_nativeAuth();
5993
6085
  init_syncSchema();
5994
6086
  init_deviceCapabilities();
5995
6087
 
5996
6088
  // src/mobile/expoProject.ts
6089
+ init_nativeAuth();
5997
6090
  import {
5998
6091
  access as access9,
5999
6092
  cp as cp2,
@@ -6032,8 +6125,12 @@ var routeSegments = (route) => route.split("/").filter(Boolean).map((segment) =>
6032
6125
  return segment;
6033
6126
  });
6034
6127
  var routeFile = (project, route) => join14(project, "app", ...routeSegments(route), "index.tsx");
6035
- var expoPackage = () => ({
6128
+ var expoPackage = (auth) => ({
6036
6129
  dependencies: {
6130
+ ...auth ? {
6131
+ "@absolutejs/auth": ABSOLUTE_EXPO_AUTH_CORE_VERSION,
6132
+ [ABSOLUTE_EXPO_AUTH_PACKAGE]: ABSOLUTE_EXPO_AUTH_VERSION
6133
+ } : {},
6037
6134
  expo: "~57.0.9",
6038
6135
  "expo-asset": "~57.0.15",
6039
6136
  "expo-constants": "~57.0.16",
@@ -6042,6 +6139,10 @@ var expoPackage = () => ({
6042
6139
  "expo-haptics": "~57.0.2",
6043
6140
  "expo-linking": "~57.0.8",
6044
6141
  "expo-router": "~57.0.17",
6142
+ ...auth ? {
6143
+ "expo-secure-store": "~57.0.2",
6144
+ "expo-web-browser": "~57.0.2"
6145
+ } : {},
6045
6146
  react: "19.2.3",
6046
6147
  "react-native": "0.86.3",
6047
6148
  "react-native-safe-area-context": "~5.7.0",
@@ -6062,7 +6163,7 @@ var expoPackage = () => ({
6062
6163
  },
6063
6164
  version: "0.0.0"
6064
6165
  });
6065
- var expoAppConfig = (config) => ({
6166
+ var expoAppConfig = (config, auth) => ({
6066
6167
  expo: {
6067
6168
  android: {
6068
6169
  intentFilters: config.deepLinkHosts.map((host2) => ({
@@ -6082,7 +6183,8 @@ var expoAppConfig = (config) => ({
6082
6183
  name: config.appName,
6083
6184
  plugins: [
6084
6185
  "expo-router",
6085
- ["expo-dev-client", { launchMode: "most-recent" }]
6186
+ ["expo-dev-client", { launchMode: "most-recent" }],
6187
+ ...auth ? ["expo-secure-store"] : []
6086
6188
  ],
6087
6189
  runtimeVersion: { policy: "appVersion" },
6088
6190
  scheme: config.deepLinkScheme,
@@ -6156,9 +6258,14 @@ config.watchFolders = [appRoot];
6156
6258
 
6157
6259
  module.exports = config;
6158
6260
  `;
6159
- var layoutSource = `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
6261
+ var layoutSource = (auth) => `${EXPO_GENERATED_HEADER}import { Stack } from 'expo-router';
6262
+ ${auth ? `import { useEffect } from 'react';
6263
+ import { startAbsoluteExpoAuth } from '../src/generated/AbsoluteAuth';` : ""}
6160
6264
 
6161
6265
  export default function AbsoluteLayout() {
6266
+ ${auth ? `useEffect(() => {
6267
+ void startAbsoluteExpoAuth();
6268
+ }, []);` : ""}
6162
6269
  return <Stack screenOptions={{ headerShown: false }} />;
6163
6270
  }
6164
6271
  `;
@@ -6193,7 +6300,39 @@ const styles = StyleSheet.create({
6193
6300
  title: { color: '#f8fafc', fontSize: 32, fontWeight: '800' }
6194
6301
  });
6195
6302
  `;
6196
- var webHostSource = (config) => {
6303
+ var authRuntimeSource = (auth, appId) => {
6304
+ const storageIdentity = createHash10("sha256").update(appId).digest("hex").slice(0, 24);
6305
+ return `${EXPO_GENERATED_HEADER}import { createAbsoluteExpoAuthClient } from '@absolutejs/auth-expo';
6306
+ import { createMobileAuthTransport, installAuthClientRuntimeTransport } from '@absolutejs/auth/client/mobile';
6307
+
6308
+ export const absoluteExpoAuth = createAbsoluteExpoAuthClient({
6309
+ allowedOrigins: [${JSON.stringify(auth.issuer)}],
6310
+ clientId: ${JSON.stringify(auth.clientId)},
6311
+ issuer: ${JSON.stringify(auth.issuer)},
6312
+ redirectUri: ${JSON.stringify(auth.redirectUri)},
6313
+ resource: ${JSON.stringify(auth.issuer)},
6314
+ scopes: ${JSON.stringify(auth.scopes)},
6315
+ storagePrefix: ${JSON.stringify(`absolutejs.auth.${storageIdentity}`)}
6316
+ });
6317
+ installAuthClientRuntimeTransport(createMobileAuthTransport(absoluteExpoAuth, { baseUrl: ${JSON.stringify(auth.issuer)} }));
6318
+
6319
+ let currentPrincipal: Awaited<ReturnType<typeof absoluteExpoAuth.principal>> = null;
6320
+ absoluteExpoAuth.onPrincipalChange(principal => {
6321
+ currentPrincipal = principal;
6322
+ });
6323
+ export const getAbsoluteExpoAuthPrincipal = () => currentPrincipal;
6324
+
6325
+ let startPromise: Promise<void> | undefined;
6326
+ export const startAbsoluteExpoAuth = () => {
6327
+ startPromise ??= absoluteExpoAuth.start().then(async () => {
6328
+ await absoluteExpoAuth.principal();
6329
+ });
6330
+
6331
+ return startPromise;
6332
+ };
6333
+ `;
6334
+ };
6335
+ var webHostSource = (config, auth) => {
6197
6336
  const nativeRoutes = [
6198
6337
  "/__absolute/native",
6199
6338
  ...Object.keys(config.expoNativeRoutes)
@@ -6205,8 +6344,9 @@ import { useEffect, useRef, useState } from 'react';
6205
6344
  import { ActivityIndicator, BackHandler, Platform, StyleSheet, View } from 'react-native';
6206
6345
  import { WebView, type WebViewMessageEvent } from 'react-native-webview';
6207
6346
  import { materializeAbsoluteWebBundle } from './webAssets';
6347
+ ${auth ? "import { absoluteExpoAuth, getAbsoluteExpoAuthPrincipal, startAbsoluteExpoAuth } from './AbsoluteAuth';" : ""}
6208
6348
 
6209
- const BRIDGE_FORMAT = 1;
6349
+ const BRIDGE_FORMAT = 2;
6210
6350
  const MAX_MESSAGE_BYTES = 64 * 1024;
6211
6351
  const MAX_HTTP_BODY_BYTES = 48 * 1024;
6212
6352
  const NATIVE_ROUTES = new Set(${JSON.stringify(nativeRoutes)});
@@ -6215,6 +6355,7 @@ const DEV_ORIGIN = Platform.OS === 'android'
6215
6355
  ? process.env.EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN
6216
6356
  : process.env.EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN;
6217
6357
  const HMR_TARGET = Platform.OS === 'android' ? 'expo-android' : 'expo-ios';
6358
+ const AUTH_ENABLED = ${auth ? "true" : "false"};
6218
6359
 
6219
6360
  const bridgeBootstrap = (path: string) => {
6220
6361
  const initialPath = DEV_ORIGIN
@@ -6222,6 +6363,7 @@ const bridgeBootstrap = (path: string) => {
6222
6363
  : JSON.stringify(path);
6223
6364
  return \`(() => {
6224
6365
  const pending = new Map();
6366
+ const listeners = new Map();
6225
6367
  let sequence = 0;
6226
6368
  let currentPath = \${initialPath};
6227
6369
  const send = value => {
@@ -6231,6 +6373,10 @@ const bridgeBootstrap = (path: string) => {
6231
6373
  };
6232
6374
  globalThis.__absoluteExpoReceive = source => {
6233
6375
  const message = JSON.parse(source);
6376
+ if (message.kind === 'event') {
6377
+ for (const listener of listeners.get(message.event) || []) listener(message.payload || {});
6378
+ return;
6379
+ }
6234
6380
  const operation = pending.get(message.id);
6235
6381
  if (!operation) return;
6236
6382
  pending.delete(message.id);
@@ -6238,9 +6384,18 @@ const bridgeBootstrap = (path: string) => {
6238
6384
  message.error ? operation.reject(new Error(message.error.message)) : operation.resolve(message.result);
6239
6385
  };
6240
6386
  globalThis.__absoluteExpoBridge = {
6387
+ on(event, listener) {
6388
+ const values = listeners.get(event) || new Set();
6389
+ values.add(listener);
6390
+ listeners.set(event, values);
6391
+ return () => {
6392
+ values.delete(listener);
6393
+ if (values.size === 0) listeners.delete(event);
6394
+ };
6395
+ },
6241
6396
  request(method, params) {
6242
6397
  const id = 'web_' + Date.now().toString(36) + '_' + (++sequence).toString(36);
6243
- send({ format: 1, id, kind: 'request', method, params, path: currentPath });
6398
+ send({ format: 2, id, kind: 'request', method, params, path: currentPath });
6244
6399
  return new Promise((resolve, reject) => {
6245
6400
  const timer = setTimeout(() => {
6246
6401
  pending.delete(id);
@@ -6251,7 +6406,7 @@ const bridgeBootstrap = (path: string) => {
6251
6406
  },
6252
6407
  setPath(path) {
6253
6408
  currentPath = path;
6254
- send({ format: 1, kind: 'event', event: 'navigation', path });
6409
+ send({ format: 2, kind: 'event', event: 'navigation', path });
6255
6410
  }
6256
6411
  };
6257
6412
  if (\${DEV_ORIGIN ? 'true' : 'false'}) {
@@ -6259,7 +6414,7 @@ const bridgeBootstrap = (path: string) => {
6259
6414
  const path = location.pathname + location.search + location.hash;
6260
6415
  if (path === currentPath) return;
6261
6416
  currentPath = path;
6262
- send({ format: 1, kind: 'event', event: 'navigation', path });
6417
+ send({ format: 2, kind: 'event', event: 'navigation', path });
6263
6418
  };
6264
6419
  for (const method of ['pushState', 'replaceState']) {
6265
6420
  const original = history[method];
@@ -6278,9 +6433,9 @@ const bridgeBootstrap = (path: string) => {
6278
6433
  const url = new URL(anchor.href, location.href);
6279
6434
  if (!${JSON.stringify(nativeRoutes)}.includes(url.pathname)) return;
6280
6435
  event.preventDefault();
6281
- send({ format: 1, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
6436
+ send({ format: 2, kind: 'event', event: 'navigation', path: url.pathname + url.search + url.hash });
6282
6437
  }, true);
6283
- send({ format: 1, kind: 'event', event: 'ready', path: currentPath });
6438
+ send({ format: 2, kind: 'event', event: 'ready', path: currentPath });
6284
6439
  })(); true;\`;
6285
6440
  };
6286
6441
 
@@ -6296,16 +6451,16 @@ const impact = async (params: Record<string, unknown>) => {
6296
6451
  };
6297
6452
 
6298
6453
  const bridgeFetch = async (params: Record<string, unknown>) => {
6299
- 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.');
6454
+ 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.');
6300
6455
  const url = new URL(params.url);
6301
6456
  if (url.origin !== PRODUCTION_ORIGIN || url.username || url.password) throw new Error('Expo bridge HTTP request left productionOrigin.');
6302
6457
  const headers = new Headers();
6303
6458
  for (const [name, value] of Object.entries(params.headers as Record<string, unknown>)) {
6304
6459
  const normalized = name.toLowerCase();
6305
- if (typeof value !== 'string' || (normalized !== 'accept' && !normalized.startsWith('x-absolute-mobile-'))) throw new Error('Expo bridge HTTP header is not allowed.');
6460
+ if (typeof value !== 'string' || (normalized !== 'accept' && normalized !== 'content-type' && !normalized.startsWith('x-absolute-mobile-'))) throw new Error('Expo bridge HTTP header is not allowed.');
6306
6461
  headers.set(normalized, value);
6307
6462
  }
6308
- const response = await fetch(url, { headers, method: 'GET', redirect: 'manual' });
6463
+ const response = await ${auth ? "absoluteExpoAuth.fetchOptional" : "fetch"}(url, { ...(typeof params.body === 'string' ? { body: params.body } : {}), headers, method: params.method, redirect: 'manual' });
6309
6464
  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.');
6310
6465
  const body = await response.text();
6311
6466
  if (new TextEncoder().encode(body).byteLength > MAX_HTTP_BODY_BYTES) throw new Error('Expo bridge HTTP response exceeds 48 KiB.');
@@ -6317,13 +6472,32 @@ const bridgeFetch = async (params: Record<string, unknown>) => {
6317
6472
  return { body, headers: responseHeaders, status: response.status };
6318
6473
  };
6319
6474
 
6475
+ const authStatus = async () => {
6476
+ ${auth ? `const user = await absoluteExpoAuth.status();
6477
+ const principal = getAbsoluteExpoAuthPrincipal();
6478
+ return { principal: principal ? { namespace: principal.namespace } : null, user };` : "throw new Error('Expo Auth is not configured.');"}
6479
+ };
6480
+
6320
6481
  export function AbsoluteWebHost() {
6321
6482
  const pathname = usePathname() || '/';
6322
6483
  const webView = useRef<WebView>(null);
6323
6484
  const [indexUri, setIndexUri] = useState<string>();
6324
6485
  const [canGoBack, setCanGoBack] = useState(false);
6486
+ const [authReady, setAuthReady] = useState(!AUTH_ENABLED);
6325
6487
  const activeWebPath = useRef(pathname);
6326
6488
 
6489
+ useEffect(() => {
6490
+ if (!AUTH_ENABLED) return;
6491
+ let active = true;
6492
+ ${auth ? `const stop = absoluteExpoAuth.onPrincipalChange(principal => {
6493
+ if (!active) return;
6494
+ const source = JSON.stringify({ event: 'auth.principal', format: BRIDGE_FORMAT, kind: 'event', path: activeWebPath.current, payload: { principal: principal ? { namespace: principal.namespace } : null } });
6495
+ webView.current?.injectJavaScript(\`globalThis.__absoluteExpoReceive(\${JSON.stringify(source)}); true;\`);
6496
+ });
6497
+ void startAbsoluteExpoAuth().then(() => { if (active) setAuthReady(true); });
6498
+ return () => { active = false; stop(); };` : ""}
6499
+ }, []);
6500
+
6327
6501
  useEffect(() => {
6328
6502
  if (DEV_ORIGIN) {
6329
6503
  const target = new URL(pathname, DEV_ORIGIN);
@@ -6373,6 +6547,16 @@ export function AbsoluteWebHost() {
6373
6547
  respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: null });
6374
6548
  } else if (message.method === 'http.fetch') {
6375
6549
  respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await bridgeFetch(message.params as Record<string, unknown>) });
6550
+ } else if (message.method === 'auth.signIn') {
6551
+ ${auth ? `const params = message.params as Record<string, unknown>;
6552
+ if (typeof params.email !== 'string' || typeof params.signup !== 'boolean') throw new Error('Expo Auth sign-in params are invalid.');
6553
+ await absoluteExpoAuth.signIn({ authorizationParameters: { login_hint: params.email, ...(params.signup ? { screen_hint: 'signup' } : {}) } });
6554
+ respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await authStatus() });` : "throw new Error('Expo Auth is not configured.');"}
6555
+ } else if (message.method === 'auth.signOut') {
6556
+ ${auth ? `await absoluteExpoAuth.signOut();
6557
+ respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: null });` : "throw new Error('Expo Auth is not configured.');"}
6558
+ } else if (message.method === 'auth.status') {
6559
+ respond({ format: BRIDGE_FORMAT, id: message.id, kind: 'response', result: await authStatus() });
6376
6560
  } else {
6377
6561
  throw new Error('Expo bridge method is not allowed.');
6378
6562
  }
@@ -6381,7 +6565,7 @@ export function AbsoluteWebHost() {
6381
6565
  }
6382
6566
  };
6383
6567
 
6384
- if (!indexUri) return <View style={styles.loading}><ActivityIndicator /></View>;
6568
+ if (!indexUri || !authReady) return <View style={styles.loading}><ActivityIndicator /></View>;
6385
6569
  return <WebView
6386
6570
  allowFileAccess
6387
6571
  allowFileAccessFromFileURLs
@@ -6414,9 +6598,17 @@ export default AbsoluteWebHost;
6414
6598
  `;
6415
6599
  var nativeWrapperSource = (wrapper, module) => `${EXPO_GENERATED_HEADER}export { default } from ${JSON.stringify(portableRelative2(dirname10(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
6416
6600
  `;
6417
- var expoTsConfig = (projectRoot, project) => ({
6601
+ var expoTsConfig = (projectRoot, project, auth) => ({
6418
6602
  compilerOptions: {
6419
6603
  paths: {
6604
+ ...auth ? {
6605
+ "@absolutejs/auth": [
6606
+ "./node_modules/@absolutejs/auth/dist/index.d.ts"
6607
+ ],
6608
+ "@absolutejs/auth/*": [
6609
+ "./node_modules/@absolutejs/auth/dist/*"
6610
+ ]
6611
+ } : {},
6420
6612
  "*": [
6421
6613
  "./node_modules/*",
6422
6614
  `${portableRelative2(project, projectRoot)}/node_modules/*`
@@ -6454,6 +6646,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
6454
6646
  throw new TypeError("Expo project generation requires mobile.engine: expo.");
6455
6647
  const projectRoot = resolve12(options.projectRoot);
6456
6648
  const project = config.nativeProjectDirectory;
6649
+ const auth = resolveAbsoluteMobileAuthManifest(projectRoot, config);
6457
6650
  const routeModules = Object.entries(config.expoNativeRoutes);
6458
6651
  const moduleChecks = await Promise.all(routeModules.map(async ([route, module]) => ({
6459
6652
  exists: await exists3(module),
@@ -6474,6 +6667,7 @@ var writeAbsoluteExpoProject = async (config, options) => {
6474
6667
  await mkdir11(project, { recursive: true });
6475
6668
  await writeFile12(marker, `format=1
6476
6669
  `);
6670
+ const authEnabled = Boolean(auth);
6477
6671
  const files = new Map([
6478
6672
  [
6479
6673
  join14(project, ".gitignore"),
@@ -6483,9 +6677,12 @@ ios/
6483
6677
  node_modules/
6484
6678
  `
6485
6679
  ],
6486
- [join14(project, "app.json"), jsonSource(expoAppConfig(config))],
6680
+ [
6681
+ join14(project, "app.json"),
6682
+ jsonSource(expoAppConfig(config, authEnabled))
6683
+ ],
6487
6684
  [join14(project, "app.config.js"), expoDynamicAppConfig],
6488
- [join14(project, "package.json"), jsonSource(expoPackage())],
6685
+ [join14(project, "package.json"), jsonSource(expoPackage(authEnabled))],
6489
6686
  [join14(project, "metro.config.js"), metroConfig(projectRoot)],
6490
6687
  [
6491
6688
  join14(project, "plugins", "withAbsoluteDevelopmentCa.js"),
@@ -6493,18 +6690,21 @@ node_modules/
6493
6690
  ],
6494
6691
  [
6495
6692
  join14(project, "tsconfig.json"),
6496
- jsonSource(expoTsConfig(projectRoot, project))
6693
+ jsonSource(expoTsConfig(projectRoot, project, authEnabled))
6497
6694
  ],
6498
- [join14(project, "app", "_layout.tsx"), layoutSource],
6695
+ [join14(project, "app", "_layout.tsx"), layoutSource(authEnabled)],
6499
6696
  [
6500
6697
  join14(project, "app", "__absolute", "native", "index.tsx"),
6501
6698
  nativeDiagnosticSource
6502
6699
  ],
6503
6700
  [
6504
6701
  join14(project, "src", "generated", "AbsoluteWebHost.tsx"),
6505
- webHostSource(config)
6702
+ webHostSource(config, auth)
6506
6703
  ]
6507
6704
  ]);
6705
+ if (auth) {
6706
+ files.set(join14(project, "src", "generated", "AbsoluteAuth.ts"), authRuntimeSource(auth, config.appId));
6707
+ }
6508
6708
  const webAssetsPath = join14(project, "src", "generated", "webAssets.ts");
6509
6709
  if (!await exists3(webAssetsPath)) {
6510
6710
  files.set(webAssetsPath, emptyWebAssetsSource);
@@ -6703,10 +6903,10 @@ var finalizeAbsoluteMobileCompatibilityBuild = async (options) => {
6703
6903
  runtime: String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)
6704
6904
  });
6705
6905
  const auth = resolveAbsoluteMobileAuthManifest(options.projectRoot, mobile);
6706
- if (mobile.engine === "expo" && auth) {
6707
- 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.");
6708
- }
6709
6906
  const sync = auth !== undefined && projectUsesAbsoluteSync(options.projectRoot);
6907
+ if (mobile.engine === "expo" && sync) {
6908
+ 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.");
6909
+ }
6710
6910
  const syncSchema = sync ? discoverAbsoluteSyncSchema(options.projectRoot) : undefined;
6711
6911
  const deviceCapabilities = resolveAbsoluteDeviceCapabilityPlan(options.projectRoot);
6712
6912
  const usesPush = deviceCapabilities.capabilities.includes("pushNotifications");
@@ -6867,11 +7067,14 @@ var installAbsoluteMobileSyncRemediation = (bridge = {
6867
7067
  init_deviceCapabilities();
6868
7068
 
6869
7069
  // src/mobile/expoBridge.ts
6870
- var ABSOLUTE_EXPO_BRIDGE_FORMAT = 1;
7070
+ var ABSOLUTE_EXPO_BRIDGE_FORMAT = 2;
6871
7071
  var ABSOLUTE_EXPO_BRIDGE_MAX_BYTES = 64 * 1024;
6872
7072
  var ABSOLUTE_EXPO_BRIDGE_METHODS = [
6873
7073
  "devices.haptics.impact",
6874
- "http.fetch"
7074
+ "http.fetch",
7075
+ "auth.signIn",
7076
+ "auth.signOut",
7077
+ "auth.status"
6875
7078
  ];
6876
7079
  var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
6877
7080
  var validId = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,80}$/u.test(value);
@@ -6911,15 +7114,27 @@ var parseRequest = (value) => {
6911
7114
  const loopbackHttp = url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]");
6912
7115
  if (url.protocol !== "https:" && !loopbackHttp)
6913
7116
  throw new TypeError("Expo bridge HTTP URL must use HTTPS.");
6914
- if (value.params.method !== "GET")
7117
+ if (typeof value.params.method !== "string" || !["DELETE", "GET", "PATCH", "POST", "PUT"].includes(value.params.method))
6915
7118
  throw new TypeError("Expo bridge HTTP method is not allowed.");
7119
+ if (value.params.body !== undefined && typeof value.params.body !== "string")
7120
+ throw new TypeError("Expo bridge HTTP body is invalid.");
7121
+ if (typeof value.params.body === "string" && new TextEncoder().encode(value.params.body).byteLength > 48 * 1024)
7122
+ throw new TypeError("Expo bridge HTTP body exceeds 48 KiB.");
7123
+ if ((value.params.method === "GET" || value.params.method === "DELETE") && value.params.body !== undefined)
7124
+ throw new TypeError("Expo bridge HTTP method cannot contain a body.");
6916
7125
  if (!isRecord8(value.params.headers))
6917
7126
  throw new TypeError("Expo bridge HTTP headers must be an object.");
6918
- const headersAllowed = Object.entries(value.params.headers).every(([name, header]) => typeof header === "string" && (name.toLowerCase() === "accept" || name.toLowerCase().startsWith("x-absolute-mobile-")));
7127
+ const headersAllowed = Object.entries(value.params.headers).every(([name, header]) => typeof header === "string" && (name.toLowerCase() === "accept" || name.toLowerCase() === "content-type" || name.toLowerCase().startsWith("x-absolute-mobile-")));
6919
7128
  if (!headersAllowed) {
6920
7129
  throw new TypeError("Expo bridge HTTP header is not allowed.");
6921
7130
  }
6922
7131
  }
7132
+ if (method === "auth.signIn") {
7133
+ if (typeof value.params.email !== "string" || value.params.email.length > 320 || typeof value.params.signup !== "boolean")
7134
+ throw new TypeError("Expo bridge Auth sign-in params are invalid.");
7135
+ }
7136
+ if ((method === "auth.signOut" || method === "auth.status") && Object.keys(value.params).length !== 0)
7137
+ throw new TypeError("Expo bridge Auth params must be empty.");
6923
7138
  return {
6924
7139
  format: ABSOLUTE_EXPO_BRIDGE_FORMAT,
6925
7140
  id: value.id,
@@ -6958,7 +7173,7 @@ var parseResponse = (value) => {
6958
7173
  };
6959
7174
  };
6960
7175
  var parseEvent = (value) => {
6961
- if (value.event !== "ready" && value.event !== "navigation") {
7176
+ if (value.event !== "ready" && value.event !== "navigation" && value.event !== "auth.principal") {
6962
7177
  throw new TypeError("Expo bridge event is not allowed.");
6963
7178
  }
6964
7179
  if (typeof value.path !== "string" || !validPath(value.path))
@@ -7020,7 +7235,8 @@ var commandEnvironment = (options) => ({
7020
7235
  ABSOLUTE_EXPO_DEVELOPMENT_CA_PATH: options.certificateAuthorityPath
7021
7236
  } : {},
7022
7237
  ...options.androidOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN: options.androidOrigin } : {},
7023
- ...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {}
7238
+ ...options.iosOrigin ? { EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN: options.iosOrigin } : {},
7239
+ ...options.metroHost ? { REACT_NATIVE_PACKAGER_HOSTNAME: options.metroHost } : {}
7024
7240
  });
7025
7241
  var absoluteExpoExecutable = async (project) => {
7026
7242
  const executable = join16(project, "node_modules", ".bin", "expo");
@@ -7034,8 +7250,8 @@ var absoluteExpoExecutable = async (project) => {
7034
7250
  var planAbsoluteExpoDevSession = (config, options) => {
7035
7251
  if (config.engine !== "expo")
7036
7252
  throw new TypeError("The Expo development controller requires Expo.");
7037
- if (options.platforms.length === 0)
7038
- throw new TypeError("Expo development requires a local target platform.");
7253
+ if (options.platforms.length === 0 && options.metro === "external")
7254
+ throw new TypeError("External Expo execution requires a target platform.");
7039
7255
  const secureOrigin = [options.androidOrigin, options.iosOrigin].some((origin) => origin && new URL(origin).protocol === "https:");
7040
7256
  if (secureOrigin && !options.certificateAuthorityPath)
7041
7257
  throw new TypeError("Expo HTTPS development requires the AbsoluteJS development CA certificate.");
@@ -7052,7 +7268,7 @@ var planAbsoluteExpoDevSession = (config, options) => {
7052
7268
  env,
7053
7269
  role: "metro"
7054
7270
  };
7055
- const prepare = {
7271
+ const prepare = options.platforms.length === 0 ? undefined : {
7056
7272
  args: [
7057
7273
  "prebuild",
7058
7274
  "--clean",
@@ -7080,7 +7296,11 @@ var planAbsoluteExpoDevSession = (config, options) => {
7080
7296
  return command;
7081
7297
  });
7082
7298
  return {
7083
- commands: [prepare, metro, ...native],
7299
+ commands: [
7300
+ ...prepare ? [prepare] : [],
7301
+ ...options.metro === "external" ? [] : [metro],
7302
+ ...native
7303
+ ],
7084
7304
  metroPort: options.metroPort,
7085
7305
  project: config.nativeProjectDirectory
7086
7306
  };
@@ -7169,47 +7389,48 @@ var startAbsoluteExpoDevSession = async (options) => {
7169
7389
  const prepareCommand = plan.commands.find((command) => command.role === "native-prepare");
7170
7390
  const metroCommand = plan.commands.find((command) => command.role === "metro");
7171
7391
  const nativeCommands = plan.commands.filter((command) => command.role === "native-build");
7172
- if (!prepareCommand)
7173
- throw new TypeError("Expo native preparation command is missing.");
7174
- if (!metroCommand)
7175
- throw new TypeError("Expo Metro command is missing.");
7176
- setState("preparing-native");
7177
- const prepareStarted = performance.now();
7178
- const prepareProcess = run(executable, prepareCommand.args, {
7179
- cwd: plan.project,
7180
- env: { ...process.env, ...prepareCommand.env },
7181
- stdio: ["ignore", "pipe", "pipe"]
7182
- });
7183
- forwardLines(prepareProcess, (line) => {
7184
- if (line)
7185
- log(`[prebuild] ${line}`);
7186
- });
7187
- const abortPrepare = () => void stopProcess(prepareProcess);
7188
- options.signal?.addEventListener("abort", abortPrepare, { once: true });
7189
- const prepareExit = await waitForExit(prepareProcess);
7190
- options.signal?.removeEventListener("abort", abortPrepare);
7191
- if (options.signal?.aborted)
7192
- throw abortError();
7193
- if (prepareExit !== 0) {
7194
- setState("failed");
7195
- throw new Error(`Expo native preparation exited with status ${prepareExit}.`);
7196
- }
7197
- const prepareMs = performance.now() - prepareStarted;
7198
- timings["preparing-native"] = prepareMs;
7199
- options.onPhaseTiming?.({
7200
- durationMs: prepareMs,
7201
- phase: "preparing-native"
7202
- });
7203
- setState("starting-metro");
7392
+ const runPrepareCommand = async (command) => {
7393
+ setState("preparing-native");
7394
+ const prepareStarted = performance.now();
7395
+ const prepareProcess = run(executable, command.args, {
7396
+ cwd: plan.project,
7397
+ env: { ...process.env, ...command.env },
7398
+ stdio: ["ignore", "pipe", "pipe"]
7399
+ });
7400
+ forwardLines(prepareProcess, (line) => {
7401
+ if (line)
7402
+ log(`[prebuild] ${line}`);
7403
+ });
7404
+ const abortPrepare = () => void stopProcess(prepareProcess);
7405
+ options.signal?.addEventListener("abort", abortPrepare, { once: true });
7406
+ const prepareExit = await waitForExit(prepareProcess);
7407
+ options.signal?.removeEventListener("abort", abortPrepare);
7408
+ if (options.signal?.aborted)
7409
+ throw abortError();
7410
+ if (prepareExit !== 0) {
7411
+ setState("failed");
7412
+ throw new Error(`Expo native preparation exited with status ${prepareExit}.`);
7413
+ }
7414
+ publishTiming("preparing-native", performance.now() - prepareStarted);
7415
+ };
7416
+ if (prepareCommand)
7417
+ await runPrepareCommand(prepareCommand);
7418
+ const managedMetro = metroCommand !== undefined;
7419
+ if (managedMetro)
7420
+ setState("starting-metro");
7204
7421
  const metroStarted = performance.now();
7205
- const metro = run(executable, metroCommand.args, {
7422
+ const metro = metroCommand ? run(executable, metroCommand.args, {
7206
7423
  cwd: plan.project,
7207
7424
  env: { ...process.env, ...metroCommand.env },
7208
7425
  stdio: ["ignore", "pipe", "pipe"]
7209
- });
7426
+ }) : undefined;
7210
7427
  let metroReady = false;
7211
7428
  let resolveMetro;
7212
7429
  const metroPromise = new Promise((resolve14, reject) => {
7430
+ if (!metro) {
7431
+ resolve14();
7432
+ return;
7433
+ }
7213
7434
  const timeout = setTimeout(() => {
7214
7435
  reject(new Error("Expo Metro did not become ready within 60 seconds."));
7215
7436
  }, METRO_READY_TIMEOUT_MS);
@@ -7224,15 +7445,19 @@ var startAbsoluteExpoDevSession = async (options) => {
7224
7445
  }
7225
7446
  });
7226
7447
  });
7227
- forwardLines(metro, (line) => {
7228
- if (line)
7229
- log(`[metro] ${line}`);
7230
- if (!metroReady && /(?:Waiting on|Metro waiting on|Dev server ready)/iu.test(line)) {
7231
- metroReady = true;
7232
- resolveMetro?.();
7233
- }
7234
- });
7235
- const abort = () => void stopProcess(metro);
7448
+ if (metro)
7449
+ forwardLines(metro, (line) => {
7450
+ if (line)
7451
+ log(`[metro] ${line}`);
7452
+ if (!metroReady && /(?:Waiting on|Metro waiting on|Dev server ready)/iu.test(line)) {
7453
+ metroReady = true;
7454
+ resolveMetro?.();
7455
+ }
7456
+ });
7457
+ const abort = () => {
7458
+ if (metro)
7459
+ stopProcess(metro);
7460
+ };
7236
7461
  options.signal?.addEventListener("abort", abort, { once: true });
7237
7462
  const runNativeCommand = async (command) => {
7238
7463
  if (options.signal?.aborted)
@@ -7313,12 +7538,8 @@ var startAbsoluteExpoDevSession = async (options) => {
7313
7538
  try {
7314
7539
  await startPhysicalIosEnrollment();
7315
7540
  await metroPromise;
7316
- const metroMs = performance.now() - metroStarted;
7317
- timings["starting-metro"] = metroMs;
7318
- options.onPhaseTiming?.({
7319
- durationMs: metroMs,
7320
- phase: "starting-metro"
7321
- });
7541
+ if (managedMetro)
7542
+ publishTiming("starting-metro", performance.now() - metroStarted);
7322
7543
  await runNativeCommands(nativeCommands);
7323
7544
  setState("ready");
7324
7545
  return {
@@ -7327,19 +7548,25 @@ var startAbsoluteExpoDevSession = async (options) => {
7327
7548
  timings,
7328
7549
  close: async () => {
7329
7550
  options.signal?.removeEventListener("abort", abort);
7330
- await stopProcess(metro);
7551
+ if (metro)
7552
+ await stopProcess(metro);
7331
7553
  await closeEnrollmentServer();
7332
7554
  setState("closed");
7333
7555
  }
7334
7556
  };
7335
7557
  } catch (error) {
7336
7558
  options.signal?.removeEventListener("abort", abort);
7337
- await stopProcess(metro);
7559
+ if (metro)
7560
+ await stopProcess(metro);
7338
7561
  await closeEnrollmentServer();
7339
7562
  setState("failed");
7340
7563
  throw error;
7341
7564
  }
7342
7565
  };
7566
+
7567
+ // src/mobile/index.ts
7568
+ init_config();
7569
+
7343
7570
  // src/mobile/ciWorkflow.ts
7344
7571
  import { existsSync as existsSync3 } from "fs";
7345
7572
  import { access as access11, mkdir as mkdir12, readFile as readFile16, writeFile as writeFile13 } from "fs/promises";
@@ -8562,6 +8789,10 @@ var applyAbsoluteNativeDeviceCapabilities = async (projectRoot, config, platform
8562
8789
  changed: results.filter(({ didChange }) => didChange).map(({ platform: platform2 }) => platform2)
8563
8790
  };
8564
8791
  };
8792
+
8793
+ // src/mobile/index.ts
8794
+ init_nativeAuth();
8795
+
8565
8796
  // src/mobile/releasePublisher.ts
8566
8797
  import { access as access12 } from "fs/promises";
8567
8798
  import { isAbsolute as isAbsolute6, relative as relative12, resolve as resolve15, sep as sep7 } from "path";
@@ -9395,155 +9626,160 @@ var http = createAbsoluteHttpClient();
9395
9626
  // src/mobile/shellHttp.ts
9396
9627
  var installAbsoluteMobileShellHttp = (origin, fetch2 = globalThis.fetch) => installAbsoluteHttpTransport(createAbsoluteHttpTransport({ fetch: fetch2, origin, runtime: "native" }));
9397
9628
  export {
9398
- writeAbsoluteMobileGithubWorkflow,
9399
- writeAbsoluteExpoProject,
9400
- writeAbsoluteCapacitorConfig,
9401
- waitForAbsoluteIosHmrLog,
9402
- verifyAbsoluteMobileCompatibilityProducer,
9403
- verifyAbsoluteMobileAssociationFiles,
9404
- validateAbsoluteSshDestination,
9405
- validateAbsoluteRemoteMacProfileName,
9406
- testAbsoluteIosPhysicalDevice,
9407
- syncAbsoluteRemoteMacProject,
9408
- syncAbsoluteExpoWebAssets,
9409
- startAbsoluteRemoteIosDevSession,
9410
- startAbsoluteIosTcpRelay,
9411
- startAbsoluteIosDevSession,
9412
- startAbsoluteIosCaEnrollmentServer,
9413
- startAbsoluteExpoDevSession,
9414
- serializeAbsoluteMobileAuthEnvironment,
9415
- runWithAbsoluteMobileProducer,
9416
- runAbsoluteAndroidUpgradeConformance,
9417
- retainAbsoluteMobileCompatibilityArtifacts,
9418
- resolveAbsoluteMobileRoute,
9419
- resolveAbsoluteMobileNavigation,
9420
- resolveAbsoluteMobileDeepLink,
9421
- resolveAbsoluteMobileCompatibilityRelease,
9422
- resolveAbsoluteMobileAuthManifest,
9423
- resolveAbsoluteDeviceCapabilityPlan,
9424
- repairAbsoluteIosDevSession,
9425
- removeAbsoluteRemoteMacProfile,
9426
- redactAbsoluteIosLog,
9427
- readAbsoluteMobileMaterializedReleases,
9428
- publishAbsoluteIosRelease,
9429
- publishAbsoluteAndroidRelease,
9430
- projectUsesAbsoluteSync,
9431
- projectUsesAbsoluteAuth,
9432
- projectImportsAbsoluteDeviceCapability,
9433
- prepareAbsoluteIosRelease,
9434
- prepareAbsoluteIosDevProject,
9435
- prepareAbsoluteAndroidRelease,
9436
- planAbsoluteExpoDevSession,
9437
- parseIosSimulators,
9438
- parseIosRuntimes,
9439
- parseIosDeviceTypes,
9440
- parseAbsoluteMobilePageRequest,
9441
- parseAbsoluteMobilePageEnvelope,
9442
- parseAbsoluteMobileCompatibilityArtifact,
9443
- parseAbsoluteMobileBuildPageMetadata,
9444
- parseAbsoluteIosLogLine,
9445
- parseAbsoluteIosHmrLog,
9446
- parseAbsoluteExpoBridgeMessage,
9447
- parseAbsoluteAndroidInstalledApp,
9448
- pairAbsoluteRemoteMac,
9449
- normalizeAbsoluteMobileConfig,
9450
- normalizeAbsoluteIosDeviceIdentifier,
9451
- normalizeAbsoluteIosDeviceHost,
9452
- navigateAbsoluteMobilePage,
9453
- missingAbsoluteDeviceCapabilityPackages,
9454
- materializeAbsoluteRemoteMacAgent,
9455
- materializeAbsoluteMobileCompatibilityBundle,
9456
- materializeAbsoluteMobileAssociationFiles,
9457
- materializeAbsoluteCapacitorWebBundle,
9458
- matchesAbsoluteMobileRoutePattern,
9459
- loadAbsoluteNativeReleasePublisher,
9460
- loadAbsoluteMobileMaterializedBundle,
9461
- loadAbsoluteDeviceCapabilityProviders,
9462
- listAbsoluteRemoteMacProfiles,
9463
- isAbsoluteIosNativeRootInput,
9464
- installAbsoluteRemoteMacAgent,
9465
- installAbsoluteMobileSyncRemediation,
9466
- installAbsoluteMobileShellHttp,
9467
- installAbsoluteMobileAuthEnvironment,
9468
- inspectAbsoluteRemoteMacLanHost,
9469
- inspectAbsoluteRemoteMac,
9470
- inspectAbsoluteMobileRouteMetadata,
9471
- inspectAbsoluteAndroidInstalledApp,
9472
- hashAbsoluteMobilePropsSchema,
9473
- getCurrentAbsoluteMobileProducerContext,
9474
- getAbsoluteRemoteMacProfile,
9475
- getAbsoluteMobileSyncRemediation,
9476
- fingerprintAbsoluteIosNativeProject,
9477
- fingerprintAbsoluteIosDevProject,
9478
- finalizeAbsoluteMobilePage,
9479
- finalizeAbsoluteMobileCompatibilityBuild,
9480
- fetchAbsoluteMobilePage,
9481
- disposeAbsoluteMobilePage,
9482
- discoverAbsoluteSyncSchema,
9483
- discoverAbsoluteDeviceCapabilities,
9484
- directAbsoluteProjectPackages,
9485
- createAbsoluteRemoteIosDevProject,
9486
- createAbsoluteMobileUpgradeResponse,
9487
- createAbsoluteMobileRouteMetadataPlugin,
9488
- createAbsoluteMobilePreviewPlugin,
9489
- createAbsoluteMobilePageRequest,
9490
- createAbsoluteMobilePageErrorResponse,
9491
- createAbsoluteMobileInvalidRequestResponse,
9492
- createAbsoluteMobileGithubWorkflow,
9493
- createAbsoluteMobileFileArtifactStore,
9494
- createAbsoluteMobileCompatibilityDispatcher,
9495
- createAbsoluteMobileCompatibilityArtifact,
9496
- createAbsoluteMobileBlobArtifactStore,
9497
- createAbsoluteMobileAuthManifest,
9498
- createAbsoluteMobileAssociationPlugin,
9499
- createAbsoluteMobileAssociationDocuments,
9500
- createAbsoluteIosNativeWatcher,
9501
- createAbsoluteExpoBridgeResponse,
9502
- createAbsoluteExpoBridgeError,
9503
- carryForwardAbsoluteMobileCompatibilityReleases,
9504
- captureAbsoluteRemoteMacCommand,
9505
- captureAbsoluteMobileRouteGraph,
9506
- buildAbsoluteMobileCompatibilityRelease,
9507
- buildAbsoluteIosRelease,
9508
- buildAbsoluteAndroidRelease,
9509
- assertAbsoluteDeviceCapabilityPackages,
9510
- applyAbsoluteNativeDeviceCapabilities,
9511
- applyAbsoluteNativeDeepLinks,
9512
- activateAbsoluteMobilePage,
9513
- acceptsAbsoluteMobilePage,
9514
- absoluteRemoteProjectSyncCommands,
9515
- absoluteRemoteMacSshBase,
9516
- absoluteMobilePreviewDocument,
9517
- absoluteIosDeviceAcceptanceCommands,
9518
- absoluteExpoExecutable,
9519
- absoluteDeviceNativeRequirements,
9520
- MOBILE_PAGE_REQUEST_HEADERS,
9521
- AbsoluteMobilePageProtocolError,
9522
- APPLE_ASSOCIATION_PATH,
9523
- ANDROID_ASSOCIATION_PATH,
9524
- ABSOLUTE_SYNC_PACKAGE,
9525
- ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION,
9526
- ABSOLUTE_REMOTE_MAC_EVENT_PREFIX,
9527
- ABSOLUTE_NATIVE_AUTH_SCOPES,
9528
- ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
9529
- ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL,
9530
- ABSOLUTE_MOBILE_ROUTE_DETAIL,
9531
- ABSOLUTE_MOBILE_RETAINED_GENERATIONS,
9532
- ABSOLUTE_MOBILE_PREVIEW_PATH,
9533
- ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
9534
- ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE,
9535
- ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT,
9536
- ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT,
9537
- ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
9538
- ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
9539
- ABSOLUTE_IOS_SIMULATOR_NAME,
9540
- ABSOLUTE_IOS_RELEASE_FORMAT,
9541
- ABSOLUTE_EXPO_BRIDGE_METHODS,
9542
- ABSOLUTE_EXPO_BRIDGE_MAX_BYTES,
9543
- ABSOLUTE_EXPO_BRIDGE_FORMAT,
9629
+ ABSOLUTE_ANDROID_RELEASE_FORMAT,
9544
9630
  ABSOLUTE_AUTH_PACKAGE,
9545
- ABSOLUTE_ANDROID_RELEASE_FORMAT
9631
+ ABSOLUTE_EXPO_AUTH_CORE_VERSION,
9632
+ ABSOLUTE_EXPO_AUTH_PACKAGE,
9633
+ ABSOLUTE_EXPO_AUTH_VERSION,
9634
+ ABSOLUTE_EXPO_BRIDGE_FORMAT,
9635
+ ABSOLUTE_EXPO_BRIDGE_MAX_BYTES,
9636
+ ABSOLUTE_EXPO_BRIDGE_METHODS,
9637
+ ABSOLUTE_IOS_RELEASE_FORMAT,
9638
+ ABSOLUTE_IOS_SIMULATOR_NAME,
9639
+ ABSOLUTE_MOBILE_CI_WORKFLOW_FORMAT,
9640
+ ABSOLUTE_MOBILE_CLIENT_MANIFEST_FORMAT,
9641
+ ABSOLUTE_MOBILE_COMPATIBILITY_FORMAT,
9642
+ ABSOLUTE_MOBILE_MATERIALIZED_BUNDLE_FORMAT,
9643
+ ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE,
9644
+ ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION,
9645
+ ABSOLUTE_MOBILE_PREVIEW_PATH,
9646
+ ABSOLUTE_MOBILE_RETAINED_GENERATIONS,
9647
+ ABSOLUTE_MOBILE_ROUTE_DETAIL,
9648
+ ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL,
9649
+ ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
9650
+ ABSOLUTE_NATIVE_AUTH_SCOPES,
9651
+ ABSOLUTE_REMOTE_MAC_EVENT_PREFIX,
9652
+ ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION,
9653
+ ABSOLUTE_SYNC_PACKAGE,
9654
+ ANDROID_ASSOCIATION_PATH,
9655
+ APPLE_ASSOCIATION_PATH,
9656
+ AbsoluteMobilePageProtocolError,
9657
+ MOBILE_PAGE_REQUEST_HEADERS,
9658
+ absoluteDeviceNativeRequirements,
9659
+ absoluteExpoExecutable,
9660
+ absoluteIosDeviceAcceptanceCommands,
9661
+ absoluteMobilePreviewDocument,
9662
+ absoluteRemoteMacSshBase,
9663
+ absoluteRemoteProjectSyncCommands,
9664
+ acceptsAbsoluteMobilePage,
9665
+ activateAbsoluteMobilePage,
9666
+ applyAbsoluteNativeDeepLinks,
9667
+ applyAbsoluteNativeDeviceCapabilities,
9668
+ assertAbsoluteDeviceCapabilityPackages,
9669
+ buildAbsoluteAndroidRelease,
9670
+ buildAbsoluteIosRelease,
9671
+ buildAbsoluteMobileCompatibilityRelease,
9672
+ captureAbsoluteMobileRouteGraph,
9673
+ captureAbsoluteRemoteMacCommand,
9674
+ carryForwardAbsoluteMobileCompatibilityReleases,
9675
+ createAbsoluteExpoBridgeError,
9676
+ createAbsoluteExpoBridgeResponse,
9677
+ createAbsoluteIosNativeWatcher,
9678
+ createAbsoluteMobileAssociationDocuments,
9679
+ createAbsoluteMobileAssociationPlugin,
9680
+ createAbsoluteMobileAuthManifest,
9681
+ createAbsoluteMobileBlobArtifactStore,
9682
+ createAbsoluteMobileCompatibilityArtifact,
9683
+ createAbsoluteMobileCompatibilityDispatcher,
9684
+ createAbsoluteMobileFileArtifactStore,
9685
+ createAbsoluteMobileGithubWorkflow,
9686
+ createAbsoluteMobileInvalidRequestResponse,
9687
+ createAbsoluteMobilePageErrorResponse,
9688
+ createAbsoluteMobilePageRequest,
9689
+ createAbsoluteMobilePreviewPlugin,
9690
+ createAbsoluteMobileRouteMetadataPlugin,
9691
+ createAbsoluteMobileUpgradeResponse,
9692
+ createAbsoluteRemoteExpoIosDevProject,
9693
+ createAbsoluteRemoteIosDevProject,
9694
+ directAbsoluteProjectPackages,
9695
+ discoverAbsoluteDeviceCapabilities,
9696
+ discoverAbsoluteSyncSchema,
9697
+ disposeAbsoluteMobilePage,
9698
+ fetchAbsoluteMobilePage,
9699
+ finalizeAbsoluteMobileCompatibilityBuild,
9700
+ finalizeAbsoluteMobilePage,
9701
+ fingerprintAbsoluteIosDevProject,
9702
+ fingerprintAbsoluteIosNativeProject,
9703
+ getAbsoluteMobileSyncRemediation,
9704
+ getAbsoluteRemoteMacProfile,
9705
+ getCurrentAbsoluteMobileProducerContext,
9706
+ hashAbsoluteMobilePropsSchema,
9707
+ inspectAbsoluteAndroidInstalledApp,
9708
+ inspectAbsoluteMobileRouteMetadata,
9709
+ inspectAbsoluteRemoteMac,
9710
+ inspectAbsoluteRemoteMacLanHost,
9711
+ installAbsoluteMobileAuthEnvironment,
9712
+ installAbsoluteMobileShellHttp,
9713
+ installAbsoluteMobileSyncRemediation,
9714
+ installAbsoluteRemoteMacAgent,
9715
+ isAbsoluteIosNativeRootInput,
9716
+ listAbsoluteRemoteMacProfiles,
9717
+ loadAbsoluteDeviceCapabilityProviders,
9718
+ loadAbsoluteMobileMaterializedBundle,
9719
+ loadAbsoluteNativeReleasePublisher,
9720
+ matchesAbsoluteMobileRoutePattern,
9721
+ materializeAbsoluteCapacitorWebBundle,
9722
+ materializeAbsoluteMobileAssociationFiles,
9723
+ materializeAbsoluteMobileCompatibilityBundle,
9724
+ materializeAbsoluteRemoteMacAgent,
9725
+ missingAbsoluteDeviceCapabilityPackages,
9726
+ navigateAbsoluteMobilePage,
9727
+ normalizeAbsoluteIosDeviceHost,
9728
+ normalizeAbsoluteIosDeviceIdentifier,
9729
+ normalizeAbsoluteMobileConfig,
9730
+ pairAbsoluteRemoteMac,
9731
+ parseAbsoluteAndroidInstalledApp,
9732
+ parseAbsoluteExpoBridgeMessage,
9733
+ parseAbsoluteIosHmrLog,
9734
+ parseAbsoluteIosLogLine,
9735
+ parseAbsoluteMobileBuildPageMetadata,
9736
+ parseAbsoluteMobileCompatibilityArtifact,
9737
+ parseAbsoluteMobilePageEnvelope,
9738
+ parseAbsoluteMobilePageRequest,
9739
+ parseIosDeviceTypes,
9740
+ parseIosRuntimes,
9741
+ parseIosSimulators,
9742
+ planAbsoluteExpoDevSession,
9743
+ prepareAbsoluteAndroidRelease,
9744
+ prepareAbsoluteIosDevProject,
9745
+ prepareAbsoluteIosRelease,
9746
+ projectImportsAbsoluteDeviceCapability,
9747
+ projectUsesAbsoluteAuth,
9748
+ projectUsesAbsoluteSync,
9749
+ publishAbsoluteAndroidRelease,
9750
+ publishAbsoluteIosRelease,
9751
+ readAbsoluteMobileMaterializedReleases,
9752
+ redactAbsoluteIosLog,
9753
+ removeAbsoluteRemoteMacProfile,
9754
+ repairAbsoluteIosDevSession,
9755
+ resolveAbsoluteDeviceCapabilityPlan,
9756
+ resolveAbsoluteMobileAuthManifest,
9757
+ resolveAbsoluteMobileCompatibilityRelease,
9758
+ resolveAbsoluteMobileDeepLink,
9759
+ resolveAbsoluteMobileNavigation,
9760
+ resolveAbsoluteMobileRoute,
9761
+ retainAbsoluteMobileCompatibilityArtifacts,
9762
+ runAbsoluteAndroidUpgradeConformance,
9763
+ runWithAbsoluteMobileProducer,
9764
+ serializeAbsoluteMobileAuthEnvironment,
9765
+ startAbsoluteExpoDevSession,
9766
+ startAbsoluteIosCaEnrollmentServer,
9767
+ startAbsoluteIosDevSession,
9768
+ startAbsoluteIosTcpRelay,
9769
+ startAbsoluteRemoteExpoIosDevSession,
9770
+ startAbsoluteRemoteIosDevSession,
9771
+ syncAbsoluteExpoWebAssets,
9772
+ syncAbsoluteRemoteMacProject,
9773
+ testAbsoluteIosPhysicalDevice,
9774
+ validateAbsoluteRemoteMacProfileName,
9775
+ validateAbsoluteSshDestination,
9776
+ verifyAbsoluteMobileAssociationFiles,
9777
+ verifyAbsoluteMobileCompatibilityProducer,
9778
+ waitForAbsoluteIosHmrLog,
9779
+ writeAbsoluteCapacitorConfig,
9780
+ writeAbsoluteExpoProject,
9781
+ writeAbsoluteMobileGithubWorkflow
9546
9782
  };
9547
9783
 
9548
- //# debugId=711828E2D236C77164756E2164756E21
9784
+ //# debugId=609EFE7CD27840A164756E2164756E21
9549
9785
  //# sourceMappingURL=index.js.map