From f96f04ea03e7451ffa551a5dec8159896fd7cbeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?nishan=20=28o=5E=E2=96=BD=5Eo=29?= Date: Tue, 9 Jun 2026 13:05:33 +0530 Subject: [PATCH 1/5] [core][android] Fix events dropped in third party expo ui module (#46624) # Why Fixes - https://github.com/expo/expo/issues/46623 Events are dropped in Third party Expo UI module views. # How - Third party Expo UI views are registered as same class `class expo.modules.kotlin.views.ComposeFunctionHolder` so it returns ExpoUI module as holder [here](https://github.com/expo/expo/blob/340306c5e4ba97f19b8c05fde44f639f56224c5d/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/viewevent/ViewEvent.kt#L30) instead of user's third party module. And then `appContext.registry.getViewDefinition(holder, view.name)?.callbacksDefinition` tries to get callbacks from ExpoUI module and tries to find user's custom view which fails and it finally logs `Cannot get callbacks for class expo.modules.ui.ExpoUIModule` - `ViewFunctionHolder` Views (Compose views) now carries its own `CallbacksDefinition` which is looked up directly on event invocation. # Test Plan - Added testcases for ExpoView/Non-ExpoView view definition resolution - Tested events with custom ExpoUI views in bare-expo custom module. # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [x] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --------- Co-authored-by: Kudo Chien --- .../expo/modules/testexpoui/MyCustomView.kt | 5 ++- .../modules/testexpoui/TestExpoUiModule.kt | 3 +- .../test-expo-ui/ios/MyCustomView.swift | 4 ++ .../test-expo-ui/src/MyCustomView.android.tsx | 1 + .../modules/test-expo-ui/src/MyCustomView.tsx | 1 + .../UI/ExtendingExpoUIScreen.android.tsx | 7 ++- .../src/screens/UI/ExtendingExpoUIScreen.tsx | 7 ++- packages/expo-modules-core/CHANGELOG.md | 3 +- .../modules/kotlin/views/ExpoComposeView.kt | 3 +- ...ModuleDefinitionBuilderComposeExtension.kt | 2 +- .../modules/kotlin/viewevent/ViewEvent.kt | 33 ++++++++------ .../kotlin/views/ViewFunctionHolder.kt | 7 ++- .../modules/kotlin/viewevent/ViewEventTest.kt | 43 +++++++++++++++++++ 13 files changed, 93 insertions(+), 26 deletions(-) create mode 100644 packages/expo-modules-core/android/src/test/java/expo/modules/kotlin/viewevent/ViewEventTest.kt diff --git a/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/MyCustomView.kt b/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/MyCustomView.kt index 2ff9b48dd75895..ab556c78bdc1f1 100644 --- a/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/MyCustomView.kt +++ b/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/MyCustomView.kt @@ -1,5 +1,6 @@ package expo.modules.testexpoui +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -18,14 +19,14 @@ data class MyCustomViewProps( ) : ComposeProps @Composable -fun FunctionalComposableScope.MyCustomViewContent(props: MyCustomViewProps) { +fun FunctionalComposableScope.MyCustomViewContent(props: MyCustomViewProps, onCustomTap: () -> Unit = {}) { Column( modifier = ModifierRegistry.applyModifiers( props.modifiers, appContext, composableScope, globalEventDispatcher - ) + ).clickable { onCustomTap() } ) { Text(text = props.title, style = MaterialTheme.typography.titleMedium) Children(UIComposableScope()) diff --git a/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/TestExpoUiModule.kt b/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/TestExpoUiModule.kt index 79f9a749648b35..7b266aa5491c8a 100644 --- a/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/TestExpoUiModule.kt +++ b/apps/bare-expo/modules/test-expo-ui/android/src/main/java/expo/modules/testexpoui/TestExpoUiModule.kt @@ -21,8 +21,9 @@ class TestExpoUiModule : Module() { } ExpoUIView("MyCustomView") { + val onCustomTap by Event() Content { props -> - MyCustomViewContent(props) + MyCustomViewContent(props) { onCustomTap(Unit) } } } } diff --git a/apps/bare-expo/modules/test-expo-ui/ios/MyCustomView.swift b/apps/bare-expo/modules/test-expo-ui/ios/MyCustomView.swift index ffd7cb739b3054..fe7e43b8b68df7 100644 --- a/apps/bare-expo/modules/test-expo-ui/ios/MyCustomView.swift +++ b/apps/bare-expo/modules/test-expo-ui/ios/MyCustomView.swift @@ -6,6 +6,7 @@ import ExpoUI final class MyCustomViewProps: UIBaseViewProps { @Field var title: String = "" + var onCustomTap = EventDispatcher() } struct MyCustomView: ExpoSwiftUI.View { @@ -17,5 +18,8 @@ struct MyCustomView: ExpoSwiftUI.View { .font(.headline) Children() } + .onTapGesture { + props.onCustomTap() + } } } diff --git a/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.android.tsx b/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.android.tsx index 77309344f177fa..4da537f93b706b 100644 --- a/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.android.tsx +++ b/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.android.tsx @@ -4,6 +4,7 @@ import { requireNativeView } from 'expo'; export interface MyCustomViewProps extends PrimitiveBaseProps { title: string; + onCustomTap?: () => void; children?: React.ReactNode; } diff --git a/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.tsx b/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.tsx index cd990b4ae7e267..590ee9aef73df8 100644 --- a/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.tsx +++ b/apps/bare-expo/modules/test-expo-ui/src/MyCustomView.tsx @@ -4,6 +4,7 @@ import { requireNativeView } from 'expo'; export interface MyCustomViewProps extends CommonViewModifierProps { title: string; + onCustomTap?: () => void; children?: React.ReactNode; } diff --git a/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.android.tsx b/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.android.tsx index 9032304d545251..4c4b0f8772daf8 100644 --- a/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.android.tsx +++ b/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.android.tsx @@ -1,6 +1,7 @@ import { Column, Host, Text } from '@expo/ui/jetpack-compose'; import { background, clip, paddingAll } from '@expo/ui/jetpack-compose/modifiers'; import { requireNativeModule } from 'expo'; +import { useState } from 'react'; import { MyCustomView, customBorder } from 'test-expo-ui'; let hasTestExpoUiModule = false; @@ -12,19 +13,21 @@ try { } export default function ExtendingExpoUIScreen() { + const [tapCount, setTapCount] = useState(0); return ( {hasTestExpoUiModule ? ( setTapCount((count) => count + 1)} modifiers={[ background('#e0f0ff'), clip({ type: 'roundedCorner', radius: 12 }), customBorder({ color: '#FF6B35', width: 3, cornerRadius: 8 }), paddingAll(16), ]}> - This is a child of MyCustomView + Tapped {tapCount} times ) : ( test-expo-ui module is not available in this environment. diff --git a/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.tsx b/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.tsx index af9ec0a84ca616..aa4bf5ca20165e 100644 --- a/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.tsx +++ b/apps/native-component-list/src/screens/UI/ExtendingExpoUIScreen.tsx @@ -1,6 +1,7 @@ import { Host, Text, VStack } from '@expo/ui/swift-ui'; import { padding, cornerRadius, background } from '@expo/ui/swift-ui/modifiers'; import { requireNativeModule } from 'expo'; +import { useState } from 'react'; import { MyCustomView, customBorder } from 'test-expo-ui'; let hasTestExpoUiModule = false; @@ -12,19 +13,21 @@ try { } export default function ExtendingExpoUIScreen() { + const [tapCount, setTapCount] = useState(0); return ( {hasTestExpoUiModule ? ( setTapCount((count) => count + 1)} modifiers={[ padding({ all: 16 }), background('#e0f0ff'), cornerRadius(12), customBorder({ color: '#FF6B35', width: 3, cornerRadius: 8 }), ]}> - This is a child of MyCustomView + Tapped {tapCount} times ) : ( test-expo-ui module is not available in this environment. diff --git a/packages/expo-modules-core/CHANGELOG.md b/packages/expo-modules-core/CHANGELOG.md index a927f70d984141..50f5ba55269a0e 100644 --- a/packages/expo-modules-core/CHANGELOG.md +++ b/packages/expo-modules-core/CHANGELOG.md @@ -10,7 +10,8 @@ ### 🐛 Bug fixes -- [android] Fix nested `Host` double-composing children. ([#46304](https://github.com/expo/expo/pull/46304) by [@nishan](https://github.com/intergalacticspacehighway)) +- [Android] Fix events being silently dropped for Compose views in custom modules. ([#46623](https://github.com/expo/expo/issues/46623) by [@benjaminkomen](https://github.com/benjaminkomen)) ([#46624](https://github.com/expo/expo/pull/46624) by [@nishan](https://github.com/intergalacticspacehighway)) +- [Android] Fix nested `Host` double-composing children. ([#46282](https://github.com/expo/expo/issues/46282) by [@sadbytes](https://github.com/sadbytes)) ([#46304](https://github.com/expo/expo/pull/46304) by [@nishan](https://github.com/intergalacticspacehighway)) - [iOS] Propagate async-function promise construction failures instead of trapping the app. ([#46106](https://github.com/expo/expo/issues/46106) by [@qutrek](https://github.com/qutrek)) ([#46145](https://github.com/expo/expo/pull/46145) by [@mvincentong](https://github.com/mvincentong)) - [iOS] Read iPad-specific supported orientations from `UISupportedInterfaceOrientations~ipad`. ([#46281](https://github.com/expo/expo/issues/46281) by [@bryandent](https://github.com/bryandent)) ([#46306](https://github.com/expo/expo/pull/46306) by [@mvincentong](https://github.com/mvincentong)) - [iOS] Throw an actionable error when a worklet is used but `react-native-worklets`'s native adapter isn't linked, instead of a misleading "not an instance of Worklet" failure. ([#46571](https://github.com/expo/expo/pull/46571) by [@chrfalch](https://github.com/chrfalch)) diff --git a/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ExpoComposeView.kt b/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ExpoComposeView.kt index 1c5a6b01d8fde8..9a4795c3910227 100644 --- a/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ExpoComposeView.kt +++ b/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ExpoComposeView.kt @@ -511,7 +511,8 @@ class ComposeFunctionHolder( appContext: AppContext, override val name: String, private val composableContent: @Composable FunctionalComposableScope.(props: Props) -> Unit, - override val props: Props + override val props: Props, + override val callbacksDefinition: CallbacksDefinition? ) : ExpoComposeView(context, appContext), ViewFunctionHolder { val propsMutableState = mutableStateOf(props) diff --git a/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt b/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt index 82520101ee394d..8369eea5af02f9 100644 --- a/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt +++ b/packages/expo-modules-core/android/src/compose/expo/modules/kotlin/views/ModuleDefinitionBuilderComposeExtension.kt @@ -143,7 +143,7 @@ class ComposeViewFunctionDefinitionBuilder @PublishedApi i } catch (e: Exception) { throw IllegalStateException("Could not instantiate props instance of $name compose component.", e) } - ComposeFunctionHolder(context, appContext, name, viewFunction, instance) + ComposeFunctionHolder(context, appContext, name, viewFunction, instance, eventBuilder.callbacksDefinition) }, callbacksDefinition = eventBuilder.callbacksDefinition, viewType = ComposeFunctionHolder::class.java, diff --git a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/viewevent/ViewEvent.kt b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/viewevent/ViewEvent.kt index e6b4540c352158..12488b74d13e91 100644 --- a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/viewevent/ViewEvent.kt +++ b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/viewevent/ViewEvent.kt @@ -4,10 +4,12 @@ import android.view.View import com.facebook.react.bridge.ReactContext import com.facebook.react.bridge.WritableMap import expo.modules.core.utilities.ifNull +import expo.modules.kotlin.ModuleRegistry import expo.modules.kotlin.getUnimoduleProxy import expo.modules.kotlin.logger import expo.modules.kotlin.types.JSTypeConverterProvider import expo.modules.kotlin.types.putGeneric +import expo.modules.kotlin.views.CallbacksDefinition import expo.modules.kotlin.views.ViewFunctionHolder fun interface ViewEventCallback { @@ -27,24 +29,13 @@ open class ViewEvent( val appContext = nativeModulesProxy.kotlinInteropModuleRegistry.appContext if (!isValidated) { - val holder = appContext.registry.getModuleHolder(view::class.java).ifNull { - logger.warn("⚠️ Cannot get module holder for ${view::class.java}") - return - } - - val callbacksDefinition = if (view is ViewFunctionHolder) { - appContext.registry.getViewDefinition(holder, view.name)?.callbacksDefinition - } else { - appContext.registry.getViewDefinition(holder, view::class.java)?.callbacksDefinition - } - - val callbacks = callbacksDefinition.ifNull { - logger.warn("⚠️ Cannot get callbacks for ${holder.module::class.java}") + val callbacks = resolveCallbacksDefinition(view, appContext.registry).ifNull { + logger.warn("⚠️ Cannot get callbacks for ${view::class.java}") return } if (!callbacks.names.any { it == name }) { - logger.warn("⚠️ Event $name wasn't exported from ${holder.module::class.java}") + logger.warn("⚠️ Event $name wasn't exported from ${view::class.java}") return } @@ -71,3 +62,17 @@ open class ViewEvent( } } } + +/** + * Resolves the callbacks declared for [view]. Views that reuse a single class + * (e.g. ComposeFunctionHolder) carry their own [CallbacksDefinition] because they + * can't be matched by class; everything else is looked up by class in the registry. + * See https://github.com/expo/expo/issues/46623. + */ +internal fun resolveCallbacksDefinition(view: View, registry: ModuleRegistry): CallbacksDefinition? { + if (view is ViewFunctionHolder) { + return view.callbacksDefinition + } + val holder = registry.getModuleHolder(view::class.java) ?: return null + return registry.getViewDefinition(holder, view::class.java)?.callbacksDefinition +} diff --git a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/ViewFunctionHolder.kt b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/ViewFunctionHolder.kt index 21c445e615a4da..13a3ef87d0bb41 100644 --- a/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/ViewFunctionHolder.kt +++ b/packages/expo-modules-core/android/src/main/java/expo/modules/kotlin/views/ViewFunctionHolder.kt @@ -1,9 +1,12 @@ package expo.modules.kotlin.views /* - * A marker interface identifying views reusing a single class (like ComposeFunctionHolder) - * that should be identified by name for things like event validation. + * A marker interface for views that reuse a single class (like ComposeFunctionHolder) and so + * can't be resolved by class. They're identified by [name] and carry their + * own [callbacksDefinition], which event invocation reads directly instead of looking it up in the + * registry. See https://github.com/expo/expo/issues/46623. */ interface ViewFunctionHolder { val name: String + val callbacksDefinition: CallbacksDefinition? } diff --git a/packages/expo-modules-core/android/src/test/java/expo/modules/kotlin/viewevent/ViewEventTest.kt b/packages/expo-modules-core/android/src/test/java/expo/modules/kotlin/viewevent/ViewEventTest.kt new file mode 100644 index 00000000000000..22e9830c311ead --- /dev/null +++ b/packages/expo-modules-core/android/src/test/java/expo/modules/kotlin/viewevent/ViewEventTest.kt @@ -0,0 +1,43 @@ +package expo.modules.kotlin.viewevent + +import android.view.View +import com.google.common.truth.Truth +import expo.modules.kotlin.ModuleHolder +import expo.modules.kotlin.ModuleRegistry +import expo.modules.kotlin.views.CallbacksDefinition +import expo.modules.kotlin.views.ViewFunctionHolder +import expo.modules.kotlin.views.ViewManagerDefinition +import io.mockk.every +import io.mockk.mockk +import io.mockk.verify +import org.junit.Test + +class ViewEventTest { + + @Test + fun `reads callbacks straight from a ViewFunctionHolder without touching the registry`() { + val callbacks = CallbacksDefinition(arrayOf("onValueChange")) + val view = mockk(moreInterfaces = arrayOf(ViewFunctionHolder::class)) + every { (view as ViewFunctionHolder).callbacksDefinition } returns callbacks + + val registry = mockk() + + Truth.assertThat(resolveCallbacksDefinition(view, registry)).isSameInstanceAs(callbacks) + verify(exactly = 0) { registry.getModuleHolder(any>()) } + } + + @Test + fun `resolves callbacks by class for a non-ViewFunctionHolder view`() { + val view = mockk() + val holder = mockk>() + val callbacks = CallbacksDefinition(arrayOf("onValueChange")) + val definition = mockk { + every { callbacksDefinition } returns callbacks + } + val registry = mockk() + every { registry.getModuleHolder(view::class.java) } returns holder + every { registry.getViewDefinition(holder, view::class.java) } returns definition + + Truth.assertThat(resolveCallbacksDefinition(view, registry)).isSameInstanceAs(callbacks) + } +} From d5742118bc013fc30cb4a98d8fd9b42ddcec3f2f Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Tue, 9 Jun 2026 10:03:41 +0200 Subject: [PATCH 2/5] [expo-sqlite] Fix JNI crash on startup with libSQL session bindings (#46651) # Why Fixes [#46627](https://github.com/expo/expo/issues/46627). On Android, an app using `expo-sqlite` with `useLibSQL: true` crashes on launch with a fatal JNI `NoSuchMethodError` (regression from SDK 55). # How [#42638](https://github.com/expo/expo/pull/42638) switched the session changeset bindings from `byte[]` to `ByteBuffer`, but only updated the Kotlin and default native code - the libSQL variant (`cpp/libsql/NativeSessionBinding.{h,cpp}`) still used `jni::JArrayByte`. So in a libSQL build, fbjni tries to register `()[B` against the Kotlin `()Ljava/nio/ByteBuffer;` method, fails, and crashes on startup. Updated the libSQL stubs to `jni::JByteBuffer` to match. # Test Plan Built an Android app with `useLibSQL: true` (the [repro](https://github.com/ifyajah/expo-sqlite-libsql-bug)). Before: crashes on launch. After: launches and `SQLiteProvider` initializes the libSQL database. # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- packages/expo-sqlite/CHANGELOG.md | 2 ++ .../src/main/cpp/libsql/NativeSessionBinding.cpp | 10 +++++----- .../src/main/cpp/libsql/NativeSessionBinding.h | 11 ++++++----- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/expo-sqlite/CHANGELOG.md b/packages/expo-sqlite/CHANGELOG.md index 01b06dc8171ec2..a026a118169c0c 100644 --- a/packages/expo-sqlite/CHANGELOG.md +++ b/packages/expo-sqlite/CHANGELOG.md @@ -8,6 +8,8 @@ ### 🐛 Bug fixes +- Fixed a fatal JNI crash on Android when using `useLibSQL: true`, caused by the libSQL session bindings still declaring `byte[]` signatures after [#42638](https://github.com/expo/expo/pull/42638) switched Kotlin and the default native bindings to `ByteBuffer`. ([#46651](https://github.com/expo/expo/pull/46651) by [@zoontek](https://github.com/zoontek)) + ### 💡 Others ## 56.0.4 — 2026-05-21 diff --git a/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.cpp b/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.cpp index 082e90d1538880..6ff0272bf0b7e6 100644 --- a/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.cpp +++ b/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.cpp @@ -56,13 +56,13 @@ void NativeSessionBinding::sqlite3session_delete() { jni::throwNewJavaException(UnsupportedOperationException::create().get()); } -jni::local_ref +jni::local_ref NativeSessionBinding::sqlite3session_changeset() { jni::throwNewJavaException(UnsupportedOperationException::create().get()); return nullptr; } -jni::local_ref +jni::local_ref NativeSessionBinding::sqlite3session_changeset_inverted() { jni::throwNewJavaException(UnsupportedOperationException::create().get()); return nullptr; @@ -70,13 +70,13 @@ NativeSessionBinding::sqlite3session_changeset_inverted() { int NativeSessionBinding::sqlite3changeset_apply( jni::alias_ref db, - jni::alias_ref changeset) { + jni::alias_ref changeset) { jni::throwNewJavaException(UnsupportedOperationException::create().get()); return -1; } -jni::local_ref NativeSessionBinding::sqlite3changeset_invert( - jni::alias_ref changeset) { +jni::local_ref NativeSessionBinding::sqlite3changeset_invert( + jni::alias_ref changeset) { jni::throwNewJavaException(UnsupportedOperationException::create().get()); return nullptr; } diff --git a/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.h b/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.h index b4f48dcabd16d3..19ecbf4c2bae74 100644 --- a/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.h +++ b/packages/expo-sqlite/android/src/main/cpp/libsql/NativeSessionBinding.h @@ -3,6 +3,7 @@ #pragma once #include +#include #include #include "NativeDatabaseBinding.h" @@ -25,13 +26,13 @@ class NativeSessionBinding : public jni::HybridClass { int sqlite3session_attach(jni::alias_ref tableName); int sqlite3session_enable(bool enabled); void sqlite3session_delete(); - jni::local_ref sqlite3session_changeset(); - jni::local_ref sqlite3session_changeset_inverted(); + jni::local_ref sqlite3session_changeset(); + jni::local_ref sqlite3session_changeset_inverted(); int sqlite3changeset_apply( jni::alias_ref db, - jni::alias_ref changeset); - jni::local_ref - sqlite3changeset_invert(jni::alias_ref changeset); + jni::alias_ref changeset); + jni::local_ref + sqlite3changeset_invert(jni::alias_ref changeset); private: explicit NativeSessionBinding( From f48fdf40a441c30f15b11a5fd643c68de8a003c3 Mon Sep 17 00:00:00 2001 From: Mathieu Acthernoene Date: Tue, 9 Jun 2026 10:31:14 +0200 Subject: [PATCH 3/5] Derive template SDK from CLI version for standalone modules (#46644) # Why Fixes future issues similar to #46632. For standalone modules, `create-expo-module` always downloaded `expo-module-template@latest` and `expo-template-blank-typescript@latest`, ignoring the SDK the CLI was meant to target. # How `create-expo-module` is published in lockstep with the SDK (56.x ships with SDK 56), so the CLI's own major version is the SDK major. Added `getTemplateDistTag()`, which turns the CLI version into a `sdk-` dist-tag (falling back to `latest` for the pre-56 versions that used the old 1.x/2.x scheme), and used it for both the module template and the example app template. The example app keeps a fallback to `latest` if the versioned template isn't published yet. # Test Plan Added unit tests for `getTemplateDistTag` covering SDK-aligned versions, the old scheme, and unparsable input. `et check-packages create-expo-module` passes (typecheck, lint, test). Note: this fixes the SDK 56 line and forward. It can't repair the already published `create-expo-module@sdk-54` (1.0.15) and `@sdk-55` (2.1.7), since those predate the SDK-aligned versioning and have no way to know their SDK. # Checklist - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- .../src/__tests__/templateUtils-test.ts | 22 ++++++++- .../src/createExampleApp.ts | 49 +++++++++++++++---- .../create-expo-module/src/templateUtils.ts | 26 +++++++++- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/packages/create-expo-module/src/__tests__/templateUtils-test.ts b/packages/create-expo-module/src/__tests__/templateUtils-test.ts index 525e08bbbf21bc..9223e721e38bd6 100644 --- a/packages/create-expo-module/src/__tests__/templateUtils-test.ts +++ b/packages/create-expo-module/src/__tests__/templateUtils-test.ts @@ -2,7 +2,7 @@ import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; -import { getGeneratedWebStubSentinel, updateWebStub } from '../templateUtils'; +import { getGeneratedWebStubSentinel, getTemplateDistTag, updateWebStub } from '../templateUtils'; import type { SubstitutionData } from '../types'; const mockData: SubstitutionData = { @@ -33,6 +33,26 @@ async function writeMinimalWebTemplate(templateDir: string) { ); } +describe('getTemplateDistTag', () => { + it('maps an SDK-aligned version to its `sdk-` tag', () => { + expect(getTemplateDistTag('56.0.3')).toBe('sdk-56'); + expect(getTemplateDistTag('57.0.0')).toBe('sdk-57'); + expect(getTemplateDistTag('60.1.2')).toBe('sdk-60'); + }); + + it('falls back to `latest` for versions from the old, non-SDK-aligned scheme', () => { + expect(getTemplateDistTag('2.1.7')).toBe('latest'); + expect(getTemplateDistTag('1.0.15')).toBe('latest'); + expect(getTemplateDistTag('0.5.0')).toBe('latest'); + }); + + it('falls back to `latest` for missing or unparsable versions', () => { + expect(getTemplateDistTag(undefined)).toBe('latest'); + expect(getTemplateDistTag('')).toBe('latest'); + expect(getTemplateDistTag('not-a-version')).toBe('latest'); + }); +}); + describe('updateWebStub', () => { let tmpDir: string; let templateDir: string; diff --git a/packages/create-expo-module/src/createExampleApp.ts b/packages/create-expo-module/src/createExampleApp.ts index 6a21ca5f16e9fd..f4cb968e17b559 100644 --- a/packages/create-expo-module/src/createExampleApp.ts +++ b/packages/create-expo-module/src/createExampleApp.ts @@ -1,10 +1,12 @@ import spawnAsync from '@expo/spawn-async'; +import chalk from 'chalk'; import fs from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import { usesExpoUI } from './features'; import { installDependencies, type PackageManagerName } from './packageManager'; +import { getTemplateDistTag } from './templateUtils'; import type { SubstitutionData } from './types'; import { env } from './utils/env'; import { newStep } from './utils/ora'; @@ -37,18 +39,23 @@ export async function createExampleApp( } await newStep('Initializing the example app', async (step) => { - const templateVersion = env.EXPO_BETA ? 'next' : 'latest'; - const template = `expo-template-blank-typescript@${templateVersion}`; - debug(`Using example template: ${template}`); - const command = createCommand(packageManager, exampleProjectSlug, template); + // Pin the example template to the same SDK as the module template (derived from the CLI's own + // version), so `create-expo-module@sdk-XX` scaffolds an SDK XX example rather than always using + // `latest`. Fall back to `latest` when the SDK can't be determined or its template isn't published. + const distTag = env.EXPO_BETA ? 'next' : getTemplateDistTag(require('../package.json').version); + try { - await spawnAsync(packageManager, command, { - cwd: targetDir, - }); + await initExampleApp(packageManager, exampleProjectSlug, targetDir, distTag); } catch (error: any) { - throw new Error( - `${command.join(' ')} failed with exit code: ${error?.status}.\n\nError stack:\n${error?.stderr}` + if (env.EXPO_BETA || distTag === 'latest') { + throw error; + } + + console.warn( + chalk.yellow(`Failed to use the "${distTag}" example template, falling back to "latest".`) ); + + await initExampleApp(packageManager, exampleProjectSlug, targetDir, 'latest'); } step.succeed('Initialized the example app'); @@ -103,6 +110,30 @@ async function installExpoUI(exampleAppPath: string): Promise { }); } +/** + * Initializes the example app from `expo-template-blank-typescript` at the given dist-tag. + */ +async function initExampleApp( + packageManager: PackageManagerName, + exampleProjectSlug: string, + targetDir: string, + distTag: string +): Promise { + const template = `expo-template-blank-typescript@${distTag}`; + debug(`Using example template: ${template}`); + const command = createCommand(packageManager, exampleProjectSlug, template); + + try { + await spawnAsync(packageManager, command, { + cwd: targetDir, + }); + } catch (error: any) { + throw new Error( + `${command.join(' ')} failed with exit code: ${error?.status}.\n\nError stack:\n${error?.stderr}` + ); + } +} + function createCommand( packageManager: PackageManagerName, exampleProjectSlug: string, diff --git a/packages/create-expo-module/src/templateUtils.ts b/packages/create-expo-module/src/templateUtils.ts index 701ec66d22e6e8..ddee73723aa1c7 100644 --- a/packages/create-expo-module/src/templateUtils.ts +++ b/packages/create-expo-module/src/templateUtils.ts @@ -158,15 +158,37 @@ async function getLocalSdkMajorVersion(): Promise { return version?.split('.')[0] ?? null; } +// The first SDK the CLI is versioned in lockstep with (CLI major == SDK major). Earlier releases +// used an independent scheme (e.g. `1.x` for sdk-54, `2.x` for sdk-55) whose major doesn't map to +// an SDK, so anything below this falls back to `latest`. +const FIRST_SDK_ALIGNED_MAJOR = 56; + +/** + * Resolves the template dist-tag targeted by a `create-expo-module` release from its own package + * version. The CLI is published in lockstep with the SDK (e.g. `56.x.y` ships alongside SDK 56), so + * its major version is the SDK major and maps to `sdk-`. Falls back to `latest` for the + * older, non-SDK-aligned versions. + */ +export function getTemplateDistTag(version: string | undefined): string { + const major = Number(version?.split('.')[0]); + return Number.isInteger(major) && major >= FIRST_SDK_ALIGNED_MAJOR ? `sdk-${major}` : 'latest'; +} + /** - * Selects correct version of the template based on the SDK version for local modules and EXPO_BETA flag. + * Selects correct version of the template based on the SDK version and EXPO_BETA flag. + * + * - For local modules, the SDK is derived from the host project's `expo` dependency. + * - For standalone modules, the SDK is derived from the CLI's own version, so that + * `create-expo-module@sdk-XX` scaffolds an SDK XX module rather than always using `latest`. + * + * In both cases we fall back to `latest` when the SDK can't be determined. */ async function getTemplateVersion(isLocal: boolean) { if (env.EXPO_BETA) { return 'next'; } if (!isLocal) { - return 'latest'; + return getTemplateDistTag(require('../package.json').version); } try { const sdkVersionMajor = await getLocalSdkMajorVersion(); From c869f35bcff1a359482d7cfe07777db21928155f Mon Sep 17 00:00:00 2001 From: Jakub Tkacz <32908614+Ubax@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:36:24 +0200 Subject: [PATCH 4/5] [expo-observe] Add unit tests for direct react-navigation and expo-router imports (#46639) # Why In order to avoid regressions like - https://github.com/expo/expo/pull/46293 # How Add tests ensuring that `@react-navigation/native` and `expo-router` are not imported directly # Test Plan CI # Checklist - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --- .../src/__tests__/optionalImport.test.ts | 58 +++++++++++++++++++ .../__tests__/optionalImport.test.ts | 26 +++++++++ .../__tests__/optionalImport.test.ts | 24 ++++++++ 3 files changed, 108 insertions(+) create mode 100644 packages/expo-observe/src/__tests__/optionalImport.test.ts create mode 100644 packages/expo-observe/src/integrations/expo-router/__tests__/optionalImport.test.ts create mode 100644 packages/expo-observe/src/integrations/react-navigation/__tests__/optionalImport.test.ts diff --git a/packages/expo-observe/src/__tests__/optionalImport.test.ts b/packages/expo-observe/src/__tests__/optionalImport.test.ts new file mode 100644 index 00000000000000..a2e178fd4b39b6 --- /dev/null +++ b/packages/expo-observe/src/__tests__/optionalImport.test.ts @@ -0,0 +1,58 @@ +jest.mock('expo-router', () => { + throw new Error('simulated: expo-router is not installed'); +}); +jest.mock('@react-navigation/native', () => { + throw new Error('simulated: @react-navigation/native is not installed'); +}); + +jest.mock('../integrations/expo-router/router', () => ({ + __esModule: true, + isRouterInstalled: true, + optionalRouter: { + useRoute: jest.fn(), + useNavigation: jest.fn(), + useCurrentRouteInfo: jest.fn(), + unstable_navigationEvents: { + enable: jest.fn(), + addListener: jest.fn(() => ({ remove: jest.fn() })), + }, + }, +})); +jest.mock('../integrations/react-navigation/reactNavigation', () => ({ + __esModule: true, + isReactNavigationInstalled: true, + optionalReactNavigation: { + NavigationContainer: () => null, + useNavigationContainerRef: jest.fn(), + useRoute: jest.fn(), + useNavigation: jest.fn(), + useStateForPath: jest.fn(), + }, +})); + +// The native module and app-metrics are unrelated to this guard; stub them so requiring +// the root entry doesn't reach native code at load time. `NativeModule`/`registerWebModule` +// are needed for the web build (`module.web.ts`), which extends `NativeModule`. +jest.mock('expo', () => ({ + requireNativeModule: jest.fn(() => ({ + configure: jest.fn(), + setBundleDefaults: jest.fn(), + dispatchEvents: jest.fn(() => Promise.resolve()), + })), + NativeModule: class {}, + registerWebModule: jest.fn((ModuleClass) => new ModuleClass()), +})); +jest.mock('expo-app-metrics', () => ({ + __esModule: true, + default: { + markInteractive: jest.fn(), + getMainSession: jest.fn(async () => ({ id: 'session-1' })), + addCustomMetricToSession: jest.fn(), + }, +})); + +describe('expo-observe root entry optional imports', () => { + it('loads with neither expo-router nor @react-navigation/native installed', () => { + expect(() => require('../index')).not.toThrow(); + }); +}); diff --git a/packages/expo-observe/src/integrations/expo-router/__tests__/optionalImport.test.ts b/packages/expo-observe/src/integrations/expo-router/__tests__/optionalImport.test.ts new file mode 100644 index 00000000000000..a97257962801b8 --- /dev/null +++ b/packages/expo-observe/src/integrations/expo-router/__tests__/optionalImport.test.ts @@ -0,0 +1,26 @@ +// `expo-router` is an optional peer dependency. The integration must reach it ONLY +// through the `router` wrapper (a try/catch require), never via a direct +// `import { x } from 'expo-router'` +jest.mock('expo-router', () => { + throw new Error('simulated: expo-router is not installed'); +}); + +jest.mock('../router', () => ({ + __esModule: true, + isRouterInstalled: true, + optionalRouter: { + useRoute: jest.fn(), + useNavigation: jest.fn(), + useCurrentRouteInfo: jest.fn(), + unstable_navigationEvents: { + enable: jest.fn(), + addListener: jest.fn(() => ({ remove: jest.fn() })), + }, + }, +})); + +describe('expo-router integration optional imports', () => { + it('loads its entry point without expo-router installed', () => { + expect(() => require('../index')).not.toThrow(); + }); +}); diff --git a/packages/expo-observe/src/integrations/react-navigation/__tests__/optionalImport.test.ts b/packages/expo-observe/src/integrations/react-navigation/__tests__/optionalImport.test.ts new file mode 100644 index 00000000000000..c01038d14280b8 --- /dev/null +++ b/packages/expo-observe/src/integrations/react-navigation/__tests__/optionalImport.test.ts @@ -0,0 +1,24 @@ +// `@react-navigation/native` is an optional peer dependency. The integration must +// reach it ONLY through the `reactNavigation` wrapper (a try/catch require), never +// via a direct `import { x } from '@react-navigation/native'` +jest.mock('@react-navigation/native', () => { + throw new Error('simulated: @react-navigation/native is not installed'); +}); + +jest.mock('../reactNavigation', () => ({ + __esModule: true, + isReactNavigationInstalled: true, + optionalReactNavigation: { + NavigationContainer: () => null, + useNavigationContainerRef: jest.fn(), + useRoute: jest.fn(), + useNavigation: jest.fn(), + useStateForPath: jest.fn(), + }, +})); + +describe('react-navigation integration optional imports', () => { + it('loads its entry point without @react-navigation/native installed', () => { + expect(() => require('../index')).not.toThrow(); + }); +}); From 82d99b6959192f5ac89c4577567dd5f4335e9f2a Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Tue, 9 Jun 2026 10:11:33 +0100 Subject: [PATCH 5/5] fix(expo,cli,router): Carry preloaded modules through from `' + + '' + + '' + + '' + ); +}); + it('sorts assets based on requires tree', () => { const assets: SerialAsset[] = [ { diff --git a/packages/@expo/cli/src/start/server/metro/serializeHtml.ts b/packages/@expo/cli/src/start/server/metro/serializeHtml.ts index 5be22ece4d8c0f..145c538a10c270 100644 --- a/packages/@expo/cli/src/start/server/metro/serializeHtml.ts +++ b/packages/@expo/cli/src/start/server/metro/serializeHtml.ts @@ -98,7 +98,9 @@ function htmlFromSerialAssets( orderedJsAssets.filter((a) => a.metadata.isAsync), route.entryPoints ); - orderedJsAssets = [...syncAssets, ...sortedAsync]; + const runtimeAssets = syncAssets.filter((a) => !a.metadata.requires?.length); + const entryAssets = syncAssets.filter((a) => !!a.metadata.requires?.length); + orderedJsAssets = [...runtimeAssets, ...sortedAsync, ...entryAssets]; } const scripts = bundleUrl diff --git a/packages/expo-router/CHANGELOG.md b/packages/expo-router/CHANGELOG.md index dbb114708e24d0..b9cb4e041619b2 100644 --- a/packages/expo-router/CHANGELOG.md +++ b/packages/expo-router/CHANGELOG.md @@ -11,6 +11,7 @@ ### 🐛 Bug fixes - [android] fix renderingMode for toolbar icons ([#46149](https://github.com/expo/expo/pull/46149) by [@Ubax](https://github.com/Ubax)) +- Allow async routes to rehydrate synchronously by carrying through preloaded modules preventing FOUC in production output ([#46539](https://github.com/expo/expo/pull/46539) by [@kitten](https://github.com/kitten)) ### 💡 Others diff --git a/packages/expo-router/build/Route.d.ts b/packages/expo-router/build/Route.d.ts index 70e1f7fc9375f6..ec2db5e847ebc1 100644 --- a/packages/expo-router/build/Route.d.ts +++ b/packages/expo-router/build/Route.d.ts @@ -32,7 +32,7 @@ export type RouteNode = { /** The type of RouteNode */ type: 'route' | 'api' | 'layout' | 'redirect' | 'rewrite'; /** Load a route into memory. Returns the exports from a route. */ - loadRoute: () => Partial; + loadRoute: () => LoadedRoute; /** Loaded initial route name. */ initialRouteName?: string; /** Nested routes */ diff --git a/packages/expo-router/build/Route.d.ts.map b/packages/expo-router/build/Route.d.ts.map index 921fa40f988af5..3daed9d20e276d 100644 --- a/packages/expo-router/build/Route.d.ts.map +++ b/packages/expo-router/build/Route.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/expo-router/build/Route.js.map b/packages/expo-router/build/Route.js.map index 60c641c84e5a61..cd00de4812257a 100644 --- a/packages/expo-router/build/Route.js.map +++ b/packages/expo-router/build/Route.js.map @@ -1 +1 @@ -{"version":3,"file":"Route.js","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;AA+Eb,oCAEC;AAED,sCAMC;AAQD,sBAMC;;AApGD,iCAAuF;AAEvF,yCAA2C;AAC3C,6CAAiE;AAmGxD,sGAnGA,kCAAqB,OAmGA;AAAE,2FAnGA,uBAAU,OAmGA;AAtC1C,MAAM,mBAAmB,GAAG,IAAA,qBAAa,EAAmB,IAAI,CAAC,CAAC;AAClE,+FAA+F;AAClF,QAAA,uBAAuB,GAAG,IAAA,qBAAa,EAElD,SAAS,CAAC,CAAC;AACA,QAAA,uBAAuB,GAAG,IAAA,qBAAa,EAAqB,EAAE,CAAC,CAAC;AAE7E,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,mBAAmB,CAAC,WAAW,GAAG,WAAW,CAAC;AAChD,CAAC;AAED,+DAA+D;AAC/D,SAAgB,YAAY;IAC1B,OAAO,IAAA,WAAG,EAAC,mBAAmB,CAAC,CAAC;AAClC,CAAC;AAED,SAAgB,aAAa;IAC3B,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAA,wBAAa,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAOD,iEAAiE;AACjE,SAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAc;IAC1D,OAAO,CACL,uBAAC,+BAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YAC7C,uBAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAAgC,GACnD,CACpC,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport type { GenerateMetadataFunction, LoaderFunction } from 'expo-server';\nimport { createContext, use, type ComponentType, type PropsWithChildren } from 'react';\n\nimport { getContextKey } from './matchers';\nimport { sortRoutesWithInitial, sortRoutes } from './sortRoutes';\nimport type { SuspenseFallbackProps } from './views/SuspenseFallback';\nimport type { ErrorBoundaryProps } from './views/Try';\n\nexport type DynamicConvention = { name: string; deep: boolean; notFound?: boolean };\n\ntype Params = Record;\n\nexport type LoadedRoute = {\n ErrorBoundary?: ComponentType;\n SuspenseFallback?: ComponentType;\n default?: ComponentType;\n unstable_settings?: Record;\n getNavOptions?: (args: any) => any;\n generateStaticParams?: (props: { params?: Params }) => Params[];\n loader?: LoaderFunction;\n generateMetadata?: GenerateMetadataFunction;\n};\n\nexport type LoadedMiddleware = Pick;\n\nexport type MiddlewareNode = {\n /** Context Module ID. Used to resolve the middleware module */\n contextKey: string;\n /** Loads middleware into memory. Returns the exports from +middleware.ts */\n loadRoute: () => Partial;\n};\n\nexport type RouteNode = {\n /** The type of RouteNode */\n type: 'route' | 'api' | 'layout' | 'redirect' | 'rewrite';\n /** Load a route into memory. Returns the exports from a route. */\n loadRoute: () => Partial;\n /** Loaded initial route name. */\n initialRouteName?: string;\n /** Nested routes */\n children: RouteNode[];\n /** Is the route a dynamic path */\n dynamic: null | DynamicConvention[];\n /** `index`, `error-boundary`, etc. Relative to the nearest `_layout.tsx` */\n route: string;\n /** Context Module ID, used for matching children. */\n contextKey: string;\n /** Redirect Context Module ID, used for matching children. */\n destinationContextKey?: string;\n /** Parent Context Module ID, used for matching static routes to their parent dynamic route. */\n parentContextKey?: string;\n /** Is the redirect permanent. */\n permanent?: boolean;\n /** Added in-memory */\n generated?: boolean;\n /** Internal screens like the directory or the auto 404 should be marked as internal. */\n internal?: boolean;\n /** File paths for async entry modules that should be included in the initial chunk request to ensure the runtime JavaScript matches the statically rendered HTML representation. */\n entryPoints?: string[];\n /** HTTP methods for this route. If undefined, assumed to be ['GET'] */\n methods?: string[];\n /** Middleware function for server-side request processing. Only present on the root route node. */\n middleware?: MiddlewareNode;\n};\n\nconst CurrentRouteContext = createContext(null);\n/** This context allows a `_layout.tsx` to provide a Suspense fallback for its child routes. */\nexport const SuspenseFallbackContext = createContext<\n ComponentType | undefined\n>(undefined);\nexport const LocalRouteParamsContext = createContext({});\n\nif (process.env.NODE_ENV !== 'production') {\n CurrentRouteContext.displayName = 'RouteNode';\n}\n\n/** Return the RouteNode at the current contextual boundary. */\nexport function useRouteNode(): RouteNode | null {\n return use(CurrentRouteContext);\n}\n\nexport function useContextKey(): string {\n const node = useRouteNode();\n if (node == null) {\n throw new Error('No filename found. This is likely a bug in expo-router.');\n }\n return getContextKey(node.contextKey);\n}\n\nexport type RouteProps = PropsWithChildren<{\n node: RouteNode;\n params: object | undefined;\n}>;\n\n/** Provides the matching routes and filename to the children. */\nexport function Route({ children, node, params }: RouteProps) {\n return (\n \n {children}\n \n );\n}\n\nexport { sortRoutesWithInitial, sortRoutes };\n"]} \ No newline at end of file +{"version":3,"file":"Route.js","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;AA+Eb,oCAEC;AAED,sCAMC;AAQD,sBAMC;;AApGD,iCAAuF;AAEvF,yCAA2C;AAC3C,6CAAiE;AAmGxD,sGAnGA,kCAAqB,OAmGA;AAAE,2FAnGA,uBAAU,OAmGA;AAtC1C,MAAM,mBAAmB,GAAG,IAAA,qBAAa,EAAmB,IAAI,CAAC,CAAC;AAClE,+FAA+F;AAClF,QAAA,uBAAuB,GAAG,IAAA,qBAAa,EAElD,SAAS,CAAC,CAAC;AACA,QAAA,uBAAuB,GAAG,IAAA,qBAAa,EAAqB,EAAE,CAAC,CAAC;AAE7E,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;IAC1C,mBAAmB,CAAC,WAAW,GAAG,WAAW,CAAC;AAChD,CAAC;AAED,+DAA+D;AAC/D,SAAgB,YAAY;IAC1B,OAAO,IAAA,WAAG,EAAC,mBAAmB,CAAC,CAAC;AAClC,CAAC;AAED,SAAgB,aAAa;IAC3B,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,IAAA,wBAAa,EAAC,IAAI,CAAC,UAAU,CAAC,CAAC;AACxC,CAAC;AAOD,iEAAiE;AACjE,SAAgB,KAAK,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAc;IAC1D,OAAO,CACL,uBAAC,+BAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YAC7C,uBAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAAgC,GACnD,CACpC,CAAC;AACJ,CAAC","sourcesContent":["'use client';\n\nimport type { GenerateMetadataFunction, LoaderFunction } from 'expo-server';\nimport { createContext, use, type ComponentType, type PropsWithChildren } from 'react';\n\nimport { getContextKey } from './matchers';\nimport { sortRoutesWithInitial, sortRoutes } from './sortRoutes';\nimport type { SuspenseFallbackProps } from './views/SuspenseFallback';\nimport type { ErrorBoundaryProps } from './views/Try';\n\nexport type DynamicConvention = { name: string; deep: boolean; notFound?: boolean };\n\ntype Params = Record;\n\nexport type LoadedRoute = {\n ErrorBoundary?: ComponentType;\n SuspenseFallback?: ComponentType;\n default?: ComponentType;\n unstable_settings?: Record;\n getNavOptions?: (args: any) => any;\n generateStaticParams?: (props: { params?: Params }) => Params[];\n loader?: LoaderFunction;\n generateMetadata?: GenerateMetadataFunction;\n};\n\nexport type LoadedMiddleware = Pick;\n\nexport type MiddlewareNode = {\n /** Context Module ID. Used to resolve the middleware module */\n contextKey: string;\n /** Loads middleware into memory. Returns the exports from +middleware.ts */\n loadRoute: () => Partial;\n};\n\nexport type RouteNode = {\n /** The type of RouteNode */\n type: 'route' | 'api' | 'layout' | 'redirect' | 'rewrite';\n /** Load a route into memory. Returns the exports from a route. */\n loadRoute: () => LoadedRoute;\n /** Loaded initial route name. */\n initialRouteName?: string;\n /** Nested routes */\n children: RouteNode[];\n /** Is the route a dynamic path */\n dynamic: null | DynamicConvention[];\n /** `index`, `error-boundary`, etc. Relative to the nearest `_layout.tsx` */\n route: string;\n /** Context Module ID, used for matching children. */\n contextKey: string;\n /** Redirect Context Module ID, used for matching children. */\n destinationContextKey?: string;\n /** Parent Context Module ID, used for matching static routes to their parent dynamic route. */\n parentContextKey?: string;\n /** Is the redirect permanent. */\n permanent?: boolean;\n /** Added in-memory */\n generated?: boolean;\n /** Internal screens like the directory or the auto 404 should be marked as internal. */\n internal?: boolean;\n /** File paths for async entry modules that should be included in the initial chunk request to ensure the runtime JavaScript matches the statically rendered HTML representation. */\n entryPoints?: string[];\n /** HTTP methods for this route. If undefined, assumed to be ['GET'] */\n methods?: string[];\n /** Middleware function for server-side request processing. Only present on the root route node. */\n middleware?: MiddlewareNode;\n};\n\nconst CurrentRouteContext = createContext(null);\n/** This context allows a `_layout.tsx` to provide a Suspense fallback for its child routes. */\nexport const SuspenseFallbackContext = createContext<\n ComponentType | undefined\n>(undefined);\nexport const LocalRouteParamsContext = createContext({});\n\nif (process.env.NODE_ENV !== 'production') {\n CurrentRouteContext.displayName = 'RouteNode';\n}\n\n/** Return the RouteNode at the current contextual boundary. */\nexport function useRouteNode(): RouteNode | null {\n return use(CurrentRouteContext);\n}\n\nexport function useContextKey(): string {\n const node = useRouteNode();\n if (node == null) {\n throw new Error('No filename found. This is likely a bug in expo-router.');\n }\n return getContextKey(node.contextKey);\n}\n\nexport type RouteProps = PropsWithChildren<{\n node: RouteNode;\n params: object | undefined;\n}>;\n\n/** Provides the matching routes and filename to the children. */\nexport function Route({ children, node, params }: RouteProps) {\n return (\n \n {children}\n \n );\n}\n\nexport { sortRoutesWithInitial, sortRoutes };\n"]} \ No newline at end of file diff --git a/packages/expo-router/build/getRoutesCore.d.ts.map b/packages/expo-router/build/getRoutesCore.d.ts.map index 68109c37cd6110..bc45bbd12106c2 100644 --- a/packages/expo-router/build/getRoutesCore.d.ts.map +++ b/packages/expo-router/build/getRoutesCore.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"getRoutesCore.d.ts","sourceRoot":"","sources":["../src/getRoutesCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAkB,SAAS,EAAE,MAAM,SAAS,CAAC;AAW5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAE5C,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC,yGAAyG;IACzG,cAAc,EAAE,CACd,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;QACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;QACrB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B,KACE,SAAS,CAAC;CAChB,CAAC;AAQF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CA6B3F;AAmpBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAwBzF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAgBxE"} \ No newline at end of file +{"version":3,"file":"getRoutesCore.d.ts","sourceRoot":"","sources":["../src/getRoutesCore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAkB,SAAS,EAAE,MAAM,SAAS,CAAC;AAW5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAE3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,4BAA4B,CAAC,EAAE,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAE5C,2BAA2B,CAAC,EAAE,OAAO,CAAC;IAEtC,yGAAyG;IACzG,cAAc,EAAE,CACd,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC,GAAG;QACzC,QAAQ,CAAC,EAAE,SAAS,CAAC;QACrB,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B,KACE,SAAS,CAAC;CAChB,CAAC;AAQF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB,CAAC;AAIF;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CA6B3F;AA6pBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAwBzF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAgBxE"} \ No newline at end of file diff --git a/packages/expo-router/build/getRoutesCore.js b/packages/expo-router/build/getRoutesCore.js index d2a9913749e4c0..bff90e4b99cc5a 100644 --- a/packages/expo-router/build/getRoutesCore.js +++ b/packages/expo-router/build/getRoutesCore.js @@ -238,6 +238,15 @@ function getDirectoryTree(contextModule, options) { else { routeModule = contextModule(filePath); } + // See: expo/src/async-require/asyncRequireModule.ts + // The "lazy" async require function returns a thenable that may carry + // a raw `_result` value that's either a promise or the synchronously resolved module + if (importMode === 'lazy' || importMode === 'lazy-once') { + routeModule = + '_result' in routeModule && routeModule._result != null + ? routeModule._result + : routeModule; + } if (process.env.NODE_ENV === 'development' && importMode === 'sync') { // In development mode, when async routes are disabled, add some extra error handling to improve the developer experience. // This can be useful when you accidentally use an async function in a route file for the default export. diff --git a/packages/expo-router/build/getRoutesCore.js.map b/packages/expo-router/build/getRoutesCore.js.map index b70494a4a02779..2249ff86a7fe99 100644 --- a/packages/expo-router/build/getRoutesCore.js.map +++ b/packages/expo-router/build/getRoutesCore.js.map @@ -1 +1 @@ -{"version":3,"file":"getRoutesCore.js","sourceRoot":"","sources":["../src/getRoutesCore.ts"],"names":[],"mappings":";;AAqFA,8BA6BC;AAwpBD,8CAwBC;AAED,0CAgBC;AAnzBD,yCASoB;AAEpB,qCAAmD;AA2DnD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,aAA6B,EAAE,OAAgB;IACvE,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAE/D,yBAAyB;IACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,4BAA4B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEtE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAC7E,IACE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QACtC,UAAU,KAAK,MAAM;QACrB,CAAC,OAAO,CAAC,mBAAmB,EAC5B,CAAC;QACD,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/B,wCAAwC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,aAA6B,EAAE,OAAgB;IACpE,MAAM,kBAAkB,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IAE7F,mDAAmD;IACnD,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC;QAC1C,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CACV,mHAAmH;gBACjH,IAAI,CAAC,SAAS,CACZ;oBACE,IAAI,EAAE;wBACJ,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,CAAC,CAAC;qBACnE;iBACF,EACD,IAAI,EACJ,CAAC,CACF,CACJ,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEnF,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEzE,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,CACjD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC9C,CAAC;IACF,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,yFAAyF,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxH,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mFAAmF;IACnF,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,2EAA2E,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CACnI,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,CAAC,CAAE,CAAC;IAEnD,MAAM,UAAU,GAAmB;QACjC,SAAS;YACP,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,OAAO,aAAa,CAAC,kBAAkB,CAAC,CAAC;gBAC3C,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,aAAa,CAAC,kBAAkB,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,UAAU,EAAE,kBAAkB;KAC/B,CAAC;IAEF,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;QACpC,OAAQ,UAAkB,CAAC,SAAS,CAAC;IACvC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,aAA6B,EAAE,OAAgB;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAE7E,MAAM,UAAU,GAAa,CAAC,uCAAuC,CAAC,CAAC,CAAC,oCAAoC;IAE5G,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC/C,CAAC;IAED,6DAA6D;IAC7D,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IAE3D,MAAM,aAAa,GAAkB;QACnC,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,cAAc,EAAE,IAAI,GAAG,EAAE;KAC1B,CAAC;IAEF,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;IACzC,MAAM,SAAS,GAAmC,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAkC,EAAE,CAAC;IAEnD,IAAI,yBAA6F,CAAC;IAElG,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAChC,2DAA2D;QAC3D,yBAAyB,KAAK,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACpD,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,oBAAoB,EAAE,+CAA+C,CACnE,IAAA,oCAAyB,EAAC,GAAG,CAAC,CAC/B;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,yBAAyB,CAAC;IACnC,CAAC,CAAC;IAEF,2FAA2F;IAC3F,4GAA4G;IAC5G,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACzC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAChF,MAAM,UAAU,GAAG,uBAAuB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAE5D,MAAM,kBAAkB,GAAG,IAAA,0BAAoB,EAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAEtE,MAAM,qBAAqB,GAAG,kBAAkB;oBAC9C,CAAC,CAAC,QAAQ,CAAC,WAAW;oBACtB,CAAC,CAAC,+CAA+C,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAE1E,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;oBAC7D,SAAS;gBACX,CAAC;gBAED,MAAM,gBAAgB,GAAG,kBAAkB;oBACzC,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,oBAAoB,EAAE,CAAC,IAAI,CACzB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,oBAAoB,KAAK,qBAAqB,CAC5D,CAAC;gBACN,MAAM,WAAW,GAAG,kBAAkB;oBACpC,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;gBAC3C,MAAM,qBAAqB,GAAG,kBAAkB;oBAC9C,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,gBAAgB,EAAE,UAAU,CAAC;gBAEjC,IAAI,CAAC,qBAAqB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBACxD;;;;;uBAKG;oBACH,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;wBAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,WAAW,mBAAmB,CAAC,CAAC;oBACpF,CAAC;oBAED,SAAS;gBACX,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnC,SAAS,CAAC,UAAU,CAAC,GAAG;oBACtB,MAAM,EAAE,UAAU;oBAClB,WAAW;oBACX,qBAAqB;oBACrB,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;oBACtC,QAAQ,EAAE,kBAAkB;oBAC5B,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACvC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/E,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE3D,4FAA4F;gBAC5F,sCAAsC;gBACtC,MAAM,8BAA8B,GAAG,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;gBAC9E,MAAM,qBAAqB,GAAG,8BAA8B;oBAC1D,CAAC,CAAC,uBAAuB,CAAC,OAAO,CAAC,WAAW,CAAC;oBAC9C,CAAC,CAAC,+CAA+C,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBAEzE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;oBAC7D,SAAS;gBACX,CAAC;gBAED,MAAM,gBAAgB,GAAG,oBAAoB,EAAE,CAAC,IAAI,CAClD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,oBAAoB,KAAK,qBAAqB,CAC5D,CAAC;gBACF,MAAM,WAAW,GAAG,gBAAgB,EAAE,oBAAoB,CAAC;gBAC3D,MAAM,qBAAqB,GAAG,gBAAgB,EAAE,UAAU,CAAC;gBAE3D,IAAI,CAAC,qBAAqB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBACxD;;;;;uBAKG;oBACH,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;wBAC9B,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,WAAW,mBAAmB,CAAC,CAAC;oBAClF,CAAC;oBAED,SAAS;gBACX,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnC,QAAQ,CAAC,UAAU,CAAC,GAAG;oBACrB,MAAM,EAAE,UAAU;oBAClB,WAAW;oBACX,qBAAqB;oBACrB,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAU,CAAC;IAErD,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACrD,SAAS;QACX,CAAC;QAED,OAAO,GAAG,IAAI,CAAC;QAEf,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEjE,+EAA+E;QAC/E,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,GAAc;YACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;YAC7D,SAAS;gBACP,IAAI,WAAgB,CAAC;gBAErB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;oBAChC,IAAI,CAAC;wBACH,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxC,CAAC;oBAAC,MAAM,CAAC;wBACP,WAAW,GAAG,EAAE,CAAC;oBACnB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxC,CAAC;gBAED,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;oBACpE,0HAA0H;oBAC1H,yGAAyG;oBACzG,IAAI,WAAW,YAAY,OAAO,EAAE,CAAC;wBACnC,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,sDAAsD,CACzE,CAAC;oBACJ,CAAC;oBAED,MAAM,aAAa,GAAG,WAAW,EAAE,OAAO,CAAC;oBAC3C,IAAI,aAAa,YAAY,OAAO,EAAE,CAAC;wBACrC,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,4EAA4E,CACvH,CAAC;oBACJ,CAAC;oBAED,4DAA4D;oBAC5D,IACE,aAAa,YAAY,QAAQ;wBACjC,kGAAkG;wBAClG,aAAa,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe,EAClD,CAAC;wBACD,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,oFAAoF,CAC/H,CAAC;oBACJ,CAAC;oBAED,wCAAwC;oBACxC,MAAM,YAAY,GAAG,WAAW,EAAE,MAAM,CAAC;oBACzC,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;wBACvD,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,4CAA4C,CAAC,CAAC;oBAClF,CAAC;oBAED,MAAM,cAAc,GAAG,WAAW,EAAE,gBAAgB,CAAC;oBACrD,IAAI,cAAc,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;wBAC3D,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,oDAAoD,CAAC,CAAC;oBAC1F,CAAC;gBACH,CAAC;gBAED,OAAO,WAAW,CAAC;YACrB,CAAC;YACD,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,EAAE,EAAE,6DAA6D;YACxE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,EAAE,EAAE,sHAAsH;SACrI,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC;YACxC,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC;YAC5D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;YACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC1B,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;oBAC5B,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,QAAQ,CAAC,WAAW;oBAC3B,QAAQ,EAAE,IAAI;oBACd,cAAc,EAAE,QAAQ;iBACzB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,QAAS,CAAC,OAAO,EAAE,CAAC;gBACtB,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;YACvB,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC;YACtC,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC1B,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;oBAC5B,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,OAAO,CAAC,WAAW;oBAC1B,QAAQ,EAAE,IAAI;oBACd,aAAa,EAAE,OAAO;iBACvB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YACjC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;YACtB,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED;;;WAGG;QACH,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,+FAA+F;YAC/F,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAExD,0EAA0E;YAC1E,IAAI,SAAS,GAAG,aAAa,CAAC;YAE9B,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;gBACrC,IAAI,YAAY,GAAG,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAEtD,oCAAoC;gBACpC,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,YAAY,GAAG;wBACb,KAAK,EAAE,IAAI,GAAG,EAAE;wBAChB,cAAc,EAAE,IAAI,GAAG,EAAE;qBAC1B,CAAC;oBACF,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBACnD,CAAC;gBAED,SAAS,GAAG,YAAY,CAAC;YAC3B,CAAC;YAED,gCAAgC;YAChC,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC;YAE1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,gBAAgB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACjI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACpC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;gBAC5C,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC;gBAC/B,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAEzC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACtC,CAAC;gBAED,iEAAiE;gBACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAE1B,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACxI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBACpC,CAAC;gBAED;;;;;mBAKG;gBACH,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACrI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,SAAS,KAAK,IAAI,CAAC;oBACnB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,aAAa,CAAC,MAAM,GAAG;YACrB,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE;aACV,CAAC;SACH,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3C,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC/B,mBAAmB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IAC3C,4EAA4E;IAC5E,OAAO,CACL,IAAA,qCAA0B,EAAC,IAAA,+BAAoB,EAAC,IAAI,CAAC,CAAC;QACpD,yBAAyB;SACxB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CACtB,CAAC;AACJ,CAAC;AAED,SAAS,+CAA+C,CAAC,IAAY;IACnE,OAAO,IAAA,yCAA8B,EAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,sDAAsD;AACtD,SAAS,qCAAqC,CAAC,MAAc;IAC3D,MAAM,IAAI,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,iCAAiC;IACtF,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,4BAA4B,CACnC,SAAwB,EACxB,OAAgB;AAChB,oDAAoD;AACpD,MAAkB;AAClB,8CAA8C;AAC9C,YAAY,GAAG,EAAE;IAEjB;;OAEG;IACH,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,cAAc,GAAG,MAAM,CAAC;QAC9B,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAE3C,8CAA8C;QAC9C,IAAI,cAAc,EAAE,CAAC;YACnB,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACpC,OAAQ,MAAc,CAAC,SAAS,CAAC;QACnC,CAAC;QAED,sFAAsF;QACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACxD,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtD,6EAA6E;QAC7E,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,oGAAoG;IACpG,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAE9E,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAE1C,wFAAwF;QACxF,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC5D,SAAS,CAAC,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAErD,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACpC,OAAQ,SAAiB,CAAC,SAAS,CAAC;QACtC,CAAC;QAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;QACtD,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAe;IAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAClE,OAAO;IACT,CAAC;IAED,SAAS,wBAAwB,CAAC,IAAe;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,gCAAgC;QAChC,MAAM,KAAK,GAAG,SAAS,EAAE,OAAO,CAAC;QACjC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,uEAAuE;YACvE,OAAO,CAAC,IAAI,CACV,UAAU,IAAI,CAAC,UAAU,4FAA4F,CACtH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CACb,kCAAkC,IAAI,CAAC,UAAU,8BAA8B,OAAO,KAAK,6EAA6E,CACzK,CAAC;QACJ,CAAC;IACH,CAAC;IAED,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,WAAmB,EACnB,OAAgB,EAChB,SAAyC,EACzC,QAAuC;IAEvC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAA,oCAAyB,EAAC,IAAA,+BAAoB,EAAC,WAAW,CAAC,CAAC,CAAC;IACzE,IAAI,KAAK,GAAG,GAAG,CAAC;IAEhB,MAAM,KAAK,GAAG,IAAA,+BAAoB,EAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAA,oCAAyB,EAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrE,MAAM,yBAAyB,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;IACpD,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,yBAAyB,KAAK,SAAS,CAAC;IACzD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAE3D,IAAI,yBAAyB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,iBAAiB,WAAW,2CAA2C,CAAC,CAAC;IAC3F,CAAC;IAED,uFAAuF;IACvF,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,KAAK,YAAY,EAAE,CAAC;QACrF,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,IAAI,KAAK,CACb,iBAAiB,WAAW,oEAAoE,YAAY,GAAG,CAChH,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC,iBAAkB,CAAC,CAAC;IACpE,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;IAEzD,IAAI,oBAAoB,EAAE,CAAC;QACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,4EAA4E;YAC5E,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC7B,+DAA+D;YAC/D,0CAA0C;YAC1C,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,iBAAiB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAClD,8FAA8F;YAC9F,WAAW,GAAG,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,iBAAiB,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YACxE,0DAA0D;YAC1D,WAAW,GAAG,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,iBAAiB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAClD,mGAAmG;YACnG,gDAAgD;YAChD,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;QAED,IAAI,KAAK,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,wDAAwD,iBAAiB,WAAW,WAAW,GAAG,CACnG,CAAC;QACJ,CAAC;QAED,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,iBAAiB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,KAAK;QACL,WAAW;QACX,QAAQ;QACR,KAAK;QACL,UAAU,EAAE,GAAG,IAAI,SAAS;QAC5B,SAAS,EAAE,GAAG,IAAI,QAAQ;KAC3B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,GAAW,EAAE,OAAoB,IAAI,GAAG,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAA,8BAAmB,EAAC,GAAG,CAAC,CAAC;IAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,qDAAqD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,IAAI;SACjB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAA4B,EAAE;QACtC,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,IAAI;aACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,2BAAgB,EAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACxC,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,IAAI,EAA6B,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEvD,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AAC/C,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAwB,EAAE,OAAgB;IACpE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC/D,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE;YAC9B,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,UAAU;aAClB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAwB,EAAE,OAAgB;IACrE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QACjE,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE;YAChC,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,YAAY;aACpB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAe,EAAE,OAAgB;IACtD;;;OAGG;IACH,wCAAwC;IACxC,MAAM,SAAS,GAAG,IAAA,6BAAkB,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,IAAI,MAAM,GAAG,kBAAkB,EAAE,KAAK,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,kGAAkG;YAClG,MAAM;gBACJ,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,MAAM,CAAC;QAC3F,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC;oBAChE,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,sHAAsH;YACtH,MAAM,6BAA6B,GACjC,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM;gBAC7C,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;YAE1D,MAAM,GAAG,6BAA6B,IAAI,MAAM,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,IAAI;QACP,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5C,QAAQ,EAAE,EAAE,EAAE,2CAA2C;QACzD,gBAAgB,EAAE,MAAM;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,wCAAwC,CAC/C,IAAe,EACf,OAAgB,EAChB,cAAwB,EAAE;IAE1B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,qBAAsB,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,UAAU,qCAAqC,CAAC,CAAC;QACnF,CAAC;QAED,6DAA6D;QAC7D,WAAW,GAAG,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEhD;;;;;WAKG;QACH,MAAM,SAAS,GAAG,IAAA,yBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,kBAAkB,EAAE,KAAK,CAAC;QACvC,wCAAwC;QACxC,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE,CAAC;gBAC9B,IAAI,CAAC;oBACH,kGAAkG;oBAClG,MAAM;wBACJ,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,MAAM,CAAC;gBAC3F,CAAC;gBAAC,OAAO,KAAU,EAAE,CAAC;oBACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;wBAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC;4BAChE,MAAM,KAAK,CAAC;wBACd,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,IAAI,SAAS,EAAE,CAAC;oBACd,sHAAsH;oBACtH,MAAM,6BAA6B,GACjC,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM;wBAC7C,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;oBAE1D,MAAM,GAAG,6BAA6B,IAAI,MAAM,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;YAC1E,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ;qBACpC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;qBACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;qBAClC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEd,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,wBAAwB,MAAM,iBAAiB,SAAS,0BAA0B,iBAAiB,EAAE,CAC/H,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,wBAAwB,MAAM,yBAAyB,iBAAiB,EAAE,CACpG,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,2GAA2G;YAC3G,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,wCAAwC,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,MAAmB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAEzC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,YAAY,KAAK,CAAC,UAAU,sEAAsE,CACnG,CAAC;IACJ,CAAC;IAED,wFAAwF;IACxF,4CAA4C;IAC5C,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { DynamicConvention, MiddlewareNode, RouteNode } from './Route';\nimport {\n matchArrayGroupName,\n matchDynamicName,\n matchGroupName,\n matchLastGroupName,\n removeFileSystemDots,\n removeFileSystemExtensions,\n removeSupportedExtensions,\n stripInvisibleSegmentsFromPath,\n} from './matchers';\nimport type { RequireContext } from './types';\nimport { shouldLinkExternally } from './utils/url';\n\nexport type Options = {\n ignore?: RegExp[];\n preserveApiRoutes?: boolean;\n ignoreRequireErrors?: boolean;\n ignoreEntryPoints?: boolean;\n /* Used to simplify testing for toEqual() comparison */\n internal_stripLoadRoute?: boolean;\n /* Used to simplify by skipping the generated routes */\n skipGenerated?: boolean;\n /** Skip routes created by `generateStaticParams()` */\n skipStaticParams?: boolean;\n /* Skip the generated not found route */\n notFound?: boolean;\n /* Enable experimental server middleware support */\n unstable_useServerMiddleware?: boolean;\n importMode?: string;\n platformRoutes?: boolean;\n sitemap?: boolean;\n platform?: string;\n redirects?: RedirectConfig[];\n rewrites?: RewriteConfig[];\n headers?: Record;\n /* Keep redirects as valid routes within the RouteConfig tree */\n preserveRedirectAndRewrites?: boolean;\n\n /** Get the system route for a location. Useful for shimming React Native imports in SSR environments. */\n getSystemRoute: (\n route: Pick & {\n defaults?: RouteNode;\n redirectConfig?: RedirectConfig;\n rewriteConfig?: RewriteConfig;\n }\n ) => RouteNode;\n};\n\ntype DirectoryNode = {\n layout?: RouteNode[];\n files: Map;\n subdirectories: Map;\n};\n\nexport type RedirectConfig = {\n source: string;\n destination: string;\n destinationContextKey: string;\n permanent?: boolean;\n methods?: string[];\n external?: boolean;\n};\n\nexport type RewriteConfig = {\n source: string;\n destination: string;\n destinationContextKey: string;\n methods?: string[];\n};\n\nconst validPlatforms = new Set(['android', 'ios', 'native', 'web']);\n\n/**\n * Given a Metro context module, return an array of nested routes.\n *\n * This is a two step process:\n * 1. Convert the RequireContext keys (file paths) into a directory tree.\n * - This should extrapolate array syntax into multiple routes\n * - Routes are given a specificity score\n * 2. Flatten the directory tree into routes\n * - Routes in directories without _layout files are hoisted to the nearest _layout\n * - The name of the route is relative to the nearest _layout\n * - If multiple routes have the same name, the most specific route is used\n */\nexport function getRoutes(contextModule: RequireContext, options: Options): RouteNode | null {\n const middleware = getMiddleware(contextModule, options);\n const directoryTree = getDirectoryTree(contextModule, options);\n\n // If there are no routes\n if (!directoryTree) {\n return null;\n }\n\n const rootNode = flattenDirectoryTreeToRoutes(directoryTree, options);\n\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n if (\n process.env.NODE_ENV === 'development' &&\n importMode === 'sync' &&\n !options.ignoreRequireErrors\n ) {\n validateRouteTreeExports(rootNode);\n }\n\n if (middleware) {\n rootNode.middleware = middleware;\n }\n\n if (!options.ignoreEntryPoints) {\n crawlAndAppendInitialRoutesAndEntryFiles(rootNode, options);\n }\n\n return rootNode;\n}\n\n/**\n * Given a RequireContext, return the middleware node if one is found. If more than one middleware file is found, an error is thrown.\n */\nfunction getMiddleware(contextModule: RequireContext, options: Options): MiddlewareNode | null {\n const allMiddlewareFiles = contextModule.keys().filter((key) => key.includes('+middleware'));\n\n // Check if middleware is enabled via plugin config\n if (!options.unstable_useServerMiddleware) {\n if (allMiddlewareFiles.length > 0) {\n console.warn(\n 'Server middleware is not enabled. Add unstable_useServerMiddleware: true to your `expo-router` plugin config.\\n\\n' +\n JSON.stringify(\n {\n expo: {\n plugins: [['expo-router', { unstable_useServerMiddleware: true }]],\n },\n },\n null,\n 2\n )\n );\n }\n return null;\n }\n\n const isValidMiddleware = (key: string) => /^\\.\\/\\+middleware\\.[tj]sx?$/.test(key);\n\n const rootMiddlewareFiles = allMiddlewareFiles.filter(isValidMiddleware);\n\n const nonRootMiddleware = allMiddlewareFiles.filter(\n (file) => !rootMiddlewareFiles.includes(file)\n );\n if (nonRootMiddleware.length > 0) {\n throw new Error(\n `The middleware file can only be placed at the root level. Remove the following files: ${nonRootMiddleware.join(', ')}`\n );\n }\n\n if (rootMiddlewareFiles.length === 0) {\n return null;\n }\n\n // In development, throw an error if there are multiple root-level middleware files\n if (rootMiddlewareFiles.length > 1) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Only one middleware file is allowed. Keep one of the conflicting files: ${rootMiddlewareFiles.map((p) => `\"${p}\"`).join(' or ')}`\n );\n }\n }\n\n const middlewareFilePath = rootMiddlewareFiles[0]!;\n\n const middleware: MiddlewareNode = {\n loadRoute() {\n if (options.ignoreRequireErrors) {\n try {\n return contextModule(middlewareFilePath);\n } catch {\n return {};\n }\n } else {\n return contextModule(middlewareFilePath);\n }\n },\n contextKey: middlewareFilePath,\n };\n\n if (options.internal_stripLoadRoute) {\n delete (middleware as any).loadRoute;\n }\n\n return middleware;\n}\n\n/**\n * Converts the RequireContext keys (file paths) into a directory tree.\n */\nfunction getDirectoryTree(contextModule: RequireContext, options: Options) {\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n\n const ignoreList: RegExp[] = [/^\\.\\/\\+(html|native-intent)\\.[tj]sx?$/]; // Ignore the top level ./+html file\n\n if (options.ignore) {\n ignoreList.push(...options.ignore);\n }\n if (!options.preserveApiRoutes) {\n ignoreList.push(/\\+api$/, /\\+api\\.[tj]sx?$/);\n }\n\n // Always ignore middleware files in regular route processing\n ignoreList.push(/\\+middleware$/, /\\+middleware\\.[tj]sx?$/);\n\n const rootDirectory: DirectoryNode = {\n files: new Map(),\n subdirectories: new Map(),\n };\n\n let hasRoutes = false;\n let isValid = false;\n\n const contextKeys = contextModule.keys();\n const redirects: Record = {};\n const rewrites: Record = {};\n\n let validRedirectDestinations: { contextKey: string; nameWithoutInvisible: string }[] | undefined;\n\n const getValidDestinations = () => {\n // Loop over contexts once and cache the valid destinations\n validRedirectDestinations ??= contextKeys.map((key) => {\n return {\n contextKey: key,\n nameWithoutInvisible: getNameWithoutInvisibleSegmentsFromRedirectPath(\n removeSupportedExtensions(key)\n ),\n };\n });\n return validRedirectDestinations;\n };\n\n // If we are keeping redirects as valid routes, then we need to add them to the contextKeys\n // This is useful for generating a sitemap with redirects, or static site generation that includes redirects\n if (options.preserveRedirectAndRewrites) {\n if (options.redirects) {\n for (const redirect of options.redirects) {\n const sourceContextKey = getSourceContextKeyFromRedirectSource(redirect.source);\n const sourceName = getNameFromRedirectPath(redirect.source);\n\n const isExternalRedirect = shouldLinkExternally(redirect.destination);\n\n const targetDestinationName = isExternalRedirect\n ? redirect.destination\n : getNameWithoutInvisibleSegmentsFromRedirectPath(redirect.destination);\n\n if (ignoreList.some((regex) => regex.test(sourceContextKey))) {\n continue;\n }\n\n const validDestination = isExternalRedirect\n ? undefined\n : getValidDestinations().find(\n (key) => key.nameWithoutInvisible === targetDestinationName\n );\n const destination = isExternalRedirect\n ? targetDestinationName\n : validDestination?.nameWithoutInvisible;\n const destinationContextKey = isExternalRedirect\n ? targetDestinationName\n : validDestination?.contextKey;\n\n if (!destinationContextKey || destination === undefined) {\n /*\n * Only throw the error when we are preserving the api routes\n * When doing a static export, API routes will not exist so the redirect destination may not exist.\n * The desired behavior for this error is to warn the user when running `expo start`, so its ok if\n * `expo export` swallows this error.\n */\n if (options.preserveApiRoutes) {\n throw new Error(`Redirect destination \"${redirect.destination}\" does not exist.`);\n }\n\n continue;\n }\n\n contextKeys.push(sourceContextKey);\n redirects[sourceName] = {\n source: sourceName,\n destination,\n destinationContextKey,\n permanent: Boolean(redirect.permanent),\n external: isExternalRedirect,\n methods: redirect.methods,\n };\n }\n }\n\n if (options.rewrites) {\n for (const rewrite of options.rewrites) {\n const sourceContextKey = getSourceContextKeyFromRedirectSource(rewrite.source);\n const sourceName = getNameFromRedirectPath(rewrite.source);\n\n // We check to see if the context key is already known so that we don't create a rewrite for\n // a route that already exists on disk\n const isSourceContextKeyAlreadyKnown = contextKeys.includes(sourceContextKey);\n const targetDestinationName = isSourceContextKeyAlreadyKnown\n ? getNameFromRedirectPath(rewrite.destination)\n : getNameWithoutInvisibleSegmentsFromRedirectPath(rewrite.destination);\n\n if (ignoreList.some((regex) => regex.test(sourceContextKey))) {\n continue;\n }\n\n const validDestination = getValidDestinations().find(\n (key) => key.nameWithoutInvisible === targetDestinationName\n );\n const destination = validDestination?.nameWithoutInvisible;\n const destinationContextKey = validDestination?.contextKey;\n\n if (!destinationContextKey || destination === undefined) {\n /*\n * Only throw the error when we are preserving the api routes\n * When doing a static export, API routes will not exist so the redirect destination may not exist.\n * The desired behavior for this error is to warn the user when running `expo start`, so its ok if\n * `expo export` swallows this error.\n */\n if (options.preserveApiRoutes) {\n throw new Error(`Rewrite destination \"${rewrite.destination}\" does not exist.`);\n }\n\n continue;\n }\n\n contextKeys.push(sourceContextKey);\n rewrites[sourceName] = {\n source: sourceName,\n destination,\n destinationContextKey,\n methods: rewrite.methods,\n };\n }\n }\n }\n\n const processedRedirectsRewrites = new Set();\n\n for (const filePath of contextKeys) {\n if (ignoreList.some((regex) => regex.test(filePath))) {\n continue;\n }\n\n isValid = true;\n\n const meta = getFileMeta(filePath, options, redirects, rewrites);\n\n // This is a file that should be ignored. e.g maybe it has an invalid platform?\n if (meta.specificity < 0) {\n continue;\n }\n\n let node: RouteNode = {\n type: meta.isApi ? 'api' : meta.isLayout ? 'layout' : 'route',\n loadRoute() {\n let routeModule: any;\n\n if (options.ignoreRequireErrors) {\n try {\n routeModule = contextModule(filePath);\n } catch {\n routeModule = {};\n }\n } else {\n routeModule = contextModule(filePath);\n }\n\n if (process.env.NODE_ENV === 'development' && importMode === 'sync') {\n // In development mode, when async routes are disabled, add some extra error handling to improve the developer experience.\n // This can be useful when you accidentally use an async function in a route file for the default export.\n if (routeModule instanceof Promise) {\n throw new Error(\n `Route \"${filePath}\" cannot be a promise when async routes is disabled.`\n );\n }\n\n const defaultExport = routeModule?.default;\n if (defaultExport instanceof Promise) {\n throw new Error(\n `The default export from route \"${filePath}\" is a promise. Ensure the React Component does not use async or promises.`\n );\n }\n\n // check if default is an async function without invoking it\n if (\n defaultExport instanceof Function &&\n // This only works on web because Hermes support async functions so we have to transform them out.\n defaultExport.constructor.name === 'AsyncFunction'\n ) {\n throw new Error(\n `The default export from route \"${filePath}\" is an async function. Ensure the React Component does not use async or promises.`\n );\n }\n\n // Validate loader export in development\n const loaderExport = routeModule?.loader;\n if (loaderExport && typeof loaderExport !== 'function') {\n throw new Error(`Route \"${filePath}\" exports a loader that is not a function.`);\n }\n\n const metadataExport = routeModule?.generateMetadata;\n if (metadataExport && typeof metadataExport !== 'function') {\n throw new Error(`Route \"${filePath}\" exports generateMetadata that is not a function.`);\n }\n }\n\n return routeModule;\n },\n contextKey: filePath,\n route: '', // This is overwritten during hoisting based upon the _layout\n dynamic: null,\n children: [], // While we are building the directory tree, we don't know the node's children just yet. This is added during hoisting\n };\n\n if (meta.isRedirect) {\n if (processedRedirectsRewrites.has(meta.route)) {\n continue;\n }\n\n const redirect = redirects[meta.route]!;\n node.destinationContextKey = redirect.destinationContextKey;\n node.permanent = redirect.permanent;\n node.generated = true;\n if (node.type === 'route') {\n node = options.getSystemRoute({\n type: 'redirect',\n route: redirect.destination,\n defaults: node,\n redirectConfig: redirect,\n });\n }\n if (redirect!.methods) {\n node.methods = redirect.methods;\n }\n node.type = 'redirect';\n processedRedirectsRewrites.add(meta.route);\n }\n\n if (meta.isRewrite) {\n if (processedRedirectsRewrites.has(meta.route)) {\n continue;\n }\n\n const rewrite = rewrites[meta.route]!;\n node.destinationContextKey = rewrite.destinationContextKey;\n node.generated = true;\n if (node.type === 'route') {\n node = options.getSystemRoute({\n type: 'rewrite',\n route: rewrite.destination,\n defaults: node,\n rewriteConfig: rewrite,\n });\n }\n if (rewrite.methods) {\n node.methods = rewrite.methods;\n }\n node.type = 'rewrite';\n processedRedirectsRewrites.add(meta.route);\n }\n\n /**\n * A single filepath may be extrapolated into multiple routes if it contains array syntax.\n * Another way to thinking about is that a filepath node is present in multiple leaves of the directory tree.\n */\n for (const route of extrapolateGroups(meta.route)) {\n // Traverse the directory tree to its leaf node, creating any missing directories along the way\n const subdirectoryParts = route.split('/').slice(0, -1);\n\n // Start at the root directory and traverse the path to the leaf directory\n let directory = rootDirectory;\n\n for (const part of subdirectoryParts) {\n let subDirectory = directory.subdirectories.get(part);\n\n // Create any missing subdirectories\n if (!subDirectory) {\n subDirectory = {\n files: new Map(),\n subdirectories: new Map(),\n };\n directory.subdirectories.set(part, subDirectory);\n }\n\n directory = subDirectory;\n }\n\n // Clone the node for this route\n node = { ...node, route };\n\n if (meta.isLayout) {\n directory.layout ??= [];\n const existing = directory.layout[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The layouts \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n node = getLayoutNode(node, options);\n directory.layout[meta.specificity] = node;\n }\n } else if (meta.isApi) {\n const fileKey = `${route}+api`;\n let nodes = directory.files.get(fileKey);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(fileKey, nodes);\n }\n\n // API Routes have no specificity, they are always the first node\n const existing = nodes[0];\n\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The API route file \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n nodes[0] = node;\n }\n } else {\n let nodes = directory.files.get(route);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(route, nodes);\n }\n\n /**\n * If there is an existing node with the same specificity, then we have a conflict.\n * NOTE(Platform Routes):\n * We cannot check for specificity conflicts here, as we haven't processed all the context keys yet!\n * This will be checked during hoisting, as well as enforcing that all routes have a non-platform route.\n */\n const existing = nodes[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The route files \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n hasRoutes ||= true;\n nodes[meta.specificity] = node;\n }\n }\n }\n }\n\n // If there are no routes/layouts then we should display the tutorial.\n if (!isValid) {\n return null;\n }\n\n /**\n * If there are no top-level _layout, add a default _layout\n * While this is a generated route, it will still be generated even if skipGenerated is true.\n */\n if (!rootDirectory.layout) {\n rootDirectory.layout = [\n options.getSystemRoute({\n type: 'layout',\n route: '',\n }),\n ];\n }\n\n // Only include the sitemap if there are routes.\n if (!options.skipGenerated) {\n if (hasRoutes && options.sitemap !== false) {\n appendSitemapRoute(rootDirectory, options);\n }\n if (options.notFound !== false) {\n appendNotFoundRoute(rootDirectory, options);\n }\n }\n return rootDirectory;\n}\n\nfunction getNameFromRedirectPath(path: string): string {\n // Removing only the filesystem extensions, to be able to handle +api, +html\n return (\n removeFileSystemExtensions(removeFileSystemDots(path))\n // Remove the leading `/`\n .replace(/^\\//, '')\n );\n}\n\nfunction getNameWithoutInvisibleSegmentsFromRedirectPath(path: string): string {\n return stripInvisibleSegmentsFromPath(getNameFromRedirectPath(path));\n}\n\n// Creates fake context key for redirects and rewrites\nfunction getSourceContextKeyFromRedirectSource(source: string): string {\n const name = getNameFromRedirectPath(source);\n const prefix = './';\n const suffix = /\\.[tj]sx?$/.test(name) ? '' : '.js'; // Ensure it has a file extension\n return `${prefix}${name}${suffix}`;\n}\n\n/**\n * Flatten the directory tree into routes, hoisting routes to the nearest _layout.\n */\nfunction flattenDirectoryTreeToRoutes(\n directory: DirectoryNode,\n options: Options,\n /* The nearest _layout file in the directory tree */\n layout?: RouteNode,\n /* Route names are relative to their layout */\n pathToRemove = ''\n) {\n /**\n * This directory has a _layout file so it becomes the new target for hoisting routes.\n */\n if (directory.layout) {\n const previousLayout = layout;\n layout = getMostSpecific(directory.layout);\n\n // Add the new layout as a child of its parent\n if (previousLayout) {\n previousLayout.children.push(layout);\n }\n\n if (options.internal_stripLoadRoute) {\n delete (layout as any).loadRoute;\n }\n\n // `route` is the absolute pathname. We need to make this relative to the last _layout\n const newRoute = layout.route.replace(pathToRemove, '');\n pathToRemove = layout.route ? `${layout.route}/` : '';\n\n // Now update this layout with the new relative route and dynamic conventions\n layout.route = newRoute;\n layout.dynamic = generateDynamic(layout.contextKey.slice(0));\n }\n\n // This should never occur as there will always be a root layout, but it makes the type system happy\n if (!layout) throw new Error('Expo Router Internal Error: No nearest layout');\n\n for (const routes of directory.files.values()) {\n const routeNode = getMostSpecific(routes);\n\n // `route` is the absolute pathname. We need to make this relative to the nearest layout\n routeNode.route = routeNode.route.replace(pathToRemove, '');\n routeNode.dynamic = generateDynamic(routeNode.route);\n\n if (options.internal_stripLoadRoute) {\n delete (routeNode as any).loadRoute;\n }\n\n layout.children.push(routeNode);\n }\n\n // Recursively flatten the subdirectories\n for (const child of directory.subdirectories.values()) {\n flattenDirectoryTreeToRoutes(child, options, layout, pathToRemove);\n }\n\n return layout;\n}\n\nfunction validateRouteTreeExports(node: RouteNode) {\n if (process.env.NODE_ENV !== 'development' || node.type === 'api') {\n return;\n }\n\n function runtimeValidateRouteNode(node: RouteNode) {\n const routeItem = node.loadRoute();\n // Have a warning for nullish ex\n const route = routeItem?.default;\n if (route == null) {\n // Do not throw an error since a user may just be creating a new route.\n console.warn(\n `Route \"${node.contextKey}\" is missing the required default export. Ensure a React component is exported as default.`\n );\n }\n if (['boolean', 'number', 'string'].includes(typeof route)) {\n throw new Error(\n `The default export from route \"${node.contextKey}\" is an unsupported type: \"${typeof route}\". Only React Components are supported as default exports from route files.`\n );\n }\n }\n\n runtimeValidateRouteNode(node);\n for (const child of node.children) {\n validateRouteTreeExports(child);\n }\n}\n\nfunction getFileMeta(\n originalKey: string,\n options: Options,\n redirects: Record,\n rewrites: Record\n) {\n // Remove the leading `./`\n const key = removeSupportedExtensions(removeFileSystemDots(originalKey));\n let route = key;\n\n const parts = removeFileSystemDots(originalKey).split('/');\n const filename = parts[parts.length - 1]!;\n const filenameParts = removeSupportedExtensions(filename).split('.');\n const filenameWithoutExtensions = filenameParts[0]!;\n const platformExtension = filenameParts[1];\n\n const isLayout = filenameWithoutExtensions === '_layout';\n const isApi = originalKey.match(/\\+api\\.(\\w+\\.)?[jt]sx?$/);\n\n if (filenameWithoutExtensions.startsWith('(') && filenameWithoutExtensions.endsWith(')')) {\n throw new Error(`Invalid route ${originalKey}. Routes cannot end with '(group)' syntax`);\n }\n\n // Nested routes cannot start with the '+' character, except for the '+not-found' route\n if (!isApi && filename.startsWith('+') && filenameWithoutExtensions !== '+not-found') {\n const renamedRoute = [...parts.slice(0, -1), filename.slice(1)].join('/');\n throw new Error(\n `Invalid route ${originalKey}. Route nodes cannot start with the '+' character. \"Rename it to ${renamedRoute}\"`\n );\n }\n let specificity = 0;\n\n const hasPlatformExtension = validPlatforms.has(platformExtension!);\n const usePlatformRoutes = options.platformRoutes ?? true;\n\n if (hasPlatformExtension) {\n if (!usePlatformRoutes) {\n // If the user has disabled platform routes, then we should ignore this file\n specificity = -1;\n } else if (!options.platform) {\n // If we don't have a platform, then we should ignore this file\n // This used by typed routes, sitemap, etc\n specificity = -1;\n } else if (platformExtension === options.platform) {\n // If the platform extension is the same as the options.platform, then it is the most specific\n specificity = 2;\n } else if (platformExtension === 'native' && options.platform !== 'web') {\n // `native` is allow but isn't as specific as the platform\n specificity = 1;\n } else if (platformExtension !== options.platform) {\n // Somehow we have a platform extension that doesn't match the options.platform and it isn't native\n // This is an invalid file and we will ignore it\n specificity = -1;\n }\n\n if (isApi && specificity !== 0) {\n throw new Error(\n `API routes cannot have platform extensions. Remove '.${platformExtension}' from '${originalKey}'`\n );\n }\n\n route = route.replace(new RegExp(`.${platformExtension}$`), '');\n }\n\n return {\n route,\n specificity,\n isLayout,\n isApi,\n isRedirect: key in redirects,\n isRewrite: key in rewrites,\n };\n}\n\n/**\n * Generates a set of strings which have the router array syntax extrapolated.\n *\n * /(a,b)/(c,d)/e.tsx => new Set(['a/c/e.tsx', 'a/d/e.tsx', 'b/c/e.tsx', 'b/d/e.tsx'])\n */\nexport function extrapolateGroups(key: string, keys: Set = new Set()): Set {\n const match = matchArrayGroupName(key);\n\n if (!match) {\n keys.add(key);\n return keys;\n }\n const groups = match.split(',');\n const groupsSet = new Set(groups);\n\n if (groupsSet.size !== groups.length) {\n throw new Error(`Array syntax cannot contain duplicate group name \"${groups}\" in \"${key}\".`);\n }\n\n if (groups.length === 1) {\n keys.add(key);\n return keys;\n }\n\n for (const group of groups) {\n extrapolateGroups(key.replace(match, group.trim()), keys);\n }\n\n return keys;\n}\n\nexport function generateDynamic(path: string): DynamicConvention[] | null {\n const dynamic = path\n .split('/')\n .map((part): DynamicConvention | null => {\n if (part === '+not-found') {\n return {\n name: '+not-found',\n deep: true,\n notFound: true,\n };\n }\n return matchDynamicName(part) ?? null;\n })\n .filter((part): part is DynamicConvention => !!part);\n\n return dynamic.length === 0 ? null : dynamic;\n}\n\nfunction appendSitemapRoute(directory: DirectoryNode, options: Options) {\n if (!directory.files.has('_sitemap') && options.getSystemRoute) {\n directory.files.set('_sitemap', [\n options.getSystemRoute({\n type: 'route',\n route: '_sitemap',\n }),\n ]);\n }\n}\n\nfunction appendNotFoundRoute(directory: DirectoryNode, options: Options) {\n if (!directory.files.has('+not-found') && options.getSystemRoute) {\n directory.files.set('+not-found', [\n options.getSystemRoute({\n type: 'route',\n route: '+not-found',\n }),\n ]);\n }\n}\n\nfunction getLayoutNode(node: RouteNode, options: Options) {\n /**\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different anchor based upon the first group name.\n */\n // We may strip loadRoute during testing\n const groupName = matchLastGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let anchor = childMatchingGroup?.route;\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n try {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n anchor =\n loaded.unstable_settings.anchor ?? loaded.unstable_settings.initialRouteName ?? anchor;\n } catch (error: any) {\n if (error instanceof Error) {\n if (!error.message.match(/You cannot dot into a client module/)) {\n throw error;\n }\n }\n }\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.anchor ??\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n anchor = groupSpecificInitialRouteName ?? anchor;\n }\n }\n\n return {\n ...node,\n route: node.route.replace(/\\/?_layout$/, ''),\n children: [], // Each layout should have its own children\n initialRouteName: anchor,\n };\n}\n\nfunction crawlAndAppendInitialRoutesAndEntryFiles(\n node: RouteNode,\n options: Options,\n entryPoints: string[] = []\n) {\n if (node.type === 'route') {\n node.entryPoints = [...new Set([...entryPoints, node.contextKey])];\n } else if (node.type === 'redirect') {\n node.entryPoints = [...new Set([...entryPoints, node.destinationContextKey!])];\n } else if (node.type === 'layout') {\n if (!node.children) {\n throw new Error(`Layout \"${node.contextKey}\" does not contain any child routes`);\n }\n\n // Every node below this layout will have it as an entryPoint\n entryPoints = [...entryPoints, node.contextKey];\n\n /**\n * Calculate the initialRouteNode\n *\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different anchor based upon the first group.\n */\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let anchor = childMatchingGroup?.route;\n // We may strip loadRoute during testing\n if (!options.internal_stripLoadRoute) {\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n try {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n anchor =\n loaded.unstable_settings.anchor ?? loaded.unstable_settings.initialRouteName ?? anchor;\n } catch (error: any) {\n if (error instanceof Error) {\n if (!error.message.match(/You cannot dot into a client module/)) {\n throw error;\n }\n }\n }\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.anchor ??\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n anchor = groupSpecificInitialRouteName ?? anchor;\n }\n }\n }\n\n if (anchor) {\n const anchorRoute = node.children.find((child) => child.route === anchor);\n if (!anchorRoute) {\n const validAnchorRoutes = node.children\n .filter((child) => !child.generated)\n .map((child) => `'${child.route}'`)\n .join(', ');\n\n if (groupName) {\n throw new Error(\n `Layout ${node.contextKey} has invalid anchor '${anchor}' for group '(${groupName})'. Valid options are: ${validAnchorRoutes}`\n );\n } else {\n throw new Error(\n `Layout ${node.contextKey} has invalid anchor '${anchor}'. Valid options are: ${validAnchorRoutes}`\n );\n }\n }\n\n // Navigators can add initialsRoutes into the history, so they need to be to be included in the entryPoints\n node.initialRouteName = anchor;\n entryPoints.push(anchorRoute.contextKey);\n }\n\n for (const child of node.children) {\n crawlAndAppendInitialRoutesAndEntryFiles(child, options, entryPoints);\n }\n }\n}\n\nfunction getMostSpecific(routes: RouteNode[]) {\n const route = routes[routes.length - 1]!;\n\n if (!routes[0]) {\n throw new Error(\n `The file ${route.contextKey} does not have a fallback sibling file without a platform extension.`\n );\n }\n\n // This works even tho routes is holey array (e.g it might have index 0 and 2 but not 1)\n // `.length` includes the holes in its count\n return route;\n}\n"]} \ No newline at end of file +{"version":3,"file":"getRoutesCore.js","sourceRoot":"","sources":["../src/getRoutesCore.ts"],"names":[],"mappings":";;AAqFA,8BA6BC;AAkqBD,8CAwBC;AAED,0CAgBC;AA7zBD,yCASoB;AAEpB,qCAAmD;AA2DnD,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,aAA6B,EAAE,OAAgB;IACvE,MAAM,UAAU,GAAG,aAAa,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,aAAa,GAAG,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAE/D,yBAAyB;IACzB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,4BAA4B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEtE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAC7E,IACE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;QACtC,UAAU,KAAK,MAAM;QACrB,CAAC,OAAO,CAAC,mBAAmB,EAC5B,CAAC;QACD,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,QAAQ,CAAC,UAAU,GAAG,UAAU,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/B,wCAAwC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,aAA6B,EAAE,OAAgB;IACpE,MAAM,kBAAkB,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;IAE7F,mDAAmD;IACnD,IAAI,CAAC,OAAO,CAAC,4BAA4B,EAAE,CAAC;QAC1C,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CACV,mHAAmH;gBACjH,IAAI,CAAC,SAAS,CACZ;oBACE,IAAI,EAAE;wBACJ,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,EAAE,4BAA4B,EAAE,IAAI,EAAE,CAAC,CAAC;qBACnE;iBACF,EACD,IAAI,EACJ,CAAC,CACF,CACJ,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,iBAAiB,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEnF,MAAM,mBAAmB,GAAG,kBAAkB,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEzE,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,MAAM,CACjD,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,mBAAmB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAC9C,CAAC;IACF,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,yFAAyF,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACxH,CAAC;IACJ,CAAC;IAED,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mFAAmF;IACnF,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,2EAA2E,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CACnI,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,CAAC,CAAE,CAAC;IAEnD,MAAM,UAAU,GAAmB;QACjC,SAAS;YACP,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,OAAO,aAAa,CAAC,kBAAkB,CAAC,CAAC;gBAC3C,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,OAAO,aAAa,CAAC,kBAAkB,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QACD,UAAU,EAAE,kBAAkB;KAC/B,CAAC;IAEF,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;QACpC,OAAQ,UAAkB,CAAC,SAAS,CAAC;IACvC,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,aAA6B,EAAE,OAAgB;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAE7E,MAAM,UAAU,GAAa,CAAC,uCAAuC,CAAC,CAAC,CAAC,oCAAoC;IAE5G,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC;QAC/B,UAAU,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;IAC/C,CAAC;IAED,6DAA6D;IAC7D,UAAU,CAAC,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAC;IAE3D,MAAM,aAAa,GAAkB;QACnC,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,cAAc,EAAE,IAAI,GAAG,EAAE;KAC1B,CAAC;IAEF,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,WAAW,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC;IACzC,MAAM,SAAS,GAAmC,EAAE,CAAC;IACrD,MAAM,QAAQ,GAAkC,EAAE,CAAC;IAEnD,IAAI,yBAA6F,CAAC;IAElG,MAAM,oBAAoB,GAAG,GAAG,EAAE;QAChC,2DAA2D;QAC3D,yBAAyB,KAAK,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YACpD,OAAO;gBACL,UAAU,EAAE,GAAG;gBACf,oBAAoB,EAAE,+CAA+C,CACnE,IAAA,oCAAyB,EAAC,GAAG,CAAC,CAC/B;aACF,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO,yBAAyB,CAAC;IACnC,CAAC,CAAC;IAEF,2FAA2F;IAC3F,4GAA4G;IAC5G,IAAI,OAAO,CAAC,2BAA2B,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;gBACzC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAChF,MAAM,UAAU,GAAG,uBAAuB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;gBAE5D,MAAM,kBAAkB,GAAG,IAAA,0BAAoB,EAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAEtE,MAAM,qBAAqB,GAAG,kBAAkB;oBAC9C,CAAC,CAAC,QAAQ,CAAC,WAAW;oBACtB,CAAC,CAAC,+CAA+C,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;gBAE1E,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;oBAC7D,SAAS;gBACX,CAAC;gBAED,MAAM,gBAAgB,GAAG,kBAAkB;oBACzC,CAAC,CAAC,SAAS;oBACX,CAAC,CAAC,oBAAoB,EAAE,CAAC,IAAI,CACzB,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,oBAAoB,KAAK,qBAAqB,CAC5D,CAAC;gBACN,MAAM,WAAW,GAAG,kBAAkB;oBACpC,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,gBAAgB,EAAE,oBAAoB,CAAC;gBAC3C,MAAM,qBAAqB,GAAG,kBAAkB;oBAC9C,CAAC,CAAC,qBAAqB;oBACvB,CAAC,CAAC,gBAAgB,EAAE,UAAU,CAAC;gBAEjC,IAAI,CAAC,qBAAqB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBACxD;;;;;uBAKG;oBACH,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;wBAC9B,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,WAAW,mBAAmB,CAAC,CAAC;oBACpF,CAAC;oBAED,SAAS;gBACX,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnC,SAAS,CAAC,UAAU,CAAC,GAAG;oBACtB,MAAM,EAAE,UAAU;oBAClB,WAAW;oBACX,qBAAqB;oBACrB,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;oBACtC,QAAQ,EAAE,kBAAkB;oBAC5B,OAAO,EAAE,QAAQ,CAAC,OAAO;iBAC1B,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACvC,MAAM,gBAAgB,GAAG,qCAAqC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC/E,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBAE3D,4FAA4F;gBAC5F,sCAAsC;gBACtC,MAAM,8BAA8B,GAAG,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;gBAC9E,MAAM,qBAAqB,GAAG,8BAA8B;oBAC1D,CAAC,CAAC,uBAAuB,CAAC,OAAO,CAAC,WAAW,CAAC;oBAC9C,CAAC,CAAC,+CAA+C,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;gBAEzE,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC;oBAC7D,SAAS;gBACX,CAAC;gBAED,MAAM,gBAAgB,GAAG,oBAAoB,EAAE,CAAC,IAAI,CAClD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,oBAAoB,KAAK,qBAAqB,CAC5D,CAAC;gBACF,MAAM,WAAW,GAAG,gBAAgB,EAAE,oBAAoB,CAAC;gBAC3D,MAAM,qBAAqB,GAAG,gBAAgB,EAAE,UAAU,CAAC;gBAE3D,IAAI,CAAC,qBAAqB,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;oBACxD;;;;;uBAKG;oBACH,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;wBAC9B,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,CAAC,WAAW,mBAAmB,CAAC,CAAC;oBAClF,CAAC;oBAED,SAAS;gBACX,CAAC;gBAED,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBACnC,QAAQ,CAAC,UAAU,CAAC,GAAG;oBACrB,MAAM,EAAE,UAAU;oBAClB,WAAW;oBACX,qBAAqB;oBACrB,OAAO,EAAE,OAAO,CAAC,OAAO;iBACzB,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAU,CAAC;IAErD,KAAK,MAAM,QAAQ,IAAI,WAAW,EAAE,CAAC;QACnC,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;YACrD,SAAS;QACX,CAAC;QAED,OAAO,GAAG,IAAI,CAAC;QAEf,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;QAEjE,+EAA+E;QAC/E,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACzB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,GAAc;YACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;YAC7D,SAAS;gBACP,IAAI,WAAgB,CAAC;gBAErB,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;oBAChC,IAAI,CAAC;wBACH,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;oBACxC,CAAC;oBAAC,MAAM,CAAC;wBACP,WAAW,GAAG,EAAE,CAAC;oBACnB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,WAAW,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACxC,CAAC;gBAED,oDAAoD;gBACpD,uEAAuE;gBACvE,qFAAqF;gBACrF,IAAI,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,WAAW,EAAE,CAAC;oBACxD,WAAW;wBACT,SAAS,IAAI,WAAW,IAAI,WAAW,CAAC,OAAO,IAAI,IAAI;4BACrD,CAAC,CAAC,WAAW,CAAC,OAAO;4BACrB,CAAC,CAAC,WAAW,CAAC;gBACpB,CAAC;gBAED,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,UAAU,KAAK,MAAM,EAAE,CAAC;oBACpE,0HAA0H;oBAC1H,yGAAyG;oBACzG,IAAI,WAAW,YAAY,OAAO,EAAE,CAAC;wBACnC,MAAM,IAAI,KAAK,CACb,UAAU,QAAQ,sDAAsD,CACzE,CAAC;oBACJ,CAAC;oBAED,MAAM,aAAa,GAAG,WAAW,EAAE,OAAO,CAAC;oBAC3C,IAAI,aAAa,YAAY,OAAO,EAAE,CAAC;wBACrC,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,4EAA4E,CACvH,CAAC;oBACJ,CAAC;oBAED,4DAA4D;oBAC5D,IACE,aAAa,YAAY,QAAQ;wBACjC,kGAAkG;wBAClG,aAAa,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe,EAClD,CAAC;wBACD,MAAM,IAAI,KAAK,CACb,kCAAkC,QAAQ,oFAAoF,CAC/H,CAAC;oBACJ,CAAC;oBAED,wCAAwC;oBACxC,MAAM,YAAY,GAAG,WAAW,EAAE,MAAM,CAAC;oBACzC,IAAI,YAAY,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;wBACvD,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,4CAA4C,CAAC,CAAC;oBAClF,CAAC;oBAED,MAAM,cAAc,GAAG,WAAW,EAAE,gBAAgB,CAAC;oBACrD,IAAI,cAAc,IAAI,OAAO,cAAc,KAAK,UAAU,EAAE,CAAC;wBAC3D,MAAM,IAAI,KAAK,CAAC,UAAU,QAAQ,oDAAoD,CAAC,CAAC;oBAC1F,CAAC;gBACH,CAAC;gBAED,OAAO,WAAW,CAAC;YACrB,CAAC;YACD,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,EAAE,EAAE,6DAA6D;YACxE,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,EAAE,EAAE,sHAAsH;SACrI,CAAC;QAEF,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC;YACxC,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC;YAC5D,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,SAAS,CAAC;YACpC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC1B,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;oBAC5B,IAAI,EAAE,UAAU;oBAChB,KAAK,EAAE,QAAQ,CAAC,WAAW;oBAC3B,QAAQ,EAAE,IAAI;oBACd,cAAc,EAAE,QAAQ;iBACzB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,QAAS,CAAC,OAAO,EAAE,CAAC;gBACtB,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;YAClC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;YACvB,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,IAAI,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC/C,SAAS;YACX,CAAC;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAE,CAAC;YACtC,IAAI,CAAC,qBAAqB,GAAG,OAAO,CAAC,qBAAqB,CAAC;YAC3D,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBAC1B,IAAI,GAAG,OAAO,CAAC,cAAc,CAAC;oBAC5B,IAAI,EAAE,SAAS;oBACf,KAAK,EAAE,OAAO,CAAC,WAAW;oBAC1B,QAAQ,EAAE,IAAI;oBACd,aAAa,EAAE,OAAO;iBACvB,CAAC,CAAC;YACL,CAAC;YACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;gBACpB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YACjC,CAAC;YACD,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;YACtB,0BAA0B,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAED;;;WAGG;QACH,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,+FAA+F;YAC/F,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAExD,0EAA0E;YAC1E,IAAI,SAAS,GAAG,aAAa,CAAC;YAE9B,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE,CAAC;gBACrC,IAAI,YAAY,GAAG,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAEtD,oCAAoC;gBACpC,IAAI,CAAC,YAAY,EAAE,CAAC;oBAClB,YAAY,GAAG;wBACb,KAAK,EAAE,IAAI,GAAG,EAAE;wBAChB,cAAc,EAAE,IAAI,GAAG,EAAE;qBAC1B,CAAC;oBACF,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;gBACnD,CAAC;gBAED,SAAS,GAAG,YAAY,CAAC;YAC3B,CAAC;YAED,gCAAgC;YAChC,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC;YAE1B,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,gBAAgB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACjI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACpC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;gBAC5C,CAAC;YACH,CAAC;iBAAM,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtB,MAAM,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC;gBAC/B,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAEzC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBACtC,CAAC;gBAED,iEAAiE;gBACjE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAE1B,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACxI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBACpC,CAAC;gBAED;;;;;mBAKG;gBACH,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAI,QAAQ,EAAE,CAAC;oBACb,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;wBAC1C,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,yCAAyC,CACrI,CAAC;oBACJ,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,SAAS,KAAK,IAAI,CAAC;oBACnB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACH,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAC1B,aAAa,CAAC,MAAM,GAAG;YACrB,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,QAAQ;gBACd,KAAK,EAAE,EAAE;aACV,CAAC;SACH,CAAC;IACJ,CAAC;IAED,gDAAgD;IAChD,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC3B,IAAI,SAAS,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC3C,kBAAkB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YAC/B,mBAAmB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAY;IAC3C,4EAA4E;IAC5E,OAAO,CACL,IAAA,qCAA0B,EAAC,IAAA,+BAAoB,EAAC,IAAI,CAAC,CAAC;QACpD,yBAAyB;SACxB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CACtB,CAAC;AACJ,CAAC;AAED,SAAS,+CAA+C,CAAC,IAAY;IACnE,OAAO,IAAA,yCAA8B,EAAC,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,sDAAsD;AACtD,SAAS,qCAAqC,CAAC,MAAc;IAC3D,MAAM,IAAI,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,iCAAiC;IACtF,OAAO,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,EAAE,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,SAAS,4BAA4B,CACnC,SAAwB,EACxB,OAAgB;AAChB,oDAAoD;AACpD,MAAkB;AAClB,8CAA8C;AAC9C,YAAY,GAAG,EAAE;IAEjB;;OAEG;IACH,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,cAAc,GAAG,MAAM,CAAC;QAC9B,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAE3C,8CAA8C;QAC9C,IAAI,cAAc,EAAE,CAAC;YACnB,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvC,CAAC;QAED,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACpC,OAAQ,MAAc,CAAC,SAAS,CAAC;QACnC,CAAC;QAED,sFAAsF;QACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACxD,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtD,6EAA6E;QAC7E,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAED,oGAAoG;IACpG,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAE9E,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;QAC9C,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;QAE1C,wFAAwF;QACxF,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC5D,SAAS,CAAC,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAErD,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACpC,OAAQ,SAAiB,CAAC,SAAS,CAAC;QACtC,CAAC;QAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAED,yCAAyC;IACzC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC;QACtD,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,wBAAwB,CAAC,IAAe;IAC/C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAClE,OAAO;IACT,CAAC;IAED,SAAS,wBAAwB,CAAC,IAAe;QAC/C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QACnC,gCAAgC;QAChC,MAAM,KAAK,GAAG,SAAS,EAAE,OAAO,CAAC;QACjC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;YAClB,uEAAuE;YACvE,OAAO,CAAC,IAAI,CACV,UAAU,IAAI,CAAC,UAAU,4FAA4F,CACtH,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YAC3D,MAAM,IAAI,KAAK,CACb,kCAAkC,IAAI,CAAC,UAAU,8BAA8B,OAAO,KAAK,6EAA6E,CACzK,CAAC;QACJ,CAAC;IACH,CAAC;IAED,wBAAwB,CAAC,IAAI,CAAC,CAAC;IAC/B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,wBAAwB,CAAC,KAAK,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAClB,WAAmB,EACnB,OAAgB,EAChB,SAAyC,EACzC,QAAuC;IAEvC,0BAA0B;IAC1B,MAAM,GAAG,GAAG,IAAA,oCAAyB,EAAC,IAAA,+BAAoB,EAAC,WAAW,CAAC,CAAC,CAAC;IACzE,IAAI,KAAK,GAAG,GAAG,CAAC;IAEhB,MAAM,KAAK,GAAG,IAAA,+BAAoB,EAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1C,MAAM,aAAa,GAAG,IAAA,oCAAyB,EAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrE,MAAM,yBAAyB,GAAG,aAAa,CAAC,CAAC,CAAE,CAAC;IACpD,MAAM,iBAAiB,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;IAE3C,MAAM,QAAQ,GAAG,yBAAyB,KAAK,SAAS,CAAC;IACzD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC;IAE3D,IAAI,yBAAyB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,KAAK,CAAC,iBAAiB,WAAW,2CAA2C,CAAC,CAAC;IAC3F,CAAC;IAED,uFAAuF;IACvF,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,KAAK,YAAY,EAAE,CAAC;QACrF,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,IAAI,KAAK,CACb,iBAAiB,WAAW,oEAAoE,YAAY,GAAG,CAChH,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,GAAG,CAAC,CAAC;IAEpB,MAAM,oBAAoB,GAAG,cAAc,CAAC,GAAG,CAAC,iBAAkB,CAAC,CAAC;IACpE,MAAM,iBAAiB,GAAG,OAAO,CAAC,cAAc,IAAI,IAAI,CAAC;IAEzD,IAAI,oBAAoB,EAAE,CAAC;QACzB,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACvB,4EAA4E;YAC5E,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC7B,+DAA+D;YAC/D,0CAA0C;YAC1C,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;aAAM,IAAI,iBAAiB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAClD,8FAA8F;YAC9F,WAAW,GAAG,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,iBAAiB,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,EAAE,CAAC;YACxE,0DAA0D;YAC1D,WAAW,GAAG,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,iBAAiB,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;YAClD,mGAAmG;YACnG,gDAAgD;YAChD,WAAW,GAAG,CAAC,CAAC,CAAC;QACnB,CAAC;QAED,IAAI,KAAK,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,wDAAwD,iBAAiB,WAAW,WAAW,GAAG,CACnG,CAAC;QACJ,CAAC;QAED,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,iBAAiB,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,KAAK;QACL,WAAW;QACX,QAAQ;QACR,KAAK;QACL,UAAU,EAAE,GAAG,IAAI,SAAS;QAC5B,SAAS,EAAE,GAAG,IAAI,QAAQ;KAC3B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,GAAW,EAAE,OAAoB,IAAI,GAAG,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAA,8BAAmB,EAAC,GAAG,CAAC,CAAC;IAEvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,qDAAqD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC;IAC/F,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,IAAI;SACjB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAA4B,EAAE;QACtC,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1B,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,IAAI;aACf,CAAC;QACJ,CAAC;QACD,OAAO,IAAA,2BAAgB,EAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACxC,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,IAAI,EAA6B,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEvD,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AAC/C,CAAC;AAED,SAAS,kBAAkB,CAAC,SAAwB,EAAE,OAAgB;IACpE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QAC/D,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE;YAC9B,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,UAAU;aAClB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAwB,EAAE,OAAgB;IACrE,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;QACjE,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE;YAChC,OAAO,CAAC,cAAc,CAAC;gBACrB,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,YAAY;aACpB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAe,EAAE,OAAgB;IACtD;;;OAGG;IACH,wCAAwC;IACxC,MAAM,SAAS,GAAG,IAAA,6BAAkB,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,IAAI,MAAM,GAAG,kBAAkB,EAAE,KAAK,CAAC;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,kGAAkG;YAClG,MAAM;gBACJ,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,MAAM,CAAC;QAC3F,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC;oBAChE,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,SAAS,EAAE,CAAC;YACd,sHAAsH;YACtH,MAAM,6BAA6B,GACjC,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM;gBAC7C,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;YAE1D,MAAM,GAAG,6BAA6B,IAAI,MAAM,CAAC;QACnD,CAAC;IACH,CAAC;IAED,OAAO;QACL,GAAG,IAAI;QACP,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5C,QAAQ,EAAE,EAAE,EAAE,2CAA2C;QACzD,gBAAgB,EAAE,MAAM;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,wCAAwC,CAC/C,IAAe,EACf,OAAgB,EAChB,cAAwB,EAAE;IAE1B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IACrE,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,qBAAsB,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,UAAU,qCAAqC,CAAC,CAAC;QACnF,CAAC;QAED,6DAA6D;QAC7D,WAAW,GAAG,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEhD;;;;;WAKG;QACH,MAAM,SAAS,GAAG,IAAA,yBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,IAAI,MAAM,GAAG,kBAAkB,EAAE,KAAK,CAAC;QACvC,wCAAwC;QACxC,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE,CAAC;gBAC9B,IAAI,CAAC;oBACH,kGAAkG;oBAClG,MAAM;wBACJ,MAAM,CAAC,iBAAiB,CAAC,MAAM,IAAI,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,MAAM,CAAC;gBAC3F,CAAC;gBAAC,OAAO,KAAU,EAAE,CAAC;oBACpB,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;wBAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,qCAAqC,CAAC,EAAE,CAAC;4BAChE,MAAM,KAAK,CAAC;wBACd,CAAC;oBACH,CAAC;gBACH,CAAC;gBAED,IAAI,SAAS,EAAE,CAAC;oBACd,sHAAsH;oBACtH,MAAM,6BAA6B,GACjC,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM;wBAC7C,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;oBAE1D,MAAM,GAAG,6BAA6B,IAAI,MAAM,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,MAAM,CAAC,CAAC;YAC1E,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ;qBACpC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;qBACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;qBAClC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEd,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,wBAAwB,MAAM,iBAAiB,SAAS,0BAA0B,iBAAiB,EAAE,CAC/H,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,wBAAwB,MAAM,yBAAyB,iBAAiB,EAAE,CACpG,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,2GAA2G;YAC3G,IAAI,CAAC,gBAAgB,GAAG,MAAM,CAAC;YAC/B,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClC,wCAAwC,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,MAAmB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAEzC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,YAAY,KAAK,CAAC,UAAU,sEAAsE,CACnG,CAAC;IACJ,CAAC;IAED,wFAAwF;IACxF,4CAA4C;IAC5C,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { DynamicConvention, MiddlewareNode, RouteNode } from './Route';\nimport {\n matchArrayGroupName,\n matchDynamicName,\n matchGroupName,\n matchLastGroupName,\n removeFileSystemDots,\n removeFileSystemExtensions,\n removeSupportedExtensions,\n stripInvisibleSegmentsFromPath,\n} from './matchers';\nimport type { RequireContext } from './types';\nimport { shouldLinkExternally } from './utils/url';\n\nexport type Options = {\n ignore?: RegExp[];\n preserveApiRoutes?: boolean;\n ignoreRequireErrors?: boolean;\n ignoreEntryPoints?: boolean;\n /* Used to simplify testing for toEqual() comparison */\n internal_stripLoadRoute?: boolean;\n /* Used to simplify by skipping the generated routes */\n skipGenerated?: boolean;\n /** Skip routes created by `generateStaticParams()` */\n skipStaticParams?: boolean;\n /* Skip the generated not found route */\n notFound?: boolean;\n /* Enable experimental server middleware support */\n unstable_useServerMiddleware?: boolean;\n importMode?: string;\n platformRoutes?: boolean;\n sitemap?: boolean;\n platform?: string;\n redirects?: RedirectConfig[];\n rewrites?: RewriteConfig[];\n headers?: Record;\n /* Keep redirects as valid routes within the RouteConfig tree */\n preserveRedirectAndRewrites?: boolean;\n\n /** Get the system route for a location. Useful for shimming React Native imports in SSR environments. */\n getSystemRoute: (\n route: Pick & {\n defaults?: RouteNode;\n redirectConfig?: RedirectConfig;\n rewriteConfig?: RewriteConfig;\n }\n ) => RouteNode;\n};\n\ntype DirectoryNode = {\n layout?: RouteNode[];\n files: Map;\n subdirectories: Map;\n};\n\nexport type RedirectConfig = {\n source: string;\n destination: string;\n destinationContextKey: string;\n permanent?: boolean;\n methods?: string[];\n external?: boolean;\n};\n\nexport type RewriteConfig = {\n source: string;\n destination: string;\n destinationContextKey: string;\n methods?: string[];\n};\n\nconst validPlatforms = new Set(['android', 'ios', 'native', 'web']);\n\n/**\n * Given a Metro context module, return an array of nested routes.\n *\n * This is a two step process:\n * 1. Convert the RequireContext keys (file paths) into a directory tree.\n * - This should extrapolate array syntax into multiple routes\n * - Routes are given a specificity score\n * 2. Flatten the directory tree into routes\n * - Routes in directories without _layout files are hoisted to the nearest _layout\n * - The name of the route is relative to the nearest _layout\n * - If multiple routes have the same name, the most specific route is used\n */\nexport function getRoutes(contextModule: RequireContext, options: Options): RouteNode | null {\n const middleware = getMiddleware(contextModule, options);\n const directoryTree = getDirectoryTree(contextModule, options);\n\n // If there are no routes\n if (!directoryTree) {\n return null;\n }\n\n const rootNode = flattenDirectoryTreeToRoutes(directoryTree, options);\n\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n if (\n process.env.NODE_ENV === 'development' &&\n importMode === 'sync' &&\n !options.ignoreRequireErrors\n ) {\n validateRouteTreeExports(rootNode);\n }\n\n if (middleware) {\n rootNode.middleware = middleware;\n }\n\n if (!options.ignoreEntryPoints) {\n crawlAndAppendInitialRoutesAndEntryFiles(rootNode, options);\n }\n\n return rootNode;\n}\n\n/**\n * Given a RequireContext, return the middleware node if one is found. If more than one middleware file is found, an error is thrown.\n */\nfunction getMiddleware(contextModule: RequireContext, options: Options): MiddlewareNode | null {\n const allMiddlewareFiles = contextModule.keys().filter((key) => key.includes('+middleware'));\n\n // Check if middleware is enabled via plugin config\n if (!options.unstable_useServerMiddleware) {\n if (allMiddlewareFiles.length > 0) {\n console.warn(\n 'Server middleware is not enabled. Add unstable_useServerMiddleware: true to your `expo-router` plugin config.\\n\\n' +\n JSON.stringify(\n {\n expo: {\n plugins: [['expo-router', { unstable_useServerMiddleware: true }]],\n },\n },\n null,\n 2\n )\n );\n }\n return null;\n }\n\n const isValidMiddleware = (key: string) => /^\\.\\/\\+middleware\\.[tj]sx?$/.test(key);\n\n const rootMiddlewareFiles = allMiddlewareFiles.filter(isValidMiddleware);\n\n const nonRootMiddleware = allMiddlewareFiles.filter(\n (file) => !rootMiddlewareFiles.includes(file)\n );\n if (nonRootMiddleware.length > 0) {\n throw new Error(\n `The middleware file can only be placed at the root level. Remove the following files: ${nonRootMiddleware.join(', ')}`\n );\n }\n\n if (rootMiddlewareFiles.length === 0) {\n return null;\n }\n\n // In development, throw an error if there are multiple root-level middleware files\n if (rootMiddlewareFiles.length > 1) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `Only one middleware file is allowed. Keep one of the conflicting files: ${rootMiddlewareFiles.map((p) => `\"${p}\"`).join(' or ')}`\n );\n }\n }\n\n const middlewareFilePath = rootMiddlewareFiles[0]!;\n\n const middleware: MiddlewareNode = {\n loadRoute() {\n if (options.ignoreRequireErrors) {\n try {\n return contextModule(middlewareFilePath);\n } catch {\n return {};\n }\n } else {\n return contextModule(middlewareFilePath);\n }\n },\n contextKey: middlewareFilePath,\n };\n\n if (options.internal_stripLoadRoute) {\n delete (middleware as any).loadRoute;\n }\n\n return middleware;\n}\n\n/**\n * Converts the RequireContext keys (file paths) into a directory tree.\n */\nfunction getDirectoryTree(contextModule: RequireContext, options: Options) {\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n\n const ignoreList: RegExp[] = [/^\\.\\/\\+(html|native-intent)\\.[tj]sx?$/]; // Ignore the top level ./+html file\n\n if (options.ignore) {\n ignoreList.push(...options.ignore);\n }\n if (!options.preserveApiRoutes) {\n ignoreList.push(/\\+api$/, /\\+api\\.[tj]sx?$/);\n }\n\n // Always ignore middleware files in regular route processing\n ignoreList.push(/\\+middleware$/, /\\+middleware\\.[tj]sx?$/);\n\n const rootDirectory: DirectoryNode = {\n files: new Map(),\n subdirectories: new Map(),\n };\n\n let hasRoutes = false;\n let isValid = false;\n\n const contextKeys = contextModule.keys();\n const redirects: Record = {};\n const rewrites: Record = {};\n\n let validRedirectDestinations: { contextKey: string; nameWithoutInvisible: string }[] | undefined;\n\n const getValidDestinations = () => {\n // Loop over contexts once and cache the valid destinations\n validRedirectDestinations ??= contextKeys.map((key) => {\n return {\n contextKey: key,\n nameWithoutInvisible: getNameWithoutInvisibleSegmentsFromRedirectPath(\n removeSupportedExtensions(key)\n ),\n };\n });\n return validRedirectDestinations;\n };\n\n // If we are keeping redirects as valid routes, then we need to add them to the contextKeys\n // This is useful for generating a sitemap with redirects, or static site generation that includes redirects\n if (options.preserveRedirectAndRewrites) {\n if (options.redirects) {\n for (const redirect of options.redirects) {\n const sourceContextKey = getSourceContextKeyFromRedirectSource(redirect.source);\n const sourceName = getNameFromRedirectPath(redirect.source);\n\n const isExternalRedirect = shouldLinkExternally(redirect.destination);\n\n const targetDestinationName = isExternalRedirect\n ? redirect.destination\n : getNameWithoutInvisibleSegmentsFromRedirectPath(redirect.destination);\n\n if (ignoreList.some((regex) => regex.test(sourceContextKey))) {\n continue;\n }\n\n const validDestination = isExternalRedirect\n ? undefined\n : getValidDestinations().find(\n (key) => key.nameWithoutInvisible === targetDestinationName\n );\n const destination = isExternalRedirect\n ? targetDestinationName\n : validDestination?.nameWithoutInvisible;\n const destinationContextKey = isExternalRedirect\n ? targetDestinationName\n : validDestination?.contextKey;\n\n if (!destinationContextKey || destination === undefined) {\n /*\n * Only throw the error when we are preserving the api routes\n * When doing a static export, API routes will not exist so the redirect destination may not exist.\n * The desired behavior for this error is to warn the user when running `expo start`, so its ok if\n * `expo export` swallows this error.\n */\n if (options.preserveApiRoutes) {\n throw new Error(`Redirect destination \"${redirect.destination}\" does not exist.`);\n }\n\n continue;\n }\n\n contextKeys.push(sourceContextKey);\n redirects[sourceName] = {\n source: sourceName,\n destination,\n destinationContextKey,\n permanent: Boolean(redirect.permanent),\n external: isExternalRedirect,\n methods: redirect.methods,\n };\n }\n }\n\n if (options.rewrites) {\n for (const rewrite of options.rewrites) {\n const sourceContextKey = getSourceContextKeyFromRedirectSource(rewrite.source);\n const sourceName = getNameFromRedirectPath(rewrite.source);\n\n // We check to see if the context key is already known so that we don't create a rewrite for\n // a route that already exists on disk\n const isSourceContextKeyAlreadyKnown = contextKeys.includes(sourceContextKey);\n const targetDestinationName = isSourceContextKeyAlreadyKnown\n ? getNameFromRedirectPath(rewrite.destination)\n : getNameWithoutInvisibleSegmentsFromRedirectPath(rewrite.destination);\n\n if (ignoreList.some((regex) => regex.test(sourceContextKey))) {\n continue;\n }\n\n const validDestination = getValidDestinations().find(\n (key) => key.nameWithoutInvisible === targetDestinationName\n );\n const destination = validDestination?.nameWithoutInvisible;\n const destinationContextKey = validDestination?.contextKey;\n\n if (!destinationContextKey || destination === undefined) {\n /*\n * Only throw the error when we are preserving the api routes\n * When doing a static export, API routes will not exist so the redirect destination may not exist.\n * The desired behavior for this error is to warn the user when running `expo start`, so its ok if\n * `expo export` swallows this error.\n */\n if (options.preserveApiRoutes) {\n throw new Error(`Rewrite destination \"${rewrite.destination}\" does not exist.`);\n }\n\n continue;\n }\n\n contextKeys.push(sourceContextKey);\n rewrites[sourceName] = {\n source: sourceName,\n destination,\n destinationContextKey,\n methods: rewrite.methods,\n };\n }\n }\n }\n\n const processedRedirectsRewrites = new Set();\n\n for (const filePath of contextKeys) {\n if (ignoreList.some((regex) => regex.test(filePath))) {\n continue;\n }\n\n isValid = true;\n\n const meta = getFileMeta(filePath, options, redirects, rewrites);\n\n // This is a file that should be ignored. e.g maybe it has an invalid platform?\n if (meta.specificity < 0) {\n continue;\n }\n\n let node: RouteNode = {\n type: meta.isApi ? 'api' : meta.isLayout ? 'layout' : 'route',\n loadRoute() {\n let routeModule: any;\n\n if (options.ignoreRequireErrors) {\n try {\n routeModule = contextModule(filePath);\n } catch {\n routeModule = {};\n }\n } else {\n routeModule = contextModule(filePath);\n }\n\n // See: expo/src/async-require/asyncRequireModule.ts\n // The \"lazy\" async require function returns a thenable that may carry\n // a raw `_result` value that's either a promise or the synchronously resolved module\n if (importMode === 'lazy' || importMode === 'lazy-once') {\n routeModule =\n '_result' in routeModule && routeModule._result != null\n ? routeModule._result\n : routeModule;\n }\n\n if (process.env.NODE_ENV === 'development' && importMode === 'sync') {\n // In development mode, when async routes are disabled, add some extra error handling to improve the developer experience.\n // This can be useful when you accidentally use an async function in a route file for the default export.\n if (routeModule instanceof Promise) {\n throw new Error(\n `Route \"${filePath}\" cannot be a promise when async routes is disabled.`\n );\n }\n\n const defaultExport = routeModule?.default;\n if (defaultExport instanceof Promise) {\n throw new Error(\n `The default export from route \"${filePath}\" is a promise. Ensure the React Component does not use async or promises.`\n );\n }\n\n // check if default is an async function without invoking it\n if (\n defaultExport instanceof Function &&\n // This only works on web because Hermes support async functions so we have to transform them out.\n defaultExport.constructor.name === 'AsyncFunction'\n ) {\n throw new Error(\n `The default export from route \"${filePath}\" is an async function. Ensure the React Component does not use async or promises.`\n );\n }\n\n // Validate loader export in development\n const loaderExport = routeModule?.loader;\n if (loaderExport && typeof loaderExport !== 'function') {\n throw new Error(`Route \"${filePath}\" exports a loader that is not a function.`);\n }\n\n const metadataExport = routeModule?.generateMetadata;\n if (metadataExport && typeof metadataExport !== 'function') {\n throw new Error(`Route \"${filePath}\" exports generateMetadata that is not a function.`);\n }\n }\n\n return routeModule;\n },\n contextKey: filePath,\n route: '', // This is overwritten during hoisting based upon the _layout\n dynamic: null,\n children: [], // While we are building the directory tree, we don't know the node's children just yet. This is added during hoisting\n };\n\n if (meta.isRedirect) {\n if (processedRedirectsRewrites.has(meta.route)) {\n continue;\n }\n\n const redirect = redirects[meta.route]!;\n node.destinationContextKey = redirect.destinationContextKey;\n node.permanent = redirect.permanent;\n node.generated = true;\n if (node.type === 'route') {\n node = options.getSystemRoute({\n type: 'redirect',\n route: redirect.destination,\n defaults: node,\n redirectConfig: redirect,\n });\n }\n if (redirect!.methods) {\n node.methods = redirect.methods;\n }\n node.type = 'redirect';\n processedRedirectsRewrites.add(meta.route);\n }\n\n if (meta.isRewrite) {\n if (processedRedirectsRewrites.has(meta.route)) {\n continue;\n }\n\n const rewrite = rewrites[meta.route]!;\n node.destinationContextKey = rewrite.destinationContextKey;\n node.generated = true;\n if (node.type === 'route') {\n node = options.getSystemRoute({\n type: 'rewrite',\n route: rewrite.destination,\n defaults: node,\n rewriteConfig: rewrite,\n });\n }\n if (rewrite.methods) {\n node.methods = rewrite.methods;\n }\n node.type = 'rewrite';\n processedRedirectsRewrites.add(meta.route);\n }\n\n /**\n * A single filepath may be extrapolated into multiple routes if it contains array syntax.\n * Another way to thinking about is that a filepath node is present in multiple leaves of the directory tree.\n */\n for (const route of extrapolateGroups(meta.route)) {\n // Traverse the directory tree to its leaf node, creating any missing directories along the way\n const subdirectoryParts = route.split('/').slice(0, -1);\n\n // Start at the root directory and traverse the path to the leaf directory\n let directory = rootDirectory;\n\n for (const part of subdirectoryParts) {\n let subDirectory = directory.subdirectories.get(part);\n\n // Create any missing subdirectories\n if (!subDirectory) {\n subDirectory = {\n files: new Map(),\n subdirectories: new Map(),\n };\n directory.subdirectories.set(part, subDirectory);\n }\n\n directory = subDirectory;\n }\n\n // Clone the node for this route\n node = { ...node, route };\n\n if (meta.isLayout) {\n directory.layout ??= [];\n const existing = directory.layout[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The layouts \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n node = getLayoutNode(node, options);\n directory.layout[meta.specificity] = node;\n }\n } else if (meta.isApi) {\n const fileKey = `${route}+api`;\n let nodes = directory.files.get(fileKey);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(fileKey, nodes);\n }\n\n // API Routes have no specificity, they are always the first node\n const existing = nodes[0];\n\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The API route file \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n nodes[0] = node;\n }\n } else {\n let nodes = directory.files.get(route);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(route, nodes);\n }\n\n /**\n * If there is an existing node with the same specificity, then we have a conflict.\n * NOTE(Platform Routes):\n * We cannot check for specificity conflicts here, as we haven't processed all the context keys yet!\n * This will be checked during hoisting, as well as enforcing that all routes have a non-platform route.\n */\n const existing = nodes[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The route files \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Remove or rename one of these files.`\n );\n }\n } else {\n hasRoutes ||= true;\n nodes[meta.specificity] = node;\n }\n }\n }\n }\n\n // If there are no routes/layouts then we should display the tutorial.\n if (!isValid) {\n return null;\n }\n\n /**\n * If there are no top-level _layout, add a default _layout\n * While this is a generated route, it will still be generated even if skipGenerated is true.\n */\n if (!rootDirectory.layout) {\n rootDirectory.layout = [\n options.getSystemRoute({\n type: 'layout',\n route: '',\n }),\n ];\n }\n\n // Only include the sitemap if there are routes.\n if (!options.skipGenerated) {\n if (hasRoutes && options.sitemap !== false) {\n appendSitemapRoute(rootDirectory, options);\n }\n if (options.notFound !== false) {\n appendNotFoundRoute(rootDirectory, options);\n }\n }\n return rootDirectory;\n}\n\nfunction getNameFromRedirectPath(path: string): string {\n // Removing only the filesystem extensions, to be able to handle +api, +html\n return (\n removeFileSystemExtensions(removeFileSystemDots(path))\n // Remove the leading `/`\n .replace(/^\\//, '')\n );\n}\n\nfunction getNameWithoutInvisibleSegmentsFromRedirectPath(path: string): string {\n return stripInvisibleSegmentsFromPath(getNameFromRedirectPath(path));\n}\n\n// Creates fake context key for redirects and rewrites\nfunction getSourceContextKeyFromRedirectSource(source: string): string {\n const name = getNameFromRedirectPath(source);\n const prefix = './';\n const suffix = /\\.[tj]sx?$/.test(name) ? '' : '.js'; // Ensure it has a file extension\n return `${prefix}${name}${suffix}`;\n}\n\n/**\n * Flatten the directory tree into routes, hoisting routes to the nearest _layout.\n */\nfunction flattenDirectoryTreeToRoutes(\n directory: DirectoryNode,\n options: Options,\n /* The nearest _layout file in the directory tree */\n layout?: RouteNode,\n /* Route names are relative to their layout */\n pathToRemove = ''\n) {\n /**\n * This directory has a _layout file so it becomes the new target for hoisting routes.\n */\n if (directory.layout) {\n const previousLayout = layout;\n layout = getMostSpecific(directory.layout);\n\n // Add the new layout as a child of its parent\n if (previousLayout) {\n previousLayout.children.push(layout);\n }\n\n if (options.internal_stripLoadRoute) {\n delete (layout as any).loadRoute;\n }\n\n // `route` is the absolute pathname. We need to make this relative to the last _layout\n const newRoute = layout.route.replace(pathToRemove, '');\n pathToRemove = layout.route ? `${layout.route}/` : '';\n\n // Now update this layout with the new relative route and dynamic conventions\n layout.route = newRoute;\n layout.dynamic = generateDynamic(layout.contextKey.slice(0));\n }\n\n // This should never occur as there will always be a root layout, but it makes the type system happy\n if (!layout) throw new Error('Expo Router Internal Error: No nearest layout');\n\n for (const routes of directory.files.values()) {\n const routeNode = getMostSpecific(routes);\n\n // `route` is the absolute pathname. We need to make this relative to the nearest layout\n routeNode.route = routeNode.route.replace(pathToRemove, '');\n routeNode.dynamic = generateDynamic(routeNode.route);\n\n if (options.internal_stripLoadRoute) {\n delete (routeNode as any).loadRoute;\n }\n\n layout.children.push(routeNode);\n }\n\n // Recursively flatten the subdirectories\n for (const child of directory.subdirectories.values()) {\n flattenDirectoryTreeToRoutes(child, options, layout, pathToRemove);\n }\n\n return layout;\n}\n\nfunction validateRouteTreeExports(node: RouteNode) {\n if (process.env.NODE_ENV !== 'development' || node.type === 'api') {\n return;\n }\n\n function runtimeValidateRouteNode(node: RouteNode) {\n const routeItem = node.loadRoute();\n // Have a warning for nullish ex\n const route = routeItem?.default;\n if (route == null) {\n // Do not throw an error since a user may just be creating a new route.\n console.warn(\n `Route \"${node.contextKey}\" is missing the required default export. Ensure a React component is exported as default.`\n );\n }\n if (['boolean', 'number', 'string'].includes(typeof route)) {\n throw new Error(\n `The default export from route \"${node.contextKey}\" is an unsupported type: \"${typeof route}\". Only React Components are supported as default exports from route files.`\n );\n }\n }\n\n runtimeValidateRouteNode(node);\n for (const child of node.children) {\n validateRouteTreeExports(child);\n }\n}\n\nfunction getFileMeta(\n originalKey: string,\n options: Options,\n redirects: Record,\n rewrites: Record\n) {\n // Remove the leading `./`\n const key = removeSupportedExtensions(removeFileSystemDots(originalKey));\n let route = key;\n\n const parts = removeFileSystemDots(originalKey).split('/');\n const filename = parts[parts.length - 1]!;\n const filenameParts = removeSupportedExtensions(filename).split('.');\n const filenameWithoutExtensions = filenameParts[0]!;\n const platformExtension = filenameParts[1];\n\n const isLayout = filenameWithoutExtensions === '_layout';\n const isApi = originalKey.match(/\\+api\\.(\\w+\\.)?[jt]sx?$/);\n\n if (filenameWithoutExtensions.startsWith('(') && filenameWithoutExtensions.endsWith(')')) {\n throw new Error(`Invalid route ${originalKey}. Routes cannot end with '(group)' syntax`);\n }\n\n // Nested routes cannot start with the '+' character, except for the '+not-found' route\n if (!isApi && filename.startsWith('+') && filenameWithoutExtensions !== '+not-found') {\n const renamedRoute = [...parts.slice(0, -1), filename.slice(1)].join('/');\n throw new Error(\n `Invalid route ${originalKey}. Route nodes cannot start with the '+' character. \"Rename it to ${renamedRoute}\"`\n );\n }\n let specificity = 0;\n\n const hasPlatformExtension = validPlatforms.has(platformExtension!);\n const usePlatformRoutes = options.platformRoutes ?? true;\n\n if (hasPlatformExtension) {\n if (!usePlatformRoutes) {\n // If the user has disabled platform routes, then we should ignore this file\n specificity = -1;\n } else if (!options.platform) {\n // If we don't have a platform, then we should ignore this file\n // This used by typed routes, sitemap, etc\n specificity = -1;\n } else if (platformExtension === options.platform) {\n // If the platform extension is the same as the options.platform, then it is the most specific\n specificity = 2;\n } else if (platformExtension === 'native' && options.platform !== 'web') {\n // `native` is allow but isn't as specific as the platform\n specificity = 1;\n } else if (platformExtension !== options.platform) {\n // Somehow we have a platform extension that doesn't match the options.platform and it isn't native\n // This is an invalid file and we will ignore it\n specificity = -1;\n }\n\n if (isApi && specificity !== 0) {\n throw new Error(\n `API routes cannot have platform extensions. Remove '.${platformExtension}' from '${originalKey}'`\n );\n }\n\n route = route.replace(new RegExp(`.${platformExtension}$`), '');\n }\n\n return {\n route,\n specificity,\n isLayout,\n isApi,\n isRedirect: key in redirects,\n isRewrite: key in rewrites,\n };\n}\n\n/**\n * Generates a set of strings which have the router array syntax extrapolated.\n *\n * /(a,b)/(c,d)/e.tsx => new Set(['a/c/e.tsx', 'a/d/e.tsx', 'b/c/e.tsx', 'b/d/e.tsx'])\n */\nexport function extrapolateGroups(key: string, keys: Set = new Set()): Set {\n const match = matchArrayGroupName(key);\n\n if (!match) {\n keys.add(key);\n return keys;\n }\n const groups = match.split(',');\n const groupsSet = new Set(groups);\n\n if (groupsSet.size !== groups.length) {\n throw new Error(`Array syntax cannot contain duplicate group name \"${groups}\" in \"${key}\".`);\n }\n\n if (groups.length === 1) {\n keys.add(key);\n return keys;\n }\n\n for (const group of groups) {\n extrapolateGroups(key.replace(match, group.trim()), keys);\n }\n\n return keys;\n}\n\nexport function generateDynamic(path: string): DynamicConvention[] | null {\n const dynamic = path\n .split('/')\n .map((part): DynamicConvention | null => {\n if (part === '+not-found') {\n return {\n name: '+not-found',\n deep: true,\n notFound: true,\n };\n }\n return matchDynamicName(part) ?? null;\n })\n .filter((part): part is DynamicConvention => !!part);\n\n return dynamic.length === 0 ? null : dynamic;\n}\n\nfunction appendSitemapRoute(directory: DirectoryNode, options: Options) {\n if (!directory.files.has('_sitemap') && options.getSystemRoute) {\n directory.files.set('_sitemap', [\n options.getSystemRoute({\n type: 'route',\n route: '_sitemap',\n }),\n ]);\n }\n}\n\nfunction appendNotFoundRoute(directory: DirectoryNode, options: Options) {\n if (!directory.files.has('+not-found') && options.getSystemRoute) {\n directory.files.set('+not-found', [\n options.getSystemRoute({\n type: 'route',\n route: '+not-found',\n }),\n ]);\n }\n}\n\nfunction getLayoutNode(node: RouteNode, options: Options) {\n /**\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different anchor based upon the first group name.\n */\n // We may strip loadRoute during testing\n const groupName = matchLastGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let anchor = childMatchingGroup?.route;\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n try {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n anchor =\n loaded.unstable_settings.anchor ?? loaded.unstable_settings.initialRouteName ?? anchor;\n } catch (error: any) {\n if (error instanceof Error) {\n if (!error.message.match(/You cannot dot into a client module/)) {\n throw error;\n }\n }\n }\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.anchor ??\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n anchor = groupSpecificInitialRouteName ?? anchor;\n }\n }\n\n return {\n ...node,\n route: node.route.replace(/\\/?_layout$/, ''),\n children: [], // Each layout should have its own children\n initialRouteName: anchor,\n };\n}\n\nfunction crawlAndAppendInitialRoutesAndEntryFiles(\n node: RouteNode,\n options: Options,\n entryPoints: string[] = []\n) {\n if (node.type === 'route') {\n node.entryPoints = [...new Set([...entryPoints, node.contextKey])];\n } else if (node.type === 'redirect') {\n node.entryPoints = [...new Set([...entryPoints, node.destinationContextKey!])];\n } else if (node.type === 'layout') {\n if (!node.children) {\n throw new Error(`Layout \"${node.contextKey}\" does not contain any child routes`);\n }\n\n // Every node below this layout will have it as an entryPoint\n entryPoints = [...entryPoints, node.contextKey];\n\n /**\n * Calculate the initialRouteNode\n *\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different anchor based upon the first group.\n */\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let anchor = childMatchingGroup?.route;\n // We may strip loadRoute during testing\n if (!options.internal_stripLoadRoute) {\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n try {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n anchor =\n loaded.unstable_settings.anchor ?? loaded.unstable_settings.initialRouteName ?? anchor;\n } catch (error: any) {\n if (error instanceof Error) {\n if (!error.message.match(/You cannot dot into a client module/)) {\n throw error;\n }\n }\n }\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.anchor ??\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n anchor = groupSpecificInitialRouteName ?? anchor;\n }\n }\n }\n\n if (anchor) {\n const anchorRoute = node.children.find((child) => child.route === anchor);\n if (!anchorRoute) {\n const validAnchorRoutes = node.children\n .filter((child) => !child.generated)\n .map((child) => `'${child.route}'`)\n .join(', ');\n\n if (groupName) {\n throw new Error(\n `Layout ${node.contextKey} has invalid anchor '${anchor}' for group '(${groupName})'. Valid options are: ${validAnchorRoutes}`\n );\n } else {\n throw new Error(\n `Layout ${node.contextKey} has invalid anchor '${anchor}'. Valid options are: ${validAnchorRoutes}`\n );\n }\n }\n\n // Navigators can add initialsRoutes into the history, so they need to be to be included in the entryPoints\n node.initialRouteName = anchor;\n entryPoints.push(anchorRoute.contextKey);\n }\n\n for (const child of node.children) {\n crawlAndAppendInitialRoutesAndEntryFiles(child, options, entryPoints);\n }\n }\n}\n\nfunction getMostSpecific(routes: RouteNode[]) {\n const route = routes[routes.length - 1]!;\n\n if (!routes[0]) {\n throw new Error(\n `The file ${route.contextKey} does not have a fallback sibling file without a platform extension.`\n );\n }\n\n // This works even tho routes is holey array (e.g it might have index 0 and 2 but not 1)\n // `.length` includes the holes in its count\n return route;\n}\n"]} \ No newline at end of file diff --git a/packages/expo-router/build/useScreens.d.ts b/packages/expo-router/build/useScreens.d.ts index 12d5e3223eed45..99b0d0b8e51ec0 100644 --- a/packages/expo-router/build/useScreens.d.ts +++ b/packages/expo-router/build/useScreens.d.ts @@ -4,6 +4,13 @@ import type { BottomTabNavigationEventMap } from './react-navigation/bottom-tabs import { type EventMapBase, type NavigationProp, type NavigationState, type ParamListBase, type RouteProp, type ScreenListeners } from './react-navigation/native'; import type { NativeStackNavigationEventMap } from './react-navigation/native-stack'; import type { UnknownOutputParams } from './types'; +declare module 'react' { + function lazy>(load: () => PromiseLike<{ + default: T; + }> | Promise<{ + default: T; + }>): React.LazyExoticComponent; +} export type ScreenProps = Record, TState extends NavigationState = NavigationState, TEventMap extends EventMapBase = EventMapBase> = { /** Name is required when used inside a Layout component. */ name?: string; diff --git a/packages/expo-router/build/useScreens.d.ts.map b/packages/expo-router/build/useScreens.d.ts.map index fe8f45be4360db..7eae985a24cc39 100644 --- a/packages/expo-router/build/useScreens.d.ts.map +++ b/packages/expo-router/build/useScreens.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/packages/expo-router/build/useScreens.js b/packages/expo-router/build/useScreens.js index 191882d4e7f89c..9299061832496c 100644 --- a/packages/expo-router/build/useScreens.js +++ b/packages/expo-router/build/useScreens.js @@ -168,12 +168,6 @@ function fromImport(value, { ErrorBoundary, SuspenseFallback, ...component }) { } return { default: component.default, SuspenseFallback }; } -function fromLoadedRoute(value, res) { - if (!(res instanceof Promise)) { - return fromImport(value, res); - } - return res.then(fromImport.bind(null, value)); -} // TODO: Maybe there's a more React-y way to do this? // Without this store, the process enters a recursive loop. const qualifiedStore = new WeakMap(); @@ -186,9 +180,22 @@ function getQualifiedRouteComponent(value) { let LayoutSuspenseFallback; // TODO: This ensures sync doesn't use React.lazy, but it's not ideal. if (import_mode_1.default === 'lazy') { - ScreenComponent = react_2.default.lazy(async () => { + ScreenComponent = react_2.default.lazy(() => { const res = value.loadRoute(); - return fromLoadedRoute(value, res); + // NOTE(@kitten): React.lazy supports promise likes, which we can use to ensure that + // the route is synchronously available, if the `loadRoute` method returns a loaded route + // synchronously + if (!('then' in res)) { + return { + then(resolve) { + const ret = fromImport(value, res); + return Promise.resolve(resolve ? resolve(ret) : ret); + }, + }; + } + else { + return res.then(fromImport.bind(null, value)); + } }); if (__DEV__) { ScreenComponent.displayName = `AsyncRoute(${value.route})`; diff --git a/packages/expo-router/build/useScreens.js.map b/packages/expo-router/build/useScreens.js.map index a5ecc2de663604..3038109dac914b 100644 --- a/packages/expo-router/build/useScreens.js.map +++ b/packages/expo-router/build/useScreens.js.map @@ -1 +1 @@ -{"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport React, { use, useEffect } from 'react';\n\nimport type { LoadedRoute, RouteNode } from './Route';\nimport { SuspenseFallbackContext, Route, sortRoutesWithInitial, useRouteNode } from './Route';\nimport { useExpoRouterStore } from './global-state/storeContext';\nimport { useColorSchemeChangesIfNeeded } from './global-state/utils';\n// Direct import to prevent a require cycle\nimport { useCurrentRouteInfo } from './hooks/useCurrentRouteInfo';\nimport EXPO_ROUTER_IMPORT_MODE from './import-mode';\nimport { ZoomTransitionEnabler } from './link/zoom/ZoomTransitionEnabler';\nimport { ZoomTransitionTargetContextProvider } from './link/zoom/zoom-transition-context-providers';\nimport { unstable_navigationEvents } from './navigationEvents';\nimport {\n hasParam,\n INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME,\n removeParams,\n} from './navigationParams';\nimport { Screen } from './primitives';\nimport type { BottomTabNavigationEventMap } from './react-navigation/bottom-tabs';\nimport {\n useStateForPath,\n type EventConsumer,\n type EventMapBase,\n type NavigationProp,\n type NavigationState,\n type ParamListBase,\n type RouteProp,\n type ScreenListeners,\n} from './react-navigation/native';\nimport type { NativeStackNavigationEventMap } from './react-navigation/native-stack';\nimport type { UnknownOutputParams } from './types';\nimport { EmptyRoute } from './views/EmptyRoute';\nimport {\n SuspenseFallback as DefaultSuspenseFallback,\n type SuspenseFallbackProps,\n} from './views/SuspenseFallback';\nimport { Try } from './views/Try';\n\nexport type ScreenProps<\n TOptions extends Record = Record,\n TState extends NavigationState = NavigationState,\n TEventMap extends EventMapBase = EventMapBase,\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest sibling route.\n * If all children are `redirect={true}`, the layout will render `null` as there are no children to render.\n */\n redirect?: boolean;\n initialParams?: Record;\n options?:\n | TOptions\n | ((prop: { route: RouteProp; navigation: any }) => TOptions);\n\n listeners?:\n | ScreenListeners\n | ((prop: {\n route: RouteProp;\n navigation: any;\n }) => ScreenListeners);\n\n getId?: ({ params }: { params?: Record }) => string | undefined;\n\n dangerouslySingular?: SingularOptions;\n};\n\nexport type SingularOptions =\n | boolean\n | ((name: string, params: UnknownOutputParams) => string | undefined);\n\nfunction getSortedChildren(\n children: RouteNode[],\n order: ScreenProps[] = [],\n initialRouteName?: string\n): { route: RouteNode; props: Partial }[] {\n if (!order?.length) {\n return children\n .sort(sortRoutesWithInitial(initialRouteName))\n .map((route) => ({ route, props: {} }));\n }\n const entries = [...children];\n\n const ordered = order\n .map(\n ({\n name,\n redirect,\n initialParams,\n listeners,\n options,\n getId,\n dangerouslySingular: singular,\n }) => {\n if (!entries.length) {\n console.warn(\n `[Layout children]: Too many screens defined. Route \"${name}\" is extraneous.`\n );\n return null;\n }\n const matchIndex = entries.findIndex(\n (child) => child.route === name || child.route === `${name}/index`\n );\n if (matchIndex === -1) {\n console.warn(\n `[Layout children]: No route named \"${name}\" exists in nested children:`,\n children.map(({ route }) => route)\n );\n return null;\n } else {\n // Get match and remove from entries\n const match = entries[matchIndex];\n entries.splice(matchIndex, 1);\n\n // Ensure to return null after removing from entries.\n if (redirect) {\n if (typeof redirect === 'string') {\n throw new Error(`Redirecting to a specific route is not supported yet.`);\n }\n return null;\n }\n\n if (getId) {\n console.warn(\n `Deprecated: prop 'getId' on screen ${name} is deprecated. Please rename the prop to 'dangerouslySingular'`\n );\n if (singular) {\n console.warn(\n `Screen ${name} cannot use both getId and dangerouslySingular together.`\n );\n }\n } else if (singular) {\n // If singular is set, use it as the getId function.\n if (typeof singular === 'string') {\n getId = () => singular;\n } else if (typeof singular === 'function' && name) {\n getId = (options) => singular(name, options.params || {});\n } else if (singular === true && name) {\n getId = (options) => getSingularId(name, options);\n }\n }\n\n return {\n route: match,\n props: { initialParams, listeners, options, getId },\n };\n }\n }\n )\n .filter(Boolean) as {\n route: RouteNode;\n props: Partial;\n }[];\n\n // Add any remaining children\n ordered.push(\n ...entries.sort(sortRoutesWithInitial(initialRouteName)).map((route) => ({ route, props: {} }))\n );\n\n return ordered;\n}\n\n/**\n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useSortedScreens(\n order: ScreenProps[],\n protectedScreens: Set,\n useOnlyUserDefinedScreens: boolean = false\n): React.ReactNode[] {\n const node = useRouteNode();\n\n const nodeChildren = node?.children ?? [];\n const children = useOnlyUserDefinedScreens\n ? nodeChildren.filter((child) =>\n order.some(\n (userDefinedScreen) =>\n userDefinedScreen.name === child.route ||\n `${userDefinedScreen.name}/index` === child.route\n )\n )\n : nodeChildren;\n\n const sorted = children.length ? getSortedChildren(children, order, node?.initialRouteName) : [];\n return React.useMemo(\n () =>\n sorted\n .filter((item) => {\n const route = item.route.route;\n return (\n !protectedScreens.has(route) && !protectedScreens.has(route.replace(/\\/index$/, ''))\n );\n })\n .map((value) => {\n return routeToScreen(value.route, value.props);\n }),\n [sorted, protectedScreens]\n );\n}\n\nfunction fromImport(\n value: RouteNode,\n { ErrorBoundary, SuspenseFallback, ...component }: LoadedRoute\n) {\n // If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a component.`.\n if (component?.default && __DEV__) {\n component.default.displayName ??= `${component.default.name ?? 'Route'}(${value.contextKey})`;\n }\n\n if (ErrorBoundary) {\n const Wrapped = React.forwardRef((props: any, ref: any) => {\n const children = React.createElement(component.default || EmptyRoute, {\n ...props,\n ref,\n });\n return {children};\n });\n\n if (__DEV__) {\n Wrapped.displayName = `ErrorBoundary(${value.contextKey})`;\n }\n\n return {\n default: Wrapped,\n SuspenseFallback,\n };\n }\n if (process.env.NODE_ENV !== 'production') {\n if (\n typeof component.default === 'object' &&\n component.default &&\n Object.keys(component.default).length === 0\n ) {\n return { default: EmptyRoute, SuspenseFallback };\n }\n }\n\n return { default: component.default, SuspenseFallback };\n}\n\nfunction fromLoadedRoute(value: RouteNode, res: LoadedRoute) {\n if (!(res instanceof Promise)) {\n return fromImport(value, res);\n }\n\n return res.then(fromImport.bind(null, value));\n}\n\n// TODO: Maybe there's a more React-y way to do this?\n// Without this store, the process enters a recursive loop.\nconst qualifiedStore = new WeakMap>();\n\n/** Wrap the component with various enhancements and add access to child routes. */\nexport function getQualifiedRouteComponent(value: RouteNode) {\n if (qualifiedStore.has(value)) {\n return qualifiedStore.get(value)!;\n }\n\n let ScreenComponent:\n | React.ForwardRefExoticComponent>\n | React.ComponentType<{ segment?: string }>;\n\n let LayoutSuspenseFallback: React.ComponentType | undefined;\n\n // TODO: This ensures sync doesn't use React.lazy, but it's not ideal.\n if (EXPO_ROUTER_IMPORT_MODE === 'lazy') {\n ScreenComponent = React.lazy(async () => {\n const res = value.loadRoute();\n return fromLoadedRoute(value, res) as Promise<{\n default: React.ComponentType;\n }>;\n });\n\n if (__DEV__) {\n ScreenComponent.displayName = `AsyncRoute(${value.route})`;\n }\n } else {\n const res = value.loadRoute();\n const result = fromImport(value, res);\n ScreenComponent = result.default!;\n LayoutSuspenseFallback = value.type === 'layout' ? result.SuspenseFallback : undefined;\n }\n const WrappedScreenComponent: typeof ScreenComponent = (props: object) => {\n useColorSchemeChangesIfNeeded();\n return ;\n };\n function BaseRoute({\n // Remove these React Navigation props to\n // enforce usage of expo-router hooks (where the query params are correct).\n route,\n navigation,\n\n // Pass all other props to the component\n ...props\n }: {\n route?: RouteProp;\n navigation: Omit<\n NavigationProp<\n ParamListBase,\n string,\n undefined,\n NavigationState,\n object,\n NativeStackNavigationEventMap | BottomTabNavigationEventMap\n >,\n 'getState'\n > & {\n getState(): NavigationState | undefined;\n };\n }) {\n const stateForPath = useStateForPath();\n const isFocused = navigation.isFocused();\n const store = useExpoRouterStore();\n const InheritedSuspenseFallback = use(SuspenseFallbackContext);\n\n const ResolvedSuspenseFallback =\n EXPO_ROUTER_IMPORT_MODE === 'lazy'\n ? DefaultSuspenseFallback\n : (LayoutSuspenseFallback ?? InheritedSuspenseFallback ?? DefaultSuspenseFallback);\n const providedSuspenseFallback =\n value.type === 'layout'\n ? (LayoutSuspenseFallback ?? InheritedSuspenseFallback)\n : InheritedSuspenseFallback;\n\n if (isFocused) {\n const state = navigation.getState();\n const isLeaf = !(state && 'state' in state.routes[state.index]!);\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }\n\n useEffect(\n () =>\n navigation.addListener('focus', () => {\n const state = navigation.getState();\n const isLeaf = !(state && 'state' in state.routes[state.index]!);\n // Because setFocusedState caches the route info, this call will only trigger rerenders\n // if the component itself didn’t rerender and the route info changed.\n // Otherwise, the update from the `if` above will handle it,\n // and this won’t cause a redundant second update.\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }),\n [navigation]\n );\n\n useEffect(() => {\n return navigation.addListener('transitionEnd', (e) => {\n if (!e?.data?.closing) {\n // When navigating to a screen, remove the no animation param to re-enable animations\n // Otherwise the navigation back would also have no animation\n if (hasParam(route?.params, INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME)) {\n navigation.replaceParams(\n removeParams(route?.params, [INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME])\n );\n }\n }\n });\n }, [navigation]);\n\n const isRouteType = value.type === 'route';\n const hasRouteKey = !!route?.key;\n\n return (\n \n \n {unstable_navigationEvents.isEnabled() && isRouteType && hasRouteKey && (\n \n )}\n \n \n \n }>\n \n \n \n \n \n );\n }\n\n if (__DEV__) {\n BaseRoute.displayName = `Route(${value.route})`;\n }\n\n qualifiedStore.set(value, BaseRoute);\n return BaseRoute;\n}\n\nfunction AnalyticsListeners({\n navigation,\n screenId,\n}: {\n navigation: EventConsumer & {\n isFocused(): boolean;\n };\n screenId: string;\n}) {\n const isFirstRenderRef = React.useRef(true);\n const hasBlurredRef = React.useRef(true);\n const routeInfo = useCurrentRouteInfo();\n\n const isFocused = navigation.isFocused();\n\n if (isFirstRenderRef.current) {\n isFirstRenderRef.current = false;\n if (routeInfo && !isFocused) {\n unstable_navigationEvents.emit('pagePreloaded', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n }\n }\n\n useEffect(() => {\n if (routeInfo) {\n return () => {\n unstable_navigationEvents.emit('pageRemoved', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n };\n }\n return () => {};\n }, [routeInfo?.params, routeInfo?.pathname, routeInfo?.segments, screenId]);\n\n // Emit `pageFocused` from an effect — not during render — so it fires after the\n // focused screen's content has committed. `hasBlurredRef` deduplicates across both paths.\n useEffect(() => {\n if (isFocused && routeInfo && hasBlurredRef.current) {\n unstable_navigationEvents.emit('pageFocused', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = false;\n }\n }, [isFocused, routeInfo?.pathname, routeInfo?.params, routeInfo?.segments, screenId]);\n\n useEffect(() => {\n if (routeInfo) {\n const cleanFocus = navigation.addListener('focus', () => {\n // If the screen was not blurred, don't emit focused again\n // hasBlurredRef will be false when the screen was initially focused\n if (hasBlurredRef.current) {\n unstable_navigationEvents.emit('pageFocused', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = false;\n }\n });\n const cleanBlur = navigation.addListener('blur', () => {\n unstable_navigationEvents.emit('pageBlurred', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = true;\n });\n return () => {\n cleanFocus();\n cleanBlur();\n };\n }\n return () => {};\n }, [navigation, routeInfo?.pathname, routeInfo?.params, routeInfo?.segments, screenId]);\n\n return null;\n}\n\nexport function screenOptionsFactory(\n route: RouteNode,\n options?: ScreenProps['options']\n): ScreenProps['options'] {\n return (args) => {\n // Only eager load generated components\n const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null;\n const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;\n const dynamicResult = typeof options === 'function' ? options?.(args) : options;\n const output = {\n ...staticResult,\n ...dynamicResult,\n };\n\n // Prevent generated screens from showing up in the tab bar.\n if (route.internal) {\n output.tabBarItemStyle = { display: 'none' };\n output.tabBarButton = () => null;\n // TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.\n output.drawerItemStyle = { height: 0, display: 'none' };\n }\n\n return output;\n };\n}\n\nexport function routeToScreen(\n route: RouteNode,\n { options, getId, ...props }: Partial = {}\n) {\n return (\n getQualifiedRouteComponent(route)}\n />\n );\n}\n\nexport function getSingularId(name: string, options: Record = {}) {\n return name\n .split('/')\n .map((segment) => {\n if (segment.startsWith('[...')) {\n return options.params?.[segment.slice(4, -1)]?.join('/') || segment;\n } else if (segment.startsWith('[') && segment.endsWith(']')) {\n return options.params?.[segment.slice(1, -1)] || segment;\n } else {\n return segment;\n }\n })\n .join('/');\n}\n"]} \ No newline at end of file +{"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport React, { use, useEffect } from 'react';\n\nimport type { LoadedRoute, RouteNode } from './Route';\nimport { SuspenseFallbackContext, Route, sortRoutesWithInitial, useRouteNode } from './Route';\nimport { useExpoRouterStore } from './global-state/storeContext';\nimport { useColorSchemeChangesIfNeeded } from './global-state/utils';\n// Direct import to prevent a require cycle\nimport { useCurrentRouteInfo } from './hooks/useCurrentRouteInfo';\nimport EXPO_ROUTER_IMPORT_MODE from './import-mode';\nimport { ZoomTransitionEnabler } from './link/zoom/ZoomTransitionEnabler';\nimport { ZoomTransitionTargetContextProvider } from './link/zoom/zoom-transition-context-providers';\nimport { unstable_navigationEvents } from './navigationEvents';\nimport {\n hasParam,\n INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME,\n removeParams,\n} from './navigationParams';\nimport { Screen } from './primitives';\nimport type { BottomTabNavigationEventMap } from './react-navigation/bottom-tabs';\nimport {\n useStateForPath,\n type EventConsumer,\n type EventMapBase,\n type NavigationProp,\n type NavigationState,\n type ParamListBase,\n type RouteProp,\n type ScreenListeners,\n} from './react-navigation/native';\nimport type { NativeStackNavigationEventMap } from './react-navigation/native-stack';\nimport type { UnknownOutputParams } from './types';\nimport { EmptyRoute } from './views/EmptyRoute';\nimport {\n SuspenseFallback as DefaultSuspenseFallback,\n type SuspenseFallbackProps,\n} from './views/SuspenseFallback';\nimport { Try } from './views/Try';\n\ndeclare module 'react' {\n export function lazy>(\n load: () => PromiseLike<{ default: T }> | Promise<{ default: T }>\n ): React.LazyExoticComponent;\n}\n\nexport type ScreenProps<\n TOptions extends Record = Record,\n TState extends NavigationState = NavigationState,\n TEventMap extends EventMapBase = EventMapBase,\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest sibling route.\n * If all children are `redirect={true}`, the layout will render `null` as there are no children to render.\n */\n redirect?: boolean;\n initialParams?: Record;\n options?:\n | TOptions\n | ((prop: { route: RouteProp; navigation: any }) => TOptions);\n\n listeners?:\n | ScreenListeners\n | ((prop: {\n route: RouteProp;\n navigation: any;\n }) => ScreenListeners);\n\n getId?: ({ params }: { params?: Record }) => string | undefined;\n\n dangerouslySingular?: SingularOptions;\n};\n\nexport type SingularOptions =\n | boolean\n | ((name: string, params: UnknownOutputParams) => string | undefined);\n\nfunction getSortedChildren(\n children: RouteNode[],\n order: ScreenProps[] = [],\n initialRouteName?: string\n): { route: RouteNode; props: Partial }[] {\n if (!order?.length) {\n return children\n .sort(sortRoutesWithInitial(initialRouteName))\n .map((route) => ({ route, props: {} }));\n }\n const entries = [...children];\n\n const ordered = order\n .map(\n ({\n name,\n redirect,\n initialParams,\n listeners,\n options,\n getId,\n dangerouslySingular: singular,\n }) => {\n if (!entries.length) {\n console.warn(\n `[Layout children]: Too many screens defined. Route \"${name}\" is extraneous.`\n );\n return null;\n }\n const matchIndex = entries.findIndex(\n (child) => child.route === name || child.route === `${name}/index`\n );\n if (matchIndex === -1) {\n console.warn(\n `[Layout children]: No route named \"${name}\" exists in nested children:`,\n children.map(({ route }) => route)\n );\n return null;\n } else {\n // Get match and remove from entries\n const match = entries[matchIndex];\n entries.splice(matchIndex, 1);\n\n // Ensure to return null after removing from entries.\n if (redirect) {\n if (typeof redirect === 'string') {\n throw new Error(`Redirecting to a specific route is not supported yet.`);\n }\n return null;\n }\n\n if (getId) {\n console.warn(\n `Deprecated: prop 'getId' on screen ${name} is deprecated. Please rename the prop to 'dangerouslySingular'`\n );\n if (singular) {\n console.warn(\n `Screen ${name} cannot use both getId and dangerouslySingular together.`\n );\n }\n } else if (singular) {\n // If singular is set, use it as the getId function.\n if (typeof singular === 'string') {\n getId = () => singular;\n } else if (typeof singular === 'function' && name) {\n getId = (options) => singular(name, options.params || {});\n } else if (singular === true && name) {\n getId = (options) => getSingularId(name, options);\n }\n }\n\n return {\n route: match,\n props: { initialParams, listeners, options, getId },\n };\n }\n }\n )\n .filter(Boolean) as {\n route: RouteNode;\n props: Partial;\n }[];\n\n // Add any remaining children\n ordered.push(\n ...entries.sort(sortRoutesWithInitial(initialRouteName)).map((route) => ({ route, props: {} }))\n );\n\n return ordered;\n}\n\n/**\n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useSortedScreens(\n order: ScreenProps[],\n protectedScreens: Set,\n useOnlyUserDefinedScreens: boolean = false\n): React.ReactNode[] {\n const node = useRouteNode();\n\n const nodeChildren = node?.children ?? [];\n const children = useOnlyUserDefinedScreens\n ? nodeChildren.filter((child) =>\n order.some(\n (userDefinedScreen) =>\n userDefinedScreen.name === child.route ||\n `${userDefinedScreen.name}/index` === child.route\n )\n )\n : nodeChildren;\n\n const sorted = children.length ? getSortedChildren(children, order, node?.initialRouteName) : [];\n return React.useMemo(\n () =>\n sorted\n .filter((item) => {\n const route = item.route.route;\n return (\n !protectedScreens.has(route) && !protectedScreens.has(route.replace(/\\/index$/, ''))\n );\n })\n .map((value) => {\n return routeToScreen(value.route, value.props);\n }),\n [sorted, protectedScreens]\n );\n}\n\nfunction fromImport(\n value: RouteNode,\n { ErrorBoundary, SuspenseFallback, ...component }: LoadedRoute\n) {\n // If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a component.`.\n if (component?.default && __DEV__) {\n component.default.displayName ??= `${component.default.name ?? 'Route'}(${value.contextKey})`;\n }\n\n if (ErrorBoundary) {\n const Wrapped = React.forwardRef((props: any, ref: any) => {\n const children = React.createElement(component.default || EmptyRoute, {\n ...props,\n ref,\n });\n return {children};\n });\n\n if (__DEV__) {\n Wrapped.displayName = `ErrorBoundary(${value.contextKey})`;\n }\n\n return {\n default: Wrapped,\n SuspenseFallback,\n };\n }\n if (process.env.NODE_ENV !== 'production') {\n if (\n typeof component.default === 'object' &&\n component.default &&\n Object.keys(component.default).length === 0\n ) {\n return { default: EmptyRoute, SuspenseFallback };\n }\n }\n\n return { default: component.default!, SuspenseFallback };\n}\n\n// TODO: Maybe there's a more React-y way to do this?\n// Without this store, the process enters a recursive loop.\nconst qualifiedStore = new WeakMap>();\n\n/** Wrap the component with various enhancements and add access to child routes. */\nexport function getQualifiedRouteComponent(value: RouteNode) {\n if (qualifiedStore.has(value)) {\n return qualifiedStore.get(value)!;\n }\n\n let ScreenComponent: React.ComponentType;\n let LayoutSuspenseFallback: React.ComponentType | undefined;\n\n // TODO: This ensures sync doesn't use React.lazy, but it's not ideal.\n if (EXPO_ROUTER_IMPORT_MODE === 'lazy') {\n ScreenComponent = React.lazy>(() => {\n const res = value.loadRoute() as LoadedRoute | PromiseLike;\n // NOTE(@kitten): React.lazy supports promise likes, which we can use to ensure that\n // the route is synchronously available, if the `loadRoute` method returns a loaded route\n // synchronously\n if (!('then' in res)) {\n return {\n then(resolve) {\n const ret = fromImport(value, res);\n return Promise.resolve(resolve ? resolve(ret) : ret);\n },\n } as PromiseLike<{ default: React.ComponentType }>;\n } else {\n return res.then(fromImport.bind(null, value));\n }\n });\n\n if (__DEV__) {\n ScreenComponent.displayName = `AsyncRoute(${value.route})`;\n }\n } else {\n const res = value.loadRoute() as LoadedRoute;\n const result = fromImport(value, res);\n ScreenComponent = result.default!;\n LayoutSuspenseFallback = value.type === 'layout' ? result.SuspenseFallback : undefined;\n }\n const WrappedScreenComponent: typeof ScreenComponent = (props: object) => {\n useColorSchemeChangesIfNeeded();\n return ;\n };\n function BaseRoute({\n // Remove these React Navigation props to\n // enforce usage of expo-router hooks (where the query params are correct).\n route,\n navigation,\n\n // Pass all other props to the component\n ...props\n }: {\n route?: RouteProp;\n navigation: Omit<\n NavigationProp<\n ParamListBase,\n string,\n undefined,\n NavigationState,\n object,\n NativeStackNavigationEventMap | BottomTabNavigationEventMap\n >,\n 'getState'\n > & {\n getState(): NavigationState | undefined;\n };\n }) {\n const stateForPath = useStateForPath();\n const isFocused = navigation.isFocused();\n const store = useExpoRouterStore();\n const InheritedSuspenseFallback = use(SuspenseFallbackContext);\n\n const ResolvedSuspenseFallback =\n EXPO_ROUTER_IMPORT_MODE === 'lazy'\n ? DefaultSuspenseFallback\n : (LayoutSuspenseFallback ?? InheritedSuspenseFallback ?? DefaultSuspenseFallback);\n const providedSuspenseFallback =\n value.type === 'layout'\n ? (LayoutSuspenseFallback ?? InheritedSuspenseFallback)\n : InheritedSuspenseFallback;\n\n if (isFocused) {\n const state = navigation.getState();\n const isLeaf = !(state && 'state' in state.routes[state.index]!);\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }\n\n useEffect(\n () =>\n navigation.addListener('focus', () => {\n const state = navigation.getState();\n const isLeaf = !(state && 'state' in state.routes[state.index]!);\n // Because setFocusedState caches the route info, this call will only trigger rerenders\n // if the component itself didn’t rerender and the route info changed.\n // Otherwise, the update from the `if` above will handle it,\n // and this won’t cause a redundant second update.\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }),\n [navigation]\n );\n\n useEffect(() => {\n return navigation.addListener('transitionEnd', (e) => {\n if (!e?.data?.closing) {\n // When navigating to a screen, remove the no animation param to re-enable animations\n // Otherwise the navigation back would also have no animation\n if (hasParam(route?.params, INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME)) {\n navigation.replaceParams(\n removeParams(route?.params, [INTERNAL_EXPO_ROUTER_NO_ANIMATION_PARAM_NAME])\n );\n }\n }\n });\n }, [navigation]);\n\n const isRouteType = value.type === 'route';\n const hasRouteKey = !!route?.key;\n\n return (\n \n \n {unstable_navigationEvents.isEnabled() && isRouteType && hasRouteKey && (\n \n )}\n \n \n \n }>\n \n \n \n \n \n );\n }\n\n if (__DEV__) {\n BaseRoute.displayName = `Route(${value.route})`;\n }\n\n qualifiedStore.set(value, BaseRoute);\n return BaseRoute;\n}\n\nfunction AnalyticsListeners({\n navigation,\n screenId,\n}: {\n navigation: EventConsumer & {\n isFocused(): boolean;\n };\n screenId: string;\n}) {\n const isFirstRenderRef = React.useRef(true);\n const hasBlurredRef = React.useRef(true);\n const routeInfo = useCurrentRouteInfo();\n\n const isFocused = navigation.isFocused();\n\n if (isFirstRenderRef.current) {\n isFirstRenderRef.current = false;\n if (routeInfo && !isFocused) {\n unstable_navigationEvents.emit('pagePreloaded', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n }\n }\n\n useEffect(() => {\n if (routeInfo) {\n return () => {\n unstable_navigationEvents.emit('pageRemoved', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n };\n }\n return () => {};\n }, [routeInfo?.params, routeInfo?.pathname, routeInfo?.segments, screenId]);\n\n // Emit `pageFocused` from an effect — not during render — so it fires after the\n // focused screen's content has committed. `hasBlurredRef` deduplicates across both paths.\n useEffect(() => {\n if (isFocused && routeInfo && hasBlurredRef.current) {\n unstable_navigationEvents.emit('pageFocused', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = false;\n }\n }, [isFocused, routeInfo?.pathname, routeInfo?.params, routeInfo?.segments, screenId]);\n\n useEffect(() => {\n if (routeInfo) {\n const cleanFocus = navigation.addListener('focus', () => {\n // If the screen was not blurred, don't emit focused again\n // hasBlurredRef will be false when the screen was initially focused\n if (hasBlurredRef.current) {\n unstable_navigationEvents.emit('pageFocused', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = false;\n }\n });\n const cleanBlur = navigation.addListener('blur', () => {\n unstable_navigationEvents.emit('pageBlurred', {\n pathname: routeInfo.pathname,\n params: routeInfo.params,\n segments: routeInfo.segments,\n screenId,\n });\n hasBlurredRef.current = true;\n });\n return () => {\n cleanFocus();\n cleanBlur();\n };\n }\n return () => {};\n }, [navigation, routeInfo?.pathname, routeInfo?.params, routeInfo?.segments, screenId]);\n\n return null;\n}\n\nexport function screenOptionsFactory(\n route: RouteNode,\n options?: ScreenProps['options']\n): ScreenProps['options'] {\n return (args) => {\n // Only eager load generated components\n const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null;\n const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;\n const dynamicResult = typeof options === 'function' ? options?.(args) : options;\n const output = {\n ...staticResult,\n ...dynamicResult,\n };\n\n // Prevent generated screens from showing up in the tab bar.\n if (route.internal) {\n output.tabBarItemStyle = { display: 'none' };\n output.tabBarButton = () => null;\n // TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.\n output.drawerItemStyle = { height: 0, display: 'none' };\n }\n\n return output;\n };\n}\n\nexport function routeToScreen(\n route: RouteNode,\n { options, getId, ...props }: Partial = {}\n) {\n return (\n getQualifiedRouteComponent(route)}\n />\n );\n}\n\nexport function getSingularId(name: string, options: Record = {}) {\n return name\n .split('/')\n .map((segment) => {\n if (segment.startsWith('[...')) {\n return options.params?.[segment.slice(4, -1)]?.join('/') || segment;\n } else if (segment.startsWith('[') && segment.endsWith(']')) {\n return options.params?.[segment.slice(1, -1)] || segment;\n } else {\n return segment;\n }\n })\n .join('/');\n}\n"]} \ No newline at end of file diff --git a/packages/expo-router/src/Route.tsx b/packages/expo-router/src/Route.tsx index 590f4a820f0861..d04254c010c652 100644 --- a/packages/expo-router/src/Route.tsx +++ b/packages/expo-router/src/Route.tsx @@ -36,7 +36,7 @@ export type RouteNode = { /** The type of RouteNode */ type: 'route' | 'api' | 'layout' | 'redirect' | 'rewrite'; /** Load a route into memory. Returns the exports from a route. */ - loadRoute: () => Partial; + loadRoute: () => LoadedRoute; /** Loaded initial route name. */ initialRouteName?: string; /** Nested routes */ diff --git a/packages/expo-router/src/getRoutesCore.ts b/packages/expo-router/src/getRoutesCore.ts index e2ec5ba614263c..7857ea18b12ef3 100644 --- a/packages/expo-router/src/getRoutesCore.ts +++ b/packages/expo-router/src/getRoutesCore.ts @@ -368,6 +368,16 @@ function getDirectoryTree(contextModule: RequireContext, options: Options) { routeModule = contextModule(filePath); } + // See: expo/src/async-require/asyncRequireModule.ts + // The "lazy" async require function returns a thenable that may carry + // a raw `_result` value that's either a promise or the synchronously resolved module + if (importMode === 'lazy' || importMode === 'lazy-once') { + routeModule = + '_result' in routeModule && routeModule._result != null + ? routeModule._result + : routeModule; + } + if (process.env.NODE_ENV === 'development' && importMode === 'sync') { // In development mode, when async routes are disabled, add some extra error handling to improve the developer experience. // This can be useful when you accidentally use an async function in a route file for the default export. diff --git a/packages/expo-router/src/useScreens.tsx b/packages/expo-router/src/useScreens.tsx index f233c430bbf22d..66f2e5d6f1ab90 100644 --- a/packages/expo-router/src/useScreens.tsx +++ b/packages/expo-router/src/useScreens.tsx @@ -38,6 +38,12 @@ import { } from './views/SuspenseFallback'; import { Try } from './views/Try'; +declare module 'react' { + export function lazy>( + load: () => PromiseLike<{ default: T }> | Promise<{ default: T }> + ): React.LazyExoticComponent; +} + export type ScreenProps< TOptions extends Record = Record, TState extends NavigationState = NavigationState, @@ -237,15 +243,7 @@ function fromImport( } } - return { default: component.default, SuspenseFallback }; -} - -function fromLoadedRoute(value: RouteNode, res: LoadedRoute) { - if (!(res instanceof Promise)) { - return fromImport(value, res); - } - - return res.then(fromImport.bind(null, value)); + return { default: component.default!, SuspenseFallback }; } // TODO: Maybe there's a more React-y way to do this? @@ -258,26 +256,33 @@ export function getQualifiedRouteComponent(value: RouteNode) { return qualifiedStore.get(value)!; } - let ScreenComponent: - | React.ForwardRefExoticComponent> - | React.ComponentType<{ segment?: string }>; - + let ScreenComponent: React.ComponentType; let LayoutSuspenseFallback: React.ComponentType | undefined; // TODO: This ensures sync doesn't use React.lazy, but it's not ideal. if (EXPO_ROUTER_IMPORT_MODE === 'lazy') { - ScreenComponent = React.lazy(async () => { - const res = value.loadRoute(); - return fromLoadedRoute(value, res) as Promise<{ - default: React.ComponentType; - }>; + ScreenComponent = React.lazy>(() => { + const res = value.loadRoute() as LoadedRoute | PromiseLike; + // NOTE(@kitten): React.lazy supports promise likes, which we can use to ensure that + // the route is synchronously available, if the `loadRoute` method returns a loaded route + // synchronously + if (!('then' in res)) { + return { + then(resolve) { + const ret = fromImport(value, res); + return Promise.resolve(resolve ? resolve(ret) : ret); + }, + } as PromiseLike<{ default: React.ComponentType }>; + } else { + return res.then(fromImport.bind(null, value)); + } }); if (__DEV__) { ScreenComponent.displayName = `AsyncRoute(${value.route})`; } } else { - const res = value.loadRoute(); + const res = value.loadRoute() as LoadedRoute; const result = fromImport(value, res); ScreenComponent = result.default!; LayoutSuspenseFallback = value.type === 'layout' ? result.SuspenseFallback : undefined; diff --git a/packages/expo/CHANGELOG.md b/packages/expo/CHANGELOG.md index 5c1e9c7513b2fd..efd54aed647272 100644 --- a/packages/expo/CHANGELOG.md +++ b/packages/expo/CHANGELOG.md @@ -18,6 +18,7 @@ - Restore RCTHostRuntimeDelegate conformance for react-native-macos ([#46420](https://github.com/expo/expo/pull/46420) by [@gabrieldonadel](https://github.com/gabrieldonadel)) - Add explicit `react-native/Libraries/Core/InitializeCore` import to native runtime entrypoint ([#46344](https://github.com/expo/expo/pull/46344) by [@kitten](https://github.com/kitten)) +- [Internal] Return thenable with sync-bailout for async require calls ([#46539](https://github.com/expo/expo/pull/46539) by [@kitten](https://github.com/kitten)) ## 56.0.5 — 2026-05-26 diff --git a/packages/expo/src/async-require/__tests__/asyncRequireModule.test.ts b/packages/expo/src/async-require/__tests__/asyncRequireModule.test.ts index 6c313c06cf1405..4d333167776da3 100644 --- a/packages/expo/src/async-require/__tests__/asyncRequireModule.test.ts +++ b/packages/expo/src/async-require/__tests__/asyncRequireModule.test.ts @@ -63,18 +63,35 @@ describe('asyncRequireModule', () => { } function asyncRequireImpl(moduleID, paths, moduleName) { - var maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths); var importAll = function() { return require.importAll(moduleID, moduleName); }; - - if (maybeLoadBundlePromise != null) { - return maybeLoadBundlePromise.then(importAll); + try { + // Try importing first to skip bundle loading when the bundle is already preloaded. + return importAll(); + } catch (error) { + var maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths); + if (maybeLoadBundlePromise != null) { + return maybeLoadBundlePromise.then(importAll); + } + throw error; } - - return importAll(); } - async function asyncRequire(moduleID, paths, moduleName) { - return asyncRequireImpl(moduleID, paths, moduleName); + function asyncRequire(moduleID, paths, moduleName) { + var ret = asyncRequireImpl(moduleID, paths, moduleName); + if (!(ret instanceof Promise)) { + return { + _result: ret, + then: function(resolve, reject) { + return Promise.resolve(ret).then(resolve, reject); + }, + }; + } + return { + _result: ret, + then: function(resolve, reject) { + return ret.then(resolve, reject); + }, + }; } asyncRequire.unstable_importMaybeSync = function(moduleID, paths) { @@ -112,7 +129,13 @@ describe('asyncRequireModule', () => { expect(result).toEqual({ default: 'module-42' }); }); - it('passes moduleName through when bundle loading is required', async () => { + it('falls back to bundle load when importAll throws, then retries with moduleName', async () => { + mockImportAll + .mockImplementationOnce(() => { + throw new Error('Module not loaded'); + }) + .mockImplementationOnce(() => ({ default: 'module-42' })); + let resolveBundle!: () => void; const bundlePromise = new Promise((resolve) => { resolveBundle = resolve; @@ -123,17 +146,62 @@ describe('asyncRequireModule', () => { const paths = { '42': '/bundles/my-module.bundle' }; const resultPromise = asyncRequire(42, paths, 'my-module'); - // importAll should not have been called yet (waiting for bundle) - expect(mockImportAll).not.toHaveBeenCalled(); + // Initial importAll attempt happened; second is gated on the bundle promise. + expect(mockImportAll).toHaveBeenCalledTimes(1); + expect((globalThis as any).__loadBundleAsync).toHaveBeenCalledWith('/bundles/my-module.bundle'); - // Resolve the bundle loading resolveBundle(); const result = await resultPromise; + expect(mockImportAll).toHaveBeenCalledTimes(2); + expect(mockImportAll).toHaveBeenLastCalledWith(42, 'my-module'); + expect(result).toEqual({ default: 'module-42' }); + }); + + it('does not load the bundle when importAll succeeds (preloaded bundle case)', async () => { + (globalThis as any).__loadBundleAsync = jest.fn(() => Promise.resolve()); + + const paths = { '42': '/bundles/my-module.bundle' }; + const result = await asyncRequire(42, paths, 'my-module'); + expect(mockImportAll).toHaveBeenCalledWith(42, 'my-module'); + expect((globalThis as any).__loadBundleAsync).not.toHaveBeenCalled(); expect(result).toEqual({ default: 'module-42' }); }); + it('re-throws the import error when no bundle path is configured', () => { + mockImportAll.mockImplementationOnce(() => { + throw new Error('Module not loaded'); + }); + + expect(() => asyncRequire(42, null, 'my-module')).toThrow('Module not loaded'); + }); + + describe('thenable return value', () => { + it('exposes a synchronous _result when no bundle load was needed', () => { + const ret = asyncRequire(42, null, 'my-module'); + + expect(typeof ret.then).toBe('function'); + expect(ret._result).toEqual({ default: 'module-42' }); + }); + + it('exposes a Promise _result when a bundle load was needed', async () => { + mockImportAll + .mockImplementationOnce(() => { + throw new Error('Module not loaded'); + }) + .mockImplementationOnce(() => ({ default: 'module-42' })); + + (globalThis as any).__loadBundleAsync = jest.fn(() => Promise.resolve()); + + const ret = asyncRequire(42, { '42': '/bundles/my-module.bundle' }, 'my-module'); + + expect(typeof ret.then).toBe('function'); + expect(ret._result).toBeInstanceOf(Promise); + await expect(ret._result).resolves.toEqual({ default: 'module-42' }); + }); + }); + describe('unstable_importMaybeSync', () => { it('returns synchronously when no bundle loading needed', () => { const result = asyncRequire.unstable_importMaybeSync(42, null); diff --git a/packages/expo/src/async-require/asyncRequireModule.ts b/packages/expo/src/async-require/asyncRequireModule.ts index 78213d0ce8d459..1abb7170aac808 100644 --- a/packages/expo/src/async-require/asyncRequireModule.ts +++ b/packages/expo/src/async-require/asyncRequireModule.ts @@ -67,22 +67,43 @@ function asyncRequireImpl( paths: DependencyMapPaths, moduleName?: string ): Promise | T { - const maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths); const importAll = () => (require as unknown as MetroRequire).importAll(moduleID, moduleName); - - if (maybeLoadBundlePromise != null) { - return maybeLoadBundlePromise.then(importAll); + try { + // Try importing first to prevent double-loading script when the page already preloaded it + return importAll(); + } catch (error) { + const maybeLoadBundlePromise = maybeLoadBundle(moduleID, paths); + if (maybeLoadBundlePromise != null) { + return maybeLoadBundlePromise.then(importAll); + } + throw error; } - - return importAll(); } -async function asyncRequire( +function asyncRequire( moduleID: number, paths: DependencyMapPaths, moduleName?: string -): Promise { - return asyncRequireImpl(moduleID, paths, moduleName); +): PromiseLike & { _result?: T | Promise } { + const ret = asyncRequireImpl(moduleID, paths, moduleName); + if (!(ret instanceof Promise)) { + // We return a thenable with an added `unstable_importMaybeSync`-like + // `_result` property to bypass this being force-converted to a promise + // for rehydration + return { + _result: ret, + then(resolve, reject) { + return Promise.resolve(ret).then(resolve, reject); + }, + }; + } else { + return { + _result: ret, + then(resolve, reject) { + return ret.then(resolve, reject); + }, + }; + } } // Synchronous version of asyncRequire, which can still return a promise