@vaadin/hilla-file-router 24.4.0-alpha9 → 24.4.0-beta2

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 (60) hide show
  1. package/package.json +5 -4
  2. package/runtime/RouterConfigurationBuilder.d.ts +56 -0
  3. package/runtime/RouterConfigurationBuilder.d.ts.map +1 -0
  4. package/runtime/RouterConfigurationBuilder.js +157 -0
  5. package/runtime/RouterConfigurationBuilder.js.map +7 -0
  6. package/runtime/createMenuItems.d.ts +4 -4
  7. package/runtime/createMenuItems.d.ts.map +1 -1
  8. package/runtime/createMenuItems.js +8 -3
  9. package/runtime/createMenuItems.js.map +2 -2
  10. package/runtime/createRoute.d.ts +3 -3
  11. package/runtime/createRoute.d.ts.map +1 -1
  12. package/runtime/createRoute.js +1 -1
  13. package/runtime/createRoute.js.map +2 -2
  14. package/runtime.d.ts +1 -1
  15. package/runtime.d.ts.map +1 -1
  16. package/runtime.js +1 -1
  17. package/runtime.js.map +1 -1
  18. package/shared/convertComponentNameToTitle.d.ts +1 -1
  19. package/shared/convertComponentNameToTitle.d.ts.map +1 -1
  20. package/shared/convertComponentNameToTitle.js +4 -7
  21. package/shared/convertComponentNameToTitle.js.map +2 -2
  22. package/shared/internal.d.ts +10 -5
  23. package/shared/transformTree.d.ts +2 -0
  24. package/shared/transformTree.d.ts.map +1 -0
  25. package/shared/transformTree.js +7 -0
  26. package/shared/transformTree.js.map +7 -0
  27. package/types.d.ts +27 -9
  28. package/vite-plugin/collectRoutesFromFS.d.ts +6 -6
  29. package/vite-plugin/collectRoutesFromFS.d.ts.map +1 -1
  30. package/vite-plugin/collectRoutesFromFS.js +55 -37
  31. package/vite-plugin/collectRoutesFromFS.js.map +2 -2
  32. package/vite-plugin/createRoutesFromMeta.d.ts +1 -1
  33. package/vite-plugin/createRoutesFromMeta.d.ts.map +1 -1
  34. package/vite-plugin/createRoutesFromMeta.js +36 -18
  35. package/vite-plugin/createRoutesFromMeta.js.map +2 -2
  36. package/vite-plugin/createViewConfigJson.d.ts +1 -1
  37. package/vite-plugin/createViewConfigJson.d.ts.map +1 -1
  38. package/vite-plugin/createViewConfigJson.js +55 -50
  39. package/vite-plugin/createViewConfigJson.js.map +2 -2
  40. package/vite-plugin/generateRuntimeFiles.d.ts.map +1 -1
  41. package/vite-plugin/generateRuntimeFiles.js +3 -2
  42. package/vite-plugin/generateRuntimeFiles.js.map +2 -2
  43. package/vite-plugin/utils.d.ts +1 -1
  44. package/vite-plugin/utils.js.map +1 -1
  45. package/vite-plugin.d.ts +8 -2
  46. package/vite-plugin.d.ts.map +1 -1
  47. package/vite-plugin.js +24 -9
  48. package/vite-plugin.js.map +2 -2
  49. package/runtime/toReactRouter.d.ts +0 -12
  50. package/runtime/toReactRouter.d.ts.map +0 -1
  51. package/runtime/toReactRouter.js +0 -25
  52. package/runtime/toReactRouter.js.map +0 -7
  53. package/runtime/utils.d.ts +0 -11
  54. package/runtime/utils.d.ts.map +0 -1
  55. package/runtime/utils.js +0 -11
  56. package/runtime/utils.js.map +0 -7
  57. package/shared/traverse.d.ts +0 -10
  58. package/shared/traverse.d.ts.map +0 -1
  59. package/shared/traverse.js +0 -14
  60. package/shared/traverse.js.map +0 -7
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-file-router",
3
- "version": "24.4.0-alpha9",
3
+ "version": "24.4.0-beta2",
4
4
  "description": "Hilla file-based router",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -8,7 +8,7 @@
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/vaadin/hilla.git",
11
- "directory": "packages/ts/hilla-file-router"
11
+ "directory": "packages/ts/file-router"
12
12
  },
13
13
  "keywords": [
14
14
  "Hilla",
@@ -26,7 +26,7 @@
26
26
  "build:copy": "cd src && copyfiles *.d.ts **/*.d.ts ..",
27
27
  "lint": "eslint src test",
28
28
  "lint:fix": "eslint src test --fix",
29
- "test": "mocha test/**/*.spec.ts --config ../../../.mocharc.cjs",
29
+ "test": "mocha test/**/*.spec.{ts,tsx} --config ../../../.mocharc.cjs",
30
30
  "test:coverage": "c8 -c ../../../.c8rc.json npm test",
31
31
  "typecheck": "tsc --noEmit"
32
32
  },
@@ -80,7 +80,8 @@
80
80
  "type-fest": "^4.9.0"
81
81
  },
