@vaadin/hilla-file-router 24.6.0-beta2 → 24.6.0-beta3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/hilla-file-router",
3
- "version": "24.6.0-beta2",
3
+ "version": "24.6.0-beta3",
4
4
  "description": "Hilla file-based router",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -79,9 +79,9 @@
79
79
  "type-fest": "^4.9.0"
80
80
  },
81
81
  "dependencies": {
82
- "@vaadin/hilla-generator-utils": "24.6.0-beta2",
83
- "@vaadin/hilla-react-auth": "24.6.0-beta2",
84
- "@vaadin/hilla-react-signals": "24.6.0-beta2",
82
+ "@vaadin/hilla-generator-utils": "24.6.0-beta3",
83
+ "@vaadin/hilla-react-auth": "24.6.0-beta3",
84
+ "@vaadin/hilla-react-signals": "24.6.0-beta3",
85
85
  "react": "^18.2.0",
86
86
  "rollup": "^4.12.0",
87
87
  "typescript": "5.6.2"
@@ -2,7 +2,7 @@ function __REGISTER__(feature, vaadinObj = window.Vaadin ??= {}) {
2
2
  vaadinObj.registrations ??= [];
3
3
  vaadinObj.registrations.push({
4
4
  is: feature ? `${"@vaadin/hilla-file-router"}/${feature}` : "@vaadin/hilla-file-router",
5
- version: "24.6.0-beta2"
5
+ version: "24.6.0-beta3"
6
6
  });
7
7
  }
8
8
  import { signal } from "@vaadin/hilla-react-signals";
@@ -1,4 +1,13 @@
1
- import type { AgnosticRoute, Module } from '../types.js';
1
+ import type { AgnosticRoute, Module, ViewConfig } from '../types.js';
2
+ /**
3
+ * Extends a router module's config with additional properties. The original
4
+ * module config is preferred over the extension.
5
+ *
6
+ * @param module - The module to extend.
7
+ * @param config - The extension config.
8
+ * @returns
9
+ */
10
+ export declare function extendModule(module: Module, config?: ViewConfig): Module;
2
11
  /**
3
12
  * Create a single framework-agnostic route object. Later, it can be transformed into a framework-specific route object,
4
13
  * e.g., the one used by React Router.
@@ -1 +1 @@
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"}
1
+ {"version":3,"file":"createRoute.d.ts","sourceRoot":"","sources":["../src/runtime/createRoute.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,CAQxE;AAED;;;;;;;;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"}
@@ -1,3 +1,12 @@
1
+ function extendModule(module, config) {
2
+ return {
3
+ ...module,
4
+ config: {
5
+ ...config,
6
+ ...module.config
7
+ }
8
+ };
9
+ }
1
10
  function createRoute(path, moduleOrChildren, children) {
2
11
  let module;
3
12
  if (Array.isArray(moduleOrChildren)) {
@@ -12,6 +21,7 @@ function createRoute(path, moduleOrChildren, children) {
12
21
  };
13
22
  }
14
23
  export {
15
- createRoute
24
+ createRoute,
25
+ extendModule
16
26
  };
17
27
  //# sourceMappingURL=createRoute.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/runtime/createRoute.ts"],
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;",
4
+ "sourcesContent": ["import type { AgnosticRoute, Module, ViewConfig } from '../types.js';\n\n/**\n * Extends a router module's config with additional properties. The original\n * module config is preferred over the extension.\n *\n * @param module - The module to extend.\n * @param config - The extension config.\n * @returns\n */\nexport function extendModule(module: Module, config?: ViewConfig): Module {\n return {\n ...module,\n config: {\n ...config,\n ...(module.config as ViewConfig),\n },\n };\n}\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": "AAUO,SAAS,aAAa,QAAgB,QAA6B;AACxE,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ;AAAA,MACN,GAAG;AAAA,MACH,GAAI,OAAO;AAAA,IACb;AAAA,EACF;AACF;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
  }
