@absolutejs/absolute 0.20.0-beta.47 → 0.20.0-beta.48

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.
@@ -5231,6 +5231,7 @@ var getCurrentAbsoluteMobileProducerContext = () => {
5231
5231
  // src/mobile/pageProtocol.ts
5232
5232
  var ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE = "application/vnd.absolute.page+json";
5233
5233
  var ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION = 1;
5234
+ var ABSOLUTE_NATIVE_ROUTE_DATA_MEDIA_TYPE = "application/vnd.absolute.native-route+json";
5234
5235
  var BAD_REQUEST_STATUS = 400;
5235
5236
  var OK_STATUS = 200;
5236
5237
  var SERVER_ERROR_STATUS = 500;
@@ -5249,6 +5250,11 @@ var acceptsAbsoluteMobilePage = (request) => {
5249
5250
  return false;
5250
5251
  return (request.headers.get("accept") ?? "").split(",").some((value) => parseMediaType(value) === ABSOLUTE_MOBILE_PAGE_MEDIA_TYPE);
5251
5252
  };
5253
+ var acceptsAbsoluteNativeRouteData = (request) => {
5254
+ if (!request)
5255
+ return false;
5256
+ return (request.headers.get("accept") ?? "").split(",").some((value) => parseMediaType(value) === ABSOLUTE_NATIVE_ROUTE_DATA_MEDIA_TYPE);
5257
+ };
5252
5258
  var readRequiredHeader = (request, name) => {
5253
5259
  const value = request.headers.get(name)?.trim();
5254
5260
  return value ? value : undefined;
@@ -5379,6 +5385,32 @@ var finalizeArchivedMobilePage = (context, input) => {
5379
5385
  return createAbsoluteMobilePageErrorResponse(page.pageId);
5380
5386
  }
5381
5387
  };
5388
+ var finalizeAbsoluteNativeRouteDevelopmentPage = (input) => {
5389
+ if (false) {}
5390
+ if (input.request?.method !== "GET") {
5391
+ return createAbsoluteMobileInvalidRequestResponse("Native-route data requests must use GET.");
5392
+ }
5393
+ if (input.request.headers.get(MOBILE_PAGE_REQUEST_HEADERS.protocol) !== String(ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION)) {
5394
+ return createAbsoluteMobileInvalidRequestResponse(`Native-route data requires protocol ${ABSOLUTE_MOBILE_PAGE_PROTOCOL_VERSION}.`);
5395
+ }
5396
+ const [representation] = input.compatibility.representations;
5397
+ if (!representation) {
5398
+ return createAbsoluteMobilePageErrorResponse(input.compatibility.pageId);
5399
+ }
5400
+ try {
5401
+ return envelopeResponse({
5402
+ contract: representation.contract,
5403
+ framework: input.compatibility.framework,
5404
+ kind: "page",
5405
+ pageId: input.compatibility.pageId,
5406
+ props: normalizeJsonValue(representation.mapProps(input.props)),
5407
+ status: input.status ?? OK_STATUS
5408
+ }, input.status ?? OK_STATUS);
5409
+ } catch (error) {
5410
+ console.error(`[Mobile] Failed to produce development native route ${input.compatibility.pageId}:`, error);
5411
+ return createAbsoluteMobilePageErrorResponse(input.compatibility.pageId);
5412
+ }
5413
+ };
5382
5414
  var createAbsoluteMobileInvalidRequestResponse = (message) => envelopeResponse({ kind: "invalid-request", message }, BAD_REQUEST_STATUS);
5383
5415
  var createAbsoluteMobilePageErrorResponse = (pageId) => envelopeResponse({
5384
5416
  code: "representation-failed",
@@ -5388,6 +5420,9 @@ var createAbsoluteMobilePageErrorResponse = (pageId) => envelopeResponse({
5388
5420
  }, SERVER_ERROR_STATUS);
5389
5421
  var createAbsoluteMobileUpgradeResponse = (result) => envelopeResponse(result, UPGRADE_REQUIRED_STATUS);
5390
5422
  var finalizeAbsoluteMobilePage = (input) => {
5423
+ if (acceptsAbsoluteNativeRouteData(input.request)) {
5424
+ return finalizeAbsoluteNativeRouteDevelopmentPage(input);
5425
+ }
5391
5426
  const parsed = parseAbsoluteMobilePageRequest(input.request);
5392
5427
  if (parsed.kind === "not-mobile")
5393
5428
  return;
@@ -6179,6 +6214,48 @@ var exists3 = async (path) => {
6179
6214
  return false;
6180
6215
  }
6181
6216
  };
6217
+ var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
6218
+ var requireManifestString = (value, field2) => {
6219
+ if (typeof value !== "string" || !value) {
6220
+ throw new TypeError(`AbsoluteJS mobile manifest ${field2} is invalid.`);
6221
+ }
6222
+ return value;
6223
+ };
6224
+ var expoNativeDataManifest = (value) => {
6225
+ if (!isRecord8(value) || !Array.isArray(value.pages) || !Array.isArray(value.routes)) {
6226
+ throw new TypeError("AbsoluteJS mobile manifest is invalid.");
6227
+ }
6228
+ const pages = value.pages.map((page) => {
6229
+ if (!isRecord8(page))
6230
+ throw new TypeError("AbsoluteJS mobile manifest page is invalid.");
6231
+ return {
6232
+ bundleHash: requireManifestString(page.bundleHash, "page.bundleHash"),
6233
+ contract: requireManifestString(page.contract, "page.contract"),
6234
+ pageId: requireManifestString(page.pageId, "page.pageId")
6235
+ };
6236
+ });
6237
+ const routes = value.routes.flatMap((route) => {
6238
+ if (!isRecord8(route) || typeof route.method !== "string") {
6239
+ throw new TypeError("AbsoluteJS mobile manifest route is invalid.");
6240
+ }
6241
+ if (route.method !== "GET")
6242
+ return [];
6243
+ return [
6244
+ {
6245
+ method: "GET",
6246
+ pageId: requireManifestString(route.pageId, "route.pageId"),
6247
+ pattern: requireManifestString(route.pattern, "route.pattern")
6248
+ }
6249
+ ];
6250
+ });
6251
+ return {
6252
+ appBuild: requireManifestString(value.appBuild, "appBuild"),
6253
+ pages,
6254
+ productionOrigin: requireManifestString(value.productionOrigin, "productionOrigin"),
6255
+ routes,
6256
+ runtime: requireManifestString(value.runtime, "runtime")
6257
+ };
6258
+ };
6182
6259
  var portableRelative2 = (from, destination) => {
6183
6260
  const value = relative10(from, destination).replaceAll("\\", "/");
6184
6261
  return value.startsWith(".") ? value : `./${value}`;
@@ -6973,7 +7050,134 @@ var catchAllRouteSource = `${EXPO_GENERATED_HEADER}import { AbsoluteWebHost } fr
6973
7050
 
6974
7051
  export default AbsoluteWebHost;
6975
7052
  `;
6976
- var nativeWrapperSource = (wrapper, module) => `${EXPO_GENERATED_HEADER}export { default } from ${JSON.stringify(portableRelative2(dirname10(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
7053
+ var nativeRouteRuntimeSource = (auth) => `${EXPO_GENERATED_HEADER}import { useLocalSearchParams, usePathname } from 'expo-router';
7054
+ import { type ComponentType, useEffect, useMemo, useState } from 'react';
7055
+ import { ActivityIndicator, Platform, Pressable, StyleSheet, Text, View } from 'react-native';
7056
+ import { ABSOLUTE_MOBILE_MANIFEST } from './webAssets';
7057
+ ${auth ? "import { absoluteExpoAuth } from './AbsoluteAuth';" : ""}
7058
+
7059
+ const PAGE_MEDIA_TYPE = 'application/vnd.absolute.page+json';
7060
+ const NATIVE_DATA_MEDIA_TYPE = 'application/vnd.absolute.native-route+json';
7061
+ const PROTOCOL = 1;
7062
+ const MAX_DATA_BYTES = 1024 * 1024;
7063
+ const DEV_ORIGIN = Platform.OS === 'android'
7064
+ ? process.env.EXPO_PUBLIC_ABSOLUTE_DEV_ANDROID_ORIGIN
7065
+ : process.env.EXPO_PUBLIC_ABSOLUTE_DEV_IOS_ORIGIN;
7066
+
7067
+ type RouteParams = Record<string, string | string[] | undefined>;
7068
+ type NativeRouteProps<PageProps extends object, Params extends object> = {
7069
+ pageProps: Readonly<PageProps>;
7070
+ params: Readonly<Params>;
7071
+ reload: () => void;
7072
+ };
7073
+ type NativeRouteState<PageProps> =
7074
+ | { kind: 'loading' }
7075
+ | { kind: 'ready'; pageProps: PageProps }
7076
+ | { kind: 'error' };
7077
+
7078
+ const isRecord = (value: unknown): value is Record<string, unknown> =>
7079
+ typeof value === 'object' && value !== null && !Array.isArray(value);
7080
+ const routeSegmentPattern = (segment: string) => {
7081
+ if (segment === '*') return '.*';
7082
+ if (segment.startsWith(':') && segment.endsWith('?')) return '[^/]*';
7083
+ if (segment.startsWith(':')) return '[^/]+';
7084
+ return segment.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
7085
+ };
7086
+ const matchesRoute = (pattern: string, pathname: string) =>
7087
+ new RegExp('^' + pattern.split('/').map(routeSegmentPattern).join('/') + '/?$').test(pathname);
7088
+ const requestPathFor = (pathname: string, params: RouteParams, pattern: string) => {
7089
+ const pathNames = new Set(pattern.split('/').filter(segment => segment.startsWith(':')).map(segment => segment.replace(/^:/, '').replace(/\\?$/, '')));
7090
+ if (pattern.endsWith('/*')) pathNames.add('absoluteWildcard');
7091
+ const query = new URLSearchParams();
7092
+ for (const [name, value] of Object.entries(params).sort(([left], [right]) => left.localeCompare(right))) {
7093
+ if (pathNames.has(name) || name === '#' || value === undefined) continue;
7094
+ for (const item of Array.isArray(value) ? value : [value]) query.append(name, item);
7095
+ }
7096
+ const search = query.toString();
7097
+ return pathname + (search ? '?' + search : '');
7098
+ };
7099
+ const productionPage = (pathname: string) => {
7100
+ if (!ABSOLUTE_MOBILE_MANIFEST) throw new Error('AbsoluteJS native route data is not prepared for production.');
7101
+ const route = ABSOLUTE_MOBILE_MANIFEST.routes.find(candidate => candidate.method === 'GET' && matchesRoute(candidate.pattern, pathname));
7102
+ if (!route) throw new Error('No trusted AbsoluteJS page route owns this native URL.');
7103
+ const page = ABSOLUTE_MOBILE_MANIFEST.pages.find(candidate => candidate.pageId === route.pageId);
7104
+ if (!page) throw new Error('The embedded AbsoluteJS page contract is incomplete.');
7105
+ return page;
7106
+ };
7107
+ const createDataRequest = (path: string) => {
7108
+ const development = typeof DEV_ORIGIN === 'string' && DEV_ORIGIN.length > 0;
7109
+ const origin = development ? DEV_ORIGIN : ABSOLUTE_MOBILE_MANIFEST?.productionOrigin;
7110
+ if (!origin) throw new Error('AbsoluteJS native route data has no trusted server origin.');
7111
+ const url = new URL(path, origin);
7112
+ if (url.origin !== new URL(origin).origin) throw new Error('AbsoluteJS native route data left its trusted origin.');
7113
+ const headers = new Headers();
7114
+ headers.set('accept', development ? NATIVE_DATA_MEDIA_TYPE : PAGE_MEDIA_TYPE);
7115
+ headers.set('x-absolute-mobile-protocol', String(PROTOCOL));
7116
+ let page: ReturnType<typeof productionPage> | undefined;
7117
+ if (!development) {
7118
+ page = productionPage(url.pathname);
7119
+ headers.set('x-absolute-mobile-app-build', ABSOLUTE_MOBILE_MANIFEST!.appBuild);
7120
+ headers.set('x-absolute-mobile-page-bundle', page.bundleHash);
7121
+ headers.set('x-absolute-mobile-page-contracts', page.contract);
7122
+ headers.set('x-absolute-mobile-page-id', page.pageId);
7123
+ headers.set('x-absolute-mobile-runtime', ABSOLUTE_MOBILE_MANIFEST!.runtime);
7124
+ }
7125
+ return { page, request: new Request(url, { headers, method: 'GET' }) };
7126
+ };
7127
+ const requestData = async <PageProps extends object>(path: string, signal: AbortSignal) => {
7128
+ const { page, request } = createDataRequest(path);
7129
+ const response = await ${auth ? "absoluteExpoAuth.fetchOptional" : "fetch"}(request, { redirect: 'manual', signal });
7130
+ if (new URL(response.url || request.url).origin !== new URL(request.url).origin || response.status >= 300 && response.status < 400) throw new Error('AbsoluteJS native route data redirected outside its contract.');
7131
+ const source = await response.text();
7132
+ if (new TextEncoder().encode(source).byteLength > MAX_DATA_BYTES) throw new Error('AbsoluteJS native route data exceeded 1 MiB.');
7133
+ let envelope: unknown;
7134
+ try { envelope = JSON.parse(source); } catch { throw new Error('The server did not return an AbsoluteJS page envelope.'); }
7135
+ if (!isRecord(envelope) || envelope.protocol !== PROTOCOL || !isRecord(envelope.response)) throw new Error('The server returned an invalid AbsoluteJS page envelope.');
7136
+ const result = envelope.response;
7137
+ if (result.kind === 'upgrade-required') throw new Error('This app version must be updated before opening this screen.');
7138
+ if (result.kind !== 'page' || !isRecord(result.props) || typeof result.pageId !== 'string' || typeof result.contract !== 'string') throw new Error('The server did not produce native route page props.');
7139
+ if (page && (result.pageId !== page.pageId || result.contract !== page.contract)) throw new Error('The server returned a different page contract than this app contains.');
7140
+ return result.props as PageProps;
7141
+ };
7142
+
7143
+ export const createAbsoluteNativeRoute = <
7144
+ PageProps extends object,
7145
+ Params extends object = RouteParams
7146
+ >(Component: ComponentType<NativeRouteProps<PageProps, Params>>, pattern: string) => {
7147
+ function AbsoluteNativeRouteScreen() {
7148
+ const pathname = usePathname() || '/';
7149
+ const params = useLocalSearchParams() as RouteParams;
7150
+ const parameterKey = JSON.stringify(params);
7151
+ const requestPath = useMemo(() => requestPathFor(pathname, params, pattern), [parameterKey, pathname]);
7152
+ const [revision, setRevision] = useState(0);
7153
+ const [state, setState] = useState<NativeRouteState<PageProps>>({ kind: 'loading' });
7154
+ useEffect(() => {
7155
+ const controller = new AbortController();
7156
+ setState({ kind: 'loading' });
7157
+ void requestData<PageProps>(requestPath, controller.signal).then(
7158
+ pageProps => { if (!controller.signal.aborted) setState({ kind: 'ready', pageProps }); },
7159
+ () => { if (!controller.signal.aborted) setState({ kind: 'error' }); }
7160
+ );
7161
+ return () => controller.abort();
7162
+ }, [requestPath, revision]);
7163
+ const reload = () => setRevision(value => value + 1);
7164
+ if (state.kind === 'loading') return <View style={styles.center}><ActivityIndicator accessibilityLabel="Loading screen" /></View>;
7165
+ if (state.kind === 'error') return <View style={styles.center}><Text accessibilityRole="alert" style={styles.error}>This screen could not load.</Text><Pressable accessibilityRole="button" onPress={reload} style={styles.button}><Text>Try again</Text></Pressable></View>;
7166
+ return <Component pageProps={state.pageProps} params={params as Params} reload={reload} />;
7167
+ }
7168
+ return AbsoluteNativeRouteScreen;
7169
+ };
7170
+
7171
+ const styles = StyleSheet.create({
7172
+ button: { backgroundColor: '#e2e8f0', borderRadius: 10, paddingHorizontal: 16, paddingVertical: 12 },
7173
+ center: { alignItems: 'center', flex: 1, gap: 16, justifyContent: 'center', padding: 24 },
7174
+ error: { color: '#b91c1c', fontSize: 16, textAlign: 'center' }
7175
+ });
7176
+ `;
7177
+ var nativeWrapperSource = (wrapper, module, runtime, route) => `${EXPO_GENERATED_HEADER}import ApplicationNativeRoute from ${JSON.stringify(portableRelative2(dirname10(wrapper), module).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
7178
+ import { createAbsoluteNativeRoute } from ${JSON.stringify(portableRelative2(dirname10(wrapper), runtime).replace(/\.(?:[cm]?[jt]sx?)$/u, ""))};
7179
+
7180
+ export default createAbsoluteNativeRoute(ApplicationNativeRoute, ${JSON.stringify(route)});
6977
7181
  `;
6978
7182
  var expoTsConfig = (projectRoot, project, auth, sync) => ({
6979
7183
  compilerOptions: {
@@ -7040,9 +7244,19 @@ var pruneStaleManagedExpoRoutes = async (project, expected) => {
7040
7244
  };
7041
7245
  var jsonSource = (value) => `${JSON.stringify(value, null, "\t")}
7042
7246
  `;
7043
- var emptyWebAssetsSource = `${EXPO_GENERATED_HEADER}export const materializeAbsoluteWebBundle = async () => {
7247
+ var nativeDataManifestTypeSource = `type AbsoluteMobileManifest = {
7248
+ appBuild: string;
7249
+ pages: readonly { bundleHash: string; contract: string; pageId: string }[];
7250
+ productionOrigin: string;
7251
+ routes: readonly { method: 'GET'; pageId: string; pattern: string }[];
7252
+ runtime: string;
7253
+ };
7254
+ `;
7255
+ var emptyWebAssetsSource = `${EXPO_GENERATED_HEADER}${nativeDataManifestTypeSource}
7256
+ export const materializeAbsoluteWebBundle = async () => {
7044
7257
  throw new Error('The embedded AbsoluteJS bundle is unavailable. Run absolute prepare before a production Expo build.');
7045
7258
  };
7259
+ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest | undefined = undefined;
7046
7260
  `;
7047
7261
  var writeAbsoluteExpoProject = async (config, options) => {
7048
7262
  if (config.engine !== "expo")
@@ -7113,6 +7327,10 @@ node_modules/
7113
7327
  join14(project, "src", "generated", "AbsoluteDevices.ts"),
7114
7328
  devicesRuntimeSource(config, devices, authEnabled)
7115
7329
  ],
7330
+ [
7331
+ join14(project, "src", "generated", "AbsoluteNativeRoute.tsx"),
7332
+ nativeRouteRuntimeSource(authEnabled)
7333
+ ],
7116
7334
  [
7117
7335
  join14(project, "src", "generated", "AbsoluteWebHost.tsx"),
7118
7336
  webHostSource(config, auth, syncEnabled)
@@ -7132,9 +7350,10 @@ node_modules/
7132
7350
  files.set(join14(project, "app", "index.tsx"), webRouteSource);
7133
7351
  }
7134
7352
  files.set(join14(project, "app", "[...absolute].tsx"), catchAllRouteSource);
7353
+ const nativeRouteRuntime = join14(project, "src", "generated", "AbsoluteNativeRoute.tsx");
7135
7354
  for (const [route, module] of routeModules) {
7136
7355
  const wrapper = route === "/" ? join14(project, "app", "index.tsx") : routeFile(project, route);
7137
- files.set(wrapper, nativeWrapperSource(wrapper, module));
7356
+ files.set(wrapper, nativeWrapperSource(wrapper, module, nativeRouteRuntime, route));
7138
7357
  }
7139
7358
  const removed = await pruneStaleManagedExpoRoutes(project, new Set([...files.keys()].filter((path) => path.startsWith(`${join14(project, "app")}${sep6}`))));
7140
7359
  const changes = await Promise.all([...files].map(([path, source]) => writeManagedFile(path, source, true)));
@@ -7177,11 +7396,13 @@ var installStagedDirectory = async (staging, destination) => {
7177
7396
  throw error;
7178
7397
  }
7179
7398
  };
7180
- var assetModuleSource = (assets, bundleId) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
7399
+ var assetModuleSource = (assets, bundleId, manifest) => `${EXPO_GENERATED_HEADER}import { Asset } from 'expo-asset';
7181
7400
  import { Directory, File, Paths } from 'expo-file-system';
7182
7401
 
7402
+ ${nativeDataManifestTypeSource}
7183
7403
  declare const require: (path: string) => number;
7184
7404
  const BUNDLE_ID = ${JSON.stringify(bundleId)};
7405
+ export const ABSOLUTE_MOBILE_MANIFEST: AbsoluteMobileManifest = ${JSON.stringify(manifest)};
7185
7406
  const ASSETS = [
7186
7407
  ${assets.map(({ asset, path }) => ` { module: require(${JSON.stringify(asset)}), path: ${JSON.stringify(path)} }`).join(`,
7187
7408
  `)}
@@ -7215,9 +7436,8 @@ var syncAbsoluteExpoWebAssets = async (config) => {
7215
7436
  }
7216
7437
  const manifestPath = join14(config.bundleDirectory, "absolute-mobile-manifest.json");
7217
7438
  const manifest = JSON.parse(await readFile14(manifestPath, "utf8"));
7218
- const appBuild = typeof manifest === "object" && manifest !== null && typeof Reflect.get(manifest, "appBuild") === "string" ? String(Reflect.get(manifest, "appBuild")) : undefined;
7219
- if (!appBuild)
7220
- throw new TypeError("AbsoluteJS mobile manifest has no appBuild.");
7439
+ const nativeDataManifest = expoNativeDataManifest(manifest);
7440
+ const { appBuild } = nativeDataManifest;
7221
7441
  const files = await walkFiles(config.bundleDirectory);
7222
7442
  const bundleHash = createHash10("sha256");
7223
7443
  const filesWithContents = await Promise.all(files.map(async (file) => ({ contents: await readFile14(file), file })));
@@ -7247,7 +7467,7 @@ var syncAbsoluteExpoWebAssets = async (config) => {
7247
7467
  throw error;
7248
7468
  }
7249
7469
  const generated = join14(config.nativeProjectDirectory, "src", "generated", "webAssets.ts");
7250
- await writeManagedFile(generated, assetModuleSource(assets, bundleId), true);
7470
+ await writeManagedFile(generated, assetModuleSource(assets, bundleId, nativeDataManifest), true);
7251
7471
  return { appBuild, assets: assets.length, bundleId, path: destination };
7252
7472
  };
7253
7473
 
@@ -7564,7 +7784,7 @@ var ABSOLUTE_EXPO_BRIDGE_METHODS = [
7564
7784
  "sync.socket.open",
7565
7785
  "sync.socket.sendChunk"
7566
7786
  ];
7567
- var isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
7787
+ var isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
7568
7788
  var validId = (value) => typeof value === "string" && /^[A-Za-z0-9_-]{1,80}$/u.test(value);
7569
7789
  var validPath = (value) => typeof value === "string" && value.startsWith("/") && !value.startsWith("//") && value.length <= 4096;
7570
7790
  var parseRequest = (value) => {
@@ -7574,7 +7794,7 @@ var parseRequest = (value) => {
7574
7794
  if (!method) {
7575
7795
  throw new TypeError("Expo bridge method is not allowed.");
7576
7796
  }
7577
- if (!isRecord8(value.params))
7797
+ if (!isRecord9(value.params))
7578
7798
  throw new TypeError("Expo bridge request params must be an object.");
7579
7799
  if (typeof value.path !== "string" || !validPath(value.path))
7580
7800
  throw new TypeError("Expo bridge request path is invalid.");
@@ -7610,7 +7830,7 @@ var parseRequest = (value) => {
7610
7830
  throw new TypeError("Expo bridge HTTP body exceeds 48 KiB.");
7611
7831
  if ((value.params.method === "GET" || value.params.method === "DELETE") && value.params.body !== undefined)
7612
7832
  throw new TypeError("Expo bridge HTTP method cannot contain a body.");
7613
- if (!isRecord8(value.params.headers))
7833
+ if (!isRecord9(value.params.headers))
7614
7834
  throw new TypeError("Expo bridge HTTP headers must be an object.");
7615
7835
  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-")));
7616
7836
  if (!headersAllowed) {
@@ -7636,13 +7856,13 @@ var parseResponse = (value) => {
7636
7856
  if (typeof value.id !== "string" || !validId(value.id))
7637
7857
  throw new TypeError("Expo bridge response id is invalid.");
7638
7858
  if (value.error !== undefined) {
7639
- if (!isRecord8(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string") {
7859
+ if (!isRecord9(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string") {
7640
7860
  throw new TypeError("Expo bridge response error is invalid.");
7641
7861
  }
7642
7862
  if (value.result !== undefined)
7643
7863
  throw new TypeError("Expo bridge response cannot contain result and error.");
7644
7864
  }
7645
- if (isRecord8(value.error)) {
7865
+ if (isRecord9(value.error)) {
7646
7866
  return {
7647
7867
  error: {
7648
7868
  code: String(value.error.code),
@@ -7666,7 +7886,7 @@ var parseEvent = (value) => {
7666
7886
  }
7667
7887
  if (typeof value.path !== "string" || !validPath(value.path))
7668
7888
  throw new TypeError("Expo bridge event path is invalid.");
7669
- if (value.payload !== undefined && !isRecord8(value.payload)) {
7889
+ if (value.payload !== undefined && !isRecord9(value.payload)) {
7670
7890
  throw new TypeError("Expo bridge event payload must be an object.");
7671
7891
  }
7672
7892
  return {
@@ -7700,7 +7920,7 @@ var parseAbsoluteExpoBridgeMessage = (source) => {
7700
7920
  cause
7701
7921
  });
7702
7922
  }
7703
- if (!isRecord8(parsed) || parsed.format !== ABSOLUTE_EXPO_BRIDGE_FORMAT) {
7923
+ if (!isRecord9(parsed) || parsed.format !== ABSOLUTE_EXPO_BRIDGE_FORMAT) {
7704
7924
  throw new TypeError("Expo bridge message format is unsupported.");
7705
7925
  }
7706
7926
  if (parsed.kind === "request")
@@ -8698,7 +8918,7 @@ init_telemetryEvent();
8698
8918
  import { Elysia as Elysia3 } from "elysia";
8699
8919
  var ABSOLUTE_MOBILE_PREVIEW_PATH = "/__absolute/mobile-preview";
8700
8920
  var escapeHtml2 = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;");
8701
- var isRecord9 = (value) => typeof value === "object" && value !== null;
8921
+ var isRecord10 = (value) => typeof value === "object" && value !== null;
8702
8922
  var normalizeEntry2 = (entry) => {
8703
8923
  const parsed = new URL(entry ?? "/", "https://absolute.invalid");
8704
8924
  return `${parsed.pathname}${parsed.search}${parsed.hash}`;
@@ -8749,7 +8969,7 @@ var createAbsoluteMobilePreviewPlugin = (mobile) => {
8749
8969
  "X-Robots-Tag": "noindex, nofollow"
8750
8970
  }
8751
8971
  })).post("/__absolute/mobile-preview-telemetry", ({ body, status }) => {
8752
- const value = isRecord9(body) ? body : undefined;
8972
+ const value = isRecord10(body) ? body : undefined;
8753
8973
  const durationMs = value?.durationMs;
8754
8974
  const platform2 = value?.platform;
8755
8975
  if (typeof durationMs !== "number" || !Number.isFinite(durationMs) || durationMs < 0 || durationMs > 300000 || platform2 !== "android" && platform2 !== "ios") {
@@ -9306,8 +9526,8 @@ var prepareAbsoluteAndroidRelease = async (publisher, options) => {
9306
9526
  }
9307
9527
  return versionCode;
9308
9528
  };
9309
- var isRecord10 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
9310
- var isPublisher = (value) => isRecord10(value) && typeof value.publish === "function";
9529
+ var isRecord11 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
9530
+ var isPublisher = (value) => isRecord11(value) && typeof value.publish === "function";
9311
9531
  var publisherModulePath = (projectRoot, requested) => {
9312
9532
  const root = resolve15(projectRoot);
9313
9533
  const path = resolve15(root, requested);
@@ -9323,7 +9543,7 @@ var loadAbsoluteNativeReleasePublisher = async (projectRoot, requestedModulePath
9323
9543
  throw new TypeError(`Native release registry module does not exist: ${modulePath}`);
9324
9544
  });
9325
9545
  const loaded = await import(pathToFileURL3(modulePath).href);
9326
- const publisher = isRecord10(loaded) ? loaded.default ?? loaded.registry : undefined;
9546
+ const publisher = isRecord11(loaded) ? loaded.default ?? loaded.registry : undefined;
9327
9547
  if (!isPublisher(publisher)) {
9328
9548
  throw new TypeError("Native release registry module must default-export a registry with publish(options).");
9329
9549
  }
@@ -10139,6 +10359,7 @@ export {
10139
10359
  ABSOLUTE_MOBILE_TRANSFORM_PROTOCOL,
10140
10360
  ABSOLUTE_NATIVE_AUTH_CLIENTS_ENV,
10141
10361
  ABSOLUTE_NATIVE_AUTH_SCOPES,
10362
+ ABSOLUTE_NATIVE_ROUTE_DATA_MEDIA_TYPE,
10142
10363
  ABSOLUTE_REMOTE_MAC_EVENT_PREFIX,
10143
10364
  ABSOLUTE_REMOTE_MAC_PROTOCOL_VERSION,
10144
10365
  ABSOLUTE_SYNC_PACKAGE,
@@ -10153,6 +10374,7 @@ export {
10153
10374
  absoluteRemoteMacSshBase,
10154
10375
  absoluteRemoteProjectSyncCommands,
10155
10376
  acceptsAbsoluteMobilePage,
10377
+ acceptsAbsoluteNativeRouteData,
10156
10378
  activateAbsoluteMobilePage,
10157
10379
  applyAbsoluteNativeDeepLinks,
10158
10380
  applyAbsoluteNativeDeviceCapabilities,
@@ -10272,5 +10494,5 @@ export {
10272
10494
  writeAbsoluteMobileGithubWorkflow
10273
10495
  };
10274
10496
 
10275
- //# debugId=CFD74BC8ED7A634C64756E2164756E21
10497
+ //# debugId=4795A6FB7632A5BE64756E2164756E21
10276
10498
  //# sourceMappingURL=index.js.map