@teardown/navigation 2.0.78 → 2.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teardown/navigation",
3
- "version": "2.0.78",
3
+ "version": "2.0.80",
4
4
  "description": "Type-safe file-based navigation for React Native",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "devDependencies": {
74
74
  "@biomejs/biome": "2.3.11",
75
- "@teardown/tsconfig": "2.0.78",
75
+ "@teardown/tsconfig": "2.0.80",
76
76
  "@types/react": "19.2.7",
77
77
  "typescript": "5.9.3"
78
78
  }
@@ -15,11 +15,16 @@ import { isHierarchicalRouteTree } from "./types";
15
15
  let createBottomTabNavigator: (() => ReturnType<typeof createNativeStackNavigator>) | null = null;
16
16
  let createDrawerNavigator: (() => ReturnType<typeof createNativeStackNavigator>) | null = null;
17
17
 
18
+ // Track which navigators are available
19
+ let bottomTabsAvailable = false;
20
+ let drawerAvailable = false;
21
+
18
22
  // Try to load optional dependencies
19
23
  try {
20
24
  // eslint-disable-next-line @typescript-eslint/no-require-imports
21
25
  const bottomTabs = require("@react-navigation/bottom-tabs");
22
26
  createBottomTabNavigator = bottomTabs.createBottomTabNavigator;
27
+ bottomTabsAvailable = true;
23
28
  } catch {
24
29
  // Bottom tabs not installed
25
30
  }
@@ -28,10 +33,57 @@ try {
28
33
  // eslint-disable-next-line @typescript-eslint/no-require-imports
29
34
  const drawer = require("@react-navigation/drawer");
30
35
  createDrawerNavigator = drawer.createDrawerNavigator;
36
+ drawerAvailable = true;
31
37
  } catch {
32
38
  // Drawer not installed
33
39
  }
34
40
 
41
+ /**
42
+ * Recursively checks a navigator node tree for required navigator types
43
+ */
44
+ function collectRequiredNavigatorTypes(node: NavigatorNode, types: Set<"tabs" | "drawer">): void {
45
+ if (node.type === "tabs") {
46
+ types.add("tabs");
47
+ } else if (node.type === "drawer") {
48
+ types.add("drawer");
49
+ }
50
+
51
+ // Check nested navigators
52
+ if (node.navigators) {
53
+ for (const nestedNode of Object.values(node.navigators)) {
54
+ collectRequiredNavigatorTypes(nestedNode, types);
55
+ }
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Validates that required navigator dependencies are installed and throws if not
61
+ */
62
+ function validateNavigatorDependencies(routeTree: NavigatorNode): void {
63
+ const requiredTypes = new Set<"tabs" | "drawer">();
64
+ collectRequiredNavigatorTypes(routeTree, requiredTypes);
65
+
66
+ const missingDeps: string[] = [];
67
+
68
+ if (requiredTypes.has("tabs") && !bottomTabsAvailable) {
69
+ missingDeps.push(
70
+ "Your route tree uses tabs navigation but @react-navigation/bottom-tabs is not installed.\n" +
71
+ " Install it with: npm install @react-navigation/bottom-tabs"
72
+ );
73
+ }
74
+
75
+ if (requiredTypes.has("drawer") && !drawerAvailable) {
76
+ missingDeps.push(
77
+ "Your route tree uses drawer navigation but @react-navigation/drawer is not installed.\n" +
78
+ " Install it with: npm install @react-navigation/drawer react-native-gesture-handler react-native-reanimated"
79
+ );
80
+ }
81
+
82
+ if (missingDeps.length > 0) {
83
+ throw new Error(`[@teardown/navigation] Missing required navigation dependencies:\n\n${missingDeps.join("\n\n")}`);
84
+ }
85
+ }
86
+
35
87
  /**
36
88
  * Options for creating a Teardown router
37
89
  */
@@ -76,18 +128,18 @@ function createNavigator(type: "stack" | "tabs" | "drawer") {
76
128
  switch (type) {
77
129
  case "tabs":
78
130
  if (!createBottomTabNavigator) {
79
- console.warn(
80
- "[@teardown/navigation] Tab navigator requested but @react-navigation/bottom-tabs is not installed. Falling back to stack."
131
+ throw new Error(
132
+ "[@teardown/navigation] Tab navigator requested but @react-navigation/bottom-tabs is not installed.\n" +
133
+ "Install it with: npm install @react-navigation/bottom-tabs"
81
134
  );
82
- return createNativeStackNavigator();
83
135
  }
84
136
  return createBottomTabNavigator();
85
137
  case "drawer":
86
138
  if (!createDrawerNavigator) {
87
- console.warn(
88
- "[@teardown/navigation] Drawer navigator requested but @react-navigation/drawer is not installed. Falling back to stack."
139
+ throw new Error(
140
+ "[@teardown/navigation] Drawer navigator requested but @react-navigation/drawer is not installed.\n" +
141
+ "Install it with: npm install @react-navigation/drawer react-native-gesture-handler react-native-reanimated"
89
142
  );
90
- return createNativeStackNavigator();
91
143
  }
92
144
  return createDrawerNavigator();
93
145
  default:
@@ -197,6 +249,9 @@ export function createTeardownRouter<T extends NavigatorNode | FlatRouteTree>(
197
249
 
198
250
  // Check if this is a hierarchical route tree
199
251
  if (isHierarchicalRouteTree(routeTree)) {
252
+ // Validate that required navigator dependencies are installed (warns early)
253
+ validateNavigatorDependencies(routeTree);
254
+
200
255
  // Set initial route name if provided
201
256
  const treeWithInitial: NavigatorNode = {
202
257
  ...routeTree,