82
82
  "dependencies": {
83
- "@vaadin/hilla-generator-utils": "24.4.0-alpha9",
83
+ "@vaadin/hilla-generator-utils": "24.4.0-beta2",
84
+ "@vaadin/hilla-react-auth": "24.4.0-beta2",
84
85
  "react": "^18.2.0",
85
86
  "rollup": "^4.12.0",
86
87
  "typescript": "5.3.2"
@@ -0,0 +1,56 @@
1
+ import { type ComponentType } from 'react';
2
+ import { type RouteObject } from 'react-router-dom';
3
+ import type { AgnosticRoute, RouterBuildOptions, RouterConfiguration, ViewConfig } from '../types.js';
4
+ interface RouteBase {
5
+ path?: string;
6
+ children?: readonly this[];
7
+ }
8
+ type RouteTransformer<T> = (original: RouteObject | undefined, overriding: T | undefined, children?: readonly RouteObject[]) => RouteObject | undefined;
9
+ /**
10
+ * A builder for creating a Vaadin-specific router for React with
11
+ * authentication and server routes support.
12
+ */
13
+ export declare class RouterConfigurationBuilder {
14
+ #private;
15
+ /**
16
+ * Adds the given routes to the current list of routes. All the routes are
17
+ * deeply merged to preserve the path uniqueness.
18
+ *
19
+ * @param routes - A list of routes to add to the current list.
20
+ */
21
+ withReactRoutes(routes: readonly RouteObject[]): this;
22
+ /**
23
+ * Adds the given file routes to the current list of routes. All the routes
24
+ * are transformed to React RouterObjects and deeply merged to preserve the
25
+ * path uniqueness.
26
+ *
27
+ * @param routes - A list of routes to add to the current list.
28
+ */
29
+ withFileRoutes(routes: readonly AgnosticRoute[]): this;
30
+ /**
31
+ * Adds the given server route element to each branch of the current list of
32
+ * routes.
33
+ *
34
+ * @param component - The React component to add to each branch of the
35
+ * current list of routes.
36
+ * @param config - An optional configuration that will be applied to
37
+ * each fallback component.
38
+ */
39
+ withFallback(component: ComponentType, config?: ViewConfig): this;
40
+ /**
41
+ * Protects all the routes that require authentication. For more details see
42
+ * {@link @vaadin/hilla-react-auth#protectRoutes} function.
43
+ *
44
+ * @param redirectPath - the path to redirect to if the route is protected
45
+ * and the user is not authenticated.
46
+ */
47
+ protect(redirectPath?: string): this;
48
+ update<T extends RouteBase>(routes: undefined, callback: RouteTransformer<undefined>): this;
49
+ update<T extends RouteBase>(routes: readonly T[], callback?: RouteTransformer<T>): this;
50
+ /**
51
+ * Builds the router with the current list of routes.
52
+ */
53
+ build(options?: RouterBuildOptions): RouterConfiguration;
54
+ }
55
+ export {};
56
+ //# sourceMappingURL=RouterConfigurationBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RouterConfigurationBuilder.d.ts","sourceRoot":"","sources":["../src/runtime/RouterConfigurationBuilder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAIL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,KAAK,EACV,aAAa,EAGb,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,EACX,MAAM,aAAa,CAAC;AAErB,UAAU,SAAS;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;CAC5B;AAQD,KAAK,gBAAgB,CAAC,CAAC,IAAI,CACzB,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,UAAU,EAAE,CAAC,GAAG,SAAS,EACzB,QAAQ,CAAC,EAAE,SAAS,WAAW,EAAE,KAC9B,WAAW,GAAG,SAAS,CAAC;AAM7B;;;GAGG;AACH,qBAAa,0BAA0B;;IAGrC;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,IAAI;IAIrD;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,IAAI;IAoCtD;;;;;;;;OAQG;IACH,YAAY,CAAC,SAAS,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,IAAI;IAuBjE;;;;;;OAMG;IACH,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI;IAUpC,MAAM,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,gBAAgB,CAAC,SAAS,CAAC,GAAG,IAAI;IAC3F,MAAM,CAAC,CAAC,SAAS,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAAG,IAAI;IAwDvF;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,mBAAmB;CASzD"}
@@ -0,0 +1,157 @@
1
+ import { protectRoute } from "@vaadin/hilla-react-auth";
2
+ import { createElement } from "react";
3
+ import {
4
+ createBrowserRouter
5
+ } from "react-router-dom";
6
+ import { convertComponentNameToTitle } from "../shared/convertComponentNameToTitle.js";
7
+ import { transformTree } from "../shared/transformTree.js";
8
+ function isReactRouteModule(module) {
9
+ return module ? "default" in module && typeof module.default === "function" : true;
10
+ }
11
+ function createRouteEntry(route) {
12
+ return [`${route.path ?? ""}-${route.children ? "n" : "i"}`, route];
13
+ }
14
+ class RouterConfigurationBuilder {
15
+ #modifiers = [];
16
+ /**
17
+ * Adds the given routes to the current list of routes. All the routes are
18
+ * deeply merged to preserve the path uniqueness.
19
+ *
20
+ * @param routes - A list of routes to add to the current list.
21
+ */
22
+ withReactRoutes(routes) {
23
+ return this.update(routes);
24
+ }
25
+ /**
26
+ * Adds the given file routes to the current list of routes. All the routes
27
+ * are transformed to React RouterObjects and deeply merged to preserve the
28
+ * path uniqueness.
29
+ *
30
+ * @param routes - A list of routes to add to the current list.
31
+ */
32
+ withFileRoutes(routes) {
33
+ return this.update(routes, (original, added, children) => {
34
+ if (added) {
35
+ const { module, path } = added;
36
+ if (!isReactRouteModule(module)) {
37
+ throw new Error(`The module for the "${path}" section doesn't have the React component exported by default`);
38
+ }
39
+ const element = module?.default ? createElement(module.default) : void 0;
40
+ const handle = {
41
+ ...module?.config,
42
+ title: module?.config?.title ?? convertComponentNameToTitle(module?.default)
43
+ };
44
+ if (path === "" && !children) {
45
+ return {
46
+ ...original,
47
+ element,
48
+ handle,
49
+ index: true
50
+ };
51
+ }
52
+ return {
53
+ ...original,
54
+ path: module?.config?.route ?? path,
55
+ element,
56
+ children,
57
+ handle
58
+ };
59
+ }
60
+ return original;
61
+ });
62
+ }
63
+ /**
64
+ * Adds the given server route element to each branch of the current list of
65
+ * routes.
66
+ *
67
+ * @param component - The React component to add to each branch of the
68
+ * current list of routes.
69
+ * @param config - An optional configuration that will be applied to
70
+ * each fallback component.
71
+ */
72
+ withFallback(component, config) {
73
+ const fallbackRoutes = [
74
+ { path: "*", element: createElement(component), handle: config },
75
+ { index: true, element: createElement(component), handle: config }
76
+ ];
77
+ this.update(fallbackRoutes, (original, added, children) => {
78
+ if (original) {
79
+ return children ? {
80
+ ...original,
81
+ children: [...children, ...fallbackRoutes]
82
+ } : original;
83
+ }
84
+ return added;
85
+ });
86
+ return this;
87
+ }
88
+ /**
89
+ * Protects all the routes that require authentication. For more details see
90
+ * {@link @vaadin/hilla-react-auth#protectRoutes} function.
91
+ *
92
+ * @param redirectPath - the path to redirect to if the route is protected
93
+ * and the user is not authenticated.
94
+ */
95
+ protect(redirectPath) {
96
+ this.update(void 0, (route, _, children) => {
97
+ const finalRoute = protectRoute(route, redirectPath);
98
+ finalRoute.children = children;
99
+ return finalRoute;
100
+ });
101
+ return this;
102
+ }
103
+ update(routes, callback = (original, overriding, children) => ({
104
+ ...original,
105
+ ...overriding,
106
+ children
107
+ })) {
108
+ this.#modifiers.push(
109
+ (existingRoutes) => transformTree(
110
+ [existingRoutes, routes],
111
+ ([original, added], next) => {
112
+ if (original && added) {
113
+ const originalMap = new Map(original.map((route) => createRouteEntry(route)));
114
+ const addedMap = new Map(added.map((route) => createRouteEntry(route)));
115
+ const paths = /* @__PURE__ */ new Set([...originalMap.keys(), ...addedMap.keys()]);
116
+ for (const path of paths) {
117
+ const originalRoute = originalMap.get(path);
118
+ const addedRoute = addedMap.get(path);
119
+ let route;
120
+ if (originalRoute && addedRoute) {
121
+ route = callback(originalRoute, addedRoute, next(originalRoute.children, addedRoute.children));
122
+ } else if (originalRoute) {
123
+ route = callback(originalRoute, void 0, next(originalRoute.children, void 0));
124
+ } else {
125
+ route = callback(void 0, addedRoute, next(void 0, addedRoute.children));
126
+ }
127
+ if (route) {
128
+ originalMap.set(path, route);
129
+ }
130
+ }
131
+ return [...originalMap.values()];
132
+ } else if (original) {
133
+ return original.map((route) => callback(route, void 0, next(route.children, void 0))).filter(Boolean);
134
+ } else if (added) {
135
+ return added.map((route) => callback(void 0, route, next(void 0, route.children))).filter(Boolean);
136
+ }
137
+ return void 0;
138
+ }
139
+ )
140
+ );
141
+ return this;
142
+ }
143
+ /**
144
+ * Builds the router with the current list of routes.
145
+ */
146
+ build(options) {
147
+ const routes = this.#modifiers.reduce((acc, mod) => mod(acc) ?? acc, void 0) ?? [];
148
+ return {
149
+ routes,
150
+ router: createBrowserRouter([...routes], { basename: new URL(document.baseURI).pathname, ...options })
151
+ };
152
+ }
153
+ }
154
+ export {
155
+ RouterConfigurationBuilder
156
+ };
157
+ //# sourceMappingURL=RouterConfigurationBuilder.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/runtime/RouterConfigurationBuilder.ts"],
4
+ "sourcesContent": ["/* eslint-disable @typescript-eslint/consistent-type-assertions */\nimport { protectRoute } from '@vaadin/hilla-react-auth';\nimport { type ComponentType, createElement } from 'react';\nimport {\n createBrowserRouter,\n type IndexRouteObject,\n type NonIndexRouteObject,\n type RouteObject,\n} from 'react-router-dom';\nimport { convertComponentNameToTitle } from '../shared/convertComponentNameToTitle.js';\nimport { transformTree } from '../shared/transformTree.js';\nimport type {\n AgnosticRoute,\n Module,\n RouteModule,\n RouterBuildOptions,\n RouterConfiguration,\n ViewConfig,\n} from '../types.js';\n\ninterface RouteBase {\n path?: string;\n children?: readonly this[];\n}\n\ntype RoutesModifier = (routes: readonly RouteObject[] | undefined) => readonly RouteObject[] | undefined;\n\nfunction isReactRouteModule(module?: Module): module is RouteModule<ComponentType> | undefined {\n return module ? 'default' in module && typeof module.default === 'function' : true;\n}\n\ntype RouteTransformer<T> = (\n original: RouteObject | undefined,\n overriding: T | undefined,\n children?: readonly RouteObject[],\n) => RouteObject | undefined;\n\nfunction createRouteEntry<T extends RouteBase>(route: T): readonly [key: string, value: T] {\n return [`${route.path ?? ''}-${route.children ? 'n' : 'i'}`, route];\n}\n\n/**\n * A builder for creating a Vaadin-specific router for React with\n * authentication and server routes support.\n */\nexport class RouterConfigurationBuilder {\n readonly #modifiers: RoutesModifier[] = [];\n\n /**\n * Adds the given routes to the current list of routes. All the routes are\n * deeply merged to preserve the path uniqueness.\n *\n * @param routes - A list of routes to add to the current list.\n */\n withReactRoutes(routes: readonly RouteObject[]): this {\n return this.update(routes);\n }\n\n /**\n * Adds the given file routes to the current list of routes. All the routes\n * are transformed to React RouterObjects and deeply merged to preserve the\n * path uniqueness.\n *\n * @param routes - A list of routes to add to the current list.\n */\n withFileRoutes(routes: readonly AgnosticRoute[]): this {\n return this.update(routes, (original, added, children) => {\n if (added) {\n const { module, path } = added;\n if (!isReactRouteModule(module)) {\n throw new Error(`The module for the \"${path}\" section doesn't have the React component exported by default`);\n }\n\n const element = module?.default ? createElement(module.default) : undefined;\n const handle = {\n ...module?.config,\n title: module?.config?.title ?? convertComponentNameToTitle(module?.default),\n };\n\n if (path === '' && !children) {\n return {\n ...original,\n element,\n handle,\n index: true,\n } as IndexRouteObject;\n }\n\n return {\n ...original,\n path: module?.config?.route ?? path,\n element,\n children,\n handle,\n } as NonIndexRouteObject;\n }\n\n return original;\n });\n }\n\n /**\n * Adds the given server route element to each branch of the current list of\n * routes.\n *\n * @param component - The React component to add to each branch of the\n * current list of routes.\n * @param config - An optional configuration that will be applied to\n * each fallback component.\n */\n withFallback(component: ComponentType, config?: ViewConfig): this {\n // Fallback adds two routes, so that the index (empty path) has a fallback too\n const fallbackRoutes = [\n { path: '*', element: createElement(component), handle: config },\n { index: true, element: createElement(component), handle: config },\n ];\n\n this.update(fallbackRoutes, (original, added, children) => {\n if (original) {\n return children\n ? ({\n ...original,\n children: [...children, ...fallbackRoutes],\n } as RouteObject)\n : original;\n }\n\n return added!;\n });\n\n return this;\n }\n\n /**\n * Protects all the routes that require authentication. For more details see\n * {@link @vaadin/hilla-react-auth#protectRoutes} function.\n *\n * @param redirectPath - the path to redirect to if the route is protected\n * and the user is not authenticated.\n */\n protect(redirectPath?: string): this {\n this.update(undefined, (route, _, children) => {\n const finalRoute = protectRoute(route!, redirectPath);\n finalRoute.children = children as RouteObject[] | undefined;\n return finalRoute;\n });\n\n return this;\n }\n\n update<T extends RouteBase>(routes: undefined, callback: RouteTransformer<undefined>): this;\n update<T extends RouteBase>(routes: readonly T[], callback?: RouteTransformer<T>): this;\n update<T extends RouteBase>(\n routes: readonly T[] | undefined,\n callback: RouteTransformer<T | undefined> = (original, overriding, children) =>\n ({\n ...original,\n ...overriding,\n children,\n }) as RouteObject,\n ): this {\n this.#modifiers.push((existingRoutes) =>\n transformTree<[readonly RouteObject[] | undefined, readonly T[] | undefined], readonly RouteObject[] | undefined>(\n [existingRoutes, routes],\n ([original, added], next) => {\n if (original && added) {\n const originalMap = new Map(original.map((route) => createRouteEntry(route)));\n const addedMap = new Map(added.map((route) => createRouteEntry(route)));\n\n const paths = new Set([...originalMap.keys(), ...addedMap.keys()]);\n\n for (const path of paths) {\n const originalRoute = originalMap.get(path);\n const addedRoute = addedMap.get(path);\n\n let route: RouteObject | undefined;\n if (originalRoute && addedRoute) {\n route = callback(originalRoute, addedRoute, next(originalRoute.children, addedRoute.children));\n } else if (originalRoute) {\n route = callback(originalRoute, undefined, next(originalRoute.children, undefined));\n } else {\n route = callback(undefined, addedRoute, next(undefined, addedRoute!.children));\n }\n\n if (route) {\n originalMap.set(path, route);\n }\n }\n\n return [...originalMap.values()];\n } else if (original) {\n return original\n .map((route) => callback(route, undefined, next(route.children, undefined)))\n .filter(Boolean) as readonly RouteObject[];\n } else if (added) {\n return added\n .map((route) => callback(undefined, route, next(undefined, route.children)))\n .filter(Boolean) as readonly RouteObject[];\n }\n\n return undefined;\n },\n ),\n );\n return this;\n }\n\n /**\n * Builds the router with the current list of routes.\n */\n build(options?: RouterBuildOptions): RouterConfiguration {\n const routes =\n this.#modifiers.reduce<readonly RouteObject[] | undefined>((acc, mod) => mod(acc) ?? acc, undefined) ?? [];\n\n return {\n routes,\n router: createBrowserRouter([...routes], { basename: new URL(document.baseURI).pathname, ...options }),\n };\n }\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -1,14 +1,14 @@
1
1
  import type { MenuItem } from '../types.js';
2
2
  /**
3
3
  * Creates menu items from the views provided by the server. The views are sorted according to the
4
- * {@link ViewConfig.menu.order} and filtered out if they are explicitly excluded via {@link ViewConfig.menu.exclude}.
4
+ * {@link ViewConfig.menu.order}, filtered out if they are explicitly excluded via {@link ViewConfig.menu.exclude}.
5
+ * Note that views with no order are put below views with an order. Ties are resolved based on the path string
6
+ * comparison.
5
7
  *
6
8
  * @param vaadinObject - The Vaadin object containing the server views.
7
9
  * @returns A list of menu items.
8
10
  */
9
11
  export declare function createMenuItems(vaadinObject?: Readonly<{
10
- server?: Readonly<{
11
- views: Readonly<Record<string, import("../shared/internal.js").ServerViewConfig>>;
12
- }> | undefined;
12
+ views: Readonly<Record<string, import("../shared/internal.js").ServerViewMapItem>>;
13
13
  }> | undefined): readonly MenuItem[];
14
14
  //# sourceMappingURL=createMenuItems.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createMenuItems.d.ts","sourceRoot":"","sources":["../src/runtime/createMenuItems.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAC;AAExD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,YAAY;;;;cAAkC,GAAG,SAAS,QAAQ,EAAE,CAwBnG"}
1
+ {"version":3,"file":"createMenuItems.d.ts","sourceRoot":"","sources":["../src/runtime/createMenuItems.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,YAAY;;cAAkC,GAAG,SAAS,QAAQ,EAAE,CA6BnG"}
@@ -1,14 +1,19 @@
1
1
  import { RouteParamType } from "../shared/routeParamType.js";
2
2
  function createMenuItems(vaadinObject = window.Vaadin) {
3
- return vaadinObject?.server?.views ? Object.entries(vaadinObject.server.views).filter(
3
+ const collator = new Intl.Collator("en-US");
4
+ return vaadinObject?.views ? Object.entries(vaadinObject.views).filter(
4
5
  ([_key, value]) => !value.menu?.exclude && !(value.params && Object.values(value.params).some((p) => p === RouteParamType.Required))
5
- ).sort(([_a, a], [_b, b]) => (a.menu?.order ?? 0) - (b.menu?.order ?? 0)).map(([path, config]) => {
6
+ ).map(([path, config]) => {
6
7
  const _path = config.params ? Object.keys(config.params).reduce((acc, key) => acc.replaceAll(key, ""), path) : path;
7
8
  return {
8
9
  to: _path,
9
10
  icon: config.menu?.icon,
10
- title: config.menu?.title ?? config.title
11
+ title: config.menu?.title ?? config.title,
12
+ order: config.menu?.order
11
13
  };
14
+ }).sort((menuA, menuB) => {
15
+ const ordersDiff = (menuA.order ?? Number.MAX_VALUE) - (menuB.order ?? Number.MAX_VALUE);
16
+ return ordersDiff !== 0 ? ordersDiff : collator.compare(menuA.to, menuB.to);
12
17
  }) : [];
13
18
  }
14
19
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/runtime/createMenuItems.ts"],
4
- "sourcesContent": ["import type { VaadinWindow } from '../shared/internal.js';\nimport { RouteParamType } from '../shared/routeParamType.js';\nimport type { MenuItem, ViewConfig } from '../types.js';\n\n/**\n * Creates menu items from the views provided by the server. The views are sorted according to the\n * {@link ViewConfig.menu.order} and filtered out if they are explicitly excluded via {@link ViewConfig.menu.exclude}.\n *\n * @param vaadinObject - The Vaadin object containing the server views.\n * @returns A list of menu items.\n */\nexport function createMenuItems(vaadinObject = (window as VaadinWindow).Vaadin): readonly MenuItem[] {\n return vaadinObject?.server?.views\n ? Object.entries(vaadinObject.server.views)\n // Filter out the views that are explicitly excluded from the menu.\n .filter(\n ([_key, value]) =>\n !value.menu?.exclude &&\n !(value.params && Object.values(value.params).some((p) => p === RouteParamType.Required)),\n )\n // Sort views according to the order specified in the view configuration.\n .sort(([_a, a], [_b, b]) => (a.menu?.order ?? 0) - (b.menu?.order ?? 0))\n // Map the views to menu items.\n .map(([path, config]) => {\n const _path = config.params\n ? Object.keys(config.params).reduce((acc, key) => acc.replaceAll(key, ''), path)\n : path;\n\n return {\n to: _path,\n icon: config.menu?.icon,\n title: config.menu?.title ?? config.title,\n };\n })\n : [];\n}\n"],
5
- "mappings": "AACA,SAAS,sBAAsB;AAUxB,SAAS,gBAAgB,eAAgB,OAAwB,QAA6B;AACnG,SAAO,cAAc,QAAQ,QACzB,OAAO,QAAQ,aAAa,OAAO,KAAK,EAErC;AAAA,IACC,CAAC,CAAC,MAAM,KAAK,MACX,CAAC,MAAM,MAAM,WACb,EAAE,MAAM,UAAU,OAAO,OAAO,MAAM,MAAM,EAAE,KAAK,CAAC,MAAM,MAAM,eAAe,QAAQ;AAAA,EAC3F,EAEC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,SAAS,MAAM,EAAE,MAAM,SAAS,EAAE,EAEtE,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM;AACvB,UAAM,QAAQ,OAAO,SACjB,OAAO,KAAK,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,IAAI,WAAW,KAAK,EAAE,GAAG,IAAI,IAC7E;AAEJ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,OAAO,MAAM;AAAA,MACnB,OAAO,OAAO,MAAM,SAAS,OAAO;AAAA,IACtC;AAAA,EACF,CAAC,IACH,CAAC;AACP;",
4
+ "sourcesContent": ["import type { VaadinWindow } from '../shared/internal.js';\nimport { RouteParamType } from '../shared/routeParamType.js';\nimport type { MenuItem, ViewConfig } from '../types.js';\n\n/**\n * Creates menu items from the views provided by the server. The views are sorted according to the\n * {@link ViewConfig.menu.order}, filtered out if they are explicitly excluded via {@link ViewConfig.menu.exclude}.\n * Note that views with no order are put below views with an order. Ties are resolved based on the path string\n * comparison.\n *\n * @param vaadinObject - The Vaadin object containing the server views.\n * @returns A list of menu items.\n */\nexport function createMenuItems(vaadinObject = (window as VaadinWindow).Vaadin): readonly MenuItem[] {\n const collator = new Intl.Collator('en-US');\n return vaadinObject?.views\n ? Object.entries(vaadinObject.views)\n // Filter out the views that are explicitly excluded from the menu.\n .filter(\n ([_key, value]) =>\n !value.menu?.exclude &&\n !(value.params && Object.values(value.params).some((p) => p === RouteParamType.Required)),\n )\n // Map the views to menu items.\n .map(([path, config]) => {\n const _path = config.params\n ? Object.keys(config.params).reduce((acc, key) => acc.replaceAll(key, ''), path)\n : path;\n\n return {\n to: _path,\n icon: config.menu?.icon,\n title: config.menu?.title ?? config.title,\n order: config.menu?.order,\n };\n })\n // Sort views according to the order specified in the view configuration.\n .sort((menuA, menuB) => {\n const ordersDiff = (menuA.order ?? Number.MAX_VALUE) - (menuB.order ?? Number.MAX_VALUE);\n return ordersDiff !== 0 ? ordersDiff : collator.compare(menuA.to, menuB.to);\n })\n : [];\n}\n"],
5
+ "mappings": "AACA,SAAS,sBAAsB;AAYxB,SAAS,gBAAgB,eAAgB,OAAwB,QAA6B;AACnG,QAAM,WAAW,IAAI,KAAK,SAAS,OAAO;AAC1C,SAAO,cAAc,QACjB,OAAO,QAAQ,aAAa,KAAK,EAE9B;AAAA,IACC,CAAC,CAAC,MAAM,KAAK,MACX,CAAC,MAAM,MAAM,WACb,EAAE,MAAM,UAAU,OAAO,OAAO,MAAM,MAAM,EAAE,KAAK,CAAC,MAAM,MAAM,eAAe,QAAQ;AAAA,EAC3F,EAEC,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM;AACvB,UAAM,QAAQ,OAAO,SACjB,OAAO,KAAK,OAAO,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,IAAI,WAAW,KAAK,EAAE,GAAG,IAAI,IAC7E;AAEJ,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,OAAO,MAAM;AAAA,MACnB,OAAO,OAAO,MAAM,SAAS,OAAO;AAAA,MACpC,OAAO,OAAO,MAAM;AAAA,IACtB;AAAA,EACF,CAAC,EAEA,KAAK,CAAC,OAAO,UAAU;AACtB,UAAM,cAAc,MAAM,SAAS,OAAO,cAAc,MAAM,SAAS,OAAO;AAC9E,WAAO,eAAe,IAAI,aAAa,SAAS,QAAQ,MAAM,IAAI,MAAM,EAAE;AAAA,EAC5E,CAAC,IACH,CAAC;AACP;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- import type { AgnosticRoute, RouteModule } from '../types.js';
1
+ import type { AgnosticRoute, Module } from '../types.js';
2
2
  /**
3
3
  * Create a single framework-agnostic route object. Later, it can be transformed into a framework-specific route object,
4
4
  * e.g., the one used by React Router.
@@ -8,6 +8,6 @@ import type { AgnosticRoute, RouteModule } from '../types.js';
8
8
  *
9
9
  * @returns A framework-agnostic route object.
10
10
  */
11
- export declare function createRoute<C = unknown>(path: string, children?: ReadonlyArray<AgnosticRoute<C>>): AgnosticRoute<C>;
12
- export declare function createRoute<C = unknown>(path: string, module: RouteModule<C>, children?: ReadonlyArray<AgnosticRoute<C>>): AgnosticRoute<C>;
11
+ export declare function createRoute(path: string, children?: readonly AgnosticRoute[]): AgnosticRoute;
12
+ export declare function createRoute(path: string, module: Module, children?: readonly AgnosticRoute[]): AgnosticRoute;
13
13
  //# sourceMappingURL=createRoute.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createRoute.d.ts","sourceRoot":"","sources":["../src/runtime/createRoute.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE9D;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;AACrH,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EACrC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,QAAQ,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,GACzC,aAAa,CAAC,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"createRoute.d.ts","sourceRoot":"","sources":["../src/runtime/createRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAEzD;;;;;;;;GAQG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,CAAC;AAC9F,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,CAAC"}
@@ -6,7 +6,7 @@ function createRoute(path, moduleOrChildren, children) {
6
6
  module = moduleOrChildren;
7
7
  }
8
8
  return {
9
- path: module?.config?.route ?? path,
9
+ path,
10
10
  module,
11
11
  children
12
12
  };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/runtime/createRoute.ts"],
4
- "sourcesContent": ["/* eslint-disable no-param-reassign */\nimport type { AgnosticRoute, RouteModule } from '../types.js';\n\n/**\n * Create a single framework-agnostic route object. Later, it can be transformed into a framework-specific route object,\n * e.g., the one used by React Router.\n *\n * @param path - A route path segment.\n * @param children - An array of child routes.\n *\n * @returns A framework-agnostic route object.\n */\nexport function createRoute<C = unknown>(path: string, children?: ReadonlyArray<AgnosticRoute<C>>): AgnosticRoute<C>;\nexport function createRoute<C = unknown>(\n path: string,\n module: RouteModule<C>,\n children?: ReadonlyArray<AgnosticRoute<C>>,\n): AgnosticRoute<C>;\nexport function createRoute<C = unknown>(\n path: string,\n moduleOrChildren?: ReadonlyArray<AgnosticRoute<C>> | RouteModule<C>,\n children?: ReadonlyArray<AgnosticRoute<C>>,\n): AgnosticRoute<C> {\n let module: RouteModule<C> | undefined;\n if (Array.isArray(moduleOrChildren)) {\n children = moduleOrChildren;\n } else {\n module = moduleOrChildren as RouteModule<C> | undefined;\n }\n\n return {\n path: module?.config?.route ?? path,\n module,\n children,\n };\n}\n"],
5
- "mappings": "AAkBO,SAAS,YACd,MACA,kBACA,UACkB;AAClB,MAAI;AACJ,MAAI,MAAM,QAAQ,gBAAgB,GAAG;AACnC,eAAW;AAAA,EACb,OAAO;AACL,aAAS;AAAA,EACX;AAEA,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ,SAAS;AAAA,IAC/B;AAAA,IACA;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import type { AgnosticRoute, Module } from '../types.js';\n\n/**\n * Create a single framework-agnostic route object. Later, it can be transformed into a framework-specific route object,\n * e.g., the one used by React Router.\n *\n * @param path - A route path segment.\n * @param children - An array of child routes.\n *\n * @returns A framework-agnostic route object.\n */\nexport function createRoute(path: string, children?: readonly AgnosticRoute[]): AgnosticRoute;\nexport function createRoute(path: string, module: Module, children?: readonly AgnosticRoute[]): AgnosticRoute;\nexport function createRoute(\n path: string,\n moduleOrChildren?: Module | readonly AgnosticRoute[],\n children?: readonly AgnosticRoute[],\n): AgnosticRoute {\n let module: Module | undefined;\n if (Array.isArray(moduleOrChildren)) {\n // eslint-disable-next-line no-param-reassign\n children = moduleOrChildren;\n } else {\n module = moduleOrChildren as Module | undefined;\n }\n\n return {\n path,\n module,\n children,\n };\n}\n"],
5
+ "mappings": "AAaO,SAAS,YACd,MACA,kBACA,UACe;AACf,MAAI;AACJ,MAAI,MAAM,QAAQ,gBAAgB,GAAG;AAEnC,eAAW;AAAA,EACb,OAAO;AACL,aAAS;AAAA,EACX;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
package/runtime.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from './runtime/createRoute.js';
2
- export * from './runtime/toReactRouter.js';
2
+ export * from './runtime/RouterConfigurationBuilder.js';
3
3
  export * from './runtime/useViewConfig.js';
4
4
  export * from './runtime/createMenuItems.js';
5
5
  //# sourceMappingURL=runtime.d.ts.map
package/runtime.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["src/runtime.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["src/runtime.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,yCAAyC,CAAC;AACxD,cAAc,4BAA4B,CAAC;AAC3C,cAAc,8BAA8B,CAAC"}
package/runtime.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export * from "./runtime/createRoute.js";
2
- export * from "./runtime/toReactRouter.js";
2
+ export * from "./runtime/RouterConfigurationBuilder.js";
3
3
  export * from "./runtime/useViewConfig.js";
4
4
  export * from "./runtime/createMenuItems.js";
5
5
  //# sourceMappingURL=runtime.js.map
package/runtime.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["src/runtime.ts"],
4
- "sourcesContent": ["export * from './runtime/createRoute.js';\nexport * from './runtime/toReactRouter.js';\nexport * from './runtime/useViewConfig.js';\nexport * from './runtime/createMenuItems.js';\n"],
4
+ "sourcesContent": ["export * from './runtime/createRoute.js';\nexport * from './runtime/RouterConfigurationBuilder.js';\nexport * from './runtime/useViewConfig.js';\nexport * from './runtime/createMenuItems.js';\n"],
5
5
  "mappings": "AAAA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
6
6
  "names": []
7
7
  }
@@ -5,5 +5,5 @@
5
5
  *
6
6
  * @returns The page title.
7
7
  */
8
- export declare function convertComponentNameToTitle(component?: unknown): string | undefined;
8
+ export declare function convertComponentNameToTitle(component: unknown): string;
9
9
  //# sourceMappingURL=convertComponentNameToTitle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertComponentNameToTitle.d.ts","sourceRoot":"","sources":["../src/shared/convertComponentNameToTitle.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAmBnF"}
1
+ {"version":3,"file":"convertComponentNameToTitle.d.ts","sourceRoot":"","sources":["../src/shared/convertComponentNameToTitle.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAetE"}
@@ -2,15 +2,12 @@ const viewPattern = /view/giu;
2
2
  const upperCaseSplitPattern = /(?=[A-Z])/gu;
3
3
  function convertComponentNameToTitle(component) {
4
4
  let name;
5
- if (typeof component === "string") {
6
- name = component;
7
- } else if (component && (typeof component === "object" || typeof component === "function") && "name" in component && typeof component.name === "string") {
5
+ if (component && (typeof component === "object" || typeof component === "function") && "name" in component && typeof component.name === "string") {
8
6
  ({ name } = component);
7
+ } else {
8
+ name = String(component);
9
9
  }
10
- if (name) {
11
- return name.replace(viewPattern, "").split(upperCaseSplitPattern).join(" ");
12
- }
13
- return void 0;
10
+ return name.replace(viewPattern, "").split(upperCaseSplitPattern).join(" ");
14
11
  }
15
12
  export {
16
13
  convertComponentNameToTitle
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/shared/convertComponentNameToTitle.ts"],
4
- "sourcesContent": ["const viewPattern = /view/giu;\nconst upperCaseSplitPattern = /(?=[A-Z])/gu;\n\n/**\n * Converts the name of the component to a page title.\n *\n * @param component - The component to convert the name from.\n *\n * @returns The page title.\n */\nexport function convertComponentNameToTitle(component?: unknown): string | undefined {\n let name: string | undefined;\n\n if (typeof component === 'string') {\n name = component;\n } else if (\n component &&\n (typeof component === 'object' || typeof component === 'function') &&\n 'name' in component &&\n typeof component.name === 'string'\n ) {\n ({ name } = component);\n }\n\n if (name) {\n return name.replace(viewPattern, '').split(upperCaseSplitPattern).join(' ');\n }\n\n return undefined;\n}\n"],
5
- "mappings": "AAAA,MAAM,cAAc;AACpB,MAAM,wBAAwB;AASvB,SAAS,4BAA4B,WAAyC;AACnF,MAAI;AAEJ,MAAI,OAAO,cAAc,UAAU;AACjC,WAAO;AAAA,EACT,WACE,cACC,OAAO,cAAc,YAAY,OAAO,cAAc,eACvD,UAAU,aACV,OAAO,UAAU,SAAS,UAC1B;AACA,KAAC,EAAE,KAAK,IAAI;AAAA,EACd;AAEA,MAAI,MAAM;AACR,WAAO,KAAK,QAAQ,aAAa,EAAE,EAAE,MAAM,qBAAqB,EAAE,KAAK,GAAG;AAAA,EAC5E;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["const viewPattern = /view/giu;\nconst upperCaseSplitPattern = /(?=[A-Z])/gu;\n\n/**\n * Converts the name of the component to a page title.\n *\n * @param component - The component to convert the name from.\n *\n * @returns The page title.\n */\nexport function convertComponentNameToTitle(component: unknown): string {\n let name: string;\n\n if (\n component &&\n (typeof component === 'object' || typeof component === 'function') &&\n 'name' in component &&\n typeof component.name === 'string'\n ) {\n ({ name } = component);\n } else {\n name = String(component);\n }\n\n return name.replace(viewPattern, '').split(upperCaseSplitPattern).join(' ');\n}\n"],
5
+ "mappings": "AAAA,MAAM,cAAc;AACpB,MAAM,wBAAwB;AASvB,SAAS,4BAA4B,WAA4B;AACtE,MAAI;AAEJ,MACE,cACC,OAAO,cAAc,YAAY,OAAO,cAAc,eACvD,UAAU,aACV,OAAO,UAAU,SAAS,UAC1B;AACA,KAAC,EAAE,KAAK,IAAI;AAAA,EACd,OAAO;AACL,WAAO,OAAO,SAAS;AAAA,EACzB;AAEA,SAAO,KAAK,QAAQ,aAAa,EAAE,EAAE,MAAM,qBAAqB,EAAE,KAAK,GAAG;AAC5E;",
6
6
  "names": []
7
7
  }
@@ -5,14 +5,19 @@ import type { RouteParamType } from './routeParamType.js';
5
5
  * Internal type used for server communication and menu building. It extends the
6
6
  * view configuration with the route parameters.
7
7
  */
8
- export type ServerViewConfig = Readonly<{ params?: Readonly<Record<string, RouteParamType>> }> & ViewConfig;
8
+ export type ServerViewConfig = Readonly<{
9
+ children?: readonly ServerViewConfig[];
10
+ params?: Readonly<Record<string, RouteParamType>>;
11
+ }> &
12
+ ViewConfig;
9
13
 
10
- export type VaadinServer = Readonly<{
11
- views: Readonly<Record<string, ServerViewConfig>>;
12
- }>;
14
+ export type ServerViewMapItem = Readonly<{
15
+ params?: Readonly<Record<string, RouteParamType>>;
16
+ }> &
17
+ ViewConfig;
13
18
 
14
19
  export type VaadinObject = Readonly<{
15
- server?: VaadinServer;
20
+ views: Readonly<Record<string, ServerViewMapItem>>;
16
21
  }>;
17
22
 
18
23
  export type VaadinWindow = Readonly<{
@@ -0,0 +1,2 @@
1
+ export declare function transformTree<T extends readonly unknown[], U>(nodes: T, transformer: (nodes: T, next: (...nodes: T) => U) => U): U;
2
+ //# sourceMappingURL=transformTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transformTree.d.ts","sourceRoot":"","sources":["../src/shared/transformTree.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,EAAE,CAAC,EAC3D,KAAK,EAAE,CAAC,EACR,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GACrD,CAAC,CAEH"}
@@ -0,0 +1,7 @@
1
+ function transformTree(nodes, transformer) {
2
+ return transformer(nodes, (...n) => transformTree(n, transformer));
3
+ }
4
+ export {
5
+ transformTree
6
+ };
7
+ //# sourceMappingURL=transformTree.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/shared/transformTree.ts"],
4
+ "sourcesContent": ["export function transformTree<T extends readonly unknown[], U>(\n nodes: T,\n transformer: (nodes: T, next: (...nodes: T) => U) => U,\n): U {\n return transformer(nodes, (...n) => transformTree(n, transformer));\n}\n"],
5
+ "mappings": "AAAO,SAAS,cACd,OACA,aACG;AACH,SAAO,YAAY,OAAO,IAAI,MAAM,cAAc,GAAG,WAAW,CAAC;AACnE;",
6
+ "names": []
7
+ }
package/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { RouteParamType } from './shared/routeParamType.js';
1
+ import type { createBrowserRouter, RouteObject } from 'react-router-dom';
2
2
 
3
3
  export type ViewConfig = Readonly<{
4
4
  /**
@@ -11,7 +11,12 @@ export type ViewConfig = Readonly<{
11
11
  /**
12
12
  * Same as in the explicit React Router configuration.
13
13
  */
14
- rolesAllowed?: readonly string[];
14
+ rolesAllowed?: readonly [string, ...string[]];
15
+
16
+ /**
17
+ * Set to true to require the user to be logged in to access the view.
18
+ */
19
+ loginRequired?: boolean;
15
20
 
16
21
  /**
17
22
  * Allows overriding the route path configuration. Uses the same syntax as
@@ -45,21 +50,27 @@ export type ViewConfig = Readonly<{
45
50
  }>;
46
51
  }>;
47
52
 
53
+ /**
54
+ * An unknown JavaScript module.
55
+ */
56
+ export type Module = Readonly<Record<string, unknown>>;
57
+
48
58
  /**
49
59
  * A module that exports a component and an optional view configuration.
50
60
  */
51
- export type RouteModule<C = unknown> = Readonly<{
52
- default: C;
53
- config?: ViewConfig;
54
- }>;
61
+ export type RouteModule<C = unknown> = Module &
62
+ Readonly<{
63
+ default: C;
64
+ config?: ViewConfig;
65
+ }>;
55
66
 
56
67
  /**
57
68
  * A framework-agnostic object generated from the file-based route.
58
69
  */
59
- export type AgnosticRoute<C = unknown> = Readonly<{
70
+ export type AgnosticRoute = Readonly<{
60
71
  path: string;
61
- module?: RouteModule<C>;
62
- children?: ReadonlyArray<AgnosticRoute<T>>;
72
+ module?: Module;
73
+ children?: readonly AgnosticRoute[];
63
74
  }>;
64
75
 
65
76
  /**
@@ -70,3 +81,10 @@ export type MenuItem = Readonly<{
70
81
  icon?: string;
71
82
  title?: string;
72
83
  }>;
84
+
85
+ export type RouterConfiguration = Readonly<{
86
+ routes: readonly RouteObject[];
87
+ router: ReturnType<typeof createBrowserRouter>;
88
+ }>;
89
+
90
+ export type RouterBuildOptions = Parameters<typeof createBrowserRouter>[1];
@@ -3,7 +3,7 @@ export type RouteMeta = Readonly<{
3
3
  path: string;
4
4
  file?: URL;
5
5
  layout?: URL;
6
- children: RouteMeta[];
6
+ children?: readonly RouteMeta[];
7
7
  }>;
8
8
  /**
9
9
  * Routes collector options.
@@ -26,16 +26,16 @@ export type CollectRoutesOptions = Readonly<{
26
26
  /**
27
27
  * Collect route metadata from the file system and build a route tree.
28
28
  *
29
- * It accepts files that start with `$` as special files.
30
- * - `$layout` contains a component that wraps the child components.
31
- * - `$index` contains a component that will be used as the index page of the directory.
29
+ * It accepts files that start with `@` as special files.
30
+ * - `@layout` contains a component that wraps the child components.
31
+ * - `@index` contains a component that will be used as the index page of the directory.
32
32
  *
33
33
  * It accepts files that start with `_` as private files. They will be ignored.
34
34
  *
35
35
  * @param dir - The directory to collect routes from.
36
36
  * @param options - The options object.
37
37
  *
38
- * @returns The route metadata tree.
38
+ * @returns The route metadata array.
39
39
  */
40
- export default function collectRoutesFromFS(dir: URL, { extensions, logger, parent }: CollectRoutesOptions): Promise<RouteMeta>;
40
+ export default function collectRoutesFromFS(dir: URL, { extensions, logger, parent }: CollectRoutesOptions): Promise<readonly RouteMeta[]>;
41
41
  //# sourceMappingURL=collectRoutesFromFS.d.ts.map