one 1.2.83 → 1.2.84
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/devtools/dev.mjs +44 -0
- package/devtools/devtools.mjs +540 -0
- package/devtools/source-inspector.mjs +201 -0
- package/dist/cjs/cli/daemon.cjs +136 -0
- package/dist/cjs/cli/daemon.js +112 -0
- package/dist/cjs/cli/daemon.js.map +6 -0
- package/dist/cjs/cli/daemon.native.js +173 -0
- package/dist/cjs/cli/daemon.native.js.map +1 -0
- package/dist/cjs/createHandleRequest.cjs +15 -8
- package/dist/cjs/createHandleRequest.js +10 -6
- package/dist/cjs/createHandleRequest.js.map +1 -1
- package/dist/cjs/createHandleRequest.native.js +8 -3
- package/dist/cjs/createHandleRequest.native.js.map +1 -1
- package/dist/cjs/daemon/index.cjs +24 -0
- package/dist/cjs/daemon/index.js +21 -0
- package/dist/cjs/daemon/index.js.map +6 -0
- package/dist/cjs/daemon/index.native.js +27 -0
- package/dist/cjs/daemon/index.native.js.map +1 -0
- package/dist/cjs/daemon/ipc.cjs +235 -0
- package/dist/cjs/daemon/ipc.js +204 -0
- package/dist/cjs/daemon/ipc.js.map +6 -0
- package/dist/cjs/daemon/ipc.native.js +276 -0
- package/dist/cjs/daemon/ipc.native.js.map +1 -0
- package/dist/cjs/daemon/picker.cjs +223 -0
- package/dist/cjs/daemon/picker.js +191 -0
- package/dist/cjs/daemon/picker.js.map +6 -0
- package/dist/cjs/daemon/picker.native.js +308 -0
- package/dist/cjs/daemon/picker.native.js.map +1 -0
- package/dist/cjs/daemon/proxy.cjs +75 -0
- package/dist/cjs/daemon/proxy.js +70 -0
- package/dist/cjs/daemon/proxy.js.map +6 -0
- package/dist/cjs/daemon/proxy.native.js +81 -0
- package/dist/cjs/daemon/proxy.native.js.map +1 -0
- package/dist/cjs/daemon/registry.cjs +85 -0
- package/dist/cjs/daemon/registry.js +81 -0
- package/dist/cjs/daemon/registry.js.map +6 -0
- package/dist/cjs/daemon/registry.native.js +120 -0
- package/dist/cjs/daemon/registry.native.js.map +1 -0
- package/dist/cjs/daemon/server.cjs +178 -0
- package/dist/cjs/daemon/server.js +179 -0
- package/dist/cjs/daemon/server.js.map +6 -0
- package/dist/cjs/daemon/server.native.js +200 -0
- package/dist/cjs/daemon/server.native.js.map +1 -0
- package/dist/cjs/daemon/tui.cjs +223 -0
- package/dist/cjs/daemon/tui.js +192 -0
- package/dist/cjs/daemon/tui.js.map +6 -0
- package/dist/cjs/daemon/tui.native.js +234 -0
- package/dist/cjs/daemon/tui.native.js.map +1 -0
- package/dist/cjs/daemon/types.cjs +16 -0
- package/dist/cjs/daemon/types.js +14 -0
- package/dist/cjs/daemon/types.js.map +6 -0
- package/dist/cjs/daemon/types.native.js +19 -0
- package/dist/cjs/daemon/types.native.js.map +1 -0
- package/dist/cjs/daemon/utils.cjs +74 -0
- package/dist/cjs/daemon/utils.js +65 -0
- package/dist/cjs/daemon/utils.js.map +6 -0
- package/dist/cjs/daemon/utils.native.js +83 -0
- package/dist/cjs/daemon/utils.native.js.map +1 -0
- package/dist/cjs/fork/createMemoryHistory.cjs +22 -8
- package/dist/cjs/fork/createMemoryHistory.js +20 -6
- package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
- package/dist/cjs/fork/createMemoryHistory.native.js +22 -8
- package/dist/cjs/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/cjs/fork/useLinking.cjs +52 -13
- package/dist/cjs/fork/useLinking.js +35 -10
- package/dist/cjs/fork/useLinking.js.map +1 -1
- package/dist/cjs/index.cjs +6 -2
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +2 -2
- package/dist/cjs/index.native.js +6 -2
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/cjs/router/linkingConfig.cjs +13 -2
- package/dist/cjs/router/linkingConfig.js +14 -5
- package/dist/cjs/router/linkingConfig.js.map +1 -1
- package/dist/cjs/router/linkingConfig.native.js +10 -1
- package/dist/cjs/router/linkingConfig.native.js.map +1 -1
- package/dist/cjs/router/routeMask.cjs +137 -0
- package/dist/cjs/router/routeMask.js +127 -0
- package/dist/cjs/router/routeMask.js.map +6 -0
- package/dist/cjs/router/routeMask.native.js +160 -0
- package/dist/cjs/router/routeMask.native.js.map +1 -0
- package/dist/cjs/router/router.cjs +26 -3
- package/dist/cjs/router/router.js +23 -3
- package/dist/cjs/router/router.js.map +1 -1
- package/dist/cjs/router/router.native.js +26 -3
- package/dist/cjs/router/router.native.js.map +1 -1
- package/dist/cjs/server/PreloadScripts.native.js +45 -39
- package/dist/cjs/server/PreloadScripts.native.js.map +1 -6
- package/dist/cjs/vite/DevHead.cjs +2 -909
- package/dist/cjs/vite/DevHead.js +1 -917
- package/dist/cjs/vite/DevHead.js.map +1 -1
- package/dist/cjs/vite/DevHead.native.js +1 -882
- package/dist/cjs/vite/DevHead.native.js.map +1 -1
- package/dist/cjs/vite/one.cjs +4 -1
- package/dist/cjs/vite/one.js +4 -2
- package/dist/cjs/vite/one.js.map +1 -1
- package/dist/cjs/vite/one.native.js +4 -1
- package/dist/cjs/vite/one.native.js.map +1 -1
- package/dist/cjs/vite/plugins/devtoolsPlugin.cjs +55 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.js +49 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.js.map +6 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.native.js +58 -0
- package/dist/cjs/vite/plugins/devtoolsPlugin.native.js.map +1 -0
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.cjs +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
- package/dist/cjs/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +7 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js +5 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +8 -1
- package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/dist/esm/cli/daemon.js +89 -0
- package/dist/esm/cli/daemon.js.map +6 -0
- package/dist/esm/cli/daemon.mjs +102 -0
- package/dist/esm/cli/daemon.mjs.map +1 -0
- package/dist/esm/cli/daemon.native.js +136 -0
- package/dist/esm/cli/daemon.native.js.map +1 -0
- package/dist/esm/createHandleRequest.js +10 -5
- package/dist/esm/createHandleRequest.js.map +1 -1
- package/dist/esm/createHandleRequest.mjs +15 -8
- package/dist/esm/createHandleRequest.mjs.map +1 -1
- package/dist/esm/createHandleRequest.native.js +8 -3
- package/dist/esm/createHandleRequest.native.js.map +1 -1
- package/dist/esm/daemon/index.js +8 -0
- package/dist/esm/daemon/index.js.map +6 -0
- package/dist/esm/daemon/index.mjs +8 -0
- package/dist/esm/daemon/index.mjs.map +1 -0
- package/dist/esm/daemon/index.native.js +8 -0
- package/dist/esm/daemon/index.native.js.map +1 -0
- package/dist/esm/daemon/ipc.js +192 -0
- package/dist/esm/daemon/ipc.js.map +6 -0
- package/dist/esm/daemon/ipc.mjs +191 -0
- package/dist/esm/daemon/ipc.mjs.map +1 -0
- package/dist/esm/daemon/ipc.native.js +229 -0
- package/dist/esm/daemon/ipc.native.js.map +1 -0
- package/dist/esm/daemon/picker.js +169 -0
- package/dist/esm/daemon/picker.js.map +6 -0
- package/dist/esm/daemon/picker.mjs +186 -0
- package/dist/esm/daemon/picker.mjs.map +1 -0
- package/dist/esm/daemon/picker.native.js +268 -0
- package/dist/esm/daemon/picker.native.js.map +1 -0
- package/dist/esm/daemon/proxy.js +47 -0
- package/dist/esm/daemon/proxy.js.map +6 -0
- package/dist/esm/daemon/proxy.mjs +40 -0
- package/dist/esm/daemon/proxy.mjs.map +1 -0
- package/dist/esm/daemon/proxy.native.js +43 -0
- package/dist/esm/daemon/proxy.native.js.map +1 -0
- package/dist/esm/daemon/registry.js +65 -0
- package/dist/esm/daemon/registry.js.map +6 -0
- package/dist/esm/daemon/registry.mjs +53 -0
- package/dist/esm/daemon/registry.mjs.map +1 -0
- package/dist/esm/daemon/registry.native.js +85 -0
- package/dist/esm/daemon/registry.native.js.map +1 -0
- package/dist/esm/daemon/server.js +167 -0
- package/dist/esm/daemon/server.js.map +6 -0
- package/dist/esm/daemon/server.mjs +143 -0
- package/dist/esm/daemon/server.mjs.map +1 -0
- package/dist/esm/daemon/server.native.js +162 -0
- package/dist/esm/daemon/server.native.js.map +1 -0
- package/dist/esm/daemon/tui.js +171 -0
- package/dist/esm/daemon/tui.js.map +6 -0
- package/dist/esm/daemon/tui.mjs +187 -0
- package/dist/esm/daemon/tui.mjs.map +1 -0
- package/dist/esm/daemon/tui.native.js +195 -0
- package/dist/esm/daemon/tui.native.js.map +1 -0
- package/dist/esm/daemon/types.js +1 -0
- package/dist/esm/daemon/types.js.map +6 -0
- package/dist/esm/daemon/types.mjs +2 -0
- package/dist/esm/daemon/types.mjs.map +1 -0
- package/dist/esm/daemon/types.native.js +2 -0
- package/dist/esm/daemon/types.native.js.map +1 -0
- package/dist/esm/daemon/utils.js +42 -0
- package/dist/esm/daemon/utils.js.map +6 -0
- package/dist/esm/daemon/utils.mjs +39 -0
- package/dist/esm/daemon/utils.mjs.map +1 -0
- package/dist/esm/daemon/utils.native.js +45 -0
- package/dist/esm/daemon/utils.native.js.map +1 -0
- package/dist/esm/fork/createMemoryHistory.js +20 -6
- package/dist/esm/fork/createMemoryHistory.js.map +1 -1
- package/dist/esm/fork/createMemoryHistory.mjs +22 -8
- package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
- package/dist/esm/fork/createMemoryHistory.native.js +22 -8
- package/dist/esm/fork/createMemoryHistory.native.js.map +1 -1
- package/dist/esm/fork/useLinking.js +35 -9
- package/dist/esm/fork/useLinking.js.map +1 -1
- package/dist/esm/fork/useLinking.mjs +52 -13
- package/dist/esm/fork/useLinking.mjs.map +1 -1
- package/dist/esm/index.js +4 -0
- 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/router/linkingConfig.js +14 -4
- package/dist/esm/router/linkingConfig.js.map +1 -1
- package/dist/esm/router/linkingConfig.mjs +12 -1
- package/dist/esm/router/linkingConfig.mjs.map +1 -1
- package/dist/esm/router/linkingConfig.native.js +10 -1
- package/dist/esm/router/linkingConfig.native.js.map +1 -1
- package/dist/esm/router/routeMask.js +111 -0
- package/dist/esm/router/routeMask.js.map +6 -0
- package/dist/esm/router/routeMask.mjs +108 -0
- package/dist/esm/router/routeMask.mjs.map +1 -0
- package/dist/esm/router/routeMask.native.js +128 -0
- package/dist/esm/router/routeMask.native.js.map +1 -0
- package/dist/esm/router/router.js +23 -2
- package/dist/esm/router/router.js.map +1 -1
- package/dist/esm/router/router.mjs +24 -3
- package/dist/esm/router/router.mjs.map +1 -1
- package/dist/esm/router/router.native.js +24 -3
- package/dist/esm/router/router.native.js.map +1 -1
- package/dist/esm/server/PreloadScripts.native.js +29 -33
- package/dist/esm/server/PreloadScripts.native.js.map +1 -6
- package/dist/esm/vite/DevHead.js +1 -917
- package/dist/esm/vite/DevHead.js.map +1 -1
- package/dist/esm/vite/DevHead.mjs +2 -909
- package/dist/esm/vite/DevHead.mjs.map +1 -1
- package/dist/esm/vite/DevHead.native.js +0 -881
- package/dist/esm/vite/DevHead.native.js.map +1 -1
- package/dist/esm/vite/one.js +4 -1
- package/dist/esm/vite/one.js.map +1 -1
- package/dist/esm/vite/one.mjs +4 -1
- package/dist/esm/vite/one.mjs.map +1 -1
- package/dist/esm/vite/one.native.js +4 -1
- package/dist/esm/vite/one.native.js.map +1 -1
- package/dist/esm/vite/plugins/devtoolsPlugin.js +33 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.js.map +6 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.mjs +31 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.mjs.map +1 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.native.js +31 -0
- package/dist/esm/vite/plugins/devtoolsPlugin.native.js.map +1 -0
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js +1 -6
- package/dist/esm/vite/plugins/fileSystemRouterPlugin.native.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.js +5 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.js.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +7 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +8 -1
- package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
- package/package.json +12 -10
- package/src/createHandleRequest.ts +16 -3
- package/src/fork/createMemoryHistory.tsx +39 -4
- package/src/fork/useLinking.ts +83 -12
- package/src/index.ts +3 -0
- package/src/router/linkingConfig.ts +21 -4
- package/src/router/routeMask.ts +293 -0
- package/src/router/router.ts +53 -1
- package/src/vite/DevHead.tsx +1 -924
- package/src/vite/one.ts +4 -0
- package/src/vite/plugins/devtoolsPlugin.ts +45 -0
- package/src/vite/plugins/fileSystemRouterPlugin.tsx +2 -7
- package/src/vite/plugins/virtualEntryPlugin.ts +12 -3
- package/src/vite/types.ts +1 -0
- package/types/cli/daemon.d.ts.map +1 -0
- package/types/createHandleRequest.d.ts.map +1 -1
- package/types/daemon/index.d.ts.map +1 -0
- package/types/daemon/ipc.d.ts.map +1 -0
- package/types/daemon/picker.d.ts.map +1 -0
- package/types/daemon/proxy.d.ts.map +1 -0
- package/types/daemon/registry.d.ts.map +1 -0
- package/types/daemon/server.d.ts.map +1 -0
- package/types/daemon/tui.d.ts.map +1 -0
- package/types/daemon/types.d.ts.map +1 -0
- package/types/daemon/utils.d.ts.map +1 -0
- package/types/fork/createMemoryHistory.d.ts +6 -2
- package/types/fork/createMemoryHistory.d.ts.map +1 -1
- package/types/fork/useLinking.d.ts.map +1 -1
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/router/linkingConfig.d.ts.map +1 -1
- package/types/router/routeMask.d.ts +130 -0
- package/types/router/routeMask.d.ts.map +1 -0
- package/types/router/router.d.ts +23 -0
- package/types/router/router.d.ts.map +1 -1
- package/types/vite/DevHead.d.ts.map +1 -1
- package/types/vite/one.d.ts.map +1 -1
- package/types/vite/plugins/devtoolsPlugin.d.ts +5 -0
- package/types/vite/plugins/devtoolsPlugin.d.ts.map +1 -0
- package/types/vite/plugins/fileSystemRouterPlugin.d.ts.map +1 -1
- package/types/vite/plugins/virtualEntryPlugin.d.ts +1 -3
- package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
- package/types/vite/types.d.ts.map +1 -1
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for a route mask.
|
|
3
|
+
* Route masking displays a different URL in the browser than the actual route being rendered.
|
|
4
|
+
* Uses history.state to store the actual route, so on page reload the router can restore the original route.
|
|
5
|
+
*/
|
|
6
|
+
export interface RouteMaskOptions {
|
|
7
|
+
/**
|
|
8
|
+
* The route pattern to match (the actual route being navigated to).
|
|
9
|
+
* Supports dynamic segments like [id] or $id.
|
|
10
|
+
*
|
|
11
|
+
* @example '/photos/[id]/modal' or '/photos/$photoId/modal'
|
|
12
|
+
*/
|
|
13
|
+
from: string
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The route pattern to display in the browser URL (the masked URL).
|
|
17
|
+
* Supports dynamic segments that will be populated from the matched params.
|
|
18
|
+
*
|
|
19
|
+
* @example '/photos/[id]' or '/photos/$photoId'
|
|
20
|
+
*/
|
|
21
|
+
to: string
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* How to handle parameters when masking.
|
|
25
|
+
* - `true` (default): Forward all matched params to the masked URL
|
|
26
|
+
* - `false`: Don't forward any params
|
|
27
|
+
* - Function: Custom param transformation
|
|
28
|
+
*
|
|
29
|
+
* @default true
|
|
30
|
+
*/
|
|
31
|
+
params?: boolean | ((matchedParams: Record<string, string>) => Record<string, string>)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* If true, unmask when the page is reloaded (show the masked URL's content).
|
|
35
|
+
* If false (default), keep the actual route on reload (show the original content).
|
|
36
|
+
*
|
|
37
|
+
* When false: Reload at /photos/5 → still shows /photos/5/modal content
|
|
38
|
+
* When true: Reload at /photos/5 → shows /photos/5 content
|
|
39
|
+
*
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
unmaskOnReload?: boolean
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* If true, encode the actual route as a base64 postfix in the URL pathname instead of history.state.
|
|
46
|
+
*
|
|
47
|
+
* URL will look like: /photos/5__L3Bob3Rvcy81L21vZGFs
|
|
48
|
+
*
|
|
49
|
+
* Benefits:
|
|
50
|
+
* - Server can parse the postfix and render the actual route (no SSR flash)
|
|
51
|
+
* - URL contains the "truth" about what to render
|
|
52
|
+
* - Works consistently across SSR, SSG, and SPA
|
|
53
|
+
* - No query parameter visible
|
|
54
|
+
*
|
|
55
|
+
* Tradeoffs:
|
|
56
|
+
* - URL has a base64 suffix visible after `__`
|
|
57
|
+
*
|
|
58
|
+
* @default false
|
|
59
|
+
*/
|
|
60
|
+
useSearchParam?: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A compiled route mask ready for matching.
|
|
65
|
+
*/
|
|
66
|
+
export interface RouteMask extends RouteMaskOptions {
|
|
67
|
+
/** Regex pattern for matching the 'from' route */
|
|
68
|
+
_fromRegex: RegExp
|
|
69
|
+
/** Parameter names extracted from the 'from' pattern */
|
|
70
|
+
_fromParams: string[]
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Creates a route mask for automatic URL masking during navigation.
|
|
75
|
+
*
|
|
76
|
+
* Route masking displays a different URL in the browser than the actual route.
|
|
77
|
+
* Uses browser history.state to store the actual route, enabling:
|
|
78
|
+
* - Modal overlays with clean shareable URLs
|
|
79
|
+
* - Different URL for in-app navigation vs direct access
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* import { createRouteMask } from 'one'
|
|
84
|
+
*
|
|
85
|
+
* const photoMask = createRouteMask({
|
|
86
|
+
* from: '/photos/[id]/modal',
|
|
87
|
+
* to: '/photos/[id]',
|
|
88
|
+
* params: true,
|
|
89
|
+
* })
|
|
90
|
+
*
|
|
91
|
+
* // In vite.config.ts:
|
|
92
|
+
* one({
|
|
93
|
+
* router: { routeMasks: [photoMask] },
|
|
94
|
+
* })
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export function createRouteMask(options: RouteMaskOptions): RouteMask {
|
|
98
|
+
const {
|
|
99
|
+
from,
|
|
100
|
+
to,
|
|
101
|
+
params = true,
|
|
102
|
+
unmaskOnReload = false,
|
|
103
|
+
useSearchParam = false,
|
|
104
|
+
} = options
|
|
105
|
+
|
|
106
|
+
// Extract parameter names and build regex from the 'from' pattern
|
|
107
|
+
const fromParams: string[] = []
|
|
108
|
+
const fromRegexStr = from
|
|
109
|
+
.split('/')
|
|
110
|
+
.map((segment) => {
|
|
111
|
+
// Handle catch-all segments [...rest] or $...rest
|
|
112
|
+
if (segment.startsWith('[...') && segment.endsWith(']')) {
|
|
113
|
+
const paramName = segment.slice(4, -1)
|
|
114
|
+
fromParams.push(paramName)
|
|
115
|
+
return '(.+)'
|
|
116
|
+
}
|
|
117
|
+
if (segment.startsWith('$...')) {
|
|
118
|
+
const paramName = segment.slice(4)
|
|
119
|
+
fromParams.push(paramName)
|
|
120
|
+
return '(.+)'
|
|
121
|
+
}
|
|
122
|
+
// Handle dynamic segments [id] or $id
|
|
123
|
+
if (segment.startsWith('[') && segment.endsWith(']')) {
|
|
124
|
+
const paramName = segment.slice(1, -1)
|
|
125
|
+
fromParams.push(paramName)
|
|
126
|
+
return '([^/]+)'
|
|
127
|
+
}
|
|
128
|
+
if (segment.startsWith('$')) {
|
|
129
|
+
const paramName = segment.slice(1)
|
|
130
|
+
fromParams.push(paramName)
|
|
131
|
+
return '([^/]+)'
|
|
132
|
+
}
|
|
133
|
+
// Static segment - escape regex special chars
|
|
134
|
+
return segment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
135
|
+
})
|
|
136
|
+
.join('/')
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
from,
|
|
140
|
+
to,
|
|
141
|
+
params,
|
|
142
|
+
unmaskOnReload,
|
|
143
|
+
useSearchParam,
|
|
144
|
+
_fromRegex: new RegExp(`^${fromRegexStr}$`),
|
|
145
|
+
_fromParams: fromParams,
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Matches a pathname against a route mask.
|
|
151
|
+
* Returns the matched params if successful, or null if no match.
|
|
152
|
+
*/
|
|
153
|
+
export function matchRouteMask(
|
|
154
|
+
pathname: string,
|
|
155
|
+
mask: RouteMask
|
|
156
|
+
): Record<string, string> | null {
|
|
157
|
+
const match = pathname.match(mask._fromRegex)
|
|
158
|
+
if (!match) return null
|
|
159
|
+
|
|
160
|
+
const params: Record<string, string> = {}
|
|
161
|
+
mask._fromParams.forEach((paramName, index) => {
|
|
162
|
+
params[paramName] = match[index + 1]
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
return params
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Builds the masked URL from a route mask and matched params.
|
|
170
|
+
*/
|
|
171
|
+
export function buildMaskedPath(
|
|
172
|
+
mask: RouteMask,
|
|
173
|
+
matchedParams: Record<string, string>
|
|
174
|
+
): string {
|
|
175
|
+
// Determine which params to use
|
|
176
|
+
let params: Record<string, string>
|
|
177
|
+
if (mask.params === false) {
|
|
178
|
+
params = {}
|
|
179
|
+
} else if (typeof mask.params === 'function') {
|
|
180
|
+
params = mask.params(matchedParams)
|
|
181
|
+
} else {
|
|
182
|
+
params = matchedParams
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Build the masked URL by replacing dynamic segments
|
|
186
|
+
return mask.to
|
|
187
|
+
.split('/')
|
|
188
|
+
.map((segment) => {
|
|
189
|
+
// Handle [...rest] or $...rest
|
|
190
|
+
if (segment.startsWith('[...') && segment.endsWith(']')) {
|
|
191
|
+
const paramName = segment.slice(4, -1)
|
|
192
|
+
return params[paramName] ?? ''
|
|
193
|
+
}
|
|
194
|
+
if (segment.startsWith('$...')) {
|
|
195
|
+
const paramName = segment.slice(4)
|
|
196
|
+
return params[paramName] ?? ''
|
|
197
|
+
}
|
|
198
|
+
// Handle [id] or $id
|
|
199
|
+
if (segment.startsWith('[') && segment.endsWith(']')) {
|
|
200
|
+
const paramName = segment.slice(1, -1)
|
|
201
|
+
return params[paramName] ?? ''
|
|
202
|
+
}
|
|
203
|
+
if (segment.startsWith('$')) {
|
|
204
|
+
const paramName = segment.slice(1)
|
|
205
|
+
return params[paramName] ?? ''
|
|
206
|
+
}
|
|
207
|
+
return segment
|
|
208
|
+
})
|
|
209
|
+
.join('/')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* URL-safe base64 encode for the _unmask suffix.
|
|
214
|
+
* Replaces +/= with URL-safe characters so the param looks like an opaque token.
|
|
215
|
+
*/
|
|
216
|
+
export function encodeUnmask(path: string): string {
|
|
217
|
+
return btoa(path).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Decode a URL-safe base64 _unmask value back to the original path.
|
|
222
|
+
*/
|
|
223
|
+
export function decodeUnmask(encoded: string): string {
|
|
224
|
+
const base64 = encoded.replace(/-/g, '+').replace(/_/g, '/')
|
|
225
|
+
return atob(base64)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* The separator used in the pathname postfix for route unmasking.
|
|
230
|
+
* e.g. /photos/3__L3Bob3Rvcy8zL21vZGFs
|
|
231
|
+
*/
|
|
232
|
+
const UNMASK_SEPARATOR = '__'
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Parse the base64-encoded unmask suffix from a pathname.
|
|
236
|
+
* Looks for `__` separator in the last path segment.
|
|
237
|
+
* Returns the decoded actual path, or null if no unmask suffix found.
|
|
238
|
+
*
|
|
239
|
+
* @example
|
|
240
|
+
* parseUnmaskFromPath('/photos/3__L3Bob3Rvcy8zL21vZGFs') // '/photos/3/modal'
|
|
241
|
+
* parseUnmaskFromPath('/photos/3') // null
|
|
242
|
+
*/
|
|
243
|
+
export function parseUnmaskFromPath(pathname: string): string | null {
|
|
244
|
+
const lastSlash = pathname.lastIndexOf('/')
|
|
245
|
+
const lastSegment = pathname.slice(lastSlash + 1)
|
|
246
|
+
const separatorIndex = lastSegment.indexOf(UNMASK_SEPARATOR)
|
|
247
|
+
|
|
248
|
+
if (separatorIndex === -1) return null
|
|
249
|
+
|
|
250
|
+
const encoded = lastSegment.slice(separatorIndex + UNMASK_SEPARATOR.length)
|
|
251
|
+
if (!encoded) return null
|
|
252
|
+
|
|
253
|
+
try {
|
|
254
|
+
return decodeUnmask(encoded)
|
|
255
|
+
} catch {
|
|
256
|
+
return null
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Finds a matching route mask for a given pathname.
|
|
262
|
+
* Returns the mask result to apply, or undefined if no match.
|
|
263
|
+
*/
|
|
264
|
+
export function findMatchingMask(
|
|
265
|
+
pathname: string,
|
|
266
|
+
routeMasks: RouteMask[]
|
|
267
|
+
):
|
|
268
|
+
| {
|
|
269
|
+
maskedPath: string
|
|
270
|
+
unmaskOnReload: boolean
|
|
271
|
+
useSearchParam: boolean
|
|
272
|
+
actualPath: string
|
|
273
|
+
}
|
|
274
|
+
| undefined {
|
|
275
|
+
for (const mask of routeMasks) {
|
|
276
|
+
const matchedParams = matchRouteMask(pathname, mask)
|
|
277
|
+
if (matchedParams) {
|
|
278
|
+
const maskedPath = buildMaskedPath(mask, matchedParams)
|
|
279
|
+
const useSearchParam = mask.useSearchParam ?? false
|
|
280
|
+
return {
|
|
281
|
+
// If useSearchParam is true, append base64-encoded actual path as pathname postfix
|
|
282
|
+
// e.g. /photos/3__L3Bob3Rvcy8zL21vZGFs
|
|
283
|
+
maskedPath: useSearchParam
|
|
284
|
+
? `${maskedPath}${UNMASK_SEPARATOR}${encodeUnmask(pathname)}`
|
|
285
|
+
: maskedPath,
|
|
286
|
+
unmaskOnReload: mask.unmaskOnReload ?? false,
|
|
287
|
+
useSearchParam,
|
|
288
|
+
actualPath: pathname,
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return undefined
|
|
293
|
+
}
|
package/src/router/router.ts
CHANGED
|
@@ -51,11 +51,43 @@ import { preloadRouteModules } from './useViteRoutes'
|
|
|
51
51
|
import { getNavigateAction } from './utils/getNavigateAction'
|
|
52
52
|
import { setClientMatches } from '../useMatches'
|
|
53
53
|
import type { RouteMatch } from '../useMatches'
|
|
54
|
+
import { type RouteMask, findMatchingMask } from './routeMask'
|
|
54
55
|
|
|
55
56
|
// Module-scoped variables
|
|
56
57
|
export let routeNode: RouteNode | null = null
|
|
57
58
|
export let rootComponent: ComponentType
|
|
58
59
|
|
|
60
|
+
// Route masks for automatic URL masking
|
|
61
|
+
let routeMasks: RouteMask[] = []
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Set route masks for automatic URL masking during navigation.
|
|
65
|
+
* Route masks transform URLs displayed in the browser without changing the actual route.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```tsx
|
|
69
|
+
* import { setRouteMasks, createRouteMask } from 'one'
|
|
70
|
+
*
|
|
71
|
+
* setRouteMasks([
|
|
72
|
+
* createRouteMask({
|
|
73
|
+
* from: '/photos/[id]/modal',
|
|
74
|
+
* to: '/photos/[id]',
|
|
75
|
+
* unmaskOnReload: true,
|
|
76
|
+
* }),
|
|
77
|
+
* ])
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export function setRouteMasks(masks: RouteMask[]) {
|
|
81
|
+
routeMasks = masks
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Get the current route masks.
|
|
86
|
+
*/
|
|
87
|
+
export function getRouteMasks(): RouteMask[] {
|
|
88
|
+
return routeMasks
|
|
89
|
+
}
|
|
90
|
+
|
|
59
91
|
// Global registry for protected routes
|
|
60
92
|
// Key: contextKey (e.g., '/protected-test'), Value: Set of protected route names
|
|
61
93
|
const protectedRouteRegistry = new Map<string, Set<string>>()
|
|
@@ -1002,8 +1034,28 @@ export async function linkTo(
|
|
|
1002
1034
|
hashes[rootState.key] = href.slice(hash)
|
|
1003
1035
|
}
|
|
1004
1036
|
|
|
1037
|
+
// Auto-apply route mask if no explicit mask provided and routeMasks are configured
|
|
1038
|
+
let finalOptions = options ?? null
|
|
1039
|
+
if (!finalOptions?.mask && routeMasks.length > 0) {
|
|
1040
|
+
// Extract pathname from href (remove search params and hash)
|
|
1041
|
+
const pathname = extractPathnameFromHref(href)
|
|
1042
|
+
const maskResult = findMatchingMask(pathname, routeMasks)
|
|
1043
|
+
if (maskResult) {
|
|
1044
|
+
finalOptions = {
|
|
1045
|
+
...finalOptions,
|
|
1046
|
+
mask: {
|
|
1047
|
+
href: maskResult.maskedPath,
|
|
1048
|
+
unmaskOnReload: maskResult.unmaskOnReload,
|
|
1049
|
+
},
|
|
1050
|
+
}
|
|
1051
|
+
if (process.env.ONE_DEBUG_ROUTER) {
|
|
1052
|
+
console.info(`[one] 🎭 Auto-masked ${pathname} → ${maskResult.maskedPath}`)
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1005
1057
|
// a bit hacky until can figure out a reliable way to tie it to the state
|
|
1006
|
-
nextOptions =
|
|
1058
|
+
nextOptions = finalOptions
|
|
1007
1059
|
|
|
1008
1060
|
startTransition(() => {
|
|
1009
1061
|
const action = getNavigateAction(state, rootState, event)
|