reactive-route 0.0.1-alpha.29 → 0.0.1-alpha.30

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.
Files changed (179) hide show
  1. package/package.json +44 -117
  2. package/LICENSE +0 -21
  3. package/README.md +0 -11
  4. package/dist/cjs/adapters/kr-observable-preact/package.json +0 -1
  5. package/dist/cjs/adapters/kr-observable-react/package.json +0 -1
  6. package/dist/cjs/adapters/kr-observable-solid/package.json +0 -1
  7. package/dist/cjs/adapters/mobx-preact/package.json +0 -1
  8. package/dist/cjs/adapters/mobx-react/package.json +0 -1
  9. package/dist/cjs/adapters/mobx-solid/package.json +0 -1
  10. package/dist/cjs/adapters/solid/package.json +0 -1
  11. package/dist/cjs/adapters/vue/package.json +0 -1
  12. package/dist/cjs/package.json +0 -1
  13. package/dist/cjs/preact/package.json +0 -1
  14. package/dist/cjs/react/package.json +0 -1
  15. package/dist/cjs/solid/package.json +0 -1
  16. package/dist/cjs/vue/package.json +0 -1
  17. package/dist/esm/adapters/kr-observable-preact/package.json +0 -1
  18. package/dist/esm/adapters/kr-observable-react/package.json +0 -1
  19. package/dist/esm/adapters/kr-observable-solid/package.json +0 -1
  20. package/dist/esm/adapters/mobx-preact/package.json +0 -1
  21. package/dist/esm/adapters/mobx-react/package.json +0 -1
  22. package/dist/esm/adapters/mobx-solid/package.json +0 -1
  23. package/dist/esm/adapters/solid/package.json +0 -1
  24. package/dist/esm/adapters/vue/package.json +0 -1
  25. package/dist/esm/package.json +0 -1
  26. package/dist/esm/preact/package.json +0 -1
  27. package/dist/esm/react/package.json +0 -1
  28. package/dist/esm/solid/package.json +0 -1
  29. package/dist/esm/vue/package.json +0 -1
  30. package/dist/tsconfig.types.react.tsbuildinfo +0 -1
  31. package/dist/tsconfig.types.solid.tsbuildinfo +0 -1
  32. package/e2e/app.test.ts +0 -130
  33. package/e2e/teardown.ts +0 -12
  34. package/playwright.config.ts +0 -54
  35. package/vitepress/.vitepress/cache/deps/_metadata.json +0 -52
  36. package/vitepress/.vitepress/cache/deps/chunk-FL23S3EK.js +0 -12705
  37. package/vitepress/.vitepress/cache/deps/chunk-FL23S3EK.js.map +0 -7
  38. package/vitepress/.vitepress/cache/deps/chunk-VGAXUAUJ.js +0 -9952
  39. package/vitepress/.vitepress/cache/deps/chunk-VGAXUAUJ.js.map +0 -7
  40. package/vitepress/.vitepress/cache/deps/package.json +0 -3
  41. package/vitepress/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -3844
  42. package/vitepress/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  43. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -588
  44. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  45. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js +0 -1153
  46. package/vitepress/.vitepress/cache/deps/vitepress___@vueuse_integrations_useFocusTrap.js.map +0 -7
  47. package/vitepress/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js +0 -1665
  48. package/vitepress/.vitepress/cache/deps/vitepress___mark__js_src_vanilla__js.js.map +0 -7
  49. package/vitepress/.vitepress/cache/deps/vitepress___minisearch.js +0 -1812
  50. package/vitepress/.vitepress/cache/deps/vitepress___minisearch.js.map +0 -7
  51. package/vitepress/.vitepress/cache/deps/vue.js +0 -342
  52. package/vitepress/.vitepress/cache/deps/vue.js.map +0 -7
  53. package/vitepress/.vitepress/config.mts +0 -72
  54. package/vitepress/.vitepress/theme/custom.css +0 -9
  55. package/vitepress/.vitepress/theme/index.ts +0 -5
  56. package/vitepress/examples/preact.md +0 -22
  57. package/vitepress/examples/react.md +0 -22
  58. package/vitepress/examples/solid.md +0 -21
  59. package/vitepress/file.svg +0 -79
  60. package/vitepress/guide/advanced.md +0 -131
  61. package/vitepress/guide/getting-started.md +0 -139
  62. package/vitepress/guide/index.md +0 -44
  63. package/vitepress/guide/preact.md +0 -33
  64. package/vitepress/guide/react.md +0 -33
  65. package/vitepress/guide/router-component.md +0 -67
  66. package/vitepress/guide/router-configuration.md +0 -185
  67. package/vitepress/guide/routes-configuration.md +0 -191
  68. package/vitepress/guide/solid.md +0 -68
  69. package/vitepress/guide/ssr.md +0 -70
  70. package/vitepress/index.md +0 -29
  71. package/vitest.vue.config.mjs +0 -23
  72. /package/{dist/cjs/adapters/kr-observable-preact/index.js → adapters/kr-observable-preact.cjs} +0 -0
  73. /package/{dist/adapters → adapters}/kr-observable-preact.d.ts +0 -0
  74. /package/{dist/adapters → adapters}/kr-observable-preact.d.ts.map +0 -0
  75. /package/{dist/esm/adapters/kr-observable-preact/index.js → adapters/kr-observable-preact.mjs} +0 -0
  76. /package/{dist/cjs/adapters/kr-observable-react/index.js → adapters/kr-observable-react.cjs} +0 -0
  77. /package/{dist/adapters → adapters}/kr-observable-react.d.ts +0 -0
  78. /package/{dist/adapters → adapters}/kr-observable-react.d.ts.map +0 -0
  79. /package/{dist/esm/adapters/kr-observable-react/index.js → adapters/kr-observable-react.mjs} +0 -0
  80. /package/{dist/cjs/adapters/kr-observable-solid/index.js → adapters/kr-observable-solid.cjs} +0 -0
  81. /package/{dist/adapters → adapters}/kr-observable-solid.d.ts +0 -0
  82. /package/{dist/adapters → adapters}/kr-observable-solid.d.ts.map +0 -0
  83. /package/{dist/esm/adapters/kr-observable-solid/index.js → adapters/kr-observable-solid.mjs} +0 -0
  84. /package/{dist/cjs/adapters/mobx-preact/index.js → adapters/mobx-preact.cjs} +0 -0
  85. /package/{dist/adapters → adapters}/mobx-preact.d.ts +0 -0
  86. /package/{dist/adapters → adapters}/mobx-preact.d.ts.map +0 -0
  87. /package/{dist/esm/adapters/mobx-preact/index.js → adapters/mobx-preact.mjs} +0 -0
  88. /package/{dist/cjs/adapters/mobx-react/index.js → adapters/mobx-react.cjs} +0 -0
  89. /package/{dist/adapters → adapters}/mobx-react.d.ts +0 -0
  90. /package/{dist/adapters → adapters}/mobx-react.d.ts.map +0 -0
  91. /package/{dist/esm/adapters/mobx-react/index.js → adapters/mobx-react.mjs} +0 -0
  92. /package/{dist/cjs/adapters/mobx-solid/index.js → adapters/mobx-solid.cjs} +0 -0
  93. /package/{dist/adapters → adapters}/mobx-solid.d.ts +0 -0
  94. /package/{dist/adapters → adapters}/mobx-solid.d.ts.map +0 -0
  95. /package/{dist/esm/adapters/mobx-solid/index.js → adapters/mobx-solid.mjs} +0 -0
  96. /package/{dist/cjs/adapters/solid/index.js → adapters/solid.cjs} +0 -0
  97. /package/{dist/adapters → adapters}/solid.d.ts +0 -0
  98. /package/{dist/adapters → adapters}/solid.d.ts.map +0 -0
  99. /package/{dist/esm/adapters/solid/index.js → adapters/solid.mjs} +0 -0
  100. /package/{dist/cjs/adapters/vue/index.js → adapters/vue.cjs} +0 -0
  101. /package/{dist/adapters → adapters}/vue.d.ts +0 -0
  102. /package/{dist/adapters → adapters}/vue.d.ts.map +0 -0
  103. /package/{dist/esm/adapters/vue/index.js → adapters/vue.mjs} +0 -0
  104. /package/{dist/core → core}/createRouter.d.ts +0 -0
  105. /package/{dist/core → core}/createRouter.d.ts.map +0 -0
  106. /package/{dist/core → core}/createRoutes.d.ts +0 -0
  107. /package/{dist/core → core}/createRoutes.d.ts.map +0 -0
  108. /package/{dist/core → core}/index.d.ts +0 -0
  109. /package/{dist/core → core}/index.d.ts.map +0 -0
  110. /package/{dist/core → core}/types/TypeAdapters.d.ts +0 -0
  111. /package/{dist/core → core}/types/TypeAdapters.d.ts.map +0 -0
  112. /package/{dist/core → core}/types/TypeCurrentRoute.d.ts +0 -0
  113. /package/{dist/core → core}/types/TypeCurrentRoute.d.ts.map +0 -0
  114. /package/{dist/core → core}/types/TypeLifecycleConfig.d.ts +0 -0
  115. /package/{dist/core → core}/types/TypeLifecycleConfig.d.ts.map +0 -0
  116. /package/{dist/core → core}/types/TypePropsRouter.d.ts +0 -0
  117. /package/{dist/core → core}/types/TypePropsRouter.d.ts.map +0 -0
  118. /package/{dist/core → core}/types/TypeRedirectParams.d.ts +0 -0
  119. /package/{dist/core → core}/types/TypeRedirectParams.d.ts.map +0 -0
  120. /package/{dist/core → core}/types/TypeRoute.d.ts +0 -0
  121. /package/{dist/core → core}/types/TypeRoute.d.ts.map +0 -0
  122. /package/{dist/core → core}/types/TypeRouteRaw.d.ts +0 -0
  123. /package/{dist/core → core}/types/TypeRouteRaw.d.ts.map +0 -0
  124. /package/{dist/core → core}/types/TypeRouter.d.ts +0 -0
  125. /package/{dist/core → core}/types/TypeRouter.d.ts.map +0 -0
  126. /package/{dist/core → core}/types/TypeValidator.d.ts +0 -0
  127. /package/{dist/core → core}/types/TypeValidator.d.ts.map +0 -0
  128. /package/{dist/core → core}/utils/PreventError.d.ts +0 -0
  129. /package/{dist/core → core}/utils/PreventError.d.ts.map +0 -0
  130. /package/{dist/core → core}/utils/RedirectError.d.ts +0 -0
  131. /package/{dist/core → core}/utils/RedirectError.d.ts.map +0 -0
  132. /package/{dist/core → core}/utils/addNames.d.ts +0 -0
  133. /package/{dist/core → core}/utils/addNames.d.ts.map +0 -0
  134. /package/{dist/core → core}/utils/constants.d.ts +0 -0
  135. /package/{dist/core → core}/utils/constants.d.ts.map +0 -0
  136. /package/{dist/core → core}/utils/dynamic.d.ts +0 -0
  137. /package/{dist/core → core}/utils/dynamic.d.ts.map +0 -0
  138. /package/{dist/core → core}/utils/findRouteByPathname.d.ts +0 -0
  139. /package/{dist/core → core}/utils/findRouteByPathname.d.ts.map +0 -0
  140. /package/{dist/core → core}/utils/getDynamicValues.d.ts +0 -0
  141. /package/{dist/core → core}/utils/getDynamicValues.d.ts.map +0 -0
  142. /package/{dist/core → core}/utils/getInitialRoute.d.ts +0 -0
  143. /package/{dist/core → core}/utils/getInitialRoute.d.ts.map +0 -0
  144. /package/{dist/core → core}/utils/getQueryValues.d.ts +0 -0
  145. /package/{dist/core → core}/utils/getQueryValues.d.ts.map +0 -0
  146. /package/{dist/core → core}/utils/getTypedEntries.d.ts +0 -0
  147. /package/{dist/core → core}/utils/getTypedEntries.d.ts.map +0 -0
  148. /package/{dist/core → core}/utils/history.d.ts +0 -0
  149. /package/{dist/core → core}/utils/history.d.ts.map +0 -0
  150. /package/{dist/core → core}/utils/loadComponentToConfig.d.ts +0 -0
  151. /package/{dist/core → core}/utils/loadComponentToConfig.d.ts.map +0 -0
  152. /package/{dist/core → core}/utils/queryString.d.ts +0 -0
  153. /package/{dist/core → core}/utils/queryString.d.ts.map +0 -0
  154. /package/{dist/core → core}/utils/replaceDynamicValues.d.ts +0 -0
  155. /package/{dist/core → core}/utils/replaceDynamicValues.d.ts.map +0 -0
  156. /package/{dist/cjs/index.js → index.cjs} +0 -0
  157. /package/{dist/esm/index.js → index.mjs} +0 -0
  158. /package/{dist/preact → preact}/Router.d.ts +0 -0
  159. /package/{dist/preact → preact}/Router.d.ts.map +0 -0
  160. /package/{dist/cjs/preact/index.js → preact/index.cjs} +0 -0
  161. /package/{dist/preact → preact}/index.d.ts +0 -0
  162. /package/{dist/preact → preact}/index.d.ts.map +0 -0
  163. /package/{dist/esm/preact/index.js → preact/index.mjs} +0 -0
  164. /package/{dist/react → react}/Router.d.ts +0 -0
  165. /package/{dist/react → react}/Router.d.ts.map +0 -0
  166. /package/{dist/cjs/react/index.js → react/index.cjs} +0 -0
  167. /package/{dist/react → react}/index.d.ts +0 -0
  168. /package/{dist/react → react}/index.d.ts.map +0 -0
  169. /package/{dist/esm/react/index.js → react/index.mjs} +0 -0
  170. /package/{dist/solid → solid}/Router.d.ts +0 -0
  171. /package/{dist/solid → solid}/Router.d.ts.map +0 -0
  172. /package/{dist/cjs/solid/index.js → solid/index.cjs} +0 -0
  173. /package/{dist/solid → solid}/index.d.ts +0 -0
  174. /package/{dist/solid → solid}/index.d.ts.map +0 -0
  175. /package/{dist/esm/solid/index.js → solid/index.mjs} +0 -0
  176. /package/{dist/cjs/vue/index.js → vue/index.cjs} +0 -0
  177. /package/{dist/vue → vue}/index.d.ts +0 -0
  178. /package/{dist/vue → vue}/index.d.ts.map +0 -0
  179. /package/{dist/esm/vue/index.js → vue/index.mjs} +0 -0