@@ -1 +1 @@
1
- {"version":3,"file":"applyLayouts.d.ts","sourceRoot":"","sources":["../src/vite-plugin/applyLayouts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AA+CH;;;;;;GAMG;AACH,wBAA8B,YAAY,CACxC,SAAS,EAAE,SAAS,SAAS,EAAE,EAC/B,WAAW,EAAE,GAAG,GACf,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAW/B"}
1
+ {"version":3,"file":"applyLayouts.d.ts","sourceRoot":"","sources":["../src/vite-plugin/applyLayouts.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd,CAAC,CAAC;AAyCH;;;;;;GAMG;AACH,wBAA8B,YAAY,CACxC,SAAS,EAAE,SAAS,SAAS,EAAE,EAC/B,WAAW,EAAE,GAAG,GACf,OAAO,CAAC,SAAS,SAAS,EAAE,CAAC,CAY/B"}
@@ -4,14 +4,10 @@ function stripLeadingSlash(path) {
4
4
  return path.startsWith("/") ? path.slice(1) : path;
5
5
  }
6
6
  function enableFlowLayout(route) {
7
- const routeWithFlowLayout = {
7
+ return {
8
8
  ...route,
9
9
  flowLayout: true
10
10
  };
11
- return route.children ? {
12
- ...routeWithFlowLayout,
13
- children: route.children.map(enableFlowLayout)
14
- } : routeWithFlowLayout;
15
11
  }
16
12
  function layoutExists(layoutPaths, path) {
17
13
  const splitPath = path.split("/");
@@ -32,15 +28,16 @@ function layoutExists(layoutPaths, path) {
32
28
  });
33
29
  }
34
30
  async function applyLayouts(routeMeta, layoutsFile) {
35
- if (!existsSync(layoutsFile)) {
31
+ try {
32
+ const layoutContents = await readFile(layoutsFile, "utf-8");
33
+ const availableLayouts = JSON.parse(layoutContents);
34
+ const layoutPaths = availableLayouts.map((layout) => stripLeadingSlash(layout.path));
35
+ return routeMeta.map(
36
+ (route) => layoutExists(layoutPaths, stripLeadingSlash(route.path)) ? enableFlowLayout(route) : route
37
+ );
38
+ } catch (e) {
36
39
  return routeMeta;
37
40
  }
38
- const layoutContents = await readFile(layoutsFile, "utf-8");
39
- const availableLayouts = JSON.parse(layoutContents);
40
- const layoutPaths = availableLayouts.map((layout) => stripLeadingSlash(layout.path));
41
- return routeMeta.map(
42
- (route) => layoutExists(layoutPaths, stripLeadingSlash(route.path)) ? enableFlowLayout(route) : route
43
- );
44
41
  }
45
42
  export {
46
43
  applyLayouts as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/vite-plugin/applyLayouts.ts"],
4
- "sourcesContent": ["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\n\n/**\n * The information about a particular server-side layout.\n */\nexport type LayoutMeta = Readonly<{\n path: string;\n}>;\n\nfunction stripLeadingSlash(path: string) {\n return path.startsWith('/') ? path.slice(1) : path;\n}\n\nfunction enableFlowLayout(route: RouteMeta): RouteMeta {\n const routeWithFlowLayout = {\n ...route,\n flowLayout: true,\n };\n return route.children\n ? {\n ...routeWithFlowLayout,\n children: route.children.map(enableFlowLayout),\n }\n : routeWithFlowLayout;\n}\n\n/**\n * Check if there is a layout available that can handle the given path.\n * Layouts match the starting parts of the path so '/' will match all paths\n * and '/home' matches '/home' anything with the start path '/home/*'\n *\n * @param layoutPaths - available layout paths\n * @param path - to check for layout\n */\nfunction layoutExists(layoutPaths: string[], path: string) {\n const splitPath: string[] = path.split('/');\n\n return layoutPaths.some((layout) => {\n if (layout.length === 0) {\n return true;\n }\n const splitLayout: string[] = layout.split('/');\n if (splitLayout.length > splitPath.length) {\n return false;\n }\n for (let i = 0; i < splitLayout.length; i++) {\n if (splitPath[i] !== splitLayout[i]) {\n return false;\n }\n }\n return true;\n });\n}\n\n/**\n * Enables Flow layout flag on the matching routes based on the information from the layouts JSON file.\n *\n * @param routeMeta - The routes tree to process.\n * @param layoutsFile - The server layouts JSON file.\n * @returns Processed routes tree.\n */\nexport default async function applyLayouts(\n routeMeta: readonly RouteMeta[],\n layoutsFile: URL,\n): Promise<readonly RouteMeta[]> {\n if (!existsSync(layoutsFile)) {\n return routeMeta;\n }\n const layoutContents = await readFile(layoutsFile, 'utf-8');\n const availableLayouts: readonly LayoutMeta[] = JSON.parse(layoutContents);\n const layoutPaths = availableLayouts.map((layout) => stripLeadingSlash(layout.path));\n\n return routeMeta.map((route) =>\n layoutExists(layoutPaths, stripLeadingSlash(route.path)) ? enableFlowLayout(route) : route,\n );\n}\n"],
5
- "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AAUzB,SAAS,kBAAkB,MAAc;AACvC,SAAO,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,CAAC,IAAI;AAChD;AAEA,SAAS,iBAAiB,OAA6B;AACrD,QAAM,sBAAsB;AAAA,IAC1B,GAAG;AAAA,IACH,YAAY;AAAA,EACd;AACA,SAAO,MAAM,WACT;AAAA,IACE,GAAG;AAAA,IACH,UAAU,MAAM,SAAS,IAAI,gBAAgB;AAAA,EAC/C,IACA;AACN;AAUA,SAAS,aAAa,aAAuB,MAAc;AACzD,QAAM,YAAsB,KAAK,MAAM,GAAG;AAE1C,SAAO,YAAY,KAAK,CAAC,WAAW;AAClC,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO;AAAA,IACT;AACA,UAAM,cAAwB,OAAO,MAAM,GAAG;AAC9C,QAAI,YAAY,SAAS,UAAU,QAAQ;AACzC,aAAO;AAAA,IACT;AACA,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAI,UAAU,CAAC,MAAM,YAAY,CAAC,GAAG;AACnC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AASA,eAAO,aACL,WACA,aAC+B;AAC/B,MAAI,CAAC,WAAW,WAAW,GAAG;AAC5B,WAAO;AAAA,EACT;AACA,QAAM,iBAAiB,MAAM,SAAS,aAAa,OAAO;AAC1D,QAAM,mBAA0C,KAAK,MAAM,cAAc;AACzE,QAAM,cAAc,iBAAiB,IAAI,CAAC,WAAW,kBAAkB,OAAO,IAAI,CAAC;AAEnF,SAAO,UAAU;AAAA,IAAI,CAAC,UACpB,aAAa,aAAa,kBAAkB,MAAM,IAAI,CAAC,IAAI,iBAAiB,KAAK,IAAI;AAAA,EACvF;AACF;",
4
+ "sourcesContent": ["import { existsSync } from 'node:fs';\nimport { readFile } from 'node:fs/promises';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\n\n/**\n * The information about a particular server-side layout.\n */\nexport type LayoutMeta = Readonly<{\n path: string;\n}>;\n\nfunction stripLeadingSlash(path: string) {\n return path.startsWith('/') ? path.slice(1) : path;\n}\n\nfunction enableFlowLayout(route: RouteMeta): RouteMeta {\n return {\n ...route,\n flowLayout: true,\n };\n}\n\n/**\n * Check if there is a layout available that can handle the given path.\n * Layouts match the starting parts of the path so '/' will match all paths\n * and '/home' matches '/home' anything with the start path '/home/*'\n *\n * @param layoutPaths - available layout paths\n * @param path - to check for layout\n */\nfunction layoutExists(layoutPaths: string[], path: string) {\n const splitPath: string[] = path.split('/');\n\n return layoutPaths.some((layout) => {\n if (layout.length === 0) {\n return true;\n }\n const splitLayout: string[] = layout.split('/');\n if (splitLayout.length > splitPath.length) {\n return false;\n }\n for (let i = 0; i < splitLayout.length; i++) {\n if (splitPath[i] !== splitLayout[i]) {\n return false;\n }\n }\n return true;\n });\n}\n\n/**\n * Enables Flow layout flag on the matching routes based on the information from the layouts JSON file.\n *\n * @param routeMeta - The routes tree to process.\n * @param layoutsFile - The server layouts JSON file.\n * @returns Processed routes tree.\n */\nexport default async function applyLayouts(\n routeMeta: readonly RouteMeta[],\n layoutsFile: URL,\n): Promise<readonly RouteMeta[]> {\n try {\n const layoutContents = await readFile(layoutsFile, 'utf-8');\n const availableLayouts: readonly LayoutMeta[] = JSON.parse(layoutContents);\n const layoutPaths = availableLayouts.map((layout) => stripLeadingSlash(layout.path));\n\n return routeMeta.map((route) =>\n layoutExists(layoutPaths, stripLeadingSlash(route.path)) ? enableFlowLayout(route) : route,\n );\n } catch (e: unknown) {\n return routeMeta;\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AAUzB,SAAS,kBAAkB,MAAc;AACvC,SAAO,KAAK,WAAW,GAAG,IAAI,KAAK,MAAM,CAAC,IAAI;AAChD;AAEA,SAAS,iBAAiB,OAA6B;AACrD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,YAAY;AAAA,EACd;AACF;AAUA,SAAS,aAAa,aAAuB,MAAc;AACzD,QAAM,YAAsB,KAAK,MAAM,GAAG;AAE1C,SAAO,YAAY,KAAK,CAAC,WAAW;AAClC,QAAI,OAAO,WAAW,GAAG;AACvB,aAAO;AAAA,IACT;AACA,UAAM,cAAwB,OAAO,MAAM,GAAG;AAC9C,QAAI,YAAY,SAAS,UAAU,QAAQ;AACzC,aAAO;AAAA,IACT;AACA,aAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAI,UAAU,CAAC,MAAM,YAAY,CAAC,GAAG;AACnC,eAAO;AAAA,MACT;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;AASA,eAAO,aACL,WACA,aAC+B;AAC/B,MAAI;AACF,UAAM,iBAAiB,MAAM,SAAS,aAAa,OAAO;AAC1D,UAAM,mBAA0C,KAAK,MAAM,cAAc;AACzE,UAAM,cAAc,iBAAiB,IAAI,CAAC,WAAW,kBAAkB,OAAO,IAAI,CAAC;AAEnF,WAAO,UAAU;AAAA,MAAI,CAAC,UACpB,aAAa,aAAa,kBAAkB,MAAM,IAAI,CAAC,IAAI,iBAAiB,KAAK,IAAI;AAAA,IACvF;AAAA,EACF,SAAS,GAAY;AACnB,WAAO;AAAA,EACT;AACF;",
6
6
  "names": []
7
7
  }
@@ -1,10 +1,4 @@
1
1
  import type { RouteMeta } from './collectRoutesFromFS.js';
2
2
  import type { RuntimeFileUrls } from './generateRuntimeFiles.js';
3
- /**
4
- * Loads all the files from the received metadata and creates a framework-agnostic route tree.
5
- *
6
- * @param views - The abstract route tree.
7
- * @param generatedDir - The directory where the generated view file will be stored.
8
- */
9
- export default function createRoutesFromMeta(views: readonly RouteMeta[], { code: codeFile }: RuntimeFileUrls): string;
3
+ export default function createRoutesFromMeta(views: readonly RouteMeta[], urls: RuntimeFileUrls): string;
10
4
  //# sourceMappingURL=createRoutesFromMeta.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"createRoutesFromMeta.d.ts","sourceRoot":"","sources":["../src/vite-plugin/createRoutesFromMeta.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAqDjE;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,MAAM,CA0ErH"}
1
+ {"version":3,"file":"createRoutesFromMeta.d.ts","sourceRoot":"","sources":["../src/vite-plugin/createRoutesFromMeta.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAyIjE,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAAC,KAAK,EAAE,SAAS,SAAS,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,MAAM,CAEvG"}
@@ -2,94 +2,110 @@ import { relative, sep } from "node:path";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { template, transform as transformer } from "@vaadin/hilla-generator-utils/ast.js";
4
4
  import createSourceFile from "@vaadin/hilla-generator-utils/createSourceFile.js";
5
- import ts, {
6
- } from "typescript";
5
+ import DependencyManager from "@vaadin/hilla-generator-utils/dependencies/DependencyManager.js";
6
+ import PathManager from "@vaadin/hilla-generator-utils/dependencies/PathManager.js";
7
+ import ts, {} from "typescript";
7
8
  import { transformTree } from "../shared/transformTree.js";
8
9
  import { convertFSRouteSegmentToURLPatternFormat } from "./utils.js";
9
10
  const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
10
- function relativize(url, generatedDir) {
11
- const result = relative(fileURLToPath(generatedDir), fileURLToPath(url)).replaceAll(sep, "/");
12
- if (!result.startsWith(".")) {
13
- return `./${result}`;
11
+ const extensions = [".ts", ".tsx", ".js", ".jsx"];
12
+ class RouteFromMetaProcessor {
13
+ #manager;
14
+ #views;
15
+ constructor(views, { code: codeFile }) {
16
+ this.#views = views;
17
+ const codeDir = new URL("./", codeFile);
18
+ this.#manager = new DependencyManager(new PathManager({ extension: ".js", relativeTo: codeDir }));
14
19
  }
15
- return result;
16
- }
17
- function createImport(mod, file) {
18
- const path = `${file.substring(0, file.lastIndexOf("."))}.js`;
19
- return template(`import * as ${mod} from '${path}';
20
- `, ([statement]) => statement);
21
- }
22
- function createRouteData(path, mod, children) {
23
- return template(
24
- `const route = createRoute("${path}", ${mod ? `, ${mod}` : ""}${children ? `, CHILDREN` : ""})`,
25
- ([statement]) => statement.declarationList.declarations[0].initializer,
26
- [
27
- transformer(
28
- (node) => ts.isIdentifier(node) && node.text === "CHILDREN" ? ts.factory.createArrayLiteralExpression(children, true) : node
29
- )
30
- ]
31
- );
32
- }
33
- function createRoutesFromMeta(views, { code: codeFile }) {
34
- const codeDir = new URL("./", codeFile);
35
- const imports = [];
36
- const errors = [];
37
- let id = 0;
38
- const routes = transformTree(views, (metas, next) => {
39
- errors.push(
40
- ...metas.map((route) => route.path).filter((item, index, arr) => arr.indexOf(item) !== index).map((dup) => `console.error("Two views share the same path: ${dup}");`)
41
- );
42
- return metas.map(({ file: file2, layout, path, children, flowLayout }) => {
43
- let _children;
44
- if (children) {
45
- _children = next(...children);
46
- }
47
- const currentId = id;
48
- id += 1;
49
- let mod;
50
- if (file2) {
51
- mod = `Page${currentId}`;
52
- imports.push(createImport(mod, relativize(file2, codeDir)));
53
- } else if (layout) {
54
- mod = `Layout${currentId}`;
55
- imports.push(createImport(mod, relativize(layout, codeDir)));
56
- }
57
- return createRouteData(convertFSRouteSegmentToURLPatternFormat(path), mod, _children);
20
+ /**
21
+ * Loads all the files from the received metadata and creates a framework-agnostic route tree.
22
+ *
23
+ * @param views - The abstract route tree.
24
+ * @param generatedDir - The directory where the generated view file will be stored.
25
+ */
26
+ process() {
27
+ const {
28
+ paths,
29
+ imports: { named, namespace }
30
+ } = this.#manager;
31
+ const errors = [];
32
+ const routes = transformTree(this.#views, (metas, next) => {
33
+ errors.push(
34
+ ...metas.map((route) => route.path).filter((item, index, arr) => arr.indexOf(item) !== index).map((dup) => `console.error("Two views share the same path: ${dup}");`)
35
+ );
36
+ return metas.map(({ file: file2, layout, path, children, flowLayout }) => {
37
+ let _children;
38
+ if (children) {
39
+ _children = next(...children);
40
+ }
41
+ let mod;
42
+ if (file2) {
43
+ const extension2 = extensions.find((ext) => file2.pathname.endsWith(ext));
44
+ mod = namespace.add(paths.createRelativePath(file2, extension2), `Page`);
45
+ } else if (layout) {
46
+ const extension2 = extensions.find((ext) => layout.pathname.endsWith(ext));
47
+ mod = namespace.add(paths.createRelativePath(layout, extension2), `Layout`);
48
+ }
49
+ const extension = flowLayout ? { flowLayout } : void 0;
50
+ return this.#createRouteData(convertFSRouteSegmentToURLPatternFormat(path), mod, extension, _children);
51
+ });
58
52
  });
59
- });
60
- if (imports.length > 0) {
61
- const createRouteImport = template(
62
- 'import { createRoute } from "@vaadin/hilla-file-router/runtime.js";',
63
- ([statement]) => statement
64
- );
65
- imports.unshift(createRouteImport);
66
- }
67
- imports.unshift(
68
- template(
69
- 'import type { AgnosticRoute } from "@vaadin/hilla-file-router/types.js";',
70
- ([statement]) => statement
71
- )
72
- );
73
- const routeDeclaration = template(
74
- `import a from 'IMPORTS';
53
+ const agnosticRouteId = named.getIdentifier("@vaadin/hilla-file-router/types.js", "AgnosticRoute") ?? named.add("@vaadin/hilla-file-router/types.js", "AgnosticRoute", true);
54
+ let routeDeclaration = template(
55
+ `${errors.join("\n")}
75
56
 
76
- ${errors.join("\n")}
77
-
78
- const routes: readonly AgnosticRoute[] = ROUTE;
57
+ const routes: readonly AGNOSTIC_ROUTE[] = ROUTE;
79
58
 
80
59
  export default routes;
81
60
  `,
82
- [
83
- transformer(
84
- (node) => ts.isImportDeclaration(node) && node.moduleSpecifier.text === "IMPORTS" ? imports : node
85
- ),
86
- transformer(
87
- (node) => ts.isIdentifier(node) && node.text === "ROUTE" ? ts.factory.createArrayLiteralExpression(routes, true) : node
88
- )
89
- ]
90
- );
91
- const file = createSourceFile(routeDeclaration, "file-routes.ts");
92
- return printer.printFile(file);
61
+ [
62
+ transformer(
63
+ (node) => ts.isIdentifier(node) && node.text === "ROUTE" ? ts.factory.createArrayLiteralExpression(routes, true) : node
64
+ ),
65
+ transformer((node) => ts.isIdentifier(node) && node.text === "AGNOSTIC_ROUTE" ? agnosticRouteId : node)
66
+ ]
67
+ );
68
+ routeDeclaration = [...this.#manager.imports.toCode(), ...routeDeclaration];
69
+ const file = createSourceFile(routeDeclaration, "file-routes.ts");
70
+ return printer.printFile(file);
71
+ }
72
+ /**
73
+ * Create an abstract route creation function call. The nested function calls
74
+ * create a route tree.
75
+ *
76
+ * @param path - The path of the route.
77
+ * @param mod - The name of the route module imported as a namespace.
78
+ * @param children - The list of child route call expressions.
79
+ */
80
+ #createRouteData(path, mod, extension, children) {
81
+ const { named } = this.#manager.imports;
82
+ let extendModuleId;
83
+ let modNode = "";
84
+ if (mod) {
85
+ if (extension) {
86
+ extendModuleId = named.getIdentifier("@vaadin/hilla-file-router/runtime.js", "extendModule") ?? named.add("@vaadin/hilla-file-router/runtime.js", "extendModule");
87
+ modNode = `, EXTEND_MODULE(MOD, ${JSON.stringify(extension)})`;
88
+ } else {
89
+ modNode = `, MOD`;
90
+ }
91
+ }
92
+ const createRouteId = named.getIdentifier("@vaadin/hilla-file-router/runtime.js", "createRoute") ?? named.add("@vaadin/hilla-file-router/runtime.js", "createRoute");
93
+ return template(
94
+ `const route = CREATE_ROUTE("${path}", ${modNode}${children ? `, CHILDREN` : ""})`,
95
+ ([statement]) => statement.declarationList.declarations[0].initializer,
96
+ [
97
+ transformer(
98
+ (node) => ts.isIdentifier(node) && node.text === "CHILDREN" ? ts.factory.createArrayLiteralExpression(children, true) : node
99
+ ),
100
+ transformer((node) => ts.isIdentifier(node) && node.text === "MOD" ? mod : node),
101
+ transformer((node) => ts.isIdentifier(node) && node.text === "EXTEND_MODULE" ? extendModuleId : node),
102
+ transformer((node) => ts.isIdentifier(node) && node.text === "CREATE_ROUTE" ? createRouteId : node)
103
+ ]
104
+ );
105
+ }
106
+ }
107
+ function createRoutesFromMeta(views, urls) {
108
+ return new RouteFromMetaProcessor(views, urls).process();
93
109
  }
94
110
  export {
95
111
  createRoutesFromMeta as default
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/vite-plugin/createRoutesFromMeta.ts"],
4
- "sourcesContent": ["import { relative, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { template, transform as transformer } from '@vaadin/hilla-generator-utils/ast.js';\nimport createSourceFile from '@vaadin/hilla-generator-utils/createSourceFile.js';\nimport ts, {\n type CallExpression,\n type ImportDeclaration,\n type StringLiteral,\n type VariableStatement,\n} from 'typescript';\n\nimport { transformTree } from '../shared/transformTree.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport type { RuntimeFileUrls } from './generateRuntimeFiles.js';\nimport { convertFSRouteSegmentToURLPatternFormat } from './utils.js';\n\nconst printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n\n/**\n * Convert a file URL to a relative path from the generated directory.\n *\n * @param url - The file URL to convert.\n * @param generatedDir - The directory where the generated view file will be stored.\n */\nfunction relativize(url: URL, generatedDir: URL): string {\n const result = relative(fileURLToPath(generatedDir), fileURLToPath(url)).replaceAll(sep, '/');\n\n if (!result.startsWith('.')) {\n return `./${result}`;\n }\n\n return result;\n}\n\n/**\n * Create an import declaration for a `views` module.\n *\n * @param mod - The name of the route module to import.\n * @param file - The file path of the module.\n */\nfunction createImport(mod: string, file: string): ImportDeclaration {\n const path = `${file.substring(0, file.lastIndexOf('.'))}.js`;\n return template(`import * as ${mod} from '${path}';\\n`, ([statement]) => statement as ts.ImportDeclaration);\n}\n\n/**\n * Create an abstract route creation function call. The nested function calls create a route tree.\n *\n * @param path - The path of the route.\n * @param mod - The name of the route module imported as a namespace.\n * @param children - The list of child route call expressions.\n */\nfunction createRouteData(path: string, mod: string | undefined, children?: readonly CallExpression[]): CallExpression {\n return template(\n `const route = createRoute(\"${path}\", ${mod ? `, ${mod}` : ''}${children ? `, CHILDREN` : ''})`,\n ([statement]) => (statement as VariableStatement).declarationList.declarations[0].initializer as CallExpression,\n [\n transformer((node) =>\n ts.isIdentifier(node) && node.text === 'CHILDREN'\n ? ts.factory.createArrayLiteralExpression(children, true)\n : node,\n ),\n ],\n );\n}\n\n/**\n * Loads all the files from the received metadata and creates a framework-agnostic route tree.\n *\n * @param views - The abstract route tree.\n * @param generatedDir - The directory where the generated view file will be stored.\n */\nexport default function createRoutesFromMeta(views: readonly RouteMeta[], { code: codeFile }: RuntimeFileUrls): string {\n const codeDir = new URL('./', codeFile);\n const imports: ImportDeclaration[] = [];\n const errors: string[] = [];\n let id = 0;\n\n const routes = transformTree<readonly RouteMeta[], readonly CallExpression[]>(views, (metas, next) => {\n errors.push(\n ...metas\n .map((route) => route.path)\n .filter((item, index, arr) => arr.indexOf(item) !== index)\n .map((dup) => `console.error(\"Two views share the same path: ${dup}\");`),\n );\n\n return metas.map(({ file, layout, path, children, flowLayout }) => {\n let _children: readonly CallExpression[] | undefined;\n\n if (children) {\n _children = next(...children);\n }\n\n const currentId = id;\n id += 1;\n\n let mod: string | undefined;\n if (file) {\n mod = `Page${currentId}`;\n imports.push(createImport(mod, relativize(file, codeDir)));\n } else if (layout) {\n mod = `Layout${currentId}`;\n imports.push(createImport(mod, relativize(layout, codeDir)));\n }\n\n return createRouteData(convertFSRouteSegmentToURLPatternFormat(path), mod, _children);\n });\n });\n\n // Prepend the import for `createRoute` if it was used\n if (imports.length > 0) {\n const createRouteImport = template(\n 'import { createRoute } from \"@vaadin/hilla-file-router/runtime.js\";',\n ([statement]) => statement as ts.ImportDeclaration,\n );\n imports.unshift(createRouteImport);\n }\n\n imports.unshift(\n template(\n 'import type { AgnosticRoute } from \"@vaadin/hilla-file-router/types.js\";',\n ([statement]) => statement as ts.ImportDeclaration,\n ),\n );\n\n const routeDeclaration = template(\n `import a from 'IMPORTS';\n\n${errors.join('\\n')}\n\nconst routes: readonly AgnosticRoute[] = ROUTE;\n\nexport default routes;\n`,\n [\n transformer((node) =>\n ts.isImportDeclaration(node) && (node.moduleSpecifier as StringLiteral).text === 'IMPORTS' ? imports : node,\n ),\n transformer((node) =>\n ts.isIdentifier(node) && node.text === 'ROUTE' ? ts.factory.createArrayLiteralExpression(routes, true) : node,\n ),\n ],\n );\n\n const file = createSourceFile(routeDeclaration, 'file-routes.ts');\n return printer.printFile(file);\n}\n"],
5
- "mappings": "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",
6
- "names": ["file"]
4
+ "sourcesContent": ["import { relative, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { template, transform as transformer } from '@vaadin/hilla-generator-utils/ast.js';\nimport createSourceFile from '@vaadin/hilla-generator-utils/createSourceFile.js';\nimport DependencyManager from '@vaadin/hilla-generator-utils/dependencies/DependencyManager.js';\nimport PathManager from '@vaadin/hilla-generator-utils/dependencies/PathManager.js';\nimport ts, { type CallExpression, type Identifier, type StringLiteral, type VariableStatement } from 'typescript';\n\nimport { transformTree } from '../shared/transformTree.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport type { RuntimeFileUrls } from './generateRuntimeFiles.js';\nimport { convertFSRouteSegmentToURLPatternFormat } from './utils.js';\n\nconst printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });\n\nconst extensions = ['.ts', '.tsx', '.js', '.jsx'];\n\nclass RouteFromMetaProcessor {\n readonly #manager: DependencyManager;\n readonly #views: readonly RouteMeta[];\n\n constructor(views: readonly RouteMeta[], { code: codeFile }: RuntimeFileUrls) {\n this.#views = views;\n\n const codeDir = new URL('./', codeFile);\n this.#manager = new DependencyManager(new PathManager({ extension: '.js', relativeTo: codeDir }));\n }\n\n /**\n * Loads all the files from the received metadata and creates a framework-agnostic route tree.\n *\n * @param views - The abstract route tree.\n * @param generatedDir - The directory where the generated view file will be stored.\n */\n process(): string {\n const {\n paths,\n imports: { named, namespace },\n } = this.#manager;\n const errors: string[] = [];\n\n const routes = transformTree<readonly RouteMeta[], readonly CallExpression[]>(this.#views, (metas, next) => {\n errors.push(\n ...metas\n .map((route) => route.path)\n .filter((item, index, arr) => arr.indexOf(item) !== index)\n .map((dup) => `console.error(\"Two views share the same path: ${dup}\");`),\n );\n\n return metas.map(({ file, layout, path, children, flowLayout }) => {\n let _children: readonly CallExpression[] | undefined;\n\n if (children) {\n _children = next(...children);\n }\n\n let mod: Identifier | undefined;\n if (file) {\n const extension = extensions.find((ext) => file.pathname.endsWith(ext));\n mod = namespace.add(paths.createRelativePath(file, extension), `Page`);\n } else if (layout) {\n const extension = extensions.find((ext) => layout.pathname.endsWith(ext));\n mod = namespace.add(paths.createRelativePath(layout, extension), `Layout`);\n }\n\n const extension = flowLayout ? { flowLayout } : undefined;\n\n return this.#createRouteData(convertFSRouteSegmentToURLPatternFormat(path), mod, extension, _children);\n });\n });\n\n const agnosticRouteId =\n named.getIdentifier('@vaadin/hilla-file-router/types.js', 'AgnosticRoute') ??\n named.add('@vaadin/hilla-file-router/types.js', 'AgnosticRoute', true);\n\n let routeDeclaration = template(\n `${errors.join('\\n')}\n\nconst routes: readonly AGNOSTIC_ROUTE[] = ROUTE;\n\nexport default routes;\n`,\n [\n transformer((node) =>\n ts.isIdentifier(node) && node.text === 'ROUTE' ? ts.factory.createArrayLiteralExpression(routes, true) : node,\n ),\n transformer((node) => (ts.isIdentifier(node) && node.text === 'AGNOSTIC_ROUTE' ? agnosticRouteId : node)),\n ],\n );\n\n routeDeclaration = [...this.#manager.imports.toCode(), ...routeDeclaration];\n\n const file = createSourceFile(routeDeclaration, 'file-routes.ts');\n return printer.printFile(file);\n }\n\n /**\n * Create an abstract route creation function call. The nested function calls\n * create a route tree.\n *\n * @param path - The path of the route.\n * @param mod - The name of the route module imported as a namespace.\n * @param children - The list of child route call expressions.\n */\n #createRouteData(\n path: string,\n mod: Identifier | undefined,\n extension?: Readonly<Record<string, unknown>>,\n children?: readonly CallExpression[],\n ): CallExpression {\n const { named } = this.#manager.imports;\n\n let extendModuleId: Identifier | undefined;\n let modNode = '';\n\n if (mod) {\n if (extension) {\n extendModuleId =\n named.getIdentifier('@vaadin/hilla-file-router/runtime.js', 'extendModule') ??\n named.add('@vaadin/hilla-file-router/runtime.js', 'extendModule');\n modNode = `, EXTEND_MODULE(MOD, ${JSON.stringify(extension)})`;\n } else {\n modNode = `, MOD`;\n }\n }\n\n const createRouteId =\n named.getIdentifier('@vaadin/hilla-file-router/runtime.js', 'createRoute') ??\n named.add('@vaadin/hilla-file-router/runtime.js', 'createRoute');\n\n return template(\n `const route = CREATE_ROUTE(\"${path}\", ${modNode}${children ? `, CHILDREN` : ''})`,\n ([statement]) => (statement as VariableStatement).declarationList.declarations[0].initializer as CallExpression,\n [\n transformer((node) =>\n ts.isIdentifier(node) && node.text === 'CHILDREN'\n ? ts.factory.createArrayLiteralExpression(children, true)\n : node,\n ),\n transformer((node) => (ts.isIdentifier(node) && node.text === 'MOD' ? mod : node)),\n transformer((node) => (ts.isIdentifier(node) && node.text === 'EXTEND_MODULE' ? extendModuleId : node)),\n transformer((node) => (ts.isIdentifier(node) && node.text === 'CREATE_ROUTE' ? createRouteId : node)),\n ],\n );\n }\n}\n\nexport default function createRoutesFromMeta(views: readonly RouteMeta[], urls: RuntimeFileUrls): string {\n return new RouteFromMetaProcessor(views, urls).process();\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["file", "extension"]
7
7
  }