@idealyst/mcp-server 1.0.99 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/data/components/Accordion.d.ts.map +1 -1
- package/dist/data/components/Accordion.js +10 -1
- package/dist/data/components/Accordion.js.map +1 -1
- package/dist/data/components/Card.d.ts.map +1 -1
- package/dist/data/components/Card.js +27 -20
- package/dist/data/components/Card.js.map +1 -1
- package/dist/data/components/Checkbox.d.ts.map +1 -1
- package/dist/data/components/Checkbox.js +4 -1
- package/dist/data/components/Checkbox.js.map +1 -1
- package/dist/data/components/Input.d.ts.map +1 -1
- package/dist/data/components/Input.js +4 -1
- package/dist/data/components/Input.js.map +1 -1
- package/dist/data/components/List.d.ts.map +1 -1
- package/dist/data/components/List.js +10 -1
- package/dist/data/components/List.js.map +1 -1
- package/dist/data/components/Pressable.d.ts.map +1 -1
- package/dist/data/components/Pressable.js +5 -1
- package/dist/data/components/Pressable.js.map +1 -1
- package/dist/data/components/RadioButton.d.ts.map +1 -1
- package/dist/data/components/RadioButton.js +4 -1
- package/dist/data/components/RadioButton.js.map +1 -1
- package/dist/data/components/Screen.d.ts.map +1 -1
- package/dist/data/components/Screen.js +12 -4
- package/dist/data/components/Screen.js.map +1 -1
- package/dist/data/components/Select.d.ts.map +1 -1
- package/dist/data/components/Select.js +5 -2
- package/dist/data/components/Select.js.map +1 -1
- package/dist/data/components/Slider.d.ts.map +1 -1
- package/dist/data/components/Slider.js +4 -1
- package/dist/data/components/Slider.js.map +1 -1
- package/dist/data/components/Switch.d.ts.map +1 -1
- package/dist/data/components/Switch.js +4 -1
- package/dist/data/components/Switch.js.map +1 -1
- package/dist/data/components/TabBar.d.ts.map +1 -1
- package/dist/data/components/TabBar.js +9 -1
- package/dist/data/components/TabBar.js.map +1 -1
- package/dist/data/components/Table.d.ts.map +1 -1
- package/dist/data/components/Table.js +9 -1
- package/dist/data/components/Table.js.map +1 -1
- package/dist/data/components/Text.d.ts.map +1 -1
- package/dist/data/components/Text.js +8 -1
- package/dist/data/components/Text.js.map +1 -1
- package/dist/data/components/TextArea.d.ts.map +1 -1
- package/dist/data/components/TextArea.js +4 -1
- package/dist/data/components/TextArea.js.map +1 -1
- package/dist/data/components/View.d.ts.map +1 -1
- package/dist/data/components/View.js +42 -39
- package/dist/data/components/View.js.map +1 -1
- package/dist/data/framework-guides.d.ts.map +1 -1
- package/dist/data/framework-guides.js +158 -0
- package/dist/data/framework-guides.js.map +1 -1
- package/dist/data/navigation-guides.d.ts.map +1 -1
- package/dist/data/navigation-guides.js +448 -12
- package/dist/data/navigation-guides.js.map +1 -1
- package/package.json +7 -6
|
@@ -245,6 +245,38 @@ Example:
|
|
|
245
245
|
}
|
|
246
246
|
\`\`\`
|
|
247
247
|
|
|
248
|
+
## Invalid Route Handling
|
|
249
|
+
|
|
250
|
+
Navigators can specify how to handle invalid routes:
|
|
251
|
+
|
|
252
|
+
\`\`\`tsx
|
|
253
|
+
import { NavigatorParam, NotFoundComponentProps } from '@idealyst/navigation';
|
|
254
|
+
|
|
255
|
+
const NotFoundPage = ({ path, params }: NotFoundComponentProps) => (
|
|
256
|
+
<View>
|
|
257
|
+
<Text>Page not found: {path}</Text>
|
|
258
|
+
</View>
|
|
259
|
+
);
|
|
260
|
+
|
|
261
|
+
const routes: NavigatorParam = {
|
|
262
|
+
path: "/",
|
|
263
|
+
type: 'navigator',
|
|
264
|
+
layout: 'stack',
|
|
265
|
+
// Component to show when route is invalid
|
|
266
|
+
notFoundComponent: NotFoundPage,
|
|
267
|
+
// Handler to redirect or show 404
|
|
268
|
+
onInvalidRoute: (path) => {
|
|
269
|
+
if (path.startsWith('/old-')) {
|
|
270
|
+
return { path: '/new-section', replace: true };
|
|
271
|
+
}
|
|
272
|
+
return undefined; // Show notFoundComponent
|
|
273
|
+
},
|
|
274
|
+
routes: [...]
|
|
275
|
+
};
|
|
276
|
+
\`\`\`
|
|
277
|
+
|
|
278
|
+
See the **Invalid Route Handling** guide for complete documentation.
|
|
279
|
+
|
|
248
280
|
## Nested Routes
|
|
249
281
|
|
|
250
282
|
Create hierarchical navigation:
|
|
@@ -843,14 +875,15 @@ Navigate to a route:
|
|
|
843
875
|
\`\`\`tsx
|
|
844
876
|
navigator.navigate({
|
|
845
877
|
path: string;
|
|
846
|
-
vars
|
|
878
|
+
vars?: Record<string, string>;
|
|
879
|
+
replace?: boolean; // Replace history entry instead of push
|
|
847
880
|
});
|
|
848
881
|
\`\`\`
|
|
849
882
|
|
|
850
883
|
Examples:
|
|
851
884
|
\`\`\`tsx
|
|
852
885
|
// Simple navigation
|
|
853
|
-
navigator.navigate({ path: '/home'
|
|
886
|
+
navigator.navigate({ path: '/home' });
|
|
854
887
|
|
|
855
888
|
// With path parameters
|
|
856
889
|
navigator.navigate({
|
|
@@ -863,8 +896,32 @@ navigator.navigate({
|
|
|
863
896
|
path: '/search',
|
|
864
897
|
vars: { q: 'react', category: 'tutorial' }
|
|
865
898
|
});
|
|
899
|
+
|
|
900
|
+
// Replace current history entry (no back navigation to current page)
|
|
901
|
+
navigator.navigate({
|
|
902
|
+
path: '/dashboard',
|
|
903
|
+
replace: true
|
|
904
|
+
});
|
|
905
|
+
\`\`\`
|
|
906
|
+
|
|
907
|
+
### Replace vs Push Navigation
|
|
908
|
+
|
|
909
|
+
By default, navigation pushes a new entry onto the history stack. Use \`replace: true\` when you want to replace the current entry instead:
|
|
910
|
+
|
|
911
|
+
\`\`\`tsx
|
|
912
|
+
// After login, replace login page in history
|
|
913
|
+
navigator.navigate({ path: '/dashboard', replace: true });
|
|
914
|
+
|
|
915
|
+
// Redirect without adding to history
|
|
916
|
+
navigator.navigate({ path: '/new-location', replace: true });
|
|
866
917
|
\`\`\`
|
|
867
918
|
|
|
919
|
+
**Use cases for replace:**
|
|
920
|
+
- Post-login redirects (user shouldn't go back to login)
|
|
921
|
+
- After form submission redirects
|
|
922
|
+
- URL canonicalization/normalization
|
|
923
|
+
- Redirect from deprecated routes
|
|
924
|
+
|
|
868
925
|
### navigator.vars
|
|
869
926
|
|
|
870
927
|
Access current route variables:
|
|
@@ -886,9 +943,25 @@ const path = navigator.currentPath;
|
|
|
886
943
|
console.log(path); // "/user/123"
|
|
887
944
|
\`\`\`
|
|
888
945
|
|
|
946
|
+
### navigator.canGoBack()
|
|
947
|
+
|
|
948
|
+
Check if back navigation is available:
|
|
949
|
+
|
|
950
|
+
\`\`\`tsx
|
|
951
|
+
const navigator = useNavigator();
|
|
952
|
+
|
|
953
|
+
if (navigator.canGoBack()) {
|
|
954
|
+
// Show back button
|
|
955
|
+
}
|
|
956
|
+
\`\`\`
|
|
957
|
+
|
|
958
|
+
**Platform behavior:**
|
|
959
|
+
- **Web**: Returns \`true\` if there's a valid parent route in the route hierarchy (e.g., \`/users/123\` can go back to \`/users\`)
|
|
960
|
+
- **Native**: Uses React Navigation's \`canGoBack()\` to check navigation stack
|
|
961
|
+
|
|
889
962
|
### navigator.goBack()
|
|
890
963
|
|
|
891
|
-
Navigate
|
|
964
|
+
Navigate back in the route hierarchy:
|
|
892
965
|
|
|
893
966
|
\`\`\`tsx
|
|
894
967
|
<Button onPress={() => navigator.goBack()}>
|
|
@@ -896,7 +969,11 @@ Navigate to previous screen (mobile only):
|
|
|
896
969
|
</Button>
|
|
897
970
|
\`\`\`
|
|
898
971
|
|
|
899
|
-
**
|
|
972
|
+
**Platform behavior:**
|
|
973
|
+
- **Web**: Navigates to the parent route (e.g., \`/users/123/edit\` → \`/users/123\` → \`/users\` → \`/\`). Does NOT use browser history - navigates up the route tree.
|
|
974
|
+
- **Native**: Uses React Navigation's \`goBack()\` to pop the navigation stack
|
|
975
|
+
|
|
976
|
+
**Important**: On web, this is NOT browser history back. It navigates to the parent path in the route hierarchy. Use this for "up" navigation within your app structure.
|
|
900
977
|
|
|
901
978
|
## Path Parameters
|
|
902
979
|
|
|
@@ -1122,15 +1199,17 @@ navigator.navigate({
|
|
|
1122
1199
|
## Platform Differences
|
|
1123
1200
|
|
|
1124
1201
|
### React Native
|
|
1202
|
+
- \`canGoBack()\` checks React Navigation stack
|
|
1125
1203
|
- \`goBack()\` uses native navigation stack
|
|
1126
1204
|
- Hardware back button supported
|
|
1127
1205
|
- Gesture-based navigation
|
|
1128
1206
|
|
|
1129
1207
|
### Web
|
|
1130
|
-
-
|
|
1208
|
+
- \`canGoBack()\` checks for valid parent route in hierarchy
|
|
1209
|
+
- \`goBack()\` navigates to parent route (NOT browser history)
|
|
1210
|
+
- Browser back/forward buttons still work for browser history
|
|
1131
1211
|
- URL updates automatically
|
|
1132
1212
|
- Bookmarkable URLs
|
|
1133
|
-
- \`goBack()\` uses browser history
|
|
1134
1213
|
|
|
1135
1214
|
## Best Practices
|
|
1136
1215
|
|
|
@@ -1148,12 +1227,17 @@ navigator.navigate({
|
|
|
1148
1227
|
### Back Navigation
|
|
1149
1228
|
|
|
1150
1229
|
\`\`\`tsx
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1230
|
+
// Conditionally show back button
|
|
1231
|
+
const { canGoBack, goBack } = useNavigator();
|
|
1232
|
+
|
|
1233
|
+
{canGoBack() && (
|
|
1234
|
+
<Button
|
|
1235
|
+
icon="arrow-left"
|
|
1236
|
+
onPress={goBack}
|
|
1237
|
+
>
|
|
1238
|
+
Back
|
|
1239
|
+
</Button>
|
|
1240
|
+
)}
|
|
1157
1241
|
\`\`\`
|
|
1158
1242
|
|
|
1159
1243
|
### Tab Navigation
|
|
@@ -1191,6 +1275,358 @@ const tabs = ['feed', 'search', 'profile'];
|
|
|
1191
1275
|
Close
|
|
1192
1276
|
</Button>
|
|
1193
1277
|
\`\`\`
|
|
1278
|
+
`,
|
|
1279
|
+
"idealyst://navigation/invalid-route-handling": `# Invalid Route Handling
|
|
1280
|
+
|
|
1281
|
+
Handle 404 pages and invalid routes with customizable redirect logic and fallback components.
|
|
1282
|
+
|
|
1283
|
+
## Overview
|
|
1284
|
+
|
|
1285
|
+
The navigation system provides two mechanisms for handling invalid routes:
|
|
1286
|
+
|
|
1287
|
+
1. **\`onInvalidRoute\`** - A handler function that can redirect to a different route
|
|
1288
|
+
2. **\`notFoundComponent\`** - A fallback component to render when no redirect is specified
|
|
1289
|
+
|
|
1290
|
+
These can be configured at each navigator level and support bubbling up to parent navigators.
|
|
1291
|
+
|
|
1292
|
+
## Basic Setup
|
|
1293
|
+
|
|
1294
|
+
### Adding a 404 Page
|
|
1295
|
+
|
|
1296
|
+
\`\`\`tsx
|
|
1297
|
+
import { NavigatorParam, NotFoundComponentProps } from '@idealyst/navigation';
|
|
1298
|
+
|
|
1299
|
+
// 404 Component receives path and params
|
|
1300
|
+
const NotFoundPage = ({ path, params }: NotFoundComponentProps) => (
|
|
1301
|
+
<Screen>
|
|
1302
|
+
<View style={{ alignItems: 'center', padding: 24 }}>
|
|
1303
|
+
<Icon name="alert-circle" size={64} color="red" />
|
|
1304
|
+
<Text size="xl">Page Not Found</Text>
|
|
1305
|
+
<Text color="secondary">The path "{path}" doesn't exist.</Text>
|
|
1306
|
+
{params && Object.keys(params).length > 0 && (
|
|
1307
|
+
<Text size="sm">Params: {JSON.stringify(params)}</Text>
|
|
1308
|
+
)}
|
|
1309
|
+
</View>
|
|
1310
|
+
</Screen>
|
|
1311
|
+
);
|
|
1312
|
+
|
|
1313
|
+
const routes: NavigatorParam = {
|
|
1314
|
+
path: "/",
|
|
1315
|
+
type: 'navigator',
|
|
1316
|
+
layout: 'stack',
|
|
1317
|
+
notFoundComponent: NotFoundPage,
|
|
1318
|
+
routes: [
|
|
1319
|
+
{ path: "", type: 'screen', component: HomeScreen },
|
|
1320
|
+
{ path: "about", type: 'screen', component: AboutScreen },
|
|
1321
|
+
]
|
|
1322
|
+
};
|
|
1323
|
+
\`\`\`
|
|
1324
|
+
|
|
1325
|
+
## NotFoundComponentProps
|
|
1326
|
+
|
|
1327
|
+
The 404 component receives information about the attempted route:
|
|
1328
|
+
|
|
1329
|
+
\`\`\`tsx
|
|
1330
|
+
type NotFoundComponentProps = {
|
|
1331
|
+
/** The full path that was attempted */
|
|
1332
|
+
path: string;
|
|
1333
|
+
/** Any route parameters that were parsed from the path */
|
|
1334
|
+
params?: Record<string, string>;
|
|
1335
|
+
};
|
|
1336
|
+
\`\`\`
|
|
1337
|
+
|
|
1338
|
+
Example usage:
|
|
1339
|
+
\`\`\`tsx
|
|
1340
|
+
const NotFoundPage = ({ path, params }: NotFoundComponentProps) => {
|
|
1341
|
+
const { navigate } = useNavigator();
|
|
1342
|
+
|
|
1343
|
+
return (
|
|
1344
|
+
<Screen>
|
|
1345
|
+
<View style={{ padding: 16, gap: 24 }}>
|
|
1346
|
+
<Text size="xl">404 - Page Not Found</Text>
|
|
1347
|
+
<Text>Attempted: {path}</Text>
|
|
1348
|
+
{params?.id && <Text>User ID: {params.id}</Text>}
|
|
1349
|
+
<Button onPress={() => navigate({ path: '/', replace: true })}>
|
|
1350
|
+
Go Home
|
|
1351
|
+
</Button>
|
|
1352
|
+
</View>
|
|
1353
|
+
</Screen>
|
|
1354
|
+
);
|
|
1355
|
+
};
|
|
1356
|
+
\`\`\`
|
|
1357
|
+
|
|
1358
|
+
## Redirect Handler
|
|
1359
|
+
|
|
1360
|
+
Use \`onInvalidRoute\` to redirect certain invalid paths:
|
|
1361
|
+
|
|
1362
|
+
\`\`\`tsx
|
|
1363
|
+
const routes: NavigatorParam = {
|
|
1364
|
+
path: "/",
|
|
1365
|
+
type: 'navigator',
|
|
1366
|
+
layout: 'stack',
|
|
1367
|
+
notFoundComponent: NotFoundPage,
|
|
1368
|
+
onInvalidRoute: (invalidPath) => {
|
|
1369
|
+
// Redirect old URLs to new locations
|
|
1370
|
+
if (invalidPath.startsWith('/old-blog')) {
|
|
1371
|
+
return { path: '/blog', replace: true };
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
// Redirect legacy paths
|
|
1375
|
+
if (invalidPath === '/legacy-dashboard') {
|
|
1376
|
+
return { path: '/dashboard', replace: true };
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
// Return undefined to show notFoundComponent
|
|
1380
|
+
return undefined;
|
|
1381
|
+
},
|
|
1382
|
+
routes: [...]
|
|
1383
|
+
};
|
|
1384
|
+
\`\`\`
|
|
1385
|
+
|
|
1386
|
+
### Handler Return Values
|
|
1387
|
+
|
|
1388
|
+
The \`onInvalidRoute\` handler can return:
|
|
1389
|
+
|
|
1390
|
+
- **\`NavigateParams\`** - Redirect to a different route
|
|
1391
|
+
- **\`undefined\`** - Show the \`notFoundComponent\` (or bubble up)
|
|
1392
|
+
|
|
1393
|
+
\`\`\`tsx
|
|
1394
|
+
type NavigateParams = {
|
|
1395
|
+
path: string;
|
|
1396
|
+
vars?: Record<string, string>;
|
|
1397
|
+
replace?: boolean; // Recommended: true for redirects
|
|
1398
|
+
};
|
|
1399
|
+
|
|
1400
|
+
onInvalidRoute: (path: string) => NavigateParams | undefined
|
|
1401
|
+
\`\`\`
|
|
1402
|
+
|
|
1403
|
+
## Scoped Handlers (Nested Navigators)
|
|
1404
|
+
|
|
1405
|
+
Each navigator can have its own 404 handling:
|
|
1406
|
+
|
|
1407
|
+
\`\`\`tsx
|
|
1408
|
+
// Settings-specific 404 page
|
|
1409
|
+
const SettingsNotFound = ({ path }: NotFoundComponentProps) => (
|
|
1410
|
+
<Screen>
|
|
1411
|
+
<View style={{ alignItems: 'center' }}>
|
|
1412
|
+
<Icon name="cog-off" size={48} color="orange" />
|
|
1413
|
+
<Text>Settings page not found: {path}</Text>
|
|
1414
|
+
</View>
|
|
1415
|
+
</Screen>
|
|
1416
|
+
);
|
|
1417
|
+
|
|
1418
|
+
// Nested settings navigator with its own handler
|
|
1419
|
+
const SettingsNavigator: NavigatorParam = {
|
|
1420
|
+
path: "settings",
|
|
1421
|
+
type: 'navigator',
|
|
1422
|
+
layout: 'stack',
|
|
1423
|
+
notFoundComponent: SettingsNotFound,
|
|
1424
|
+
onInvalidRoute: (path) => {
|
|
1425
|
+
// Redirect deprecated settings paths
|
|
1426
|
+
if (path.includes('legacy-setting')) {
|
|
1427
|
+
return { path: '/settings/general', replace: true };
|
|
1428
|
+
}
|
|
1429
|
+
return undefined; // Show SettingsNotFound
|
|
1430
|
+
},
|
|
1431
|
+
routes: [
|
|
1432
|
+
{ path: "", type: 'screen', component: SettingsHome },
|
|
1433
|
+
{ path: "general", type: 'screen', component: GeneralSettings },
|
|
1434
|
+
{ path: "account", type: 'screen', component: AccountSettings },
|
|
1435
|
+
]
|
|
1436
|
+
};
|
|
1437
|
+
|
|
1438
|
+
// Root navigator with global 404
|
|
1439
|
+
const AppRouter: NavigatorParam = {
|
|
1440
|
+
path: "/",
|
|
1441
|
+
type: 'navigator',
|
|
1442
|
+
layout: 'stack',
|
|
1443
|
+
notFoundComponent: GlobalNotFound, // Fallback for non-settings routes
|
|
1444
|
+
routes: [
|
|
1445
|
+
{ path: "", type: 'screen', component: HomeScreen },
|
|
1446
|
+
SettingsNavigator, // Has its own 404 handling
|
|
1447
|
+
{ path: "about", type: 'screen', component: AboutScreen },
|
|
1448
|
+
]
|
|
1449
|
+
};
|
|
1450
|
+
\`\`\`
|
|
1451
|
+
|
|
1452
|
+
## Handler Bubbling
|
|
1453
|
+
|
|
1454
|
+
Invalid routes bubble up through the navigator hierarchy:
|
|
1455
|
+
|
|
1456
|
+
\`\`\`
|
|
1457
|
+
Invalid route detected: /settings/invalid-page
|
|
1458
|
+
↓
|
|
1459
|
+
Check /settings navigator's onInvalidRoute
|
|
1460
|
+
↓
|
|
1461
|
+
┌─────────────────────────────────────────┐
|
|
1462
|
+
│ Returns NavigateParams? │
|
|
1463
|
+
│ YES → Redirect to that route │
|
|
1464
|
+
│ NO (undefined) → Check notFoundComponent │
|
|
1465
|
+
└─────────────────────────────────────────┘
|
|
1466
|
+
↓
|
|
1467
|
+
Has notFoundComponent?
|
|
1468
|
+
YES → Render it with { path, params }
|
|
1469
|
+
NO → Bubble up to parent navigator
|
|
1470
|
+
↓
|
|
1471
|
+
No parent handles it?
|
|
1472
|
+
→ console.warn("No handler for invalid route")
|
|
1473
|
+
\`\`\`
|
|
1474
|
+
|
|
1475
|
+
## Platform Behavior
|
|
1476
|
+
|
|
1477
|
+
### Web
|
|
1478
|
+
|
|
1479
|
+
- Invalid routes trigger the catch-all route at each navigator level
|
|
1480
|
+
- The \`onInvalidRoute\` handler is called when the 404 route is rendered
|
|
1481
|
+
- If handler returns \`NavigateParams\`, navigation uses \`replace: true\` by default
|
|
1482
|
+
- URL stays at the invalid path when showing \`notFoundComponent\`
|
|
1483
|
+
|
|
1484
|
+
### Mobile (React Native)
|
|
1485
|
+
|
|
1486
|
+
- Invalid routes trigger navigation to a hidden 404 screen
|
|
1487
|
+
- The handler is called during the \`navigate()\` function
|
|
1488
|
+
- If handler returns \`NavigateParams\`, redirects to that route
|
|
1489
|
+
- If no handler/component, logs a warning
|
|
1490
|
+
|
|
1491
|
+
## Complete Example
|
|
1492
|
+
|
|
1493
|
+
\`\`\`tsx
|
|
1494
|
+
import { NavigatorParam, NotFoundComponentProps } from '@idealyst/navigation';
|
|
1495
|
+
import { Screen, View, Text, Button, Icon, Card } from '@idealyst/components';
|
|
1496
|
+
|
|
1497
|
+
// Global 404 - detailed error page
|
|
1498
|
+
const GlobalNotFound = ({ path, params }: NotFoundComponentProps) => {
|
|
1499
|
+
const { navigate } = useNavigator();
|
|
1500
|
+
|
|
1501
|
+
return (
|
|
1502
|
+
<Screen>
|
|
1503
|
+
<View style={{ padding: 24, gap: 24, alignItems: 'center', flex: 1, justifyContent: 'center' }}>
|
|
1504
|
+
<Icon name="alert-circle-outline" size={64} color="red" />
|
|
1505
|
+
<Text size="xl" weight="bold">Page Not Found</Text>
|
|
1506
|
+
<Text color="secondary">The page you're looking for doesn't exist.</Text>
|
|
1507
|
+
|
|
1508
|
+
<Card style={{ marginTop: 16, padding: 16 }}>
|
|
1509
|
+
<Text size="sm" weight="semibold">Attempted path:</Text>
|
|
1510
|
+
<Text size="sm" color="secondary">{path}</Text>
|
|
1511
|
+
{params && Object.keys(params).length > 0 && (
|
|
1512
|
+
<>
|
|
1513
|
+
<Text size="sm" weight="semibold" style={{ marginTop: 8 }}>Params:</Text>
|
|
1514
|
+
<Text size="sm" color="secondary">{JSON.stringify(params)}</Text>
|
|
1515
|
+
</>
|
|
1516
|
+
)}
|
|
1517
|
+
</Card>
|
|
1518
|
+
|
|
1519
|
+
<Button style={{ marginTop: 24 }} onPress={() => navigate({ path: '/', replace: true })}>
|
|
1520
|
+
Go Home
|
|
1521
|
+
</Button>
|
|
1522
|
+
</View>
|
|
1523
|
+
</Screen>
|
|
1524
|
+
);
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
// Admin section 404 - simpler style
|
|
1528
|
+
const AdminNotFound = ({ path }: NotFoundComponentProps) => {
|
|
1529
|
+
const { navigate } = useNavigator();
|
|
1530
|
+
|
|
1531
|
+
return (
|
|
1532
|
+
<Screen>
|
|
1533
|
+
<View padding={16} style={{ alignItems: 'center' }}>
|
|
1534
|
+
<Icon name="shield-off" size={48} color="orange" />
|
|
1535
|
+
<Text size="lg">Admin page not found</Text>
|
|
1536
|
+
<Button
|
|
1537
|
+
type="outlined"
|
|
1538
|
+
size="sm"
|
|
1539
|
+
onPress={() => navigate({ path: '/admin', replace: true })}
|
|
1540
|
+
>
|
|
1541
|
+
Back to Admin
|
|
1542
|
+
</Button>
|
|
1543
|
+
</View>
|
|
1544
|
+
</Screen>
|
|
1545
|
+
);
|
|
1546
|
+
};
|
|
1547
|
+
|
|
1548
|
+
// Admin navigator with redirect logic
|
|
1549
|
+
const AdminNavigator: NavigatorParam = {
|
|
1550
|
+
path: "admin",
|
|
1551
|
+
type: 'navigator',
|
|
1552
|
+
layout: 'stack',
|
|
1553
|
+
notFoundComponent: AdminNotFound,
|
|
1554
|
+
onInvalidRoute: (path) => {
|
|
1555
|
+
// Redirect old admin paths
|
|
1556
|
+
if (path.includes('old-users')) {
|
|
1557
|
+
return { path: '/admin/users', replace: true };
|
|
1558
|
+
}
|
|
1559
|
+
if (path.includes('deprecated')) {
|
|
1560
|
+
return { path: '/admin', replace: true };
|
|
1561
|
+
}
|
|
1562
|
+
return undefined; // Show AdminNotFound
|
|
1563
|
+
},
|
|
1564
|
+
routes: [
|
|
1565
|
+
{ path: "", type: 'screen', component: AdminDashboard },
|
|
1566
|
+
{ path: "users", type: 'screen', component: AdminUsers },
|
|
1567
|
+
{ path: "settings", type: 'screen', component: AdminSettings },
|
|
1568
|
+
]
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
// Root app router
|
|
1572
|
+
const AppRouter: NavigatorParam = {
|
|
1573
|
+
path: "/",
|
|
1574
|
+
type: 'navigator',
|
|
1575
|
+
layout: 'drawer',
|
|
1576
|
+
notFoundComponent: GlobalNotFound,
|
|
1577
|
+
onInvalidRoute: (path) => {
|
|
1578
|
+
// Global redirects
|
|
1579
|
+
if (path === '/home') {
|
|
1580
|
+
return { path: '/', replace: true };
|
|
1581
|
+
}
|
|
1582
|
+
return undefined;
|
|
1583
|
+
},
|
|
1584
|
+
routes: [
|
|
1585
|
+
{ path: "", type: 'screen', component: HomeScreen },
|
|
1586
|
+
AdminNavigator,
|
|
1587
|
+
{ path: "about", type: 'screen', component: AboutScreen },
|
|
1588
|
+
{ path: "contact", type: 'screen', component: ContactScreen },
|
|
1589
|
+
]
|
|
1590
|
+
};
|
|
1591
|
+
|
|
1592
|
+
export default AppRouter;
|
|
1593
|
+
\`\`\`
|
|
1594
|
+
|
|
1595
|
+
## Best Practices
|
|
1596
|
+
|
|
1597
|
+
1. **Always provide a root notFoundComponent** - Ensures all invalid routes are handled
|
|
1598
|
+
2. **Use scoped handlers for sections** - Different 404 styles for different app areas
|
|
1599
|
+
3. **Redirect deprecated URLs** - Use \`onInvalidRoute\` to maintain URL compatibility
|
|
1600
|
+
4. **Include helpful information** - Show the attempted path and suggest alternatives
|
|
1601
|
+
5. **Provide navigation options** - Add buttons to go home or back
|
|
1602
|
+
6. **Use \`replace: true\` for redirects** - Prevents invalid routes in browser history
|
|
1603
|
+
7. **Log unhandled routes** - Monitor for missing pages in production
|
|
1604
|
+
|
|
1605
|
+
## TypeScript Types
|
|
1606
|
+
|
|
1607
|
+
\`\`\`tsx
|
|
1608
|
+
import {
|
|
1609
|
+
NavigatorParam,
|
|
1610
|
+
NotFoundComponentProps,
|
|
1611
|
+
NavigateParams
|
|
1612
|
+
} from '@idealyst/navigation';
|
|
1613
|
+
|
|
1614
|
+
// NotFoundComponentProps
|
|
1615
|
+
type NotFoundComponentProps = {
|
|
1616
|
+
path: string;
|
|
1617
|
+
params?: Record<string, string>;
|
|
1618
|
+
};
|
|
1619
|
+
|
|
1620
|
+
// Handler signature
|
|
1621
|
+
type InvalidRouteHandler = (invalidPath: string) => NavigateParams | undefined;
|
|
1622
|
+
|
|
1623
|
+
// NavigateParams (used by handler return and navigate function)
|
|
1624
|
+
type NavigateParams = {
|
|
1625
|
+
path: string;
|
|
1626
|
+
vars?: Record<string, string>;
|
|
1627
|
+
replace?: boolean;
|
|
1628
|
+
};
|
|
1629
|
+
\`\`\`
|
|
1194
1630
|
`,
|
|
1195
1631
|
};
|
|
1196
1632
|
//# sourceMappingURL=navigation-guides.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigation-guides.js","sourceRoot":"","sources":["../../src/data/navigation-guides.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,gCAAgC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4FnC;IAEC,2CAA2C,EAAE
|
|
1
|
+
{"version":3,"file":"navigation-guides.js","sourceRoot":"","sources":["../../src/data/navigation-guides.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAA2B;IACtD,gCAAgC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4FnC;IAEC,2CAA2C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsO9C;IAEC,uCAAuC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuN1C;IAEC,sCAAsC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkTzC;IAEC,qCAAqC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6axC;IAEC,8CAA8C,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+VjD;CACA,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@idealyst/mcp-server",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "MCP server providing documentation and examples for the Idealyst framework",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"start": "node dist/index.js"
|
|
23
23
|
},
|
|
24
24
|
"publishConfig": {
|
|
25
|
-
"access": "public"
|
|
25
|
+
"access": "public",
|
|
26
|
+
"registry": "https://registry.npmjs.org"
|
|
26
27
|
},
|
|
27
28
|
"keywords": [
|
|
28
29
|
"idealyst",
|
|
@@ -34,9 +35,9 @@
|
|
|
34
35
|
"author": "Idealyst",
|
|
35
36
|
"license": "MIT",
|
|
36
37
|
"dependencies": {
|
|
37
|
-
"@idealyst/components": "^1.0
|
|
38
|
-
"@idealyst/navigation": "^1.0
|
|
39
|
-
"@idealyst/theme": "^1.0
|
|
38
|
+
"@idealyst/components": "^1.1.0",
|
|
39
|
+
"@idealyst/navigation": "^1.1.0",
|
|
40
|
+
"@idealyst/theme": "^1.1.0",
|
|
40
41
|
"@modelcontextprotocol/sdk": "^1.0.4"
|
|
41
42
|
},
|
|
42
43
|
"devDependencies": {
|
|
@@ -49,4 +50,4 @@
|
|
|
49
50
|
"tsx": "^4.7.0",
|
|
50
51
|
"typescript": "^5.0.0"
|
|
51
52
|
}
|
|
52
|
-
}
|
|
53
|
+
}
|