@@ -1,185 +0,0 @@
1
- # Router Configuration
2
-
3
- The router is the central piece that manages the state of the router and provides methods for navigation. It's created using the `createRouter` function.
4
-
5
- ## Creating a Router Store
6
-
7
- ```typescript [router.ts]
8
- import { createRouter } from 'reactive-route';
9
- import { adapters } from 'reactive-route/adapters/{reactive-system}';
10
-
11
- const routes = createRoutes({
12
- // ...your config
13
- });
14
-
15
- // If you prefer Context and SSR
16
- export function getRouter() {
17
- return createRouter({ routes, adapters });
18
- }
19
-
20
- // If you prefer singletons
21
- export const router = createRouter({ routes, adapters })
22
- ```
23
-
24
- The `createRouter` function accepts an object with the following properties:
25
-
26
- | Property | Type | Description |
27
- |-------------------|-----------------------------------|------------------------------------------------------------|
28
- | `routes` | `ReturnType<typeof createRoutes>` | The routes configuration |
29
- | `adapters` | `TypeAdapters` | Adapters for the state management system |
30
- | `lifecycleParams` | `Array<any>` | Built-in DI for `beforeEnter` and `beforeLeave` (optional) |
31
-
32
- You may pass your own adapters if they satisfy the model
33
-
34
- ```typescript
35
- type TypeAdapters = {
36
- batch: (cb: () => void) => void;
37
- autorun: (cb: () => void) => any;
38
- replaceObject: <TObj extends Record<string, any>>(obj: TObj, newObj: TObj) => void;
39
- makeObservable: <TObj extends Record<string, any>>(obj: TObj) => TObj;
40
- observer?: (comp: any) => any;
41
- };
42
- ```
43
-
44
- ## Router API
45
-
46
- The router store provides several methods for navigation and state management:
47
-
48
- | Property | Type | Description |
49
- |---------------------|-------------------------------------------------|------------------------------|
50
- | `currentRoute` | `TypeCurrentRoute<typeof routes['routeKey']>` | The current route data |
51
- | `routesHistory` | `Array<string>` | The history of visited paths |
52
- | `isRedirecting` | `boolean` | The indicator of redirecting |
53
- | `redirect` | `(config: TypeRedirectToParams): Promise<void>` | The navigation function |
54
- | `restoreFromURL` | `(params: { pathname: string }): Promise<void>` | To restore from url |
55
- | `restoreFromServer` | `(obj: TypeRouter): Promise<void>` | To restore from object |
56
- | `routes` | `ReturnType<typeof createRoutes>` | Routes configuration |
57
- | `lifecycleParams` | `Array<any>` | Custom lifecycle parameters |
58
-
59
- ### redirect
60
-
61
- Navigates to a specified route:
62
-
63
- ```typescript
64
- await router.redirect({
65
- route: 'about',
66
- // with dynamic parameters
67
- params: { id: '123' },
68
- // with query parameters
69
- query: { q: 's' },
70
- // if you want to replace history state instead of pushing
71
- replace: true,
72
- });
73
- ```
74
-
75
- This function is fully TypeScript-typed, and TypeScript hints will be shown for autocomplete.
76
-
77
- ```typescript
78
- const routes = createRoutes({
79
- static: {
80
- path: '/static',
81
- loader: () => import('./pages/static'),
82
- },
83
- dynamic: {
84
- path: '/page/:foo',
85
- params: {
86
- foo: (value: string) => value.length > 0,
87
- },
88
- query: {
89
- q: (value: string) => value.length > 0,
90
- },
91
- loader: () => import('./pages/dynamic'),
92
- },
93
-
94
- // other routes
95
- });
96
-
97
- // Good
98
- redirect({ route: 'static' })
99
- redirect({ route: 'dynamic', params: { foo: 'bar' } })
100
- redirect({ route: 'dynamic', params: { foo: 'bar' }, query: { q: 's' } })
101
-
102
- // TS errors
103
- redirect({ });
104
- redirect({ route: 'nonExisting' });
105
- redirect({ route: 'static', params: {} });
106
- redirect({ route: 'dynamic' });
107
- redirect({ route: 'dynamic', params: {} });
108
- redirect({ route: 'dynamic', params: { a: 'b' } });
109
- redirect({ route: 'dynamic', params: { foo: 'bar' }, query: { some: 'value' } });
110
- ```
111
-
112
- ### restoreFromURL
113
-
114
- Initializes the basic route from the current URL:
115
-
116
- ```typescript
117
- // Client-side
118
- await router.restoreFromURL({
119
- pathname: location.pathname + location.search,
120
- });
121
-
122
- // Server-side
123
- await router.restoreFromURL({
124
- // use your framework's way to get the full path + search
125
- pathname: req.originalUrl,
126
- });
127
- ```
128
-
129
- ### restoreFromServer
130
-
131
- Initializes the basic route from an object, for example SSR-prepared data:
132
-
133
- ```typescript
134
- await router.restoreFromServer({ routesHistory, currentRoute });
135
- ```
136
-
137
- ### currentRoute
138
-
139
- ```typescript
140
- import { TypeCurrentRoute } from 'reactive-route';
141
-
142
- const currentRoute = router.currentRoute
143
- as TypeCurrentRoute<typeof router.routes.dynamic>;
144
- ```
145
-
146
- The current route object has the following properties:
147
-
148
- | Property | Type | Description |
149
- |------------|-------------------------------------------------------|-------------------------------------------------------------------|
150
- | `name` | `string (keyof typeof routes)` | The name of the route |
151
- | `path` | `string (typeof routes[keyof typeof routes]['path'])` | The path of the route |
152
- | `params` | `Record<string, string>` | The parameters of the route |
153
- | `query` | `Record<string, string>` | The query parameters of the route |
154
- | `props` | `Record<string, any>` | The props for the component |
155
- | `pageId` | `string` | The name of the page, if exported from the page loader (optional) |
156
-
157
- Note that TS-typing is static and `currentRoute` is not necessarily this one. When redirecting is finished,
158
- it will become a new route instance, so if you use `autorun` to track current params, check `currentRoute.name` first.
159
-
160
- ## isRedirecting
161
-
162
- If you need to show loaders on redirects, you may use this parameter. For global loader:
163
-
164
- ```tsx
165
- const GlobalHeader = () => {
166
- const { router } = useContext(StoreContext);
167
-
168
- return router.isRedirecting ? <Loader /> : null;
169
- }
170
- ```
171
-
172
- Or for a local one:
173
-
174
- ```tsx
175
- const GlobalHeader = () => {
176
- const { router } = useContext(StoreContext);
177
-
178
- return <Button isLoading={router.isRedirecting} />;
179
- }
180
- ```
181
-
182
- ## routesHistory
183
-
184
- This array includes all the visited paths and may be used for logging or to check from which route
185
- the user came to the current page.
@@ -1,191 +0,0 @@
1
- # Routes Configuration
2
-
3
- The router configuration is the heart of Reactive Route. It defines all the routes in your application, their paths, parameters, and behavior.
4
-
5
- Use the `createRoutes` function to create a router configuration:
6
-
7
- ```typescript
8
- import { createRoutes } from 'reactive-route';
9
-
10
- const routes = createRoutes({
11
- // Your route definitions go here.
12
-
13
- // These routes are required
14
- notFound: {
15
- path: '/not-found',
16
- loader: () => import('./pages/error'),
17
- },
18
- internalError: {
19
- path: '/internal-error',
20
- loader: () => import('./pages/error'),
21
- },
22
- });
23
- ```
24
-
25
- ## Route Definition
26
-
27
- Each route is defined as a key-value pair in the configuration object. The key is the route name, and the value is an object with the route configuration.
28
-
29
- | Property | Type | Description |
30
- |---------------|--------------------------------------------------|-------------------------------------------------------------------------------------------------------|
31
- | `path` | `string` | The URL path for the route. Can include dynamic segments prefixed with `:` |
32
- | `loader` | `() => Promise<{ default, pageId, ...rest }>` | A function that returns a Promise resolving to the component (it should be in the **default** export) |
33
- | `props` | `Record<string, any>` | Static props to pass to the component (optional) |
34
- | `params` | `Record<string, (value: string) => boolean>` | Validation functions for path parameters (required if route type is Dynamic) |
35
- | `query` | `Record<string, (value: string) => boolean>` | Validation functions for query parameters (optional) |
36
- | `pageId` | `string` | An optimization for nested routes to avoid page's rerender (optional) |
37
- | `beforeEnter` | `(config: TypeLifecycleConfig) => Promise<void>` | Hook called before entering the route (optional) |
38
- | `beforeLeave` | `(config: TypeLifecycleConfig) => Promise<void>` | Hook called before leaving the route (optional) |
39
-
40
- ## Route Types
41
-
42
- ### Static Routes
43
-
44
- Static routes have fixed paths without parameters:
45
-
46
- ```typescript
47
- home: {
48
- path: '/',
49
- loader: () => import('./pages/Home'),
50
- }
51
- ```
52
-
53
- ### Dynamic Routes
54
-
55
- Dynamic routes have parameters in their paths, indicated by a colon prefix:
56
-
57
- ```typescript
58
- user: {
59
- path: '/user/:id',
60
- params: {
61
- id: (value) => /^\d+$/.test(value), // Validation function
62
- },
63
- loader: () => import('./pages/User'),
64
- }
65
- ```
66
-
67
- A validation function is required, and if it's not satisfied, the user will be redirected to the "notFound" route.
68
- If the page is rendered, you can be sure that all the params are validated and present in `router.currentRoute`.
69
-
70
- ### Routes with Query Parameters
71
-
72
- Both Static Routes and Dynamic Routes may have query parameters:
73
-
74
- ```typescript
75
- search: {
76
- path: '/search',
77
- query: {
78
- text: (value) => value.length > 0,
79
- },
80
- loader: () => import('./pages/Search'),
81
- }
82
- ```
83
-
84
- A validation function is required, and if it's not satisfied, the parameter will be inaccessible from the
85
- store. This means that all query parameters are optional and may be `undefined` in `router.currentRoute`.
86
-
87
- ## Navigation Guards
88
-
89
- Navigation guards allow you to control the navigation flow in your application. Both `beforeEnter` and `beforeLeave` are async functions.
90
-
91
- The `beforeEnter` hook is called before entering a route. It can be used to redirect to another route,
92
- perform authentication checks, and load data.
93
-
94
- The `beforeLeave` hook is called before leaving a route. It can be used to prevent navigation or
95
- show a confirmation dialog.
96
-
97
- ```typescript
98
- dashboard: {
99
- path: '/dashboard',
100
- loader: () => import('./pages/protected'),
101
- async beforeEnter(config) {
102
- await api.loadUser();
103
-
104
- if (!isAuthenticated()) {
105
- return config.redirect({ route: 'login', query: { return: 'dashboard' } });
106
- }
107
-
108
- await api.loadDashboard();
109
- },
110
- async beforeLeave(config) {
111
- const hasUnsavedChanges = await api.checkSavedForm();
112
-
113
- if (hasUnsavedChanges) {
114
- const confirmed = window.confirm(
115
- `You have unsaved changes. Are you sure you want to leave?`
116
- );
117
-
118
- if (!confirmed) return config.preventRedirect();
119
- }
120
-
121
- if (config.nextRoute.name === 'user') {
122
- return config.preventRedirect();
123
- }
124
- },
125
- }
126
- ```
127
-
128
- Always remember to use `return` with `config.redirect` and `config.preventRedirect` to ensure proper flow control.
129
-
130
- Uncaught errors in `beforeEnter` or `beforeLeave` will lead to the rendering of the "internalError" route,
131
- so it's important to handle errors properly using `try-catch` blocks or `Promise.catch()` methods.
132
-
133
- Note that `beforeEnter` is called on dynamic parameter changes, but not called on query changes.
134
- This behavior may become configurable in future versions.
135
-
136
- ### Accessing Route Information
137
-
138
- The `config` is an object with parameters as follows:
139
-
140
- ```typescript
141
- type TypeLifecycleConfig = {
142
- nextUrl: string;
143
- nextRoute: any;
144
- nextPathname: string;
145
- nextQuery?: any;
146
- nextSearch?: string;
147
-
148
- currentUrl?: string;
149
- currentQuery?: any;
150
- currentRoute?: any;
151
- currentSearch?: string;
152
- currentPathname?: string;
153
-
154
- redirect: (params: any) => void;
155
- preventRedirect: () => void;
156
- };
157
- ```
158
-
159
- Be careful with `config.redirect` function. It accepts the same route data as `router.redirect`,
160
- but is not typed. So, if you refactor your routes, TS errors will not be shown here which may lead to
161
- incorrect redirects.
162
-
163
- ### Accessing Custom Parameters in Lifecycle Hooks
164
-
165
- Both `beforeEnter` and `beforeLeave` support passing custom parameters. These parameters are passed through
166
- `createRouter({ lifecycleParams })` as will be described in the next section of the documentation.
167
-
168
- ```typescript
169
- const routes = createRoutes({
170
- dashboard: {
171
- path: '/dashboard',
172
- loader: () => import('./pages/protected'),
173
- async beforeEnter(config, userStore: UserStore, uiStore: UIStore) {
174
- if (!userStore.isAuthenticated()) {
175
- return config.redirect({ route: 'login' });
176
- }
177
- },
178
- async beforeLeave(config, userStore, uiStore) {
179
- console.log(userStore, uiStore);
180
- },
181
- },
182
-
183
- // Other routes
184
- });
185
-
186
- createRouter({ routes, lifecycleParams: [new UserStore(), new UIStore()] })
187
- ```
188
-
189
- This approach may not be necessary for CSR-only projects with singletons, as you can simply import `userStore`
190
- and `uiStore` directly. However, for SSR projects, it's a powerful helper because you can't use singletons
191
- in that context, and each store needs to be created for every request.
@@ -1,68 +0,0 @@
1
- # Solid.js Integration
2
-
3
- ## Solid.js native reactivity
4
-
5
- The relevant imports are as follows
6
-
7
- ```typescript
8
- import { Router } from 'reactive-route/solid';
9
- import { adapters } from 'reactive-route/adapters/solid';
10
- ```
11
-
12
- No extra packages or configuration needed.
13
-
14
- ## Mobx
15
-
16
- The relevant imports are as follows
17
-
18
- ```typescript
19
- import { Router } from 'reactive-route/solid';
20
- import { adapters } from 'reactive-route/adapters/mobx-solid';
21
- ```
22
-
23
- You should ensure that package `mobx` is installed.
24
-
25
- Actually Solid.js has no native integration with MobX. So if you use MobX with Solid.js you probably
26
- use something like this:
27
-
28
- ```typescript
29
- import { Reaction } from 'mobx';
30
- import { enableExternalSource } from 'solid-js';
31
-
32
- let id = 0;
33
-
34
- enableExternalSource((fn, trigger) => {
35
- const reaction = new Reaction(`mobx@${++id}`, trigger);
36
-
37
- return {
38
- track: (x) => {
39
- let next;
40
- reaction.track(() => (next = fn(x)));
41
- return next;
42
- },
43
- dispose: () => reaction.dispose(),
44
- };
45
- });
46
- ```
47
-
48
- ... or has better alternatives. Anyway, something like this should be included in your entry file.
49
-
50
- ## Observable
51
-
52
- The relevant imports are as follows
53
-
54
- ```typescript
55
- import { Router } from 'reactive-route/solid';
56
- import { adapters } from 'reactive-route/adapters/kr-observable-solid';
57
- ```
58
-
59
- You should ensure that package `kr-observable` is installed.
60
-
61
- Be sure to enable integration in your entry file
62
-
63
- ```typescript
64
- import { enableObservable } from 'kr-observable/solidjs';
65
-
66
- enableObservable();
67
- ```
68
-
@@ -1,70 +0,0 @@
1
- # Server-Side Rendering
2
-
3
- For server-side rendering, you need to initialize the router store on both the server and the client.
4
- Use `renderToString` and `hydrate` from you framework, as well as `escapeAllStrings` and `unescapeAllStrings` -
5
- for example, from `lodash`. These utilities are not included in `reactive-route`.
6
-
7
- ### Server
8
-
9
- ```tsx [server.tsx]
10
- import { getRouter } from './router';
11
- import { StoreContext } from './StoreContext';
12
- import { RedirectError } from 'reactive-route';
13
-
14
- express()
15
- .get('*', async (req, res) => {
16
- const template = fs.readFileSync(templatePath, 'utf-8');
17
-
18
- const router = getRouter();
19
-
20
- try {
21
- await router.restoreFromURL({ pathname: req.originalUrl });
22
- } catch (error: any) {
23
- // The redirects on server-side are made manually, because
24
- // we can't manipulate the browser's url and history
25
- if (error instanceof RedirectError) {
26
- // error.message is a full new path here
27
- return res.redirect(error.message);
28
- }
29
-
30
- console.error(error);
31
-
32
- return res.status(500).send('Unexpected error');
33
- }
34
-
35
- const htmlMarkup = renderToString(
36
- <StoreContext.Provider value={{ router }}>
37
- <App />
38
- </StoreContext.Provider>
39
- );
40
-
41
- // A very simple method of serialization, but sufficient for react-route
42
- const storeJS = JSON.parse(JSON.stringify({ router }));
43
- const initialData = JSON.stringify(escapeAllStrings(storeJS));
44
-
45
- res.send(
46
- template
47
- .replace(`<!-- HTML -->`, htmlMarkup)
48
- .replace('<!-- INITIAL_DATA -->', initialData)
49
- );
50
- })
51
- ```
52
-
53
- ### Client
54
-
55
- ```tsx [client.tsx]
56
- import { getRouter } from './router';
57
- import { StoreContext } from './StoreContext';
58
-
59
- const router = getRouter();
60
- const initialData = unescapeAllStrings(window.INITIAL_DATA);
61
-
62
- await router.restoreFromServer(initialData.router);
63
-
64
- hydrate(
65
- document.getElementById('app'),
66
- <StoreContext.Provider value={{ router }}>
67
- <App />
68
- </StoreContext.Provider>
69
- );
70
- ```
@@ -1,29 +0,0 @@
1
- ---
2
- layout: home
3
-
4
- hero:
5
- name: "Reactive Route"
6
- text: "Framework-agnostic reactive routing"
7
- tagline: A lightweight, flexible, and reactive router for React, Preact and Solid.js
8
- actions:
9
- - theme: brand
10
- text: Get Started
11
- link: /guide/
12
- - theme: alt
13
- text: View on GitHub
14
- link: https://github.com/dkazakov8/reactive-route
15
-
16
- features:
17
- - title: Framework Agnostic
18
- details: Core routing logic is framework-agnostic, with adapters for React, Preact and Solid.js
19
- - title: State Management Integration
20
- details: Seamlessly integrates with MobX, Observable, and Solid.js reactivity systems
21
- - title: Type Safety
22
- details: Built with TypeScript for type safety and better developer experience
23
- - title: Config-based
24
- details: Define your routes in a simple, declarative configuration object
25
- - title: Navigation Guards
26
- details: Powerful async beforeEnter and beforeLeave route lifecycle with DI
27
- - title: SSR Support
28
- details: Full support for server-side rendering in any supported framework
29
- ---
@@ -1,23 +0,0 @@
1
- import { defineConfig } from 'vitest/config';
2
-
3
- export default defineConfig({
4
- test: {
5
- projects: ['packages/vue/vitest.config.mjs' /*, 'packages/vue/vitest.ssr.config.mjs'*/],
6
- coverage: {
7
- clean: false,
8
- enabled: true,
9
- provider: 'istanbul',
10
- reporter: ['text', ['cobertura', { file: 'core.xml' }]],
11
- reportsDirectory: './.nyc_output',
12
- include: ['packages/*'],
13
- exclude: ['packages/*/test/*', 'packages/shared'],
14
- },
15
- onConsoleLog(log) {
16
- if (log.includes('a is not defined') /*|| log.includes('warn')*/) {
17
- return false;
18
- }
19
-
20
- return true;
21
- },
22
- },
23
- });
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes