one 1.16.8 → 1.16.9
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/cjs/Root.cjs +7 -6
- package/dist/cjs/Root.native.js +7 -6
- package/dist/cjs/Root.native.js.map +1 -1
- package/dist/cjs/babel-plugins/one-router-metro.cjs +5 -0
- package/dist/cjs/babel-plugins/one-router-metro.native.js +6 -0
- package/dist/cjs/babel-plugins/one-router-metro.native.js.map +1 -1
- package/dist/cjs/babel-plugins/one-router-metro.test.cjs +20 -0
- package/dist/cjs/babel-plugins/one-router-metro.test.native.js +20 -0
- package/dist/cjs/babel-plugins/one-router-metro.test.native.js.map +1 -1
- package/dist/cjs/cli/build.cjs +16 -1
- package/dist/cjs/cli/build.native.js +16 -1
- package/dist/cjs/cli/build.native.js.map +1 -1
- package/dist/cjs/cli/dev.cjs +12 -2
- package/dist/cjs/cli/dev.native.js +12 -2
- package/dist/cjs/cli/dev.native.js.map +1 -1
- package/dist/cjs/cli/install-error-handlers.cjs +132 -0
- package/dist/cjs/cli/install-error-handlers.native.js +144 -0
- package/dist/cjs/cli/install-error-handlers.native.js.map +1 -0
- package/dist/cjs/createApp.cjs +3 -0
- package/dist/cjs/createApp.native.js +1 -0
- package/dist/cjs/createApp.native.js.map +1 -1
- package/dist/cjs/fork/extractPathFromURL.cjs +19 -0
- package/dist/cjs/fork/extractPathFromURL.native.js +25 -0
- package/dist/cjs/fork/extractPathFromURL.native.js.map +1 -1
- package/dist/cjs/fork/extractPathFromURL.test.cjs +37 -0
- package/dist/cjs/fork/extractPathFromURL.test.native.js +40 -0
- package/dist/cjs/fork/extractPathFromURL.test.native.js.map +1 -0
- package/dist/cjs/headless.cjs +1 -0
- package/dist/cjs/headless.native.js +1 -0
- package/dist/cjs/headless.native.js.map +1 -1
- package/dist/cjs/index.cjs +4 -0
- package/dist/cjs/index.native.js +4 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/link/getLinking.cjs +48 -0
- package/dist/cjs/link/getLinking.native.js +54 -0
- package/dist/cjs/link/getLinking.native.js.map +1 -0
- package/dist/cjs/link/linking.cjs +4 -0
- package/dist/cjs/link/linking.native.js +9 -0
- package/dist/cjs/link/linking.native.js.map +1 -1
- package/dist/cjs/metro-config/getViteMetroPluginOptions.cjs +2 -0
- package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js +2 -0
- package/dist/cjs/metro-config/getViteMetroPluginOptions.native.js.map +1 -1
- package/dist/cjs/router/Route.cjs +1 -1
- package/dist/cjs/router/Route.native.js +1 -1
- package/dist/cjs/router/Route.native.js.map +1 -1
- package/dist/cjs/router/getLinkingConfig.cjs +13 -2
- package/dist/cjs/router/getLinkingConfig.native.js +14 -2
- package/dist/cjs/router/getLinkingConfig.native.js.map +1 -1
- package/dist/cjs/router/getLinkingConfig.test.cjs +41 -0
- package/dist/cjs/router/getLinkingConfig.test.native.js +44 -0
- package/dist/cjs/router/getLinkingConfig.test.native.js.map +1 -0
- package/dist/cjs/router/getRouteInfo.cjs +1 -1
- package/dist/cjs/router/getRouteInfo.native.js +2 -2
- package/dist/cjs/router/getRouteInfo.native.js.map +1 -1
- package/dist/cjs/router/linkingConfig.cjs +34 -9
- package/dist/cjs/router/linkingConfig.native.js +35 -9
- package/dist/cjs/router/linkingConfig.native.js.map +1 -1
- package/dist/cjs/router/router.cjs +6 -6
- package/dist/cjs/router/router.native.js +6 -6
- package/dist/cjs/router/router.native.js.map +1 -1
- package/dist/cjs/router/sitemap.cjs +65 -0
- package/dist/cjs/router/sitemap.native.js +75 -0
- package/dist/cjs/router/sitemap.native.js.map +1 -0
- package/dist/cjs/router/sitemap.test.cjs +34 -0
- package/dist/cjs/router/sitemap.test.native.js +37 -0
- package/dist/cjs/router/sitemap.test.native.js.map +1 -0
- package/dist/cjs/router/useInitializeOneRouter.cjs +5 -5
- package/dist/cjs/router/useInitializeOneRouter.native.js +5 -5
- package/dist/cjs/router/useInitializeOneRouter.native.js.map +1 -1
- package/dist/cjs/serve.cjs +14 -1
- package/dist/cjs/serve.native.js +14 -1
- package/dist/cjs/serve.native.js.map +1 -1
- package/dist/cjs/views/Navigator.cjs +1 -1
- package/dist/cjs/views/Navigator.native.js +1 -1
- package/dist/cjs/views/Navigator.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +2 -0
- package/dist/cjs/vite/one.native.js +4 -2
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +4 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +6 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.cjs +13 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js +13 -0
- package/dist/cjs/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
- package/dist/esm/Root.mjs +8 -7
- package/dist/esm/Root.mjs.map +1 -1
- package/dist/esm/Root.native.js +8 -7
- package/dist/esm/Root.native.js.map +1 -1
- package/dist/esm/babel-plugins/one-router-metro.mjs +5 -0
- package/dist/esm/babel-plugins/one-router-metro.mjs.map +1 -1
- package/dist/esm/babel-plugins/one-router-metro.native.js +6 -0
- package/dist/esm/babel-plugins/one-router-metro.native.js.map +1 -1
- package/dist/esm/babel-plugins/one-router-metro.test.mjs +20 -0
- package/dist/esm/babel-plugins/one-router-metro.test.mjs.map +1 -1
- package/dist/esm/babel-plugins/one-router-metro.test.native.js +20 -0
- package/dist/esm/babel-plugins/one-router-metro.test.native.js.map +1 -1
- package/dist/esm/cli/build.mjs +16 -1
- package/dist/esm/cli/build.mjs.map +1 -1
- package/dist/esm/cli/build.native.js +16 -1
- package/dist/esm/cli/build.native.js.map +1 -1
- package/dist/esm/cli/dev.mjs +12 -2
- package/dist/esm/cli/dev.mjs.map +1 -1
- package/dist/esm/cli/dev.native.js +12 -2
- package/dist/esm/cli/dev.native.js.map +1 -1
- package/dist/esm/cli/install-error-handlers.mjs +105 -0
- package/dist/esm/cli/install-error-handlers.mjs.map +1 -0
- package/dist/esm/cli/install-error-handlers.native.js +114 -0
- package/dist/esm/cli/install-error-handlers.native.js.map +1 -0
- package/dist/esm/createApp.mjs +3 -0
- package/dist/esm/createApp.mjs.map +1 -1
- package/dist/esm/createApp.native.js +1 -0
- package/dist/esm/createApp.native.js.map +1 -1
- package/dist/esm/fork/extractPathFromURL.mjs +19 -0
- package/dist/esm/fork/extractPathFromURL.mjs.map +1 -1
- package/dist/esm/fork/extractPathFromURL.native.js +25 -0
- package/dist/esm/fork/extractPathFromURL.native.js.map +1 -1
- package/dist/esm/fork/extractPathFromURL.test.mjs +38 -0
- package/dist/esm/fork/extractPathFromURL.test.mjs.map +1 -0
- package/dist/esm/fork/extractPathFromURL.test.native.js +38 -0
- package/dist/esm/fork/extractPathFromURL.test.native.js.map +1 -0
- package/dist/esm/headless.mjs +1 -0
- package/dist/esm/headless.mjs.map +1 -1
- package/dist/esm/headless.native.js +1 -0
- package/dist/esm/headless.native.js.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +3 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/index.native.js +3 -1
- package/dist/esm/index.native.js.map +1 -1
- package/dist/esm/link/getLinking.mjs +22 -0
- package/dist/esm/link/getLinking.mjs.map +1 -0
- package/dist/esm/link/getLinking.native.js +25 -0
- package/dist/esm/link/getLinking.native.js.map +1 -0
- package/dist/esm/link/linking.mjs +4 -1
- package/dist/esm/link/linking.mjs.map +1 -1
- package/dist/esm/link/linking.native.js +9 -1
- package/dist/esm/link/linking.native.js.map +1 -1
- package/dist/esm/metro-config/getViteMetroPluginOptions.mjs +2 -0
- package/dist/esm/metro-config/getViteMetroPluginOptions.mjs.map +1 -1
- package/dist/esm/metro-config/getViteMetroPluginOptions.native.js +2 -0
- package/dist/esm/metro-config/getViteMetroPluginOptions.native.js.map +1 -1
- package/dist/esm/router/Route.mjs +2 -2
- package/dist/esm/router/Route.mjs.map +1 -1
- package/dist/esm/router/Route.native.js +2 -2
- package/dist/esm/router/Route.native.js.map +1 -1
- package/dist/esm/router/getLinkingConfig.mjs +14 -4
- package/dist/esm/router/getLinkingConfig.mjs.map +1 -1
- package/dist/esm/router/getLinkingConfig.native.js +15 -4
- package/dist/esm/router/getLinkingConfig.native.js.map +1 -1
- package/dist/esm/router/getLinkingConfig.test.mjs +42 -0
- package/dist/esm/router/getLinkingConfig.test.mjs.map +1 -0
- package/dist/esm/router/getLinkingConfig.test.native.js +42 -0
- package/dist/esm/router/getLinkingConfig.test.native.js.map +1 -0
- package/dist/esm/router/getRouteInfo.mjs +2 -2
- package/dist/esm/router/getRouteInfo.mjs.map +1 -1
- package/dist/esm/router/getRouteInfo.native.js +3 -3
- package/dist/esm/router/getRouteInfo.native.js.map +1 -1
- package/dist/esm/router/linkingConfig.mjs +35 -10
- package/dist/esm/router/linkingConfig.mjs.map +1 -1
- package/dist/esm/router/linkingConfig.native.js +36 -10
- package/dist/esm/router/linkingConfig.native.js.map +1 -1
- package/dist/esm/router/router.mjs +7 -7
- package/dist/esm/router/router.mjs.map +1 -1
- package/dist/esm/router/router.native.js +7 -7
- package/dist/esm/router/router.native.js.map +1 -1
- package/dist/esm/router/sitemap.mjs +39 -0
- package/dist/esm/router/sitemap.mjs.map +1 -0
- package/dist/esm/router/sitemap.native.js +46 -0
- package/dist/esm/router/sitemap.native.js.map +1 -0
- package/dist/esm/router/sitemap.test.mjs +35 -0
- package/dist/esm/router/sitemap.test.mjs.map +1 -0
- package/dist/esm/router/sitemap.test.native.js +35 -0
- package/dist/esm/router/sitemap.test.native.js.map +1 -0
- package/dist/esm/router/useInitializeOneRouter.mjs +5 -5
- package/dist/esm/router/useInitializeOneRouter.mjs.map +1 -1
- package/dist/esm/router/useInitializeOneRouter.native.js +5 -5
- package/dist/esm/router/useInitializeOneRouter.native.js.map +1 -1
- package/dist/esm/serve.mjs +14 -1
- package/dist/esm/serve.mjs.map +1 -1
- package/dist/esm/serve.native.js +14 -1
- package/dist/esm/serve.native.js.map +1 -1
- package/dist/esm/views/Navigator.mjs +2 -2
- package/dist/esm/views/Navigator.mjs.map +1 -1
- package/dist/esm/views/Navigator.native.js +2 -2
- package/dist/esm/views/Navigator.native.js.map +1 -1
- package/dist/esm/vite/one.mjs +2 -0
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +4 -2
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +4 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +6 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs +13 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js +13 -0
- package/dist/esm/vite/plugins/virtualEntryPlugin.test.native.js.map +1 -1
- package/metro-entry.js +3 -0
- package/package.json +9 -9
- package/src/Root.tsx +15 -6
- package/src/babel-plugins/one-router-metro.test.ts +33 -0
- package/src/babel-plugins/one-router-metro.ts +9 -0
- package/src/cli/build.ts +25 -1
- package/src/cli/dev.ts +18 -5
- package/src/cli/install-error-handlers.ts +172 -0
- package/src/createApp.native.tsx +1 -0
- package/src/createApp.tsx +5 -0
- package/src/fork/extractPathFromURL.test.ts +90 -0
- package/src/fork/extractPathFromURL.ts +28 -0
- package/src/headless.tsx +3 -0
- package/src/index.ts +2 -0
- package/src/link/getLinking.ts +56 -0
- package/src/link/linking.native.ts +7 -0
- package/src/link/linking.ts +4 -0
- package/src/metro-config/getViteMetroPluginOptions.ts +3 -0
- package/src/router/Route.tsx +2 -2
- package/src/router/getLinkingConfig.test.ts +63 -0
- package/src/router/getLinkingConfig.ts +27 -3
- package/src/router/getRouteInfo.ts +2 -2
- package/src/router/linkingConfig.ts +52 -8
- package/src/router/router.ts +12 -7
- package/src/router/sitemap.test.ts +50 -0
- package/src/router/sitemap.ts +66 -0
- package/src/router/useInitializeOneRouter.ts +7 -5
- package/src/serve.ts +22 -1
- package/src/views/Navigator.tsx +2 -2
- package/src/vite/one.ts +2 -0
- package/src/vite/plugins/virtualEntryPlugin.test.ts +17 -0
- package/src/vite/plugins/virtualEntryPlugin.ts +8 -0
- package/src/vite/types.ts +23 -0
- package/types/Root.d.ts +2 -0
- package/types/Root.d.ts.map +1 -1
- package/types/babel-plugins/one-router-metro.d.ts +1 -0
- package/types/babel-plugins/one-router-metro.d.ts.map +1 -1
- package/types/cli/build.d.ts.map +1 -1
- package/types/cli/dev.d.ts.map +1 -1
- package/types/cli/install-error-handlers.d.ts +4 -0
- package/types/cli/install-error-handlers.d.ts.map +1 -0
- package/types/createApp.d.ts +2 -0
- package/types/createApp.d.ts.map +1 -1
- package/types/createApp.native.d.ts.map +1 -1
- package/types/fork/extractPathFromURL.d.ts.map +1 -1
- package/types/fork/extractPathFromURL.test.d.ts +2 -0
- package/types/fork/extractPathFromURL.test.d.ts.map +1 -0
- package/types/headless.d.ts +2 -0
- package/types/headless.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/link/getLinking.d.ts +22 -0
- package/types/link/getLinking.d.ts.map +1 -0
- package/types/link/linking.d.ts +1 -0
- package/types/link/linking.d.ts.map +1 -1
- package/types/link/linking.native.d.ts +1 -0
- package/types/link/linking.native.d.ts.map +1 -1
- package/types/metro-config/getViteMetroPluginOptions.d.ts +2 -1
- package/types/metro-config/getViteMetroPluginOptions.d.ts.map +1 -1
- package/types/router/getLinkingConfig.d.ts +3 -1
- package/types/router/getLinkingConfig.d.ts.map +1 -1
- package/types/router/getLinkingConfig.test.d.ts +2 -0
- package/types/router/getLinkingConfig.test.d.ts.map +1 -0
- package/types/router/linkingConfig.d.ts +5 -4
- package/types/router/linkingConfig.d.ts.map +1 -1
- package/types/router/router.d.ts +2 -1
- package/types/router/router.d.ts.map +1 -1
- package/types/router/sitemap.d.ts +14 -0
- package/types/router/sitemap.d.ts.map +1 -0
- package/types/router/sitemap.test.d.ts +2 -0
- package/types/router/sitemap.test.d.ts.map +1 -0
- package/types/router/useInitializeOneRouter.d.ts +2 -1
- package/types/router/useInitializeOneRouter.d.ts.map +1 -1
- package/types/serve.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/types.d.ts +23 -0
- package/types/vite/types.d.ts.map +1 -1
package/src/headless.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import './setup'
|
|
2
2
|
|
|
3
|
+
import type { OneLinkingConfig } from './link/getLinking'
|
|
3
4
|
import { Root } from './Root'
|
|
4
5
|
import { resolveClientLoader } from './clientLoaderResolver'
|
|
5
6
|
import { render } from './render'
|
|
@@ -13,6 +14,7 @@ export type CreateHeadlessAppProps = {
|
|
|
13
14
|
routerRoot: string
|
|
14
15
|
path?: string
|
|
15
16
|
flags?: One.Flags
|
|
17
|
+
linking?: OneLinkingConfig
|
|
16
18
|
getSetupPromise?: () => Promise<unknown>
|
|
17
19
|
}
|
|
18
20
|
|
|
@@ -34,6 +36,7 @@ export function createApp(options: CreateHeadlessAppProps) {
|
|
|
34
36
|
flags={options.flags}
|
|
35
37
|
routes={options.routes}
|
|
36
38
|
routerRoot={options.routerRoot}
|
|
39
|
+
linking={options.linking}
|
|
37
40
|
path={
|
|
38
41
|
options.path || (typeof window !== 'undefined' ? window.location.href : '/')
|
|
39
42
|
}
|
package/src/index.ts
CHANGED
|
@@ -77,7 +77,9 @@ export {
|
|
|
77
77
|
useSegments,
|
|
78
78
|
useUnstableGlobalHref,
|
|
79
79
|
} from './hooks'
|
|
80
|
+
export { useSitemap, type SitemapType } from './router/sitemap'
|
|
80
81
|
export { href } from './href'
|
|
82
|
+
export { getLinking, type OneLinkingConfig } from './link/getLinking'
|
|
81
83
|
// components
|
|
82
84
|
export { Stack } from './layouts/Stack'
|
|
83
85
|
export { Tabs } from './layouts/Tabs'
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export type OneLinkingConfig = {
|
|
2
|
+
/**
|
|
3
|
+
* Custom app scheme or schemes. Each scheme is expanded to double- and
|
|
4
|
+
* triple-slashed URL prefixes.
|
|
5
|
+
*/
|
|
6
|
+
scheme?: string | string[]
|
|
7
|
+
/**
|
|
8
|
+
* Fully qualified URL prefixes to strip before matching routes.
|
|
9
|
+
*
|
|
10
|
+
* For host-bearing custom scheme URLs, include the host:
|
|
11
|
+
* `myapp://app`.
|
|
12
|
+
*/
|
|
13
|
+
prefixes?: string[]
|
|
14
|
+
filter?: (url: string) => boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type NormalizedOneLinkingConfig = {
|
|
18
|
+
prefixes: string[]
|
|
19
|
+
filter?: (url: string) => boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getLinking(config: OneLinkingConfig = {}): OneLinkingConfig {
|
|
23
|
+
return config
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function normalizeLinkingConfig(
|
|
27
|
+
config: OneLinkingConfig | undefined,
|
|
28
|
+
defaultPrefixes: string[] = []
|
|
29
|
+
): NormalizedOneLinkingConfig {
|
|
30
|
+
// merge: defaults from the native manifest combine with whatever the user
|
|
31
|
+
// provides via scheme/prefixes, so URLs from any registered scheme are
|
|
32
|
+
// recognized even when the user only mentions a subset
|
|
33
|
+
const merged = [
|
|
34
|
+
...defaultPrefixes,
|
|
35
|
+
...getSchemePrefixes(config?.scheme),
|
|
36
|
+
...(config?.prefixes ?? []),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
prefixes: dedupe(merged),
|
|
41
|
+
filter: config?.filter,
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function getSchemePrefixes(scheme: string | string[] | undefined): string[] {
|
|
46
|
+
const schemes = Array.isArray(scheme) ? scheme : scheme ? [scheme] : []
|
|
47
|
+
|
|
48
|
+
return schemes.flatMap((value) => {
|
|
49
|
+
const normalized = value.replace(/:\/+$/, '')
|
|
50
|
+
return [`${normalized}://`, `${normalized}:///`]
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function dedupe(values: string[]): string[] {
|
|
55
|
+
return [...new Set(values.filter(Boolean))]
|
|
56
|
+
}
|
|
@@ -62,6 +62,13 @@ export function getRootURL(): string {
|
|
|
62
62
|
return _rootURL
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
export function getDefaultLinkingPrefixes(): string[] {
|
|
66
|
+
return Linking.collectManifestSchemes?.().flatMap((scheme) => {
|
|
67
|
+
const normalized = scheme.replace(/:\/+$/, '')
|
|
68
|
+
return [`${normalized}://`, `${normalized}:///`]
|
|
69
|
+
}) ?? []
|
|
70
|
+
}
|
|
71
|
+
|
|
65
72
|
export function addEventListener(listener: (url: string) => void) {
|
|
66
73
|
let callback: (({ url }: { url: string }) => void) | undefined
|
|
67
74
|
|
package/src/link/linking.ts
CHANGED
|
@@ -12,6 +12,10 @@ export function getRootURL(): string {
|
|
|
12
12
|
return '/'
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
export function getDefaultLinkingPrefixes(): string[] {
|
|
16
|
+
return []
|
|
17
|
+
}
|
|
18
|
+
|
|
15
19
|
export function addEventListener(listener: (url: string) => void) {
|
|
16
20
|
if (typeof window === 'undefined') {
|
|
17
21
|
return () => {}
|
|
@@ -20,12 +20,14 @@ export function getViteMetroPluginOptions({
|
|
|
20
20
|
projectRoot,
|
|
21
21
|
relativeRouterRoot,
|
|
22
22
|
ignoredRouteFiles,
|
|
23
|
+
linking,
|
|
23
24
|
userDefaultConfigOverrides,
|
|
24
25
|
setupFile,
|
|
25
26
|
}: {
|
|
26
27
|
projectRoot: string
|
|
27
28
|
relativeRouterRoot: string
|
|
28
29
|
ignoredRouteFiles?: Array<`**/*${string}`>
|
|
30
|
+
linking?: unknown
|
|
29
31
|
userDefaultConfigOverrides?: NonNullable<
|
|
30
32
|
Parameters<typeof metroPlugin>[0]
|
|
31
33
|
>['defaultConfigOverrides']
|
|
@@ -236,6 +238,7 @@ export function getViteMetroPluginOptions({
|
|
|
236
238
|
),
|
|
237
239
|
ONE_ROUTER_ROOT_FOLDER_NAME: relativeRouterRoot,
|
|
238
240
|
ONE_ROUTER_REQUIRE_CONTEXT_REGEX_STRING: routerRequireContextRegexString,
|
|
241
|
+
ONE_ROUTER_LINKING_CONFIG: linking,
|
|
239
242
|
ONE_SETUP_FILE_NATIVE: (() => {
|
|
240
243
|
if (!setupFile) return undefined
|
|
241
244
|
// Extract native setup file path
|
package/src/router/Route.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import type { ErrorBoundaryProps } from '../views/Try'
|
|
|
4
4
|
import type { LoaderProps } from '../types'
|
|
5
5
|
import type { One } from '../vite/types'
|
|
6
6
|
import type { ParamValidator, RouteValidationFn } from '../validateParams'
|
|
7
|
-
import {
|
|
7
|
+
import { getResolvedLinking } from './linkingConfig'
|
|
8
8
|
import { getContextKey } from './matchers'
|
|
9
9
|
import { mergeDynamicParams } from './params'
|
|
10
10
|
import { routeInfo } from './router'
|
|
@@ -153,7 +153,7 @@ function getParamsFromCurrentUrl(route?: {
|
|
|
153
153
|
path?: string
|
|
154
154
|
params?: Record<string, string | undefined>
|
|
155
155
|
}): Record<string, any> | undefined {
|
|
156
|
-
const linking =
|
|
156
|
+
const linking = getResolvedLinking()
|
|
157
157
|
if (!linking?.getStateFromPath) return undefined
|
|
158
158
|
const path =
|
|
159
159
|
routeInfo?.unstable_globalHref ||
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { normalizeLinkingConfig } from '../link/getLinking'
|
|
3
|
+
import { getRoutes } from './getRoutes'
|
|
4
|
+
import { getLinkingConfig } from './getLinkingConfig'
|
|
5
|
+
import { getMockContext } from '../testing-utils'
|
|
6
|
+
|
|
7
|
+
describe('getLinkingConfig', () => {
|
|
8
|
+
it('expands configured schemes into prefixes', () => {
|
|
9
|
+
const routes = getRoutes(getMockContext(['_layout.tsx', 'index.tsx']))!
|
|
10
|
+
const linking = getLinkingConfig(routes, true, {
|
|
11
|
+
scheme: 'threepunchconvo',
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
expect(linking.prefixes).toEqual([
|
|
15
|
+
'threepunchconvo://',
|
|
16
|
+
'threepunchconvo:///',
|
|
17
|
+
])
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('merges explicit prefixes with scheme-derived prefixes', () => {
|
|
21
|
+
const routes = getRoutes(getMockContext(['_layout.tsx', 'index.tsx']))!
|
|
22
|
+
const linking = getLinkingConfig(routes, true, {
|
|
23
|
+
scheme: 'threepunchconvo',
|
|
24
|
+
prefixes: ['threepunchconvo://app'],
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
expect(linking.prefixes).toEqual([
|
|
28
|
+
'threepunchconvo://',
|
|
29
|
+
'threepunchconvo:///',
|
|
30
|
+
'threepunchconvo://app',
|
|
31
|
+
])
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
describe('normalizeLinkingConfig', () => {
|
|
36
|
+
it('merges manifest-default prefixes with user-supplied scheme/prefixes', () => {
|
|
37
|
+
const result = normalizeLinkingConfig(
|
|
38
|
+
{ scheme: 'foo', prefixes: ['https://example.test/app'] },
|
|
39
|
+
['bar://', 'bar:///']
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
expect(result.prefixes).toEqual([
|
|
43
|
+
'bar://',
|
|
44
|
+
'bar:///',
|
|
45
|
+
'foo://',
|
|
46
|
+
'foo:///',
|
|
47
|
+
'https://example.test/app',
|
|
48
|
+
])
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('falls back to manifest-default prefixes when nothing is configured', () => {
|
|
52
|
+
const result = normalizeLinkingConfig(undefined, ['bar://', 'bar:///'])
|
|
53
|
+
expect(result.prefixes).toEqual(['bar://', 'bar:///'])
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
it('dedupes overlapping defaults and configured prefixes', () => {
|
|
57
|
+
const result = normalizeLinkingConfig(
|
|
58
|
+
{ scheme: 'foo' },
|
|
59
|
+
['foo://', 'foo:///']
|
|
60
|
+
)
|
|
61
|
+
expect(result.prefixes).toEqual(['foo://', 'foo:///'])
|
|
62
|
+
})
|
|
63
|
+
})
|
|
@@ -3,10 +3,16 @@ import type { State } from '../fork/getPathFromState'
|
|
|
3
3
|
import { getReactNavigationConfig, type Screen } from '../getReactNavigationConfig'
|
|
4
4
|
import {
|
|
5
5
|
addEventListener,
|
|
6
|
+
getDefaultLinkingPrefixes,
|
|
6
7
|
getInitialURL,
|
|
7
8
|
getPathFromState,
|
|
8
9
|
getStateFromPath,
|
|
9
10
|
} from '../link/linking'
|
|
11
|
+
import {
|
|
12
|
+
normalizeLinkingConfig,
|
|
13
|
+
type OneLinkingConfig,
|
|
14
|
+
} from '../link/getLinking'
|
|
15
|
+
import { evictOldest } from '../utils/evictOldest'
|
|
10
16
|
import type { RouteNode } from './Route'
|
|
11
17
|
|
|
12
18
|
export function getNavigationConfig(
|
|
@@ -23,10 +29,19 @@ export type OneLinkingOptions = LinkingOptions<object> & {
|
|
|
23
29
|
getPathFromState?: typeof getPathFromState
|
|
24
30
|
}
|
|
25
31
|
|
|
26
|
-
export function getLinkingConfig(
|
|
32
|
+
export function getLinkingConfig(
|
|
33
|
+
routes: RouteNode,
|
|
34
|
+
metaOnly = true,
|
|
35
|
+
linking?: OneLinkingConfig
|
|
36
|
+
): OneLinkingOptions {
|
|
27
37
|
const config = getNavigationConfig(routes, metaOnly)
|
|
38
|
+
const resolvedLinking = normalizeLinkingConfig(
|
|
39
|
+
linking,
|
|
40
|
+
getDefaultLinkingPrefixes()
|
|
41
|
+
)
|
|
28
42
|
return {
|
|
29
|
-
prefixes:
|
|
43
|
+
prefixes: resolvedLinking.prefixes,
|
|
44
|
+
filter: resolvedLinking.filter,
|
|
30
45
|
// @ts-expect-error
|
|
31
46
|
config,
|
|
32
47
|
// A custom getInitialURL is used on native to ensure the app always starts at
|
|
@@ -53,7 +68,15 @@ export function getLinkingConfig(routes: RouteNode, metaOnly = true): OneLinking
|
|
|
53
68
|
|
|
54
69
|
export const stateCache = new Map<string, any>()
|
|
55
70
|
|
|
56
|
-
|
|
71
|
+
const STATE_CACHE_THRESHOLD = 5000
|
|
72
|
+
const STATE_CACHE_EVICTION = 1000
|
|
73
|
+
|
|
74
|
+
export function clearStateCache() {
|
|
75
|
+
stateCache.clear()
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** memoize getStateFromPath by pathname. cache is cleared when the route tree
|
|
79
|
+
* or linking config changes (see ensureBaseLinkingConfig in linkingConfig.ts). */
|
|
57
80
|
function getStateFromPathMemoized(
|
|
58
81
|
path: string,
|
|
59
82
|
options: Parameters<typeof getStateFromPath>[1]
|
|
@@ -63,6 +86,7 @@ function getStateFromPathMemoized(
|
|
|
63
86
|
return cached
|
|
64
87
|
}
|
|
65
88
|
const result = getStateFromPath(path, options)
|
|
89
|
+
evictOldest(stateCache, STATE_CACHE_THRESHOLD, STATE_CACHE_EVICTION)
|
|
66
90
|
stateCache.set(path, result)
|
|
67
91
|
return result
|
|
68
92
|
}
|
|
@@ -4,14 +4,14 @@ import { stripBaseUrl } from '../fork/getStateFromPath-mods'
|
|
|
4
4
|
import type { OneRouter } from '../interfaces/router'
|
|
5
5
|
import { getNormalizedStatePath, type UrlObject } from './getNormalizedStatePath'
|
|
6
6
|
import { isIndexPath } from './isIndexPath'
|
|
7
|
-
import {
|
|
7
|
+
import { getResolvedLinking } from './linkingConfig'
|
|
8
8
|
|
|
9
9
|
export function getRouteInfo(state: OneRouter.ResultState) {
|
|
10
10
|
return getRouteInfoFromState(
|
|
11
11
|
(state: Parameters<typeof originalGetPathFromState>[0], asPath: boolean) => {
|
|
12
12
|
return getPathDataFromState(state, {
|
|
13
13
|
screens: [],
|
|
14
|
-
...
|
|
14
|
+
...getResolvedLinking()?.config,
|
|
15
15
|
preserveDynamicRoutes: asPath,
|
|
16
16
|
preserveGroups: asPath,
|
|
17
17
|
})
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { isWebClient } from '../constants'
|
|
2
2
|
import type { OneRouter } from '../interfaces/router'
|
|
3
|
+
import type { OneLinkingConfig } from '../link/getLinking'
|
|
3
4
|
import { evictOldest } from '../utils/evictOldest'
|
|
4
5
|
import {
|
|
6
|
+
clearStateCache,
|
|
5
7
|
getLinkingConfig as createLinkingConfig,
|
|
6
8
|
type OneLinkingOptions,
|
|
7
9
|
} from './getLinkingConfig'
|
|
@@ -12,12 +14,13 @@ let linkingConfig: OneLinkingOptions | undefined
|
|
|
12
14
|
// cache the base linking config (route-tree dependent, not URL-dependent)
|
|
13
15
|
let cachedBaseLinkingConfig: OneLinkingOptions | undefined
|
|
14
16
|
let cachedRouteNodeForLinking: RouteNode | null = null
|
|
17
|
+
let cachedLinkingConfigKey = ''
|
|
15
18
|
|
|
16
19
|
// cache getStateFromPath results by path for SSR performance
|
|
17
20
|
// same path always produces the same navigation state (route tree is static in prod)
|
|
18
21
|
const ssrStateCache = new Map<string, OneRouter.ResultState | undefined>()
|
|
19
22
|
|
|
20
|
-
export function
|
|
23
|
+
export function getResolvedLinking() {
|
|
21
24
|
return linkingConfig
|
|
22
25
|
}
|
|
23
26
|
|
|
@@ -33,13 +36,25 @@ export function resetLinking() {
|
|
|
33
36
|
* Ensure the base linking config is initialized for a given route tree.
|
|
34
37
|
* Does not set any per-request state.
|
|
35
38
|
*/
|
|
36
|
-
export function ensureBaseLinkingConfig(
|
|
39
|
+
export function ensureBaseLinkingConfig(
|
|
40
|
+
routeNode: RouteNode | null,
|
|
41
|
+
linking?: OneLinkingConfig
|
|
42
|
+
) {
|
|
43
|
+
const linkingConfigKey = getLinkingConfigKey(linking)
|
|
37
44
|
if (
|
|
38
45
|
routeNode &&
|
|
39
|
-
(routeNode !== cachedRouteNodeForLinking ||
|
|
46
|
+
(routeNode !== cachedRouteNodeForLinking ||
|
|
47
|
+
linkingConfigKey !== cachedLinkingConfigKey ||
|
|
48
|
+
!cachedBaseLinkingConfig)
|
|
40
49
|
) {
|
|
41
|
-
|
|
50
|
+
// route tree or linking config changed — drop memoized navigation states
|
|
51
|
+
// so getStateFromPathMemoized doesn't return entries computed against
|
|
52
|
+
// the previous configuration
|
|
53
|
+
clearStateCache()
|
|
54
|
+
ssrStateCache.clear()
|
|
55
|
+
cachedBaseLinkingConfig = createLinkingConfig(routeNode, true, linking)
|
|
42
56
|
cachedRouteNodeForLinking = routeNode
|
|
57
|
+
cachedLinkingConfigKey = linkingConfigKey
|
|
43
58
|
}
|
|
44
59
|
}
|
|
45
60
|
|
|
@@ -49,11 +64,12 @@ export function ensureBaseLinkingConfig(routeNode: RouteNode | null) {
|
|
|
49
64
|
*/
|
|
50
65
|
export function getSSRInitialState(
|
|
51
66
|
routeNode: RouteNode | null,
|
|
52
|
-
initialLocation: URL
|
|
67
|
+
initialLocation: URL,
|
|
68
|
+
linking?: OneLinkingConfig
|
|
53
69
|
): OneRouter.ResultState | undefined {
|
|
54
70
|
if (!routeNode) return undefined
|
|
55
71
|
|
|
56
|
-
ensureBaseLinkingConfig(routeNode)
|
|
72
|
+
ensureBaseLinkingConfig(routeNode, linking)
|
|
57
73
|
if (!cachedBaseLinkingConfig) return undefined
|
|
58
74
|
|
|
59
75
|
const path = initialLocation.pathname + (initialLocation.search || '')
|
|
@@ -70,13 +86,14 @@ export function getSSRInitialState(
|
|
|
70
86
|
|
|
71
87
|
export function setupLinking(
|
|
72
88
|
routeNode: RouteNode | null,
|
|
73
|
-
initialLocation?: URL
|
|
89
|
+
initialLocation?: URL,
|
|
90
|
+
linking?: OneLinkingConfig
|
|
74
91
|
): OneRouter.ResultState | undefined {
|
|
75
92
|
let initialState: OneRouter.ResultState | undefined
|
|
76
93
|
|
|
77
94
|
if (routeNode) {
|
|
78
95
|
// reuse ensureBaseLinkingConfig to avoid duplicating cache logic
|
|
79
|
-
ensureBaseLinkingConfig(routeNode)
|
|
96
|
+
ensureBaseLinkingConfig(routeNode, linking)
|
|
80
97
|
|
|
81
98
|
// shallow copy so per-request mutations (getInitialURL) don't affect cache
|
|
82
99
|
linkingConfig = { ...cachedBaseLinkingConfig! }
|
|
@@ -101,3 +118,30 @@ export function setupLinking(
|
|
|
101
118
|
|
|
102
119
|
return initialState
|
|
103
120
|
}
|
|
121
|
+
|
|
122
|
+
// each unique filter function gets a stable id so reference-equal filters
|
|
123
|
+
// share a cache key while distinct filters invalidate it
|
|
124
|
+
const filterIds = new WeakMap<NonNullable<OneLinkingConfig['filter']>, number>()
|
|
125
|
+
let filterIdCounter = 0
|
|
126
|
+
function getFilterId(filter: OneLinkingConfig['filter']) {
|
|
127
|
+
if (!filter) return 0
|
|
128
|
+
let id = filterIds.get(filter)
|
|
129
|
+
if (id === undefined) {
|
|
130
|
+
id = ++filterIdCounter
|
|
131
|
+
filterIds.set(filter, id)
|
|
132
|
+
}
|
|
133
|
+
return id
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function getLinkingConfigKey(linking: OneLinkingConfig | undefined) {
|
|
137
|
+
// sort prefixes/schemes so ordering doesn't cause spurious cache misses
|
|
138
|
+
const schemes = Array.isArray(linking?.scheme)
|
|
139
|
+
? [...linking.scheme].sort()
|
|
140
|
+
: (linking?.scheme ?? null)
|
|
141
|
+
const prefixes = linking?.prefixes ? [...linking.prefixes].sort() : null
|
|
142
|
+
return JSON.stringify({
|
|
143
|
+
scheme: schemes,
|
|
144
|
+
prefixes,
|
|
145
|
+
filterId: getFilterId(linking?.filter),
|
|
146
|
+
})
|
|
147
|
+
}
|
package/src/router/router.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { Platform } from 'react-native'
|
|
|
20
20
|
import { devtoolsRegistry } from '../devtools/registry'
|
|
21
21
|
import type { OneRouter } from '../interfaces/router'
|
|
22
22
|
import { resolveHref } from '../link/href'
|
|
23
|
+
import type { OneLinkingConfig } from '../link/getLinking'
|
|
23
24
|
import { openExternalURL } from '../link/openExternalURL'
|
|
24
25
|
import { resolve } from '../link/path'
|
|
25
26
|
import { checkBlocker } from '../useBlocker'
|
|
@@ -45,7 +46,7 @@ import type { UrlObject } from './getNormalizedStatePath'
|
|
|
45
46
|
import { getRouteInfo } from './getRouteInfo'
|
|
46
47
|
import { getRoutes } from './getRoutes'
|
|
47
48
|
import { setLastAction } from './lastAction'
|
|
48
|
-
import {
|
|
49
|
+
import { getResolvedLinking, resetLinking, setupLinking } from './linkingConfig'
|
|
49
50
|
import type { RouteNode } from './Route'
|
|
50
51
|
import { sortRoutes } from './sortRoutes'
|
|
51
52
|
import { getQualifiedRouteComponent } from './useScreens'
|
|
@@ -214,7 +215,8 @@ let cachedContext: One.RouteContext | null = null
|
|
|
214
215
|
export function initialize(
|
|
215
216
|
context: One.RouteContext,
|
|
216
217
|
ref: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>,
|
|
217
|
-
initialLocation?: URL
|
|
218
|
+
initialLocation?: URL,
|
|
219
|
+
linking?: OneLinkingConfig
|
|
218
220
|
) {
|
|
219
221
|
cleanUpState()
|
|
220
222
|
|
|
@@ -281,7 +283,7 @@ export function initialize(
|
|
|
281
283
|
}
|
|
282
284
|
|
|
283
285
|
navigationRef = ref as unknown as OneRouter.NavigationRef
|
|
284
|
-
setupLinkingAndRouteInfo(initialLocation)
|
|
286
|
+
setupLinkingAndRouteInfo(initialLocation, linking)
|
|
285
287
|
subscribeToNavigationChanges()
|
|
286
288
|
}
|
|
287
289
|
|
|
@@ -297,8 +299,11 @@ function cleanUpState() {
|
|
|
297
299
|
storeSubscribers.clear()
|
|
298
300
|
}
|
|
299
301
|
|
|
300
|
-
function setupLinkingAndRouteInfo(
|
|
301
|
-
|
|
302
|
+
function setupLinkingAndRouteInfo(
|
|
303
|
+
initialLocation?: URL,
|
|
304
|
+
linking?: OneLinkingConfig
|
|
305
|
+
) {
|
|
306
|
+
initialState = setupLinking(routeNode, initialLocation, linking)
|
|
302
307
|
|
|
303
308
|
// capture the original pathname before React Navigation's linking can modify it
|
|
304
309
|
initialPathname =
|
|
@@ -557,7 +562,7 @@ function getSnapshot() {
|
|
|
557
562
|
linkTo,
|
|
558
563
|
routeNode,
|
|
559
564
|
rootComponent,
|
|
560
|
-
linking:
|
|
565
|
+
linking: getResolvedLinking(),
|
|
561
566
|
hasAttemptedToHideSplash,
|
|
562
567
|
initialState,
|
|
563
568
|
rootState,
|
|
@@ -1059,7 +1064,7 @@ export async function linkTo(
|
|
|
1059
1064
|
)
|
|
1060
1065
|
}
|
|
1061
1066
|
|
|
1062
|
-
const linking =
|
|
1067
|
+
const linking = getResolvedLinking()
|
|
1063
1068
|
|
|
1064
1069
|
if (!linking) {
|
|
1065
1070
|
throw new Error('Attempted to link to route when no routes are present')
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { getRoutes } from './getRoutes'
|
|
3
|
+
import { getSitemap } from './sitemap'
|
|
4
|
+
import { getMockContext } from '../testing-utils'
|
|
5
|
+
|
|
6
|
+
describe('getSitemap', () => {
|
|
7
|
+
it('maps the route tree to a public sitemap shape', () => {
|
|
8
|
+
const routes = getRoutes(
|
|
9
|
+
getMockContext([
|
|
10
|
+
'_layout.tsx',
|
|
11
|
+
'index.tsx',
|
|
12
|
+
'(app)/_layout.tsx',
|
|
13
|
+
'(app)/thread/[id].tsx',
|
|
14
|
+
'docs/[...slug].tsx',
|
|
15
|
+
])
|
|
16
|
+
)!
|
|
17
|
+
const sitemap = getSitemap(routes)!
|
|
18
|
+
|
|
19
|
+
expect(sitemap).toMatchObject({
|
|
20
|
+
contextKey: './_layout.tsx',
|
|
21
|
+
href: '/',
|
|
22
|
+
isInternal: false,
|
|
23
|
+
isGenerated: false,
|
|
24
|
+
children: expect.arrayContaining([
|
|
25
|
+
expect.objectContaining({
|
|
26
|
+
contextKey: './index.tsx',
|
|
27
|
+
filename: 'index',
|
|
28
|
+
href: '/',
|
|
29
|
+
}),
|
|
30
|
+
expect.objectContaining({
|
|
31
|
+
contextKey: './(app)/_layout.tsx',
|
|
32
|
+
filename: '(app)/_layout',
|
|
33
|
+
href: '/(app)',
|
|
34
|
+
children: expect.arrayContaining([
|
|
35
|
+
expect.objectContaining({
|
|
36
|
+
contextKey: './(app)/thread/[id].tsx',
|
|
37
|
+
filename: 'thread/[id]',
|
|
38
|
+
href: '/(app)/thread/[id]',
|
|
39
|
+
}),
|
|
40
|
+
]),
|
|
41
|
+
}),
|
|
42
|
+
expect.objectContaining({
|
|
43
|
+
contextKey: './docs/[...slug].tsx',
|
|
44
|
+
filename: 'docs/[...slug]',
|
|
45
|
+
href: '/docs/[...slug]',
|
|
46
|
+
}),
|
|
47
|
+
]),
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
})
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import type { OneRouter } from '../interfaces/router'
|
|
3
|
+
import type { RouteNode } from './Route'
|
|
4
|
+
import { removeSupportedExtensions } from './matchers'
|
|
5
|
+
import { routeNode } from './router'
|
|
6
|
+
import { sortRoutes } from './sortRoutes'
|
|
7
|
+
|
|
8
|
+
export type SitemapType = {
|
|
9
|
+
contextKey: string
|
|
10
|
+
filename: string
|
|
11
|
+
href: string | OneRouter.Href
|
|
12
|
+
isInitial: boolean
|
|
13
|
+
isInternal: boolean
|
|
14
|
+
isGenerated: boolean
|
|
15
|
+
children: SitemapType[]
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function useSitemap(): SitemapType | null {
|
|
19
|
+
return useMemo(() => getSitemap(routeNode), [routeNode])
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getSitemap(root: RouteNode | null): SitemapType | null {
|
|
23
|
+
return root ? mapRouteToSitemap(root, []) : null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function mapRouteToSitemap(route: RouteNode, parents: string[]): SitemapType {
|
|
27
|
+
return {
|
|
28
|
+
contextKey: route.contextKey,
|
|
29
|
+
filename: getRouteFilename(route),
|
|
30
|
+
href: getRouteHref(route, parents),
|
|
31
|
+
isInitial: route.initialRouteName === route.route,
|
|
32
|
+
isInternal: route.internal ?? false,
|
|
33
|
+
isGenerated: route.generated ?? false,
|
|
34
|
+
children: [...route.children]
|
|
35
|
+
.sort(sortRoutes)
|
|
36
|
+
.map((child) => mapRouteToSitemap(child, getRouteSegments(route, parents))),
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getRouteSegments(route: RouteNode, parents: string[]) {
|
|
41
|
+
return [...parents, ...route.route.split('/')]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// the sitemap exposes route patterns rather than concrete sample URLs:
|
|
45
|
+
// dynamic segments stay as `[id]` / `[...slug]`, and `index` collapses to '/'.
|
|
46
|
+
// callers wanting clickable links should fill in their own params.
|
|
47
|
+
function getRouteHref(route: RouteNode, parents: string[]) {
|
|
48
|
+
const path = getRouteSegments(route, parents)
|
|
49
|
+
.map((segment) => (segment === 'index' ? '' : segment))
|
|
50
|
+
.filter(Boolean)
|
|
51
|
+
.join('/')
|
|
52
|
+
|
|
53
|
+
return `/${path}`
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getRouteFilename(route: RouteNode) {
|
|
57
|
+
const contextKey = removeSupportedExtensions(route.contextKey)
|
|
58
|
+
const segments = contextKey.split('/')
|
|
59
|
+
|
|
60
|
+
if (route.contextKey.match(/_layout\.[jt]sx?$/)) {
|
|
61
|
+
return segments.slice(-2).join('/')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const routeSegmentsCount = route.route.split('/').length
|
|
65
|
+
return segments.slice(-routeSegmentsCount).join('/')
|
|
66
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useNavigationContainerRef } from '@react-navigation/native'
|
|
2
2
|
import { resetLoaderState } from '../useLoader'
|
|
3
3
|
import type { One } from '../vite/types'
|
|
4
|
+
import type { OneLinkingConfig } from '../link/getLinking'
|
|
4
5
|
import * as routerStore from './router'
|
|
5
6
|
import { initialize } from './router'
|
|
6
7
|
import { getSSRInitialState, ensureBaseLinkingConfig } from './linkingConfig'
|
|
@@ -15,7 +16,8 @@ let ssrRouteTreeInitialized = false
|
|
|
15
16
|
|
|
16
17
|
export function useInitializeOneRouter(
|
|
17
18
|
context: One.RouteContext,
|
|
18
|
-
initialLocation: URL | undefined
|
|
19
|
+
initialLocation: URL | undefined,
|
|
20
|
+
linking?: OneLinkingConfig
|
|
19
21
|
) {
|
|
20
22
|
const navigationRef = useNavigationContainerRef()
|
|
21
23
|
|
|
@@ -23,15 +25,15 @@ export function useInitializeOneRouter(
|
|
|
23
25
|
if (typeof window === 'undefined') {
|
|
24
26
|
if (!ssrRouteTreeInitialized) {
|
|
25
27
|
// first SSR request: full initialization to set up route tree, root component, etc.
|
|
26
|
-
initialize(context, navigationRef, initialLocation)
|
|
28
|
+
initialize(context, navigationRef, initialLocation, linking)
|
|
27
29
|
ssrRouteTreeInitialized = true
|
|
28
30
|
// also ensure linking config base is cached
|
|
29
|
-
ensureBaseLinkingConfig(routerStore.routeNode)
|
|
31
|
+
ensureBaseLinkingConfig(routerStore.routeNode, linking)
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
// per-request: compute initialState from URL (cached by path)
|
|
33
35
|
const initialState = initialLocation
|
|
34
|
-
? getSSRInitialState(routerStore.routeNode, initialLocation)
|
|
36
|
+
? getSSRInitialState(routerStore.routeNode, initialLocation, linking)
|
|
35
37
|
: routerStore.initialState
|
|
36
38
|
|
|
37
39
|
// return per-request snapshot to prevent concurrent request trampling
|
|
@@ -48,7 +50,7 @@ export function useInitializeOneRouter(
|
|
|
48
50
|
const contexts = '__react_navigation__elements_contexts'
|
|
49
51
|
globalThis[contexts] = new Map<string, React.Context<any>>()
|
|
50
52
|
|
|
51
|
-
initialize(context, navigationRef, initialLocation)
|
|
53
|
+
initialize(context, navigationRef, initialLocation, linking)
|
|
52
54
|
lastInitVersion = initVersion
|
|
53
55
|
}
|
|
54
56
|
|
package/src/serve.ts
CHANGED
|
@@ -8,8 +8,29 @@ import { setupBuildInfo } from './server/setupBuildOptions'
|
|
|
8
8
|
import { ensureExists } from './utils/ensureExists'
|
|
9
9
|
import type { One } from './vite/types'
|
|
10
10
|
|
|
11
|
+
// formatErrorSafely + the prepareStackTrace guard prevent a buggy transitive
|
|
12
|
+
// formatter (source-map-support without recursion guard) from pinning the
|
|
13
|
+
// serve process forever. see cli/install-error-handlers.ts for the full
|
|
14
|
+
// story behind the 9-day Onejs:build zombies on the soot CI runner.
|
|
15
|
+
import {
|
|
16
|
+
formatErrorSafely,
|
|
17
|
+
installPrepareStackTraceGuard,
|
|
18
|
+
} from './cli/install-error-handlers'
|
|
19
|
+
|
|
20
|
+
installPrepareStackTraceGuard()
|
|
21
|
+
|
|
11
22
|
process.on('uncaughtException', (err) => {
|
|
12
|
-
|
|
23
|
+
try {
|
|
24
|
+
process.stderr.write(`[one serve] uncaught exception\n${formatErrorSafely(err)}\n`)
|
|
25
|
+
} catch {}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
process.on('unhandledRejection', (reason) => {
|
|
29
|
+
try {
|
|
30
|
+
process.stderr.write(
|
|
31
|
+
`[one serve] unhandled rejection\n${formatErrorSafely(reason)}\n`,
|
|
32
|
+
)
|
|
33
|
+
} catch {}
|
|
13
34
|
})
|
|
14
35
|
|
|
15
36
|
export async function serve(
|