@vaadin/hilla-file-router 24.9.1 → 24.9.3

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.9.1",
3
+ "version": "24.9.3",
4
4
  "description": "Hilla file-based router",
5
5
  "main": "index.js",
6
6
  "module": "index.js",
@@ -62,9 +62,9 @@
62
62
  },
63
63
  "dependencies": {
64
64
  "@ungap/with-resolvers": "0.1.0",
65
- "@vaadin/hilla-generator-utils": "24.9.1",
66
- "@vaadin/hilla-react-auth": "24.9.1",
67
- "@vaadin/hilla-react-signals": "24.9.1",
65
+ "@vaadin/hilla-generator-utils": "24.9.3",
66
+ "@vaadin/hilla-react-auth": "24.9.3",
67
+ "@vaadin/hilla-react-signals": "24.9.3",
68
68
  "tsc-template": "0.2.3",
69
69
  "typescript": "5.8.3"
70
70
  }
@@ -1 +1 @@
1
- {"mappings":"AAEA,SAAS,yCAA4D;AAErE,OAAO,6BAA6B,4DAA6D;AACjG,OAAO,6DAA8D;AACrE,OAAO,qDAAsD;AAC7D,OAAO,+CAAgD;AACvD,OAAO,mCAAoC;AAC3C,SAAS,6CAA8C;AACvD,OAAO,4CAA6C;;;;;;;;;;;;;;;;;;;;AAsBpD,OAAO,MAAM,2BAA2B;CACtC,AAASA,aAAkC,CAAE;CAC7C,iBAAiB;CACjB,eAAe;;;;;;;;;;CAWf,gBAAgBC,QAAsC;AACpD,OAAK,OAAO,OAAO;AACnB,SAAO;CACR;;;;;;;;;;;CAYD,eAAeC,QAAwC;AACrD,OAAK,OAAO,QAAQ,qBAAqB;AACzC,SAAO;CACR;;;;;;;;;;;;;;;;;;;;CAqBD,aAAaC,WAA0BC,QAA2B;AAChE,OAAK,KAAKC,gBAAgB;AACxB,QAAKA,iBAAiB;AACtB,QAAK,WAAW,UAAU;GAE1B,MAAM,iBAAiB,qBAAqB,WAAW,OAAO;AAE9D,QAAK;;IAEH;;IAEA,0BAA0B,eAAe;CAC1C;EACF;AACD,SAAO;CACR;CAED,mBAAyB;AACvB,OAAKL,WAAW,KAAK,CAAC,mBAAmB,kBAAkB,eAAe,CAAC;AAC3E,SAAO;CACR;;;;;;;;;;;;;CAcD,WAAWG,WAAgC;AACzC,OAAK,KAAKG,cAAc;AACtB,QAAKA,eAAe;AACpB,QAAKN,WAAW,KAAK,CAAC,mBAAmB,YAAY,gBAAgB,UAAU,CAAC;EACjF;AACD,SAAO;CACR;CAED,qBAA2B;AACzB,OAAKA,WAAW,KAAK,CAAC,mBAAmB,iBAAiB,eAAe,CAAC;AAC1E,SAAO;CACR;;;;;;;;;;CAWD,QAAQO,cAA6B;AACnC,OAAK,OAAO,WAAW,yBAAyB,aAAa,CAAC;AAC9D,SAAO;CACR;CA2BD,OAA4BC,QAAkCC,UAAqC;AACjG,OAAKT,WAAW,KAAK,CAAC,mBAAmB,gBAAgB,gBAAgB,QAAQ,SAAS,CAAC;AAC3F,SAAO;CACR;;;;;;;;;;;;;;;CAgBD,MAAMU,SAAmD;AACvD,OAAK,oBAAoB;EACzB,MAAM,SACJ,KAAKV,WAAW,OAA2C,CAAC,KAAK,QAAQ,IAAI,IAAI,IAAI,KAAK,UAAU,IAAI,CAAE;AAE5G,SAAO;GACL;GACA,QAAQ,oBAAoB,CAAC,GAAG,MAAO,GAAE;IAAE,UAAU,IAAI,IAAI,SAAS,SAAS;IAAU,GAAG;GAAS,EAAC;EACvG;CACF;AACF","names":["#modifiers","routes: readonly RouteObject[]","routes: readonly AgnosticRoute[]","component: ComponentType","config?: ViewConfig","#isFallbackSet","#isLayoutSet","redirectPath?: string","routes: readonly T[] | undefined","callback: RouteTransformer<T>","options?: RouterBuildOptions"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/RouterConfigurationBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\nimport type { ComponentType } from 'react';\nimport { createBrowserRouter, type RouteObject } from 'react-router';\nimport type { AgnosticRoute, RouterBuildOptions, RouterConfiguration, ViewConfig } from '../../types.js';\nimport createFallbackTransformer, { createFallbackRoutes } from './createFallbackTransformer.js';\nimport createProtectTransformer from './createProtectTransformer.js';\nimport fileRouteTransformer from './fileRouteTransformer.js';\nimport mergeDeepWildcard from './mergeDeepWildcard.js';\nimport mergeLayout from './mergeLayout.js';\nimport { mergeRouteTrees } from './mergeRouteTrees.js';\nimport mergeSkipLayouts from './mergeSkipLayout.js';\nimport type { RouteLike, RouteTreeModifier, RouteTransformer } from './utils.js';\n\n/**\n * A configuration builder for creating a Vaadin-specific router for React with\n * authentication and server routes support.\n *\n * The configuration builder allows you to compose and modify route trees by\n * chaining methods that add custom React routes, generated file-based routes,\n * layout components, etc. Modifiers are accumulated and applied in order when\n * building the final router configuration.\n *\n * @example\n * ```typescript\n * const { routes, router } = new RouteConfigurationBuilder()\n * .withFileRoutes(fileRoutes)\n * .withReactRoutes({ path: '/foo/baz', element: <FooBazPage /> })\n * .withFallback(Flow)\n * .protect('/login')\n * .build();\n * ```\n */\nexport class RouterConfigurationBuilder {\n readonly #modifiers: RouteTreeModifier[] = [];\n #isFallbackSet = false;\n #isLayoutSet = false;\n\n /**\n * Adds the given React routes to the current list of routes. All the routes\n * are deeply merged to preserve the path uniqueness.\n *\n * @param routes - An array of React Router route objects to be merged into\n * the current route list.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withReactRoutes(routes: readonly RouteObject[]): this {\n this.update(routes);\n return this;\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 - An array of file-based route objects to be processed and\n * merged into the current route list.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withFileRoutes(routes: readonly AgnosticRoute[]): this {\n this.update(routes, fileRouteTransformer);\n return this;\n }\n\n /**\n * Adds a fallback component for each branch of the current route tree.\n *\n * The fallback component is used when no other route matches the requested\n * URL. In terms of Vaadin application, after no match on the client side, the\n * turn goes to the server-side router.\n *\n * @remarks This method can be called only once. All the subsequent calls will\n * be ignored.\n *\n * @remarks This method also runs the `withLayout` method with the given\n * component to make sure server-side layout is applied to routes.\n *\n * @param component - The component to use as the fallback and layout\n * component.\n * @param config - Optional view configuration for the fallback component.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withFallback(component: ComponentType, config?: ViewConfig): this {\n if (!this.#isFallbackSet) {\n this.#isFallbackSet = true;\n this.withLayout(component);\n\n const fallbackRoutes = createFallbackRoutes(component, config);\n\n this.update(\n // Add the fallback routes to the end of the route tree.\n fallbackRoutes,\n // Add the fallback routes to each route tree branch via transformer.\n createFallbackTransformer(fallbackRoutes),\n );\n }\n return this;\n }\n\n withDeepWildcard(): this {\n this.#modifiers.push((originalRoutes) => mergeDeepWildcard(originalRoutes));\n return this;\n }\n\n /**\n * Adds the parent layout to all views with the `flowLayouts` flag set in the\n * ViewConfiguration.\n *\n * @remarks This method can be called only once. All the subsequent calls will\n * be ignored.\n *\n * @param component - The component to use as the layout for the routes.\n * Usually, it is `Flow` component.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withLayout(component: ComponentType): this {\n if (!this.#isLayoutSet) {\n this.#isLayoutSet = true;\n this.#modifiers.push((originalRoutes) => mergeLayout(originalRoutes, component));\n }\n return this;\n }\n\n withLayoutSkipping(): this {\n this.#modifiers.push((originalRoutes) => mergeSkipLayouts(originalRoutes));\n return this;\n }\n\n /**\n * Adds protection to the route, requiring authentication or authorization to\n * access it.\n *\n * @param redirectPath - Optional path to redirect to when protection fails.\n * If not provided, the default redirect page (`/login`) will be used.\n *\n * @returns The current instance of the builder for method chaining.\n */\n protect(redirectPath?: string): this {\n this.update(undefined, createProtectTransformer(redirectPath));\n return this;\n }\n\n /**\n * Deeply updates the current route tree, merging the existing routes with the\n * given routes using the provided transformer callback.\n *\n * @param routes - The routes used to update the current route tree.\n * @param callback - A transformer function that defines how the routes should\n * be modified. Required if `routes` are not provided.\n *\n * @returns This RouteConfigurationBuilder instance for method chaining\n */\n update(routes: undefined, callback: RouteTransformer): this;\n\n /**\n * Deeply updates the current route tree, merging the existing routes with the\n * given routes using the provided transformer callback.\n *\n * @typeParam T - The type of routes being updated.\n *\n * @param routes - The routes used to update the current route tree.\n * @param callback - A transformer function that defines how the routes should\n * be modified. Required if `routes` are not provided.\n *\n * @returns This RouteConfigurationBuilder instance for method chaining\n */\n update<T extends RouteLike>(routes: readonly T[], callback?: RouteTransformer<T>): this;\n update<T extends RouteLike>(routes: readonly T[] | undefined, callback: RouteTransformer<T>): this {\n this.#modifiers.push((originalRoutes) => mergeRouteTrees(originalRoutes, routes, callback));\n return this;\n }\n\n /**\n * Builds the router configuration by applying all registered modifiers to the\n * routes.\n *\n * @remarks\n * This method applies the the logic for layout skipping along with any other\n * registered modifiers to transform the routes.\n *\n * @param options - Optional React `createBrowserRouter` options to configure\n * the router.\n *\n * @returns A RouterConfiguration object containing the processed routes and\n * configured browser router\n */\n build(options?: RouterBuildOptions): RouterConfiguration {\n this.withLayoutSkipping();\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"],"version":3}
1
+ {"mappings":"AAEA,SAAS,yCAA4D;AAErE,OAAO,6BAA6B,4DAA6D;AACjG,OAAO,6DAA8D;AACrE,OAAO,qDAAsD;AAC7D,OAAO,+CAAgD;AACvD,OAAO,mCAAoC;AAC3C,SAAS,6CAA8C;AACvD,OAAO,4CAA6C;;;;;;;;;;;;;;;;;;;;AAsBpD,OAAO,MAAM,2BAA2B;CACtC,AAASA,aAAkC,CAAE;CAC7C,iBAAiB;CACjB,eAAe;;;;;;;;;;CAWf,gBAAgBC,QAAsC;AACpD,OAAK,OAAO,OAAO;AACnB,SAAO;CACR;;;;;;;;;;;CAYD,eAAeC,QAAwC;AACrD,OAAK,OAAO,QAAQ,qBAAqB;AACzC,SAAO;CACR;;;;;;;;;;;;;;;;;;;;CAqBD,aAAaC,WAA0BC,QAA2B;AAChE,OAAK,KAAKC,gBAAgB;AACxB,QAAKA,iBAAiB;AACtB,QAAK,WAAW,UAAU;GAE1B,MAAM,iBAAiB,qBAAqB,WAAW,OAAO;AAE9D,QAAK;;IAEH;;IAEA,0BAA0B,eAAe;CAC1C;EACF;AACD,SAAO;CACR;CAED,mBAAyB;AACvB,OAAKL,WAAW,KAAK,CAAC,mBAAmB,kBAAkB,eAAe,CAAC;AAC3E,SAAO;CACR;;;;;;;;;;;;;CAcD,WAAWG,WAAgC;AACzC,OAAK,KAAKG,cAAc;AACtB,QAAKA,eAAe;AACpB,QAAKN,WAAW,KAAK,CAAC,mBAAmB,YAAY,gBAAgB,UAAU,CAAC;EACjF;AACD,SAAO;CACR;CAED,qBAA2B;AACzB,OAAKA,WAAW,KAAK,CAAC,mBAAmB,iBAAiB,eAAe,CAAC;AAC1E,SAAO;CACR;;;;;;;;;;CAWD,QAAQO,cAA6B;AACnC,OAAK,OAAO,WAAW,yBAAyB,aAAa,CAAC;AAC9D,SAAO;CACR;CA2BD,OAA4BC,QAAkCC,UAAqC;AACjG,OAAKT,WAAW,KAAK,CAAC,mBAAmB,gBAAgB,gBAAgB,QAAQ,SAAS,CAAC;AAC3F,SAAO;CACR;;;;;;;;;;;;;;;CAgBD,MAAMU,SAAmD;AACvD,OAAK,oBAAoB;EACzB,MAAM,SACJ,KAAKV,WAAW,OAA2C,CAAC,KAAK,QAAQ,IAAI,IAAI,IAAI,KAAK,UAAU,IAAI,CAAE;AAE5G,SAAO;GACL;GACA,QAAQ,oBAAoB,CAAC,GAAG,MAAO,GAAE;IAAE,UAAU,IAAI,IAAI,SAAS,SAAS;IAAU,GAAG;GAAS,EAAC;EACvG;CACF;AACF","names":["#modifiers","routes: readonly RouteObject[]","routes: readonly AgnosticRoute[]","component: ComponentType","config?: ViewConfig","#isFallbackSet","#isLayoutSet","redirectPath?: string","routes: readonly T[] | undefined","callback: RouteTransformer<T>","options?: RouterBuildOptions"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/RouterConfigurationBuilder.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\nimport type { ComponentType } from 'react';\nimport { createBrowserRouter, type RouteObject } from 'react-router';\nimport type { AgnosticRoute, RouterBuildOptions, RouterConfiguration, ViewConfig } from '../../types.js';\nimport createFallbackTransformer, { createFallbackRoutes } from './createFallbackTransformer.js';\nimport createProtectTransformer from './createProtectTransformer.js';\nimport fileRouteTransformer from './fileRouteTransformer.js';\nimport mergeDeepWildcard from './mergeDeepWildcard.js';\nimport mergeLayout from './mergeLayout.js';\nimport { mergeRouteTrees } from './mergeRouteTrees.js';\nimport mergeSkipLayouts from './mergeSkipLayout.js';\nimport type { RouteLike, RouteTreeModifier, RouteTransformer } from './utils.js';\n\n/**\n * A configuration builder for creating a Vaadin-specific router for React with\n * authentication and server routes support.\n *\n * The configuration builder allows you to compose and modify route trees by\n * chaining methods that add custom React routes, generated file-based routes,\n * layout components, etc. Modifiers are accumulated and applied in order when\n * building the final router configuration.\n *\n * @example\n * ```typescript\n * const { routes, router } = new RouteConfigurationBuilder()\n * .withFileRoutes(fileRoutes)\n * .withReactRoutes({ path: '/foo/baz', element: <FooBazPage /> })\n * .withFallback(Flow)\n * .protect('/login')\n * .build();\n * ```\n */\nexport class RouterConfigurationBuilder {\n readonly #modifiers: RouteTreeModifier[] = [];\n #isFallbackSet = false;\n #isLayoutSet = false;\n\n /**\n * Adds the given React routes to the current list of routes. All the routes\n * are deeply merged to preserve the path uniqueness.\n *\n * @param routes - An array of React Router route objects to be merged into\n * the current route list.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withReactRoutes(routes: readonly RouteObject[]): this {\n this.update(routes);\n return this;\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 - An array of file-based route objects to be processed and\n * merged into the current route list.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withFileRoutes(routes: readonly AgnosticRoute[]): this {\n this.update(routes, fileRouteTransformer);\n return this;\n }\n\n /**\n * Adds a fallback component for each branch of the current route tree.\n *\n * The fallback component is used when no other route matches the requested\n * URL. In terms of Vaadin application, after no match on the client side, the\n * turn goes to the server-side router.\n *\n * @remarks This method can be called only once. All the subsequent calls will\n * be ignored.\n *\n * @remarks This method also runs the `withLayout` method with the given\n * component to make sure server-side layout is applied to routes.\n *\n * @param component - The component to use as the fallback and layout\n * component.\n * @param config - Optional view configuration for the fallback component.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withFallback(component: ComponentType, config?: ViewConfig): this {\n if (!this.#isFallbackSet) {\n this.#isFallbackSet = true;\n this.withLayout(component);\n\n const fallbackRoutes = createFallbackRoutes(component, config);\n\n this.update(\n // Add the fallback routes to the end of the route tree.\n fallbackRoutes,\n // Add the fallback routes to each route tree branch via transformer.\n createFallbackTransformer(fallbackRoutes),\n );\n }\n return this;\n }\n\n withDeepWildcard(): this {\n this.#modifiers.push((originalRoutes) => mergeDeepWildcard(originalRoutes));\n return this;\n }\n\n /**\n * Adds the parent layout to all views with the `flowLayouts` flag set in the\n * ViewConfiguration.\n *\n * @remarks This method can be called only once. All the subsequent calls will\n * be ignored.\n *\n * @param component - The component to use as the layout for the routes.\n * Usually, it is `Flow` component.\n *\n * @returns The current instance of the builder for method chaining.\n */\n withLayout(component: ComponentType): this {\n if (!this.#isLayoutSet) {\n this.#isLayoutSet = true;\n this.#modifiers.push((originalRoutes) => mergeLayout(originalRoutes, component));\n }\n return this;\n }\n\n withLayoutSkipping(): this {\n this.#modifiers.push((originalRoutes) => mergeSkipLayouts(originalRoutes));\n return this;\n }\n\n /**\n * Adds protection to the route, requiring authentication or authorization to\n * access it.\n *\n * @param redirectPath - Optional path to redirect to when protection fails.\n * If not provided, the default redirect page (`/login`) will be used.\n *\n * @returns The current instance of the builder for method chaining.\n */\n protect(redirectPath?: string): this {\n this.update(undefined, createProtectTransformer(redirectPath));\n return this;\n }\n\n /**\n * Deeply updates the current route tree, merging the existing routes with the\n * given routes using the provided transformer callback.\n *\n * @param routes - The routes used to update the current route tree.\n * @param callback - A transformer function that defines how the routes should\n * be modified. Required if `routes` are not provided.\n *\n * @returns This RouteConfigurationBuilder instance for method chaining\n */\n update(routes: undefined, callback: RouteTransformer): this;\n\n /**\n * Deeply updates the current route tree, merging the existing routes with the\n * given routes using the provided transformer callback.\n *\n * @typeParam T - The type of routes being updated.\n *\n * @param routes - The routes used to update the current route tree.\n * @param callback - A transformer function that defines how the routes should\n * be modified. Required if `routes` are not provided.\n *\n * @returns This RouteConfigurationBuilder instance for method chaining\n */\n update<T extends RouteLike>(routes: readonly T[], callback?: RouteTransformer<T>): this;\n update<T extends RouteLike>(routes: readonly T[] | undefined, callback: RouteTransformer<T>): this {\n this.#modifiers.push((originalRoutes) => mergeRouteTrees(originalRoutes, routes, callback));\n return this;\n }\n\n /**\n * Builds the router configuration by applying all registered modifiers to the\n * routes.\n *\n * @remarks\n * This method applies the the logic for layout skipping along with any other\n * registered modifiers to transform the routes.\n *\n * @param options - Optional React `createBrowserRouter` options to configure\n * the router.\n *\n * @returns A RouterConfiguration object containing the processed routes and\n * configured browser router\n */\n build(options?: RouterBuildOptions): RouterConfiguration {\n this.withLayoutSkipping();\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"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAA6B,4BAA6B;AAG1D,SACE,eACA,cACA,iBACA,iBACA,mCAEkB;;;;;;;;;AAmBpB,OAAO,SAAS,qBAAqBA,WAA0BC,QAAqC;AAClG,QAAO,CACL;EAAE,MAAM;EAAK,SAAS,cAAc,UAAU;EAAE,QAAQ;CAAQ,GAChE;EAAE,OAAO;EAAM,SAAS,cAAc,UAAU;EAAE,QAAQ;CAAQ,CACnE;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBD,eAAe,SAAS,0BAA0B,CAAC,kBAAkB,cAA8B,EAAoB;AACrH,QAAO,CAAC,EAAE,UAAU,UAAU,UAAU,MAAM,KAAK;AACjD,MAAI,aAAa,cAAc,UAAU,gBAAgB,gBAAgB,KAAK,MAAM;AAClF,QAAK,UAAU;AACb,WAAO;GACR;GAED,IAAIC;AAEJ,OAAI,SAAS,KAAK,CAAC,UAAU,gBAAgB,MAAM,CAAC,EAAE;AACpD,eAAW,CAAC,aAAc;GAC3B,WAAU,SAAS,KAAK,CAAC,UAAU,aAAa,MAAM,IAAI,gBAAgB,MAAM,CAAC,EAAE;AAClF,eAAW,CAAC,gBAAiB;GAC9B,OAAM;AACL,eAAW,CAAC,kBAAkB,aAAc;GAC7C;AAGD,UAAO;IACL,GAAG;IACH,UAAU,CAAC,GAAG,UAAU,GAAG,QAAS;GACrC;EACF;AAED,SAAO;CACR;AACF","names":["component: ComponentType","config?: ViewConfig","fallback: RouteObject[]"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/createFallbackTransformer.ts"],"sourcesContent":["import { type ComponentType, createElement } from 'react';\nimport type { RouteObject, NonIndexRouteObject } from 'react-router';\nimport type { ViewConfig } from '../../types.js';\nimport {\n getHandleFlag,\n isIndexRoute,\n isOptionalRoute,\n isWildcardRoute,\n RouteHandleFlag,\n type RouteTransformer,\n} from './utils.js';\n\n/**\n * A tuple of fallback routes:\n * - A wildcard route (`path: '*'`) that renders the component for any unmatched\n * path.\n * - An index route (`index: true`) that renders the component for the empty\n * path.\n */\nexport type FallbackRoutes = readonly [notFoundFallback: RouteObject, indexFallback: RouteObject];\n\n/**\n * Creates fallback routes for handling unmatched paths and index routes.\n *\n * @param component - The React component to render for the fallback routes\n * @param config - Optional view configuration to attach to the route handles\n *\n * @returns A tuple of fallback routes.\n */\nexport function createFallbackRoutes(component: ComponentType, config?: ViewConfig): FallbackRoutes {\n return [\n { path: '*', element: createElement(component), handle: config },\n { index: true, element: createElement(component), handle: config },\n ];\n}\n\n/**\n * Creates a route transformer that adds fallback routes to handle unmatched\n * paths.\n *\n * This transformer adds two types of fallback routes:\n * - A wildcard route (`path: '*'`) that renders the specified fallback\n * component for any unmatched path.\n * - An index fallback route (`index: true`) that renders the fallback component\n * for the empty path.\n *\n * The transformer logic determines which fallback to add based on the existing\n * child routes:\n * - If a wildcard child route already defined, only the index fallback is\n * added.\n * - If an index or optional child route exists, only the wildcard fallback is\n * added.\n * - Otherwise, both fallback routes are added.\n *\n * @param component - The React component to render as the fallback.\n * @param config - A view configuration of the fallback route if any.\n * @returns A route transformer function.\n */\nexport default function createFallbackTransformer([notFoundFallback, indexFallback]: FallbackRoutes): RouteTransformer {\n return ({ original, override, children, dupe }) => {\n if (original && !getHandleFlag(original, RouteHandleFlag.IGNORE_FALLBACK) && !dupe) {\n if (!children) {\n return original; //: IndexRouteObject;\n }\n\n let fallback: RouteObject[];\n\n if (children.some((route) => isWildcardRoute(route))) {\n fallback = [indexFallback];\n } else if (children.some((route) => isIndexRoute(route) || isOptionalRoute(route))) {\n fallback = [notFoundFallback];\n } else {\n fallback = [notFoundFallback, indexFallback];\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return {\n ...original,\n children: [...children, ...fallback],\n } as NonIndexRouteObject;\n }\n\n return override as RouteObject | undefined;\n };\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAA6B,4BAA6B;AAG1D,SACE,eACA,cACA,iBACA,iBACA,mCAEkB;;;;;;;;;AAmBpB,OAAO,SAAS,qBAAqBA,WAA0BC,QAAqC;AAClG,QAAO,CACL;EAAE,MAAM;EAAK,SAAS,cAAc,UAAU;EAAE,QAAQ;CAAQ,GAChE;EAAE,OAAO;EAAM,SAAS,cAAc,UAAU;EAAE,QAAQ;CAAQ,CACnE;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBD,eAAe,SAAS,0BAA0B,CAAC,kBAAkB,cAA8B,EAAoB;AACrH,QAAO,CAAC,EAAE,UAAU,UAAU,UAAU,MAAM,KAAK;AACjD,MAAI,aAAa,cAAc,UAAU,gBAAgB,gBAAgB,KAAK,MAAM;AAClF,QAAK,UAAU;AACb,WAAO;GACR;GAED,IAAIC;AAEJ,OAAI,SAAS,KAAK,CAAC,UAAU,gBAAgB,MAAM,CAAC,EAAE;AACpD,eAAW,CAAC,aAAc;GAC3B,WAAU,SAAS,KAAK,CAAC,UAAU,aAAa,MAAM,IAAI,gBAAgB,MAAM,CAAC,EAAE;AAClF,eAAW,CAAC,gBAAiB;GAC9B,OAAM;AACL,eAAW,CAAC,kBAAkB,aAAc;GAC7C;AAGD,UAAO;IACL,GAAG;IACH,UAAU,CAAC,GAAG,UAAU,GAAG,QAAS;GACrC;EACF;AAED,SAAO;CACR;AACF","names":["component: ComponentType","config?: ViewConfig","fallback: RouteObject[]"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/createFallbackTransformer.ts"],"sourcesContent":["import { type ComponentType, createElement } from 'react';\nimport type { RouteObject, NonIndexRouteObject } from 'react-router';\nimport type { ViewConfig } from '../../types.js';\nimport {\n getHandleFlag,\n isIndexRoute,\n isOptionalRoute,\n isWildcardRoute,\n RouteHandleFlag,\n type RouteTransformer,\n} from './utils.js';\n\n/**\n * A tuple of fallback routes:\n * - A wildcard route (`path: '*'`) that renders the component for any unmatched\n * path.\n * - An index route (`index: true`) that renders the component for the empty\n * path.\n */\nexport type FallbackRoutes = readonly [notFoundFallback: RouteObject, indexFallback: RouteObject];\n\n/**\n * Creates fallback routes for handling unmatched paths and index routes.\n *\n * @param component - The React component to render for the fallback routes\n * @param config - Optional view configuration to attach to the route handles\n *\n * @returns A tuple of fallback routes.\n */\nexport function createFallbackRoutes(component: ComponentType, config?: ViewConfig): FallbackRoutes {\n return [\n { path: '*', element: createElement(component), handle: config },\n { index: true, element: createElement(component), handle: config },\n ];\n}\n\n/**\n * Creates a route transformer that adds fallback routes to handle unmatched\n * paths.\n *\n * This transformer adds two types of fallback routes:\n * - A wildcard route (`path: '*'`) that renders the specified fallback\n * component for any unmatched path.\n * - An index fallback route (`index: true`) that renders the fallback component\n * for the empty path.\n *\n * The transformer logic determines which fallback to add based on the existing\n * child routes:\n * - If a wildcard child route already defined, only the index fallback is\n * added.\n * - If an index or optional child route exists, only the wildcard fallback is\n * added.\n * - Otherwise, both fallback routes are added.\n *\n * @param component - The React component to render as the fallback.\n * @param config - A view configuration of the fallback route if any.\n * @returns A route transformer function.\n */\nexport default function createFallbackTransformer([notFoundFallback, indexFallback]: FallbackRoutes): RouteTransformer {\n return ({ original, override, children, dupe }) => {\n if (original && !getHandleFlag(original, RouteHandleFlag.IGNORE_FALLBACK) && !dupe) {\n if (!children) {\n return original; //: IndexRouteObject;\n }\n\n let fallback: RouteObject[];\n\n if (children.some((route) => isWildcardRoute(route))) {\n fallback = [indexFallback];\n } else if (children.some((route) => isIndexRoute(route) || isOptionalRoute(route))) {\n fallback = [notFoundFallback];\n } else {\n fallback = [notFoundFallback, indexFallback];\n }\n\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return {\n ...original,\n children: [...children, ...fallback],\n } as NonIndexRouteObject;\n }\n\n return override as RouteObject | undefined;\n };\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,8CAA+C;;;;;;;;;;AAaxD,eAAe,SAAS,yBAAyBA,cAAyC;AACxF,QAAO,CAAC,EAAE,UAAU,UAAU,KAAK;AACjC,OAAK,UAAU;AACb,UAAO;EACR;EAED,MAAM,aAAa,aAAa,UAAU,aAAa;AACvD,aAAW,WAAW;AACtB,SAAO;CACR;AACF","names":["redirectPath?: string"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/createProtectTransformer.ts"],"sourcesContent":["import { protectRoute } from '@vaadin/hilla-react-auth';\nimport type { RouteObject } from 'react-router';\nimport type { RouteTransformer } from './utils.js';\n\n/**\n * Creates a route transformer that applies route protection to a given route,\n * optionally redirecting unauthorized access to a specified path.\n *\n * @param redirectPath - Optional path to redirect unauthorized users to.\n * Defaults to '/login'.\n *\n * @returns A route transformer function that applies protection to the route.\n */\nexport default function createProtectTransformer(redirectPath?: string): RouteTransformer {\n return ({ original, children }) => {\n if (!original) {\n return original;\n }\n\n const finalRoute = protectRoute(original, redirectPath);\n finalRoute.children = children as RouteObject[] | undefined;\n return finalRoute;\n };\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,8CAA+C;;;;;;;;;;AAaxD,eAAe,SAAS,yBAAyBA,cAAyC;AACxF,QAAO,CAAC,EAAE,UAAU,UAAU,KAAK;AACjC,OAAK,UAAU;AACb,UAAO;EACR;EAED,MAAM,aAAa,aAAa,UAAU,aAAa;AACvD,aAAW,WAAW;AACtB,SAAO;CACR;AACF","names":["redirectPath?: string"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/createProtectTransformer.ts"],"sourcesContent":["import { protectRoute } from '@vaadin/hilla-react-auth';\nimport type { RouteObject } from 'react-router';\nimport type { RouteTransformer } from './utils.js';\n\n/**\n * Creates a route transformer that applies route protection to a given route,\n * optionally redirecting unauthorized access to a specified path.\n *\n * @param redirectPath - Optional path to redirect unauthorized users to.\n * Defaults to '/login'.\n *\n * @returns A route transformer function that applies protection to the route.\n */\nexport default function createProtectTransformer(redirectPath?: string): RouteTransformer {\n return ({ original, children }) => {\n if (!original) {\n return original;\n }\n\n const finalRoute = protectRoute(original, redirectPath);\n finalRoute.children = children as RouteObject[] | undefined;\n return finalRoute;\n };\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,4BAA6B;AAEtC,SAAS,gFAAiF;AAE1F,SAAS,sCAAqE;;;;;;;;;;;;;;AAe9E,eAAe,SAAS,qBAAqB,EAC3C,UACA,UACA,UACuC,EAA2B;AAClE,MAAK,UAAU;AACb,SAAO;CACR;CAED,MAAM,EAAE,QAAQ,YAAY,QAAQ,SAAS,SAAS,QAAQ,QAAQ,MAAM,YAAY,GAAG;AAE3F,KAAI,WAAW,mBAAmB,OAAO,EAAE;AACzC,QAAM,IAAI,OACP,sBAAsB,KAAK;CAE/B;CAED,MAAM,UAAU,YAAY,cAAc,UAAU,GAAG;CACvD,MAAM,SAAS;EACb,GAAG;EACH,OAAO,QAAQ,SAAS,4BAA4B,UAAU;EAC9D,YAAY,QAAQ,cAAc;CACnC;AAED,KAAI,SAAS,OAAO,UAAU;AAC5B,SAAO;GACL,GAAI;GACJ;GACA;GACA,OAAO;EACR;CACF;AAED,QAAO;EACL,GAAI;EACJ,MAAM,QAAQ,SAAS;EACvB;EACU;EACV;CACD;AACF","names":[],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/fileRouteTransformer.ts"],"sourcesContent":["import { createElement } from 'react';\nimport type { IndexRouteObject, NonIndexRouteObject, RouteObject } from 'react-router';\nimport { convertComponentNameToTitle } from '../../shared/convertComponentNameToTitle.js';\nimport type { AgnosticRoute } from '../../types.js';\nimport { isReactRouteModule, type RouteTransformerOptions } from './utils.js';\n\n/**\n * Transforms a framework-agnostic route into a route object compatible with\n * React Router and merges it with the existing route object if any.\n *\n * @param options - The route transformer options containing the existing route,\n * any overrides, and child routes.\n *\n * @returns A `RouteObject` representing the transformed route, or the original\n * route if no override is provided.\n *\n * @throws If the provided module does not export a React component by default\n * nor a ViewConfig object as \"config\".\n */\nexport default function fileRouteTransformer({\n original,\n override,\n children,\n}: RouteTransformerOptions<AgnosticRoute>): RouteObject | undefined {\n if (!override) {\n return original;\n }\n\n const { module, component = module?.default, config = module?.config, path, flowLayout } = override;\n\n if (module && !isReactRouteModule(module)) {\n throw new Error(\n `The module for the \"${path}\" section doesn't have the React component exported by default or a ViewConfig object exported as \"config\"`,\n );\n }\n\n const element = component ? createElement(component) : undefined;\n const handle = {\n ...config,\n title: config?.title ?? convertComponentNameToTitle(component),\n flowLayout: config?.flowLayout ?? flowLayout,\n };\n\n if (path === '' && !children) {\n return {\n ...(original as IndexRouteObject),\n element,\n handle,\n index: true,\n } satisfies IndexRouteObject;\n }\n\n return {\n ...(original as NonIndexRouteObject),\n path: config?.route ?? path,\n element,\n children: children as RouteObject[] | undefined,\n handle,\n } satisfies NonIndexRouteObject;\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,4BAA6B;AAEtC,SAAS,gFAAiF;AAE1F,SAAS,sCAAqE;;;;;;;;;;;;;;AAe9E,eAAe,SAAS,qBAAqB,EAC3C,UACA,UACA,UACuC,EAA2B;AAClE,MAAK,UAAU;AACb,SAAO;CACR;CAED,MAAM,EAAE,QAAQ,YAAY,QAAQ,SAAS,SAAS,QAAQ,QAAQ,MAAM,YAAY,GAAG;AAE3F,KAAI,WAAW,mBAAmB,OAAO,EAAE;AACzC,QAAM,IAAI,OACP,sBAAsB,KAAK;CAE/B;CAED,MAAM,UAAU,YAAY,cAAc,UAAU,GAAG;CACvD,MAAM,SAAS;EACb,GAAG;EACH,OAAO,QAAQ,SAAS,4BAA4B,UAAU;EAC9D,YAAY,QAAQ,cAAc;CACnC;AAED,KAAI,SAAS,OAAO,UAAU;AAC5B,SAAO;GACL,GAAI;GACJ;GACA;GACA,OAAO;EACR;CACF;AAED,QAAO;EACL,GAAI;EACJ,MAAM,QAAQ,SAAS;EACvB;EACU;EACV;CACD;AACF","names":[],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/fileRouteTransformer.ts"],"sourcesContent":["import { createElement } from 'react';\nimport type { IndexRouteObject, NonIndexRouteObject, RouteObject } from 'react-router';\nimport { convertComponentNameToTitle } from '../../shared/convertComponentNameToTitle.js';\nimport type { AgnosticRoute } from '../../types.js';\nimport { isReactRouteModule, type RouteTransformerOptions } from './utils.js';\n\n/**\n * Transforms a framework-agnostic route into a route object compatible with\n * React Router and merges it with the existing route object if any.\n *\n * @param options - The route transformer options containing the existing route,\n * any overrides, and child routes.\n *\n * @returns A `RouteObject` representing the transformed route, or the original\n * route if no override is provided.\n *\n * @throws If the provided module does not export a React component by default\n * nor a ViewConfig object as \"config\".\n */\nexport default function fileRouteTransformer({\n original,\n override,\n children,\n}: RouteTransformerOptions<AgnosticRoute>): RouteObject | undefined {\n if (!override) {\n return original;\n }\n\n const { module, component = module?.default, config = module?.config, path, flowLayout } = override;\n\n if (module && !isReactRouteModule(module)) {\n throw new Error(\n `The module for the \"${path}\" section doesn't have the React component exported by default or a ViewConfig object exported as \"config\"`,\n );\n }\n\n const element = component ? createElement(component) : undefined;\n const handle = {\n ...config,\n title: config?.title ?? convertComponentNameToTitle(component),\n flowLayout: config?.flowLayout ?? flowLayout,\n };\n\n if (path === '' && !children) {\n return {\n ...(original as IndexRouteObject),\n element,\n handle,\n index: true,\n } satisfies IndexRouteObject;\n }\n\n return {\n ...(original as NonIndexRouteObject),\n path: config?.route ?? path,\n element,\n children: children as RouteObject[] | undefined,\n handle,\n } satisfies NonIndexRouteObject;\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AACA,SAAS,oDAAqD;AAC9D,SAAS,mCAAoC;AAE7C,eAAe,SAAS,kBACtBA,gBACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;AAED,QAAO,cAA8D,gBAAgB,MAAM,CAAC,QAAQ,SAClG,OAAO,OAAsB,CAAC,KAAK,OAAO,GAAG,QAAQ;EACnD,MAAM,WAAW,IAAI,KAAK,gBAAgB;EAC1C,MAAM,WAAW,MAAM,WACnB,KACE,YAAY,MAAM,SAAS,MAAM,CAAC,OAAO,gBAAgB,EAAE,CAAC,GACxD,CAAC,GAAG,MAAM,UAAU,QAAS,IAC7B,MAAM,SACX,GACD;AAEJ,MAAI,KAAK;GACP,GAAG;GACH;EACD,EAAgB;AAEjB,SAAO;CACR,GAAE,CAAE,EAAC,CACP;AACF","names":["originalRoutes: readonly RouteObject[] | undefined"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/mergeDeepWildcard.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { isWildcardRoute } from './utils.js';\n\nexport default function mergeDeepWildcard(\n originalRoutes: readonly RouteObject[] | undefined,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n return transformTree<readonly RouteObject[], readonly RouteObject[]>(originalRoutes, null, (routes, next) =>\n routes.reduce<RouteObject[]>((acc, route, _, arr) => {\n const wildcard = arr.find(isWildcardRoute);\n const children = route.children\n ? next(\n wildcard && route.children.every((r) => !isWildcardRoute(r))\n ? [...route.children, wildcard]\n : route.children,\n )\n : undefined;\n\n acc.push({\n ...route,\n children,\n } as RouteObject);\n\n return acc;\n }, []),\n );\n}\n"],"version":3}
1
+ {"mappings":"AACA,SAAS,oDAAqD;AAC9D,SAAS,mCAAoC;AAE7C,eAAe,SAAS,kBACtBA,gBACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;AAED,QAAO,cAA8D,gBAAgB,MAAM,CAAC,QAAQ,SAClG,OAAO,OAAsB,CAAC,KAAK,OAAO,GAAG,QAAQ;EACnD,MAAM,WAAW,IAAI,KAAK,gBAAgB;EAC1C,MAAM,WAAW,MAAM,WACnB,KACE,YAAY,MAAM,SAAS,MAAM,CAAC,OAAO,gBAAgB,EAAE,CAAC,GACxD,CAAC,GAAG,MAAM,UAAU,QAAS,IAC7B,MAAM,SACX,GACD;AAEJ,MAAI,KAAK;GACP,GAAG;GACH;EACD,EAAgB;AAEjB,SAAO;CACR,GAAE,CAAE,EAAC,CACP;AACF","names":["originalRoutes: readonly RouteObject[] | undefined"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/mergeDeepWildcard.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { isWildcardRoute } from './utils.js';\n\nexport default function mergeDeepWildcard(\n originalRoutes: readonly RouteObject[] | undefined,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n return transformTree<readonly RouteObject[], readonly RouteObject[]>(originalRoutes, null, (routes, next) =>\n routes.reduce<RouteObject[]>((acc, route, _, arr) => {\n const wildcard = arr.find(isWildcardRoute);\n const children = route.children\n ? next(\n wildcard && route.children.every((r) => !isWildcardRoute(r))\n ? [...route.children, wildcard]\n : route.children,\n )\n : undefined;\n\n acc.push({\n ...route,\n children,\n } as RouteObject);\n\n return acc;\n }, []),\n );\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,4BAAiD;AAE1D,SAAS,oDAAqD;AAC9D,SAAS,eAAe,mCAAoC;;;;;;;;;;;;;;;;;;;;;;AAuB5D,eAAe,SAAS,YACtBA,gBACAC,WACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;CAQD,MAAM,SAAS,cAA8C,gBAAgB,MAAM,CAAC,QAAQ,SAM1F,OAAO,OACL,CAAC,QAAQ,UAAU;EACjB,MAAM,EAAE,QAAQ,QAAQ,SAAS,GAAG,KAAK,MAAM,YAAY,CAAE,EAAC;EAE9D,MAAM,OAAO,cAAc,OAAO,gBAAgB,YAAY;AAK9D,MAAI,SAAS,MAAM;AACjB,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,CAAC,GAAG,QAAQ,GAAG,OAAQ,IAAG;GACtD,EAAgB;EAClB,WAAU,OAAO,SAAS,GAAG;AAG5B,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,SAAS;GACrC,EAAgB;EAClB;AAKD,MAAI,SAAS,SAAS,OAAO,SAAS,GAAG;AACvC,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,SAAS;GACrC,EAAgB;EAClB;AAKD,MAAI,SAAS,cAAc,OAAO,OAAO,MAAM,CAAC,EAAE,MAAM,KAAK,SAAS,MAAM,KAAK,IAAI,QAAQ,SAAS,IAAI;AACxG,UAAO,QAAQ,KAAK;IAClB,GAAG;IACH,UAAU,MAAM,WAAW,UAAU;GACtC,EAAgB;EAClB;AAED,SAAO;CACR,GACD;EAAE,QAAQ,CAAE;EAAE,QAAQ,CAAE;EAAE,SAAS,CAAE;CAAE,EACxC,CACF;AAED,QAAO;EACL,GAAI,OAAO,OAAO,SACd,CAGE;GACE,SAAS,cAAc,UAAU;GACjC,UAAU,OAAO;GACjB,QAAQ,GACL,gBAAgB,kBAAkB,KACpC;EACF,CACF,IACD,CAAE;EAEN,GAAG,OAAO;EAEV,GAAG,OAAO;CACX;AACF","names":["originalRoutes: readonly RouteObject[] | undefined","component: ComponentType"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/mergeLayout.ts"],"sourcesContent":["import { createElement, type ComponentType } from 'react';\nimport type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { getHandleFlag, RouteHandleFlag } from './utils.js';\n\n/**\n * Splits out the server-side route tree based on the {@link ViewConfiguration.flowLayout}\n * flag, and wraps them in the provided server layout component.\n *\n * @remarks\n * Internally, routes are categorized into three groups:\n * - **Server routes**: Routes with `flowLayout` flag explicitly set to `true`,\n * or routes whose children have the flag enabled.\n * - **Client routes**: Routes with `flowLayout` flag explicitly set to `false`,\n * or routes with client-side children.\n * - **Unknown routes**: Routes without explicit flags that inherit behavior\n * from their parent context.\n *\n * Server routes get the {@link RouteHandleFlag.IGNORE_FALLBACK} flag set to\n * prevent fallback route interference. Client routes are preserved as-is.\n *\n * @param originalRoutes - The current route tree to process.\n * @param component - The layout component to wrap around server routes.\n *\n * @returns A new route configuration with the layout applied to server routes.\n */\nexport default function mergeLayout(\n originalRoutes: readonly RouteObject[] | undefined,\n component: ComponentType,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n type Groups<T = readonly RouteObject[]> = Readonly<{\n server: T;\n client: T;\n unknown: T;\n }>;\n\n const result = transformTree<readonly RouteObject[], Groups>(originalRoutes, null, (routes, next) =>\n // Group routes onto:\n // - a server routes group,\n // - a client routes group,\n // - a group of routes which alignment cannot be classified; their\n // destination depends on the parent route alignment.\n routes.reduce<Groups<RouteObject[]>>(\n (groups, route) => {\n const { server, client, unknown } = next(route.children ?? []);\n\n const flag = getHandleFlag(route, RouteHandleFlag.FLOW_LAYOUT);\n\n // If the route has `flowLayout` flag explicitly enabled, it goes to\n // the server group. The children are also affected by the flag\n // unless they have it explicitly disabled.\n if (flag === true) {\n groups.server.push({\n ...route,\n children: route.children ? [...server, ...unknown] : undefined,\n } as RouteObject);\n } else if (server.length > 0) {\n // Even if the route doesn't have the flag, it goes to the server\n // group if any of the children has the flag enabled.\n groups.server.push({\n ...route,\n children: route.children ? server : undefined,\n } as RouteObject);\n }\n\n // If the route has `flowLayout` flag explicitly disabled, it goes\n // to the client group. The route children are not affected by the\n // flag.\n if (flag === false || client.length > 0) {\n groups.client.push({\n ...route,\n children: route.children ? client : undefined,\n } as RouteObject);\n }\n\n // The route without the flag goes to the `unknown` group. Then it\n // will be moved to either server or client group based on the parent\n // route.\n if (flag === undefined && (groups.server.every(({ path }) => path !== route.path) || unknown.length > 0)) {\n groups.unknown.push({\n ...route,\n children: route.children ? unknown : undefined,\n } as RouteObject);\n }\n\n return groups;\n },\n { server: [], client: [], unknown: [] },\n ),\n );\n\n return [\n ...(result.server.length\n ? [\n // Wrap the server routes with the layout component and make it ignore\n // fallback, so that the server routes are not affected by it.\n {\n element: createElement(component),\n children: result.server as RouteObject[],\n handle: {\n [RouteHandleFlag.IGNORE_FALLBACK]: true,\n },\n },\n ]\n : []),\n // The client routes are preserved without wrapping.\n ...result.client,\n // The unknown routes are considered as client routes.\n ...result.unknown,\n ];\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,4BAAiD;AAE1D,SAAS,oDAAqD;AAC9D,SAAS,eAAe,mCAAoC;;;;;;;;;;;;;;;;;;;;;;AAuB5D,eAAe,SAAS,YACtBA,gBACAC,WACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;CAQD,MAAM,SAAS,cAA8C,gBAAgB,MAAM,CAAC,QAAQ,SAM1F,OAAO,OACL,CAAC,QAAQ,UAAU;EACjB,MAAM,EAAE,QAAQ,QAAQ,SAAS,GAAG,KAAK,MAAM,YAAY,CAAE,EAAC;EAE9D,MAAM,OAAO,cAAc,OAAO,gBAAgB,YAAY;AAK9D,MAAI,SAAS,MAAM;AACjB,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,CAAC,GAAG,QAAQ,GAAG,OAAQ,IAAG;GACtD,EAAgB;EAClB,WAAU,OAAO,SAAS,GAAG;AAG5B,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,SAAS;GACrC,EAAgB;EAClB;AAKD,MAAI,SAAS,SAAS,OAAO,SAAS,GAAG;AACvC,UAAO,OAAO,KAAK;IACjB,GAAG;IACH,UAAU,MAAM,WAAW,SAAS;GACrC,EAAgB;EAClB;AAKD,MAAI,SAAS,cAAc,OAAO,OAAO,MAAM,CAAC,EAAE,MAAM,KAAK,SAAS,MAAM,KAAK,IAAI,QAAQ,SAAS,IAAI;AACxG,UAAO,QAAQ,KAAK;IAClB,GAAG;IACH,UAAU,MAAM,WAAW,UAAU;GACtC,EAAgB;EAClB;AAED,SAAO;CACR,GACD;EAAE,QAAQ,CAAE;EAAE,QAAQ,CAAE;EAAE,SAAS,CAAE;CAAE,EACxC,CACF;AAED,QAAO;EACL,GAAI,OAAO,OAAO,SACd,CAGE;GACE,SAAS,cAAc,UAAU;GACjC,UAAU,OAAO;GACjB,QAAQ,GACL,gBAAgB,kBAAkB,KACpC;EACF,CACF,IACD,CAAE;EAEN,GAAG,OAAO;EAEV,GAAG,OAAO;CACX;AACF","names":["originalRoutes: readonly RouteObject[] | undefined","component: ComponentType"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/mergeLayout.ts"],"sourcesContent":["import { createElement, type ComponentType } from 'react';\nimport type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { getHandleFlag, RouteHandleFlag } from './utils.js';\n\n/**\n * Splits out the server-side route tree based on the {@link ViewConfiguration.flowLayout}\n * flag, and wraps them in the provided server layout component.\n *\n * @remarks\n * Internally, routes are categorized into three groups:\n * - **Server routes**: Routes with `flowLayout` flag explicitly set to `true`,\n * or routes whose children have the flag enabled.\n * - **Client routes**: Routes with `flowLayout` flag explicitly set to `false`,\n * or routes with client-side children.\n * - **Unknown routes**: Routes without explicit flags that inherit behavior\n * from their parent context.\n *\n * Server routes get the {@link RouteHandleFlag.IGNORE_FALLBACK} flag set to\n * prevent fallback route interference. Client routes are preserved as-is.\n *\n * @param originalRoutes - The current route tree to process.\n * @param component - The layout component to wrap around server routes.\n *\n * @returns A new route configuration with the layout applied to server routes.\n */\nexport default function mergeLayout(\n originalRoutes: readonly RouteObject[] | undefined,\n component: ComponentType,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n type Groups<T = readonly RouteObject[]> = Readonly<{\n server: T;\n client: T;\n unknown: T;\n }>;\n\n const result = transformTree<readonly RouteObject[], Groups>(originalRoutes, null, (routes, next) =>\n // Group routes onto:\n // - a server routes group,\n // - a client routes group,\n // - a group of routes which alignment cannot be classified; their\n // destination depends on the parent route alignment.\n routes.reduce<Groups<RouteObject[]>>(\n (groups, route) => {\n const { server, client, unknown } = next(route.children ?? []);\n\n const flag = getHandleFlag(route, RouteHandleFlag.FLOW_LAYOUT);\n\n // If the route has `flowLayout` flag explicitly enabled, it goes to\n // the server group. The children are also affected by the flag\n // unless they have it explicitly disabled.\n if (flag === true) {\n groups.server.push({\n ...route,\n children: route.children ? [...server, ...unknown] : undefined,\n } as RouteObject);\n } else if (server.length > 0) {\n // Even if the route doesn't have the flag, it goes to the server\n // group if any of the children has the flag enabled.\n groups.server.push({\n ...route,\n children: route.children ? server : undefined,\n } as RouteObject);\n }\n\n // If the route has `flowLayout` flag explicitly disabled, it goes\n // to the client group. The route children are not affected by the\n // flag.\n if (flag === false || client.length > 0) {\n groups.client.push({\n ...route,\n children: route.children ? client : undefined,\n } as RouteObject);\n }\n\n // The route without the flag goes to the `unknown` group. Then it\n // will be moved to either server or client group based on the parent\n // route.\n if (flag === undefined && (groups.server.every(({ path }) => path !== route.path) || unknown.length > 0)) {\n groups.unknown.push({\n ...route,\n children: route.children ? unknown : undefined,\n } as RouteObject);\n }\n\n return groups;\n },\n { server: [], client: [], unknown: [] },\n ),\n );\n\n return [\n ...(result.server.length\n ? [\n // Wrap the server routes with the layout component and make it ignore\n // fallback, so that the server routes are not affected by it.\n {\n element: createElement(component),\n children: result.server as RouteObject[],\n handle: {\n [RouteHandleFlag.IGNORE_FALLBACK]: true,\n },\n },\n ]\n : []),\n // The client routes are preserved without wrapping.\n ...result.client,\n // The unknown routes are considered as client routes.\n ...result.unknown,\n ];\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAEA,SAAS,oDAAuF;AAChG,SAAS,kCAAwG;AAOjH,SAAS,wBAA6C,EACpD,UACA,UACA,UAC2B,EAAe;AAE1C,QAAO;EACL,GAAG;EACH,GAAG;EACH;CACD;AACF;;;;;;;;;;;;;;;;;;;;;;AA4BD,OAAO,SAAS,gBACdA,gBACAC,MACAC,cAAmC,yBACC;AACpC,QAAO,cAAc,CAAC,gBAAgB,IAAK,GAAW,MAAM,CAAC,CAAC,UAAU,MAAM,EAAE,SAAS;AACvF,MAAI,YAAY,OAAO;AACrB,UAAO,eAAe,UAAU,OAAO;IAAE;IAAa;GAAM,EAAC;EAC9D;AAED,MAAI,UAAU;AACZ,UAAO,4BAA4B,UAAU;IAAE;IAAa;GAAM,EAAC;EACpE;AAED,MAAI,OAAO;AACT,UAAO,MAAM,IAAI,CAAC,UAAU,sBAAsB,OAAO;IAAE;IAAa;GAAM,EAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK;EAC1G;AAED,SAAO;CACR,EAAC;AACH;;;;;;;;;;;;;;;;;;;AAoBD,SAAS,eACPC,WACAC,WACAC,KACwB;CACxB,MAAM,WAAW,IAAI,IAAI,CAAC,GAAG,UAAU,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,EAAE,GAAG,UAAU,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,AAAC;AAEjH,QAAO,MAAM,KAAK,SAAS,CAAC,OAAsB,CAAC,KAAK,YAAY;EAElE,MAAM,iBAAiB,UAAU,OAAO,CAAC,MAAM,eAAe,EAAE,KAAK,QAAQ;EAG7E,MAAM,aAAa,UAAU,OAAO,CAAC,MAAM,eAAe,EAAE,KAAK,QAAQ;AAEzE,MAAI,WAAW,SAAS,GAAG;AACzB,SAAM,IAAI,MAAM;EACjB;EAED,MAAM,CAAC,SAAS,GAAG;AAEnB,MAAI,eAAe,SAAS,KAAK,UAAU;AACzC,8CAA2C,gBAAgB,UAAU,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,KAAK,MAAM,CAAC;EAC9G,WAAU,eAAe,SAAS,GAAG;AACpC,uCAAoC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,KAAK,MAAM,CAAC;EAC7F,WAAU,UAAU;GACnB,MAAM,QAAQ,sBAAsB,UAAU,IAAI;AAElD,OAAI,OAAO;AACT,QAAI,KAAK,MAAM;GAChB;EACF;AAED,SAAO;CACR,GAAE,CAAE,EAAC;AACP;;;;;;;;;;;;;;;;;;;;;AAsBD,SAAS,2CACPC,QACAC,UACA,EAAE,aAAa,MAA6B,EACpB;AACxB,QAAO,OAAO,IACZ,CAAC,OAAO,UACN,YAAY;EACV,UAAU;EACV;EACA,UAAU,KAAK,CAAC,MAAM,UAAU,SAAS,QAAS,EAAC;EACnD,MAAM,QAAQ,OAAO,SAAS;CAC/B,EAAC,IAAI,MACT;AACF;AAED,SAAS,oCAAoCC,wBAAiC;AAC5E,QAAO,CACLF,QACA,EAAE,aAAa,MAA6B,KAE5C,OAAO,IACL,CAAC,OAAO,UACN,YAAY;EACV,UAAU;EACV,UAAU,KAAK,CAAC,MAAM,UAAU,SAAU,EAAC;EAC3C,MAAM,0BAA0B,QAAQ,OAAO,SAAS;CACzD,EAAC,IAAI,MACT;AACJ;;;;;;;;;;;;;;;;;;AAmBD,MAAM,sCAAsC,oCAAoC,KAAK;;;;;;;;;;;;;AAcrF,MAAM,8BAA8B,oCAAoC,MAAM;;;;;;;;;;;;;AAc9E,SAAS,sBACPC,UACA,EAAE,aAAa,MAA6B,EACnB;AACzB,QAAO,YAAY;EACjB,UAAU;EACV;EACA,UAAU,KAAK,CAAC,WAAW,SAAS,QAAS,EAAC;CAC/C,EAAC;AACH","names":["existingRoutes: readonly RouteObject[] | undefined","tree: readonly T[] | undefined","transformer: RouteTransformer<T>","originals: readonly RouteObject[]","overrides: readonly T[]","ctx: TransformerContext<T>","routes: readonly RouteObject[]","override: T","shouldHandleDuplicates: boolean"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/mergeRouteTrees.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\nimport type { RouteObject } from 'react-router';\nimport { transformTree, type TreeTransformerNextCallback } from '../../shared/transformTree.js';\nimport { createRouteKey, type RouteLike, type RouteTransformer, type RouteTransformerOptions } from './utils.js';\n\ntype RoutesOverridesPair<T> = readonly [\n routes: readonly RouteObject[] | undefined,\n overrides: readonly T[] | undefined,\n];\n\nfunction defaultRouteTransformer<T extends RouteLike>({\n original,\n override,\n children,\n}: RouteTransformerOptions<T>): RouteObject {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return {\n ...original,\n ...override,\n children,\n } as RouteObject;\n}\n\ntype TransformerContext<T extends RouteLike> = Readonly<{\n transformer: RouteTransformer<T>;\n next: TreeTransformerNextCallback<RoutesOverridesPair<T>, readonly RouteObject[] | undefined>;\n}>;\n\n/**\n * Updates a route tree by merging, transforming, or replacing route objects.\n *\n * This function takes an existing route tree and a new tree of routes, then\n * applies a transformer recursively to produce an updated route tree. The\n * update strategy depends on the presence of the original and added trees:\n * - If both `existingRoutes` and `tree` are provided, they are recursively\n * merged them using the provided transformer.\n * - If only `existingRoutes` is provided, only the original routes are\n * transformed.\n * - If only `tree` is provided, it is transformed and used as a new route tree.\n *\n * @typeParam T - The type of the route-like objects in the tree.\n *\n * @param existingRoutes - The current route tree.\n * @param tree - The new tree of route-like objects to merge recursively.\n * @param transformer - A function to transform route objects.\n *\n * @returns The updated route tree as an array of `RouteObject`, or `undefined`\n * if no routes are present.\n */\nexport function mergeRouteTrees<T extends RouteLike>(\n existingRoutes: readonly RouteObject[] | undefined,\n tree: readonly T[] | undefined,\n transformer: RouteTransformer<T> = defaultRouteTransformer,\n): readonly RouteObject[] | undefined {\n return transformTree([existingRoutes, tree] as const, null, ([original, added], next) => {\n if (original && added) {\n return mergeBothTrees(original, added, { transformer, next });\n }\n\n if (original) {\n return transformOriginalRoutesOnly(original, { transformer, next });\n }\n\n if (added) {\n return added.map((route) => transformOverrideOnly(route, { transformer, next })).filter((r) => r != null);\n }\n\n return undefined;\n });\n}\n\n/**\n * Merges two route trees into a single one, applying transformations and\n * overrides as specified by the provided context.\n *\n * For each unique path, this function:\n * - Applies the override to all matching original routes if both exist.\n * - Transforms original routes if no override exists.\n * - Transforms override and adds it as a new route if no original route exists.\n *\n * @typeParam T - The type of the override route, extending `RouteLike`.\n *\n * @param originals - The original tree of route objects.\n * @param overrides - The tree of override route objects.\n * @param ctx - The context used for transforming and applying overrides.\n *\n * @returns A new tree of merged and transformed route objects.\n * @throws If multiple overrides with the same route key are found.\n */\nfunction mergeBothTrees<T extends RouteLike>(\n originals: readonly RouteObject[],\n overrides: readonly T[],\n ctx: TransformerContext<T>,\n): readonly RouteObject[] {\n const pathKeys = new Set([...originals.map((r) => createRouteKey(r)), ...overrides.map((r) => createRouteKey(r))]);\n\n return Array.from(pathKeys).reduce<RouteObject[]>((acc, pathKey) => {\n // For the original routes, we can have multiple routes with the same path.\n const originalRoutes = originals.filter((r) => createRouteKey(r) === pathKey);\n\n // However, for the added routes, we can only take the first one.\n const _overrides = overrides.filter((r) => createRouteKey(r) === pathKey);\n\n if (_overrides.length > 1) {\n throw new Error('Adding multiple routes with the same path is not allowed');\n }\n\n const [override] = _overrides;\n\n if (originalRoutes.length > 0 && override) {\n applyOverrideForMultipleRoutesWithSamePath(originalRoutes, override, ctx).forEach((route) => acc.push(route));\n } else if (originalRoutes.length > 0) {\n transformOriginalRoutesWithSamePath(originalRoutes, ctx).forEach((route) => acc.push(route));\n } else if (override) {\n const route = transformOverrideOnly(override, ctx);\n\n if (route) {\n acc.push(route);\n }\n }\n\n return acc;\n }, []);\n}\n\n/**\n * In this case, we have multiple original routes and one override per path. To\n * merge everything together, we apply the transformer to each original route in\n * conjunction with the override.\n *\n * @remarks To disambiguate the routes, we pass the `dupe` flag to the\n * transformer for each original route except the last one, which is considered\n * the \"main\" route. It follows the React Router logic, where the last route\n * serves as the fallback for all previous routes with the same path.\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param override - The override route-like to apply.\n * @param transformer - The transformer function to apply to each route/override\n * pair.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the override applied.\n */\nfunction applyOverrideForMultipleRoutesWithSamePath<T extends RouteLike>(\n routes: readonly RouteObject[],\n override: T,\n { transformer, next }: TransformerContext<T>,\n): readonly RouteObject[] {\n return routes.map(\n (route, index) =>\n transformer({\n original: route,\n override,\n children: next([route.children, override.children]),\n dupe: index < routes.length - 1,\n }) ?? route,\n );\n}\n\nfunction createOriginalRoutesOnlyTransformer(shouldHandleDuplicates: boolean) {\n return <T extends RouteLike>(\n routes: readonly RouteObject[],\n { transformer, next }: TransformerContext<T>,\n ): readonly RouteObject[] =>\n routes.map(\n (route, index) =>\n transformer({\n original: route,\n children: next([route.children, undefined]),\n dupe: shouldHandleDuplicates && index < routes.length - 1,\n }) ?? route,\n );\n}\n\n/**\n * In this case, we have multiple original routes and one override per path. To\n * merge everything together, we apply the transformer to each original route in\n * conjunction with the override.\n *\n * @remarks As in {@link applyOverrideForMultipleRoutesWithSamePath}, here the\n * `dupe` flag is also used to indicate that the transforming route is not the\n * \"main\" route (the last one in the list).\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param transformer - The transformer function to apply to each route.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the transformer applied.\n */\nconst transformOriginalRoutesWithSamePath = createOriginalRoutesOnlyTransformer(true);\n\n/**\n * In this case, we don't have override tree at all, so we simply transform the\n * original routes only.\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param transformer - The transformer function to apply to each route.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the transformer applied.\n */\nconst transformOriginalRoutesOnly = createOriginalRoutesOnlyTransformer(false);\n\n/**\n * In this case, we have no original routes, so we simply apply the\n * transformer to the override tree, creating a new route object.\n *\n * This function adds a completely new route to the tree.\n *\n * @param override - The override route-like to apply.\n * @param transformer - The transformer function to apply to the override.\n * @param next - The next callback to call with the children of the override.\n *\n * @returns The new route created from the override.\n */\nfunction transformOverrideOnly<T extends RouteLike>(\n override: T,\n { transformer, next }: TransformerContext<T>,\n): RouteObject | undefined {\n return transformer({\n original: undefined,\n override,\n children: next([undefined, override.children]),\n });\n}\n"],"version":3}
1
+ {"mappings":"AAEA,SAAS,oDAAuF;AAChG,SAAS,kCAAwG;AAOjH,SAAS,wBAA6C,EACpD,UACA,UACA,UAC2B,EAAe;AAE1C,QAAO;EACL,GAAG;EACH,GAAG;EACH;CACD;AACF;;;;;;;;;;;;;;;;;;;;;;AA4BD,OAAO,SAAS,gBACdA,gBACAC,MACAC,cAAmC,yBACC;AACpC,QAAO,cAAc,CAAC,gBAAgB,IAAK,GAAW,MAAM,CAAC,CAAC,UAAU,MAAM,EAAE,SAAS;AACvF,MAAI,YAAY,OAAO;AACrB,UAAO,eAAe,UAAU,OAAO;IAAE;IAAa;GAAM,EAAC;EAC9D;AAED,MAAI,UAAU;AACZ,UAAO,4BAA4B,UAAU;IAAE;IAAa;GAAM,EAAC;EACpE;AAED,MAAI,OAAO;AACT,UAAO,MAAM,IAAI,CAAC,UAAU,sBAAsB,OAAO;IAAE;IAAa;GAAM,EAAC,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK;EAC1G;AAED,SAAO;CACR,EAAC;AACH;;;;;;;;;;;;;;;;;;;AAoBD,SAAS,eACPC,WACAC,WACAC,KACwB;CACxB,MAAM,WAAW,IAAI,IAAI,CAAC,GAAG,UAAU,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,EAAE,GAAG,UAAU,IAAI,CAAC,MAAM,eAAe,EAAE,CAAC,AAAC;AAEjH,QAAO,MAAM,KAAK,SAAS,CAAC,OAAsB,CAAC,KAAK,YAAY;EAElE,MAAM,iBAAiB,UAAU,OAAO,CAAC,MAAM,eAAe,EAAE,KAAK,QAAQ;EAG7E,MAAM,aAAa,UAAU,OAAO,CAAC,MAAM,eAAe,EAAE,KAAK,QAAQ;AAEzE,MAAI,WAAW,SAAS,GAAG;AACzB,SAAM,IAAI,MAAM;EACjB;EAED,MAAM,CAAC,SAAS,GAAG;AAEnB,MAAI,eAAe,SAAS,KAAK,UAAU;AACzC,8CAA2C,gBAAgB,UAAU,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,KAAK,MAAM,CAAC;EAC9G,WAAU,eAAe,SAAS,GAAG;AACpC,uCAAoC,gBAAgB,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,KAAK,MAAM,CAAC;EAC7F,WAAU,UAAU;GACnB,MAAM,QAAQ,sBAAsB,UAAU,IAAI;AAElD,OAAI,OAAO;AACT,QAAI,KAAK,MAAM;GAChB;EACF;AAED,SAAO;CACR,GAAE,CAAE,EAAC;AACP;;;;;;;;;;;;;;;;;;;;;AAsBD,SAAS,2CACPC,QACAC,UACA,EAAE,aAAa,MAA6B,EACpB;AACxB,QAAO,OAAO,IACZ,CAAC,OAAO,UACN,YAAY;EACV,UAAU;EACV;EACA,UAAU,KAAK,CAAC,MAAM,UAAU,SAAS,QAAS,EAAC;EACnD,MAAM,QAAQ,OAAO,SAAS;CAC/B,EAAC,IAAI,MACT;AACF;AAED,SAAS,oCAAoCC,wBAAiC;AAC5E,QAAO,CACLF,QACA,EAAE,aAAa,MAA6B,KAE5C,OAAO,IACL,CAAC,OAAO,UACN,YAAY;EACV,UAAU;EACV,UAAU,KAAK,CAAC,MAAM,UAAU,SAAU,EAAC;EAC3C,MAAM,0BAA0B,QAAQ,OAAO,SAAS;CACzD,EAAC,IAAI,MACT;AACJ;;;;;;;;;;;;;;;;;;AAmBD,MAAM,sCAAsC,oCAAoC,KAAK;;;;;;;;;;;;;AAcrF,MAAM,8BAA8B,oCAAoC,MAAM;;;;;;;;;;;;;AAc9E,SAAS,sBACPC,UACA,EAAE,aAAa,MAA6B,EACnB;AACzB,QAAO,YAAY;EACjB,UAAU;EACV;EACA,UAAU,KAAK,CAAC,WAAW,SAAS,QAAS,EAAC;CAC/C,EAAC;AACH","names":["existingRoutes: readonly RouteObject[] | undefined","tree: readonly T[] | undefined","transformer: RouteTransformer<T>","originals: readonly RouteObject[]","overrides: readonly T[]","ctx: TransformerContext<T>","routes: readonly RouteObject[]","override: T","shouldHandleDuplicates: boolean"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/mergeRouteTrees.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-use-before-define */\nimport type { RouteObject } from 'react-router';\nimport { transformTree, type TreeTransformerNextCallback } from '../../shared/transformTree.js';\nimport { createRouteKey, type RouteLike, type RouteTransformer, type RouteTransformerOptions } from './utils.js';\n\ntype RoutesOverridesPair<T> = readonly [\n routes: readonly RouteObject[] | undefined,\n overrides: readonly T[] | undefined,\n];\n\nfunction defaultRouteTransformer<T extends RouteLike>({\n original,\n override,\n children,\n}: RouteTransformerOptions<T>): RouteObject {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n return {\n ...original,\n ...override,\n children,\n } as RouteObject;\n}\n\ntype TransformerContext<T extends RouteLike> = Readonly<{\n transformer: RouteTransformer<T>;\n next: TreeTransformerNextCallback<RoutesOverridesPair<T>, readonly RouteObject[] | undefined>;\n}>;\n\n/**\n * Updates a route tree by merging, transforming, or replacing route objects.\n *\n * This function takes an existing route tree and a new tree of routes, then\n * applies a transformer recursively to produce an updated route tree. The\n * update strategy depends on the presence of the original and added trees:\n * - If both `existingRoutes` and `tree` are provided, they are recursively\n * merged them using the provided transformer.\n * - If only `existingRoutes` is provided, only the original routes are\n * transformed.\n * - If only `tree` is provided, it is transformed and used as a new route tree.\n *\n * @typeParam T - The type of the route-like objects in the tree.\n *\n * @param existingRoutes - The current route tree.\n * @param tree - The new tree of route-like objects to merge recursively.\n * @param transformer - A function to transform route objects.\n *\n * @returns The updated route tree as an array of `RouteObject`, or `undefined`\n * if no routes are present.\n */\nexport function mergeRouteTrees<T extends RouteLike>(\n existingRoutes: readonly RouteObject[] | undefined,\n tree: readonly T[] | undefined,\n transformer: RouteTransformer<T> = defaultRouteTransformer,\n): readonly RouteObject[] | undefined {\n return transformTree([existingRoutes, tree] as const, null, ([original, added], next) => {\n if (original && added) {\n return mergeBothTrees(original, added, { transformer, next });\n }\n\n if (original) {\n return transformOriginalRoutesOnly(original, { transformer, next });\n }\n\n if (added) {\n return added.map((route) => transformOverrideOnly(route, { transformer, next })).filter((r) => r != null);\n }\n\n return undefined;\n });\n}\n\n/**\n * Merges two route trees into a single one, applying transformations and\n * overrides as specified by the provided context.\n *\n * For each unique path, this function:\n * - Applies the override to all matching original routes if both exist.\n * - Transforms original routes if no override exists.\n * - Transforms override and adds it as a new route if no original route exists.\n *\n * @typeParam T - The type of the override route, extending `RouteLike`.\n *\n * @param originals - The original tree of route objects.\n * @param overrides - The tree of override route objects.\n * @param ctx - The context used for transforming and applying overrides.\n *\n * @returns A new tree of merged and transformed route objects.\n * @throws If multiple overrides with the same route key are found.\n */\nfunction mergeBothTrees<T extends RouteLike>(\n originals: readonly RouteObject[],\n overrides: readonly T[],\n ctx: TransformerContext<T>,\n): readonly RouteObject[] {\n const pathKeys = new Set([...originals.map((r) => createRouteKey(r)), ...overrides.map((r) => createRouteKey(r))]);\n\n return Array.from(pathKeys).reduce<RouteObject[]>((acc, pathKey) => {\n // For the original routes, we can have multiple routes with the same path.\n const originalRoutes = originals.filter((r) => createRouteKey(r) === pathKey);\n\n // However, for the added routes, we can only take the first one.\n const _overrides = overrides.filter((r) => createRouteKey(r) === pathKey);\n\n if (_overrides.length > 1) {\n throw new Error('Adding multiple routes with the same path is not allowed');\n }\n\n const [override] = _overrides;\n\n if (originalRoutes.length > 0 && override) {\n applyOverrideForMultipleRoutesWithSamePath(originalRoutes, override, ctx).forEach((route) => acc.push(route));\n } else if (originalRoutes.length > 0) {\n transformOriginalRoutesWithSamePath(originalRoutes, ctx).forEach((route) => acc.push(route));\n } else if (override) {\n const route = transformOverrideOnly(override, ctx);\n\n if (route) {\n acc.push(route);\n }\n }\n\n return acc;\n }, []);\n}\n\n/**\n * In this case, we have multiple original routes and one override per path. To\n * merge everything together, we apply the transformer to each original route in\n * conjunction with the override.\n *\n * @remarks To disambiguate the routes, we pass the `dupe` flag to the\n * transformer for each original route except the last one, which is considered\n * the \"main\" route. It follows the React Router logic, where the last route\n * serves as the fallback for all previous routes with the same path.\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param override - The override route-like to apply.\n * @param transformer - The transformer function to apply to each route/override\n * pair.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the override applied.\n */\nfunction applyOverrideForMultipleRoutesWithSamePath<T extends RouteLike>(\n routes: readonly RouteObject[],\n override: T,\n { transformer, next }: TransformerContext<T>,\n): readonly RouteObject[] {\n return routes.map(\n (route, index) =>\n transformer({\n original: route,\n override,\n children: next([route.children, override.children]),\n dupe: index < routes.length - 1,\n }) ?? route,\n );\n}\n\nfunction createOriginalRoutesOnlyTransformer(shouldHandleDuplicates: boolean) {\n return <T extends RouteLike>(\n routes: readonly RouteObject[],\n { transformer, next }: TransformerContext<T>,\n ): readonly RouteObject[] =>\n routes.map(\n (route, index) =>\n transformer({\n original: route,\n children: next([route.children, undefined]),\n dupe: shouldHandleDuplicates && index < routes.length - 1,\n }) ?? route,\n );\n}\n\n/**\n * In this case, we have multiple original routes and one override per path. To\n * merge everything together, we apply the transformer to each original route in\n * conjunction with the override.\n *\n * @remarks As in {@link applyOverrideForMultipleRoutesWithSamePath}, here the\n * `dupe` flag is also used to indicate that the transforming route is not the\n * \"main\" route (the last one in the list).\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param transformer - The transformer function to apply to each route.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the transformer applied.\n */\nconst transformOriginalRoutesWithSamePath = createOriginalRoutesOnlyTransformer(true);\n\n/**\n * In this case, we don't have override tree at all, so we simply transform the\n * original routes only.\n *\n * @typeParam T - The type of the route-like to apply.\n *\n * @param routes - Original routes to update (they all have the same path).\n * @param transformer - The transformer function to apply to each route.\n * @param next - The next callback to call with the children of the routes.\n *\n * @returns The updated routes with the transformer applied.\n */\nconst transformOriginalRoutesOnly = createOriginalRoutesOnlyTransformer(false);\n\n/**\n * In this case, we have no original routes, so we simply apply the\n * transformer to the override tree, creating a new route object.\n *\n * This function adds a completely new route to the tree.\n *\n * @param override - The override route-like to apply.\n * @param transformer - The transformer function to apply to the override.\n * @param next - The next callback to call with the children of the override.\n *\n * @returns The new route created from the override.\n */\nfunction transformOverrideOnly<T extends RouteLike>(\n override: T,\n { transformer, next }: TransformerContext<T>,\n): RouteObject | undefined {\n return transformer({\n original: undefined,\n override,\n children: next([undefined, override.children]),\n });\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AACA,SAAS,oDAAqD;AAC9D,SAAS,eAAe,mCAAoC;;;;;;;;;;;;;;;;;AAkB5D,eAAe,SAAS,iBACtBA,gBACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;CAOD,MAAM,SAAS,cAA8C,gBAAgB,MAAM,CAAC,QAAQ,SAE1F,OAAO,OACL,CAAC,OAAO,UAAU;AAEhB,MAAI,cAAc,OAAO,gBAAgB,aAAa,EAAE;AACtD,SAAM,QAAQ,KAAK,MAAM;AACzB,UAAO;EACR;AAGD,OAAK,MAAM,UAAU,QAAQ;AAC3B,SAAM,QAAQ,KAAK,MAAM;AACzB,UAAO;EACR;EAGD,MAAM,EAAE,SAAS,SAAS,GAAG,KAAK,MAAM,YAAY,CAAE,EAAC;AAKvD,MAAI,QAAQ,SAAS,GAAG;GACtB,MAAM,EAAE,QAAS,GAAG,MAAM,GAAG;AAE7B,SAAM,QAAQ,KAAK;IACjB,GAAG;IACH,UAAU;GACX,EAAgB;EAClB;AAID,MAAI,QAAQ,SAAS,GAAG;AACtB,SAAM,QAAQ,KAAK;IACjB,GAAG;IACH,UAAU;GACX,EAAgB;EAClB;AAED,SAAO;CACR,GACD;EAAE,SAAS,CAAE;EAAE,SAAS,CAAE;CAAE,EAC7B,CACF;AAID,QAAO,CACL,GAAI,OAAO,QAAQ,SACf,CACE;EACE,UAAU,OAAO;EACjB,QAAQ,GACL,gBAAgB,kBAAkB,KACpC;CACF,CACF,IACD,CAAE,GACN,GAAG,OAAO,OACX;AACF","names":["originalRoutes: readonly RouteObject[] | undefined"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/mergeSkipLayout.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { getHandleFlag, RouteHandleFlag } from './utils.js';\n\n/**\n * Processes a tree of route objects and splits them into two separate trees:\n * - routes marked with {@link ViewConfiguration.skipLayout} flag that require\n * no layout rendering,\n * - regular routes that should render with their layouts.\n *\n * For routes with the {@link ViewConfiguration.skipLayout} flag, the layout\n * element is removed. The resulting routes are also marked with\n * {@link ViewConfiguration.ignoreFallback} flag to prevent rendering\n * server-side layouts for them.\n *\n * @param originalRoutes - The current route tree to process.\n *\n * @returns A new array containing reorganized routes with skipped routes first\n * (wrapped in an ignore-fallback container) followed by regular routes.\n */\nexport default function mergeSkipLayouts(\n originalRoutes: readonly RouteObject[] | undefined,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n type Groups<T = readonly RouteObject[]> = Readonly<{\n skipped: T;\n regular: T;\n }>;\n\n const result = transformTree<readonly RouteObject[], Groups>(originalRoutes, null, (routes, next) =>\n // Split a single routes list onto two separate lists.\n routes.reduce<Groups<RouteObject[]>>(\n (lists, route) => {\n // If the route has `skipLayout` flag, it goes to the `skipped` list.\n if (getHandleFlag(route, RouteHandleFlag.SKIP_LAYOUTS)) {\n lists.skipped.push(route);\n return lists;\n }\n\n // If the route is leaf, it goes to the `regular` list.\n if (!route.children?.length) {\n lists.regular.push(route);\n return lists;\n }\n\n // As of children, we have to split them into two lists as well.\n const { skipped, regular } = next(route.children ?? []);\n\n // If we have `skipped` list of children, we have to remove the\n // `element` property of the router to prevent the layout from\n // rendering. Then, we add the current route to the `skipped` list.\n if (skipped.length > 0) {\n const { element, ...rest } = route;\n\n lists.skipped.push({\n ...rest,\n children: skipped,\n } as RouteObject);\n }\n\n // In case of `regular` children, we just add the current route to\n // the `regular` list if there are any children.\n if (regular.length > 0) {\n lists.regular.push({\n ...route,\n children: regular,\n } as RouteObject);\n }\n\n return lists;\n },\n { skipped: [], regular: [] },\n ),\n );\n\n // We don't need a fallback for the skipped routes, so we have to wrap\n // them with the route with the `IGNORE_FALLBACK` flag.\n return [\n ...(result.skipped.length\n ? [\n {\n children: result.skipped as RouteObject[],\n handle: {\n [RouteHandleFlag.IGNORE_FALLBACK]: true,\n },\n },\n ]\n : []),\n ...result.regular,\n ];\n}\n"],"version":3}
1
+ {"mappings":"AACA,SAAS,oDAAqD;AAC9D,SAAS,eAAe,mCAAoC;;;;;;;;;;;;;;;;;AAkB5D,eAAe,SAAS,iBACtBA,gBACoC;AACpC,MAAK,gBAAgB;AACnB,SAAO;CACR;CAOD,MAAM,SAAS,cAA8C,gBAAgB,MAAM,CAAC,QAAQ,SAE1F,OAAO,OACL,CAAC,OAAO,UAAU;AAEhB,MAAI,cAAc,OAAO,gBAAgB,aAAa,EAAE;AACtD,SAAM,QAAQ,KAAK,MAAM;AACzB,UAAO;EACR;AAGD,OAAK,MAAM,UAAU,QAAQ;AAC3B,SAAM,QAAQ,KAAK,MAAM;AACzB,UAAO;EACR;EAGD,MAAM,EAAE,SAAS,SAAS,GAAG,KAAK,MAAM,YAAY,CAAE,EAAC;AAKvD,MAAI,QAAQ,SAAS,GAAG;GACtB,MAAM,EAAE,QAAS,GAAG,MAAM,GAAG;AAE7B,SAAM,QAAQ,KAAK;IACjB,GAAG;IACH,UAAU;GACX,EAAgB;EAClB;AAID,MAAI,QAAQ,SAAS,GAAG;AACtB,SAAM,QAAQ,KAAK;IACjB,GAAG;IACH,UAAU;GACX,EAAgB;EAClB;AAED,SAAO;CACR,GACD;EAAE,SAAS,CAAE;EAAE,SAAS,CAAE;CAAE,EAC7B,CACF;AAID,QAAO,CACL,GAAI,OAAO,QAAQ,SACf,CACE;EACE,UAAU,OAAO;EACjB,QAAQ,GACL,gBAAgB,kBAAkB,KACpC;CACF,CACF,IACD,CAAE,GACN,GAAG,OAAO,OACX;AACF","names":["originalRoutes: readonly RouteObject[] | undefined"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/mergeSkipLayout.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport { transformTree } from '../../shared/transformTree.js';\nimport { getHandleFlag, RouteHandleFlag } from './utils.js';\n\n/**\n * Processes a tree of route objects and splits them into two separate trees:\n * - routes marked with {@link ViewConfiguration.skipLayout} flag that require\n * no layout rendering,\n * - regular routes that should render with their layouts.\n *\n * For routes with the {@link ViewConfiguration.skipLayout} flag, the layout\n * element is removed. The resulting routes are also marked with\n * {@link ViewConfiguration.ignoreFallback} flag to prevent rendering\n * server-side layouts for them.\n *\n * @param originalRoutes - The current route tree to process.\n *\n * @returns A new array containing reorganized routes with skipped routes first\n * (wrapped in an ignore-fallback container) followed by regular routes.\n */\nexport default function mergeSkipLayouts(\n originalRoutes: readonly RouteObject[] | undefined,\n): readonly RouteObject[] | undefined {\n if (!originalRoutes) {\n return originalRoutes;\n }\n\n type Groups<T = readonly RouteObject[]> = Readonly<{\n skipped: T;\n regular: T;\n }>;\n\n const result = transformTree<readonly RouteObject[], Groups>(originalRoutes, null, (routes, next) =>\n // Split a single routes list onto two separate lists.\n routes.reduce<Groups<RouteObject[]>>(\n (lists, route) => {\n // If the route has `skipLayout` flag, it goes to the `skipped` list.\n if (getHandleFlag(route, RouteHandleFlag.SKIP_LAYOUTS)) {\n lists.skipped.push(route);\n return lists;\n }\n\n // If the route is leaf, it goes to the `regular` list.\n if (!route.children?.length) {\n lists.regular.push(route);\n return lists;\n }\n\n // As of children, we have to split them into two lists as well.\n const { skipped, regular } = next(route.children ?? []);\n\n // If we have `skipped` list of children, we have to remove the\n // `element` property of the router to prevent the layout from\n // rendering. Then, we add the current route to the `skipped` list.\n if (skipped.length > 0) {\n const { element, ...rest } = route;\n\n lists.skipped.push({\n ...rest,\n children: skipped,\n } as RouteObject);\n }\n\n // In case of `regular` children, we just add the current route to\n // the `regular` list if there are any children.\n if (regular.length > 0) {\n lists.regular.push({\n ...route,\n children: regular,\n } as RouteObject);\n }\n\n return lists;\n },\n { skipped: [], regular: [] },\n ),\n );\n\n // We don't need a fallback for the skipped routes, so we have to wrap\n // them with the route with the `IGNORE_FALLBACK` flag.\n return [\n ...(result.skipped.length\n ? [\n {\n children: result.skipped as RouteObject[],\n handle: {\n [RouteHandleFlag.IGNORE_FALLBACK]: true,\n },\n },\n ]\n : []),\n ...result.regular,\n ];\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":";;;;;;AAsDA,OAAO,SAAS,mBAAmBA,QAAuC;AACxE,QACG,aAAa,iBAAiB,OAAO,YAAY,cACjD,YAAY,iBAAiB,OAAO,WAAW;AAEnD;;;;;;;AAQD,OAAO,SAAS,eAAoCC,OAAkB;AACpE,SAAQ,EAAE,MAAM,QAAQ,GAAG,GAAG,MAAM,WAAW,MAAM,IAAI;AAC1D;;;;;;;;;;;;;;;;;;;AAoBD,OAAO,MAAM,kBAAkB;CAC7B,aAAa;CACb,iBAAiB;CACjB,cAAc;AACf;;;;;;;;AAUD,OAAO,SAAS,cAAyCC,OAAoBC,MAA8B;AACzG,YAAW,MAAM,WAAW,YAAY,QAAQ,MAAM,QAAQ;AAC5D,SAAQ,MAAM,OAA8B;CAC7C;AAED,QAAO;AACR;;;;;;AAOD,OAAO,SAAS,aAAaD,OAA6B;AACxD,UAAS,MAAM;AAChB;;;;;;AAOD,OAAO,SAAS,gBAAgBA,OAA6B;AAC3D,UAAS,MAAM,MAAM,SAAS,IAAI;AACnC;;;;;;AAOD,OAAO,SAAS,gBAAgBA,OAA6B;AAC3D,QAAO,MAAM,SAAS;AACvB","names":["module: Module","route: T","route: RouteObject","flag: T"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/configuration-builder/utils.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport type { Module, RouteModule } from '../../types.js';\n\n/**\n * A function type that modifies the current route tree.\n *\n * @param routes - The current route tree to process.\n * @returns An optional readonly array of RouteObject instances after modification\n */\nexport type RouteTreeModifier = (routes: readonly RouteObject[] | undefined) => readonly RouteObject[] | undefined;\n\n/**\n * A route-like object that can be used in the route tree.\n */\nexport interface RouteLike {\n path?: string;\n children?: readonly this[];\n}\n\n/**\n * Options for transforming a route object within the route configuration builder.\n *\n * @typeParam T - The type of the override object.\n */\nexport type RouteTransformerOptions<T extends RouteLike> = Readonly<{\n /**\n * Array of child route objects. If omitted, the route is considered leaf.\n */\n children?: readonly RouteObject[];\n /**\n * The original route object to transform.\n */\n original?: RouteObject;\n /**\n * Override object to apply custom transformations.\n */\n override?: T;\n /**\n * Indicates whether the route is a duplicate. Used to handle cases where\n * multiple routes may share the same path.\n */\n dupe?: boolean;\n}>;\n\nexport type RouteTransformer<T extends RouteLike = RouteLike> = (\n opts: RouteTransformerOptions<T>,\n) => RouteObject | undefined;\n\n/**\n * Checks if the given module is a valid React route module.\n *\n * @param module - The JS module to check.\n * @returns True if the module is a valid React route module, false otherwise.\n */\nexport function isReactRouteModule(module: Module): module is RouteModule {\n return (\n ('default' in module && typeof module.default === 'function') ||\n ('config' in module && typeof module.config === 'object')\n );\n}\n\n/**\n * Creates a unique key for a route based on its path and children.\n *\n * @param route - The route object to create a key for.\n * @returns A unique key string for the route.\n */\nexport function createRouteKey<T extends RouteLike>(route: T): string {\n return `${route.path ?? ''}-${route.children ? 'n' : 'i'}`;\n}\n\n/**\n * A set of flags that can be used to control the behavior of routes in the\n * router configuration.\n *\n * @remarks\n * These flags work together to control route rendering behavior:\n *\n * **Layout Control:**\n * - `FLOW_LAYOUT: true` - Route renders with server-side layout (Flow\n * component)\n * - `FLOW_LAYOUT: false` - Route renders without server-side layout\n * (client-only)\n * - `SKIP_LAYOUTS: true` - Route bypasses ALL layouts (overrides FLOW_LAYOUT)\n *\n * **Fallback Control:**\n * - `IGNORE_FALLBACK: true` - Route ignores fallback components, used\n * internally by {@link mergeLayout} and {@link mergeSkipLayouts}\n */\nexport const RouteHandleFlag = {\n FLOW_LAYOUT: 'flowLayout',\n IGNORE_FALLBACK: 'ignoreFallback',\n SKIP_LAYOUTS: 'skipLayouts',\n} as const;\nexport type RouteHandleFlag = (typeof RouteHandleFlag)[keyof typeof RouteHandleFlag];\n\n/**\n * Retrieves a specific flag from the route's handle object.\n *\n * @param route - The route object to retrieve the flag from.\n * @param flag - The flag to retrieve.\n * @returns The value of the flag if it exists, otherwise undefined.\n */\nexport function getHandleFlag<T extends RouteHandleFlag>(route: RouteObject, flag: T): boolean | undefined {\n if (typeof route.handle === 'object' && flag in route.handle) {\n return (route.handle as Record<T, boolean>)[flag];\n }\n\n return undefined;\n}\n\n/**\n * Determines whether the given route object represents an index route.\n *\n * @param route - The route object to check.\n */\nexport function isIndexRoute(route: RouteObject): boolean {\n return !!route.index;\n}\n\n/**\n * Determines whether the given route is optional based on its path.\n *\n * @param route - The route object to check.\n */\nexport function isOptionalRoute(route: RouteObject): boolean {\n return !!route.path?.includes('?');\n}\n\n/**\n * Determines whether the given route is a wildcard route.\n *\n * @param route - The route object to check.\n */\nexport function isWildcardRoute(route: RouteObject): boolean {\n return route.path === '*';\n}\n"],"version":3}
1
+ {"mappings":";;;;;;AAsDA,OAAO,SAAS,mBAAmBA,QAAuC;AACxE,QACG,aAAa,iBAAiB,OAAO,YAAY,cACjD,YAAY,iBAAiB,OAAO,WAAW;AAEnD;;;;;;;AAQD,OAAO,SAAS,eAAoCC,OAAkB;AACpE,SAAQ,EAAE,MAAM,QAAQ,GAAG,GAAG,MAAM,WAAW,MAAM,IAAI;AAC1D;;;;;;;;;;;;;;;;;;;AAoBD,OAAO,MAAM,kBAAkB;CAC7B,aAAa;CACb,iBAAiB;CACjB,cAAc;AACf;;;;;;;;AAUD,OAAO,SAAS,cAAyCC,OAAoBC,MAA8B;AACzG,YAAW,MAAM,WAAW,YAAY,QAAQ,MAAM,QAAQ;AAC5D,SAAQ,MAAM,OAA8B;CAC7C;AAED,QAAO;AACR;;;;;;AAOD,OAAO,SAAS,aAAaD,OAA6B;AACxD,UAAS,MAAM;AAChB;;;;;;AAOD,OAAO,SAAS,gBAAgBA,OAA6B;AAC3D,UAAS,MAAM,MAAM,SAAS,IAAI;AACnC;;;;;;AAOD,OAAO,SAAS,gBAAgBA,OAA6B;AAC3D,QAAO,MAAM,SAAS;AACvB","names":["module: Module","route: T","route: RouteObject","flag: T"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/configuration-builder/utils.ts"],"sourcesContent":["import type { RouteObject } from 'react-router';\nimport type { Module, RouteModule } from '../../types.js';\n\n/**\n * A function type that modifies the current route tree.\n *\n * @param routes - The current route tree to process.\n * @returns An optional readonly array of RouteObject instances after modification\n */\nexport type RouteTreeModifier = (routes: readonly RouteObject[] | undefined) => readonly RouteObject[] | undefined;\n\n/**\n * A route-like object that can be used in the route tree.\n */\nexport interface RouteLike {\n path?: string;\n children?: readonly this[];\n}\n\n/**\n * Options for transforming a route object within the route configuration builder.\n *\n * @typeParam T - The type of the override object.\n */\nexport type RouteTransformerOptions<T extends RouteLike> = Readonly<{\n /**\n * Array of child route objects. If omitted, the route is considered leaf.\n */\n children?: readonly RouteObject[];\n /**\n * The original route object to transform.\n */\n original?: RouteObject;\n /**\n * Override object to apply custom transformations.\n */\n override?: T;\n /**\n * Indicates whether the route is a duplicate. Used to handle cases where\n * multiple routes may share the same path.\n */\n dupe?: boolean;\n}>;\n\nexport type RouteTransformer<T extends RouteLike = RouteLike> = (\n opts: RouteTransformerOptions<T>,\n) => RouteObject | undefined;\n\n/**\n * Checks if the given module is a valid React route module.\n *\n * @param module - The JS module to check.\n * @returns True if the module is a valid React route module, false otherwise.\n */\nexport function isReactRouteModule(module: Module): module is RouteModule {\n return (\n ('default' in module && typeof module.default === 'function') ||\n ('config' in module && typeof module.config === 'object')\n );\n}\n\n/**\n * Creates a unique key for a route based on its path and children.\n *\n * @param route - The route object to create a key for.\n * @returns A unique key string for the route.\n */\nexport function createRouteKey<T extends RouteLike>(route: T): string {\n return `${route.path ?? ''}-${route.children ? 'n' : 'i'}`;\n}\n\n/**\n * A set of flags that can be used to control the behavior of routes in the\n * router configuration.\n *\n * @remarks\n * These flags work together to control route rendering behavior:\n *\n * **Layout Control:**\n * - `FLOW_LAYOUT: true` - Route renders with server-side layout (Flow\n * component)\n * - `FLOW_LAYOUT: false` - Route renders without server-side layout\n * (client-only)\n * - `SKIP_LAYOUTS: true` - Route bypasses ALL layouts (overrides FLOW_LAYOUT)\n *\n * **Fallback Control:**\n * - `IGNORE_FALLBACK: true` - Route ignores fallback components, used\n * internally by {@link mergeLayout} and {@link mergeSkipLayouts}\n */\nexport const RouteHandleFlag = {\n FLOW_LAYOUT: 'flowLayout',\n IGNORE_FALLBACK: 'ignoreFallback',\n SKIP_LAYOUTS: 'skipLayouts',\n} as const;\nexport type RouteHandleFlag = (typeof RouteHandleFlag)[keyof typeof RouteHandleFlag];\n\n/**\n * Retrieves a specific flag from the route's handle object.\n *\n * @param route - The route object to retrieve the flag from.\n * @param flag - The flag to retrieve.\n * @returns The value of the flag if it exists, otherwise undefined.\n */\nexport function getHandleFlag<T extends RouteHandleFlag>(route: RouteObject, flag: T): boolean | undefined {\n if (typeof route.handle === 'object' && flag in route.handle) {\n return (route.handle as Record<T, boolean>)[flag];\n }\n\n return undefined;\n}\n\n/**\n * Determines whether the given route object represents an index route.\n *\n * @param route - The route object to check.\n */\nexport function isIndexRoute(route: RouteObject): boolean {\n return !!route.index;\n}\n\n/**\n * Determines whether the given route is optional based on its path.\n *\n * @param route - The route object to check.\n */\nexport function isOptionalRoute(route: RouteObject): boolean {\n return !!route.path?.includes('?');\n}\n\n/**\n * Determines whether the given route is a wildcard route.\n *\n * @param route - The route object to check.\n */\nexport function isWildcardRoute(route: RouteObject): boolean {\n return route.path === '*';\n}\n"],"version":3}
@@ -19,7 +19,7 @@ export function createMenuItems() {
19
19
  vaadinObj.registrations ??= [];
20
20
  vaadinObj.registrations.push({
21
21
  is: feature ? `@vaadin/hilla-file-router/${feature}` : "@vaadin/hilla-file-router",
22
- version: "24.9.1"
22
+ version: "24.9.3"
23
23
  });
24
24
  })("createMenuItems", window.Vaadin);
25
25
  const collator = new Intl.Collator("en-US");
@@ -1 +1 @@
1
- {"mappings":"AACA,SAAsB,2CAA4C;AAIlE,OAAO,MAAMA,cAAkF,OAC5F,OAAwB,QAAQ,MAClC;AAED,SAAS,WAAWC,OAA4B;AAC9C,UAAS,MAAM,MAAM;AACtB;AAED,SAAS,uBAAuBC,MAAuB;AACrD,QAAO,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,QAAQ,WAAW,IAAI,CAAC;AAClE;;;;;;;;;AAUD,OAAO,SAAS,kBAA2D;AAGzE,EAAC,CAAC,SAAS,YAAa,WAAW,WAAW,CAAE,MAAM;AACtD,YAAU,kBAAkB,CAAE;AAC9B,YAAU,cAAc,KAAK;GAC3B,IAAI,WAAW,4BAA4B,QAAQ,IAAI;GACvD,SAAS;EACV,EAAC;CACH,GAAE,mBAAoB,OAAwB,OAAO;CACpD,MAAM,WAAW,IAAI,KAAK,SAAS;AACnC,MAAK,YAAY,OAAO;AACtB,SAAO,CAAE;CACV;CAED,MAAM,QAAQ,OAAO,QAAQ,YAAY,MAAM;AAE/C,QACE,MAEG,OAAO,CAAC,CAAC,MAAM,MAAM,MAAM,WAAW,MAAM,KAAK,uBAAuB,KAAK,CAAC,CAE9E,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM;EACxB,IAAI;EACJ,MAAM,OAAO,MAAM;EACnB,OAAO,OAAO,MAAM,SAAS,OAAO;EACpC,OAAO,OAAO,MAAM;EACpB,QAAQ,OAAO;CAChB,GAAE,CAEF,KAAK,CAAC,OAAO,UAAU;EACtB,MAAM,cAAc,MAAM,SAAS,OAAO,cAAc,MAAM,SAAS,OAAO;AAC9E,SAAO,eAAe,IAAI,aAAa,SAAS,QAAQ,MAAM,IAAI,MAAM,GAAG;CAC5E,EAAC;AAEP;AAED,IAAI,OAAO,KAAK,KAAK;AACnB,QAAO,KAAK,IAAI,GAAG,mBAAmB,MAAM;AAC1C,QAAM,iBAAiB,CACpB,KAAK,OAAO,SAAS,KAAK,MAAM,CAAC,CACjC,KAAK,CAAC,SAAS;AACd,eAAY,QAAQ;EACrB,EAAC,CACD,MAAM,CAACC,MAAe;AACrB,WAAQ,MAAM,8BAA8B,EAAE;EAC/C,EAAC;CACL,EAAC;AACH","names":["viewsSignal: Signal<Readonly<Record<string, Readonly<ViewConfig>>> | undefined>","value: ViewConfig","path: string","e: unknown"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/createMenuItems.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { type Signal, signal } from '@vaadin/hilla-react-signals';\nimport type { VaadinWindow } from '../shared/internal.js';\nimport type { MenuItem, ViewConfig } from '../types.js';\n\nexport const viewsSignal: Signal<Readonly<Record<string, Readonly<ViewConfig>>> | undefined> = signal(\n (window as VaadinWindow).Vaadin?.views,\n);\n\nfunction isExcluded(value: ViewConfig): boolean {\n return !!value.menu?.exclude;\n}\n\nfunction hasVariablePathSegment(path: string): boolean {\n return path.split('/').some((segment) => segment.startsWith(':'));\n}\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 * @returns A list of menu items.\n */\nexport function createMenuItems<T = unknown>(): ReadonlyArray<MenuItem<T>> {\n // @ts-expect-error: esbuild injection\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n ((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-file-router/${feature}` : '@vaadin/hilla-file-router',\n version: '24.9.1',\n });\n})('createMenuItems', (window as VaadinWindow).Vaadin);\n const collator = new Intl.Collator('en-US');\n if (!viewsSignal.value) {\n return [];\n }\n\n const views = Object.entries(viewsSignal.value);\n\n return (\n views\n // Filter out the views that are explicitly excluded from the menu.\n .filter(([path, value]) => !isExcluded(value) && !hasVariablePathSegment(path))\n // Map the views to menu items.\n .map(([path, config]) => ({\n to: path,\n icon: config.menu?.icon,\n title: config.menu?.title ?? config.title,\n order: config.menu?.order,\n detail: config.detail as T | undefined,\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\nif (import.meta.hot) {\n import.meta.hot.on('fs-route-update', () => {\n fetch('?v-r=routeinfo')\n .then(async (resp) => resp.json())\n .then((json) => {\n viewsSignal.value = json;\n })\n .catch((e: unknown) => {\n console.error('Failed to fetch route info', e);\n });\n });\n}\n"],"version":3}
1
+ {"mappings":"AACA,SAAsB,2CAA4C;AAIlE,OAAO,MAAMA,cAAkF,OAC5F,OAAwB,QAAQ,MAClC;AAED,SAAS,WAAWC,OAA4B;AAC9C,UAAS,MAAM,MAAM;AACtB;AAED,SAAS,uBAAuBC,MAAuB;AACrD,QAAO,KAAK,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,QAAQ,WAAW,IAAI,CAAC;AAClE;;;;;;;;;AAUD,OAAO,SAAS,kBAA2D;AAGzE,EAAC,CAAC,SAAS,YAAa,WAAW,WAAW,CAAE,MAAM;AACtD,YAAU,kBAAkB,CAAE;AAC9B,YAAU,cAAc,KAAK;GAC3B,IAAI,WAAW,4BAA4B,QAAQ,IAAI;GACvD,SAAS;EACV,EAAC;CACH,GAAE,mBAAoB,OAAwB,OAAO;CACpD,MAAM,WAAW,IAAI,KAAK,SAAS;AACnC,MAAK,YAAY,OAAO;AACtB,SAAO,CAAE;CACV;CAED,MAAM,QAAQ,OAAO,QAAQ,YAAY,MAAM;AAE/C,QACE,MAEG,OAAO,CAAC,CAAC,MAAM,MAAM,MAAM,WAAW,MAAM,KAAK,uBAAuB,KAAK,CAAC,CAE9E,IAAI,CAAC,CAAC,MAAM,OAAO,MAAM;EACxB,IAAI;EACJ,MAAM,OAAO,MAAM;EACnB,OAAO,OAAO,MAAM,SAAS,OAAO;EACpC,OAAO,OAAO,MAAM;EACpB,QAAQ,OAAO;CAChB,GAAE,CAEF,KAAK,CAAC,OAAO,UAAU;EACtB,MAAM,cAAc,MAAM,SAAS,OAAO,cAAc,MAAM,SAAS,OAAO;AAC9E,SAAO,eAAe,IAAI,aAAa,SAAS,QAAQ,MAAM,IAAI,MAAM,GAAG;CAC5E,EAAC;AAEP;AAED,IAAI,OAAO,KAAK,KAAK;AACnB,QAAO,KAAK,IAAI,GAAG,mBAAmB,MAAM;AAC1C,QAAM,iBAAiB,CACpB,KAAK,OAAO,SAAS,KAAK,MAAM,CAAC,CACjC,KAAK,CAAC,SAAS;AACd,eAAY,QAAQ;EACrB,EAAC,CACD,MAAM,CAACC,MAAe;AACrB,WAAQ,MAAM,8BAA8B,EAAE;EAC/C,EAAC;CACL,EAAC;AACH","names":["viewsSignal: Signal<Readonly<Record<string, Readonly<ViewConfig>>> | undefined>","value: ViewConfig","path: string","e: unknown"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/createMenuItems.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport { type Signal, signal } from '@vaadin/hilla-react-signals';\nimport type { VaadinWindow } from '../shared/internal.js';\nimport type { MenuItem, ViewConfig } from '../types.js';\n\nexport const viewsSignal: Signal<Readonly<Record<string, Readonly<ViewConfig>>> | undefined> = signal(\n (window as VaadinWindow).Vaadin?.views,\n);\n\nfunction isExcluded(value: ViewConfig): boolean {\n return !!value.menu?.exclude;\n}\n\nfunction hasVariablePathSegment(path: string): boolean {\n return path.split('/').some((segment) => segment.startsWith(':'));\n}\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 * @returns A list of menu items.\n */\nexport function createMenuItems<T = unknown>(): ReadonlyArray<MenuItem<T>> {\n // @ts-expect-error: esbuild injection\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n ((feature, vaadinObj = (globalThis.Vaadin ??= {})) => {\n vaadinObj.registrations ??= [];\n vaadinObj.registrations.push({\n is: feature ? `@vaadin/hilla-file-router/${feature}` : '@vaadin/hilla-file-router',\n version: '24.9.3',\n });\n})('createMenuItems', (window as VaadinWindow).Vaadin);\n const collator = new Intl.Collator('en-US');\n if (!viewsSignal.value) {\n return [];\n }\n\n const views = Object.entries(viewsSignal.value);\n\n return (\n views\n // Filter out the views that are explicitly excluded from the menu.\n .filter(([path, value]) => !isExcluded(value) && !hasVariablePathSegment(path))\n // Map the views to menu items.\n .map(([path, config]) => ({\n to: path,\n icon: config.menu?.icon,\n title: config.menu?.title ?? config.title,\n order: config.menu?.order,\n detail: config.detail as T | undefined,\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\nif (import.meta.hot) {\n import.meta.hot.on('fs-route-update', () => {\n fetch('?v-r=routeinfo')\n .then(async (resp) => resp.json())\n .then((json) => {\n viewsSignal.value = json;\n })\n .catch((e: unknown) => {\n console.error('Failed to fetch route info', e);\n });\n });\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;AAaA,OAAO,SAAS,aAAaA,QAAuBC,QAA6B;AAC/E,QAAO;EACL,GAAG;EACH,QAAQ;GACN,GAAG;GACH,GAAI,QAAQ;EACb;CACF;AACF;AAED,SAAS,iBAAiBC,OAAwC;AAChE,UACI,iBACM,UAAU,qBACR,UAAU,YAAY,cAAc,SAAS,MAAM,aAAa,OAAO,IAAI,aAAa;AAErG;AAsCD,OAAO,SAAS,YACdC,MACAC,6BACAC,kBACAC,UACe;CACf,IAAI,yBAAyB;CAC7B,IAAIC;CACJ,IAAIC;AACJ,KAAI,MAAM,QAAQ,4BAA4B,EAAE;AAE9C,aAAW;CACZ,WACC,iBAAiB,4BAA4B,KAC3C,iCAAiC,2BAA2B,qBAAqB,UACnF;AACA,cAAY;AACZ,WAAS;CACV,WAAU,6BAA6B;AACtC,GAAC,CAAE,SAAS,WAAW,OAAQ,GAAG;AAClC,2BAAyB;CAC1B;AAED,QAAO;EACL;EACA,QAAQ,yBAAyB;GAAE,SAAS;GAAW;EAAQ,IAAG;EAClE;EACA;EACA;CACD;AACF","names":["module: Module | null","config?: ViewConfig","value: unknown","path: string","moduleOrChildrenOrComponent?: Module | ComponentType | readonly AgnosticRoute[]","childrenOrConfig?: readonly AgnosticRoute[] | ViewConfig","children?: readonly AgnosticRoute[]","component: ComponentType | undefined","config: ViewConfig | undefined"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/createRoute.ts"],"sourcesContent":["import type { ComponentType } from 'react';\nimport type { AgnosticRoute, Module, RouteModule, 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 *\n * @deprecated Use object spread syntax instead.\n */\nexport function extendModule(module: Module | null, config?: ViewConfig): Module {\n return {\n ...module,\n config: {\n ...config,\n ...(module?.config as ViewConfig),\n },\n };\n}\n\nfunction isReactComponent(value: unknown): value is ComponentType {\n return (\n !!value &&\n (typeof value === 'function' ||\n (typeof value === 'object' && '$$typeof' in value && value.$$typeof === Symbol.for('react.lazy')))\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;\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 module - A module that exports a component and an optional config object.\n * @param children - An array of child routes.\n *\n * @deprecated Use `createRoute(path, component, config, children)` instead.\n */\nexport function createRoute(path: string, module: Module, children?: readonly AgnosticRoute[]): AgnosticRoute;\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 component - A React component.\n * @param config - An optional config object.\n * @param children - An array of child routes.\n */\nexport function createRoute(\n path: string,\n component: ComponentType,\n config: ViewConfig | undefined,\n children?: readonly AgnosticRoute[],\n): AgnosticRoute;\nexport function createRoute(\n path: string,\n moduleOrChildrenOrComponent?: Module | ComponentType | readonly AgnosticRoute[],\n childrenOrConfig?: readonly AgnosticRoute[] | ViewConfig,\n children?: readonly AgnosticRoute[],\n): AgnosticRoute {\n let isDeprecatedModuleUsed = false;\n let component: ComponentType | undefined;\n let config: ViewConfig | undefined;\n if (Array.isArray(moduleOrChildrenOrComponent)) {\n // eslint-disable-next-line no-param-reassign\n children = moduleOrChildrenOrComponent;\n } else if (\n isReactComponent(moduleOrChildrenOrComponent) ||\n (!moduleOrChildrenOrComponent && !!childrenOrConfig && typeof childrenOrConfig === 'object')\n ) {\n component = moduleOrChildrenOrComponent;\n config = childrenOrConfig as ViewConfig;\n } else if (moduleOrChildrenOrComponent) {\n ({ default: component, config } = moduleOrChildrenOrComponent as RouteModule);\n isDeprecatedModuleUsed = true;\n }\n\n return {\n path,\n module: isDeprecatedModuleUsed ? { default: component, config } : undefined,\n component,\n config,\n children,\n };\n}\n"],"version":3}
1
+ {"mappings":";;;;;;;;;;AAaA,OAAO,SAAS,aAAaA,QAAuBC,QAA6B;AAC/E,QAAO;EACL,GAAG;EACH,QAAQ;GACN,GAAG;GACH,GAAI,QAAQ;EACb;CACF;AACF;AAED,SAAS,iBAAiBC,OAAwC;AAChE,UACI,iBACM,UAAU,qBACR,UAAU,YAAY,cAAc,SAAS,MAAM,aAAa,OAAO,IAAI,aAAa;AAErG;AAsCD,OAAO,SAAS,YACdC,MACAC,6BACAC,kBACAC,UACe;CACf,IAAI,yBAAyB;CAC7B,IAAIC;CACJ,IAAIC;AACJ,KAAI,MAAM,QAAQ,4BAA4B,EAAE;AAE9C,aAAW;CACZ,WACC,iBAAiB,4BAA4B,KAC3C,iCAAiC,2BAA2B,qBAAqB,UACnF;AACA,cAAY;AACZ,WAAS;CACV,WAAU,6BAA6B;AACtC,GAAC,CAAE,SAAS,WAAW,OAAQ,GAAG;AAClC,2BAAyB;CAC1B;AAED,QAAO;EACL;EACA,QAAQ,yBAAyB;GAAE,SAAS;GAAW;EAAQ,IAAG;EAClE;EACA;EACA;CACD;AACF","names":["module: Module | null","config?: ViewConfig","value: unknown","path: string","moduleOrChildrenOrComponent?: Module | ComponentType | readonly AgnosticRoute[]","childrenOrConfig?: readonly AgnosticRoute[] | ViewConfig","children?: readonly AgnosticRoute[]","component: ComponentType | undefined","config: ViewConfig | undefined"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/createRoute.ts"],"sourcesContent":["import type { ComponentType } from 'react';\nimport type { AgnosticRoute, Module, RouteModule, 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 *\n * @deprecated Use object spread syntax instead.\n */\nexport function extendModule(module: Module | null, config?: ViewConfig): Module {\n return {\n ...module,\n config: {\n ...config,\n ...(module?.config as ViewConfig),\n },\n };\n}\n\nfunction isReactComponent(value: unknown): value is ComponentType {\n return (\n !!value &&\n (typeof value === 'function' ||\n (typeof value === 'object' && '$$typeof' in value && value.$$typeof === Symbol.for('react.lazy')))\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;\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 module - A module that exports a component and an optional config object.\n * @param children - An array of child routes.\n *\n * @deprecated Use `createRoute(path, component, config, children)` instead.\n */\nexport function createRoute(path: string, module: Module, children?: readonly AgnosticRoute[]): AgnosticRoute;\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 component - A React component.\n * @param config - An optional config object.\n * @param children - An array of child routes.\n */\nexport function createRoute(\n path: string,\n component: ComponentType,\n config: ViewConfig | undefined,\n children?: readonly AgnosticRoute[],\n): AgnosticRoute;\nexport function createRoute(\n path: string,\n moduleOrChildrenOrComponent?: Module | ComponentType | readonly AgnosticRoute[],\n childrenOrConfig?: readonly AgnosticRoute[] | ViewConfig,\n children?: readonly AgnosticRoute[],\n): AgnosticRoute {\n let isDeprecatedModuleUsed = false;\n let component: ComponentType | undefined;\n let config: ViewConfig | undefined;\n if (Array.isArray(moduleOrChildrenOrComponent)) {\n // eslint-disable-next-line no-param-reassign\n children = moduleOrChildrenOrComponent;\n } else if (\n isReactComponent(moduleOrChildrenOrComponent) ||\n (!moduleOrChildrenOrComponent && !!childrenOrConfig && typeof childrenOrConfig === 'object')\n ) {\n component = moduleOrChildrenOrComponent;\n config = childrenOrConfig as ViewConfig;\n } else if (moduleOrChildrenOrComponent) {\n ({ default: component, config } = moduleOrChildrenOrComponent as RouteModule);\n isDeprecatedModuleUsed = true;\n }\n\n return {\n path,\n module: isDeprecatedModuleUsed ? { default: component, config } : undefined,\n component,\n config,\n children,\n };\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AACA,SAAS,gCAAiC;;;;AAM1C,OAAO,SAAS,gBAAqD;CACnE,MAAM,UAAU,YAAY;AAC5B,QAAO,QAAQ,QAAQ,SAAS,IAAI;AACrC","names":[],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime/useViewConfig.ts"],"sourcesContent":["import type { UIMatch } from 'react-router';\nimport { useMatches } from 'react-router';\nimport type { ViewConfig } from '../types.js';\n\n/**\n * Hook to return the {@link ViewConfig} for the current route.\n */\nexport function useViewConfig<M extends ViewConfig>(): M | undefined {\n const matches = useMatches() as ReadonlyArray<UIMatch<unknown, M>>;\n return matches[matches.length - 1]?.handle;\n}\n"],"version":3}
1
+ {"mappings":"AACA,SAAS,gCAAiC;;;;AAM1C,OAAO,SAAS,gBAAqD;CACnE,MAAM,UAAU,YAAY;AAC5B,QAAO,QAAQ,QAAQ,SAAS,IAAI;AACrC","names":[],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime/useViewConfig.ts"],"sourcesContent":["import type { UIMatch } from 'react-router';\nimport { useMatches } from 'react-router';\nimport type { ViewConfig } from '../types.js';\n\n/**\n * Hook to return the {@link ViewConfig} for the current route.\n */\nexport function useViewConfig<M extends ViewConfig>(): M | undefined {\n const matches = useMatches() as ReadonlyArray<UIMatch<unknown, M>>;\n return matches[matches.length - 1]?.handle;\n}\n"],"version":3}
package/runtime.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"AAAA;AACA;AACA;AACA","names":[],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/runtime.ts"],"sourcesContent":["export * from './runtime/createRoute.js';\nexport * from './runtime/configuration-builder/RouterConfigurationBuilder.js';\nexport * from './runtime/useViewConfig.js';\nexport * from './runtime/createMenuItems.js';\n"],"version":3}
1
+ {"mappings":"AAAA;AACA;AACA;AACA","names":[],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/runtime.ts"],"sourcesContent":["export * from './runtime/createRoute.js';\nexport * from './runtime/configuration-builder/RouterConfigurationBuilder.js';\nexport * from './runtime/useViewConfig.js';\nexport * from './runtime/createMenuItems.js';\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,MAAM,cAAc;AACpB,MAAM,wBAAwB;;;;;;;;AAS9B,OAAO,SAAS,4BAA4BA,WAA4B;CACtE,IAAIC;AAEJ,KACE,qBACQ,cAAc,mBAAmB,cAAc,eACvD,UAAU,oBACH,UAAU,SAAS,UAC1B;AACA,GAAC,CAAE,KAAM,GAAG;CACb,OAAM;AACL,SAAO,OAAO,UAAU;CACzB;AAED,QAAO,KAAK,QAAQ,aAAa,GAAG,CAAC,MAAM,sBAAsB,CAAC,KAAK,IAAI;AAC5E","names":["component: unknown","name: string"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/shared/convertComponentNameToTitle.ts"],"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"],"version":3}
1
+ {"mappings":"AAAA,MAAM,cAAc;AACpB,MAAM,wBAAwB;;;;;;;;AAS9B,OAAO,SAAS,4BAA4BA,WAA4B;CACtE,IAAIC;AAEJ,KACE,qBACQ,cAAc,mBAAmB,cAAc,eACvD,UAAU,oBACH,UAAU,SAAS,UAC1B;AACA,GAAC,CAAE,KAAM,GAAG;CACb,OAAM;AACL,SAAO,OAAO,UAAU;CACzB;AAED,QAAO,KAAK,QAAQ,aAAa,GAAG,CAAC,MAAM,sBAAsB,CAAC,KAAK,IAAI;AAC5E","names":["component: unknown","name: string"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/shared/convertComponentNameToTitle.ts"],"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"],"version":3}
@@ -1 +1 @@
1
- {"mappings":";;;AAGA,OAAO,IAAK,0CAAL;AACL;AACA;AACA;;AACD","names":[],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/shared/routeParamType.ts"],"sourcesContent":["/**\n * The type of route parameter.\n */\nexport enum RouteParamType {\n Required = 'req',\n Optional = 'opt',\n Wildcard = '*',\n}\n"],"version":3}
1
+ {"mappings":";;;AAGA,OAAO,IAAK,0CAAL;AACL;AACA;AACA;;AACD","names":[],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/shared/routeParamType.ts"],"sourcesContent":["/**\n * The type of route parameter.\n */\nexport enum RouteParamType {\n Required = 'req',\n Optional = 'opt',\n Wildcard = '*',\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAWA,OAAO,SAAS,cACdA,OACAC,SACAC,aACG;AACH,QAAO,YAAY,OAAO,CAAC,GAAG,MAAM,YAAY,cAAc,GAAG,KAAK,YAAY,EAAE,QAAQ;AAC7F","names":["nodes: T","context: C","transformer: TreeTransformer<T, U, C>"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/shared/transformTree.ts"],"sourcesContent":["export type TreeTransformerNextCallback<T extends readonly unknown[], U, C extends object | null = null> = (\n nodes: T,\n context?: C,\n) => U;\n\nexport type TreeTransformer<T extends readonly unknown[], U, C extends object | null = null> = (\n nodes: T,\n next: TreeTransformerNextCallback<T, U, C>,\n context: C,\n) => U;\n\nexport function transformTree<T extends readonly unknown[], U, C extends object | null = null>(\n nodes: T,\n context: C,\n transformer: TreeTransformer<T, U, C>,\n): U {\n return transformer(nodes, (n, ctx = context) => transformTree(n, ctx, transformer), context);\n}\n"],"version":3}
1
+ {"mappings":"AAWA,OAAO,SAAS,cACdA,OACAC,SACAC,aACG;AACH,QAAO,YAAY,OAAO,CAAC,GAAG,MAAM,YAAY,cAAc,GAAG,KAAK,YAAY,EAAE,QAAQ;AAC7F","names":["nodes: T","context: C","transformer: TreeTransformer<T, U, C>"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/shared/transformTree.ts"],"sourcesContent":["export type TreeTransformerNextCallback<T extends readonly unknown[], U, C extends object | null = null> = (\n nodes: T,\n context?: C,\n) => U;\n\nexport type TreeTransformer<T extends readonly unknown[], U, C extends object | null = null> = (\n nodes: T,\n next: TreeTransformerNextCallback<T, U, C>,\n context: C,\n) => U;\n\nexport function transformTree<T extends readonly unknown[], U, C extends object | null = null>(\n nodes: T,\n context: C,\n transformer: TreeTransformer<T, U, C>,\n): U {\n return transformer(nodes, (n, ctx = context) => transformTree(n, ctx, transformer), context);\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,kCAAmC;AAC5C,SAAS,MAAM,iCAAkC;AACjD,SAAS,iDAAkD;AAE3D,SAAS,yBAA0B;;;;;;;;AAgBnC,eAAe,eAAe,aAC5BA,WACAC,aAC+B;AAC/B,KAAI;EACF,MAAM,iBAAiB,MAAM,SAAS,aAAa,QAAQ;EAC3D,MAAMC,mBAA0C,KAAK,MAAM,eAAe;EAC1E,MAAM,cAAc,iBAAiB,IAAI,CAAC,WAAW,MAAM,OAAO,KAAK,CAAC;AAExE,SAAO,cACL,WACA,EAAE,MAAM,GAAI,GACZ,CAAC,OAAO,MAAM,QACZ,MAAM,IAAI,CAAC,SAAS;GAClB,MAAM,cAAc,KAAK,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC;GACpD,MAAM,WAAW,KAAK,WAAW,KAAK,KAAK,UAAU,EAAE,MAAM,YAAa,EAAC,GAAG;AAE9E,UAAO,YAAY,KAAK,CAAC,UAAU,SAAS,MAAM,YAAY,CAAC,WAAW,KAAK,CAAC,GAC5E;IAAE,GAAG;IAAM,YAAY;IAAM;GAAU,IACvC;IAAE,GAAG;IAAM;GAAU;EAC1B,EAAC,CACL;CACF,SAAQC,GAAY;AACnB,MAAI,aAAa,SAAS,UAAU,KAAK,EAAE,SAAS,UAAU;AAC5D,UAAO;EACR;AAED,QAAM;CACP;AACF","names":["routeMeta: readonly RouteMeta[]","layoutsFile: URL","availableLayouts: readonly LayoutMeta[]","e: unknown"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/applyLayouts.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path/posix';\nimport { transformTree } from '../shared/transformTree.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport { strip } from './utils.js';\n\n/**\n * The information about a particular server-side layout.\n */\nexport type LayoutMeta = Readonly<{\n path: string;\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) => strip(layout.path));\n\n return transformTree<readonly RouteMeta[], readonly RouteMeta[], { path: string }>(\n routeMeta,\n { path: '' },\n (metas, next, ctx) =>\n metas.map((meta) => {\n const currentPath = join(ctx.path, strip(meta.path));\n const children = meta.children ? next(meta.children, { path: currentPath }) : undefined;\n\n return layoutPaths.some((path) => !relative(path, currentPath).startsWith('..'))\n ? { ...meta, flowLayout: true, children }\n : { ...meta, children };\n }),\n );\n } catch (e: unknown) {\n if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {\n return routeMeta;\n }\n\n throw e;\n }\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,kCAAmC;AAC5C,SAAS,MAAM,iCAAkC;AACjD,SAAS,iDAAkD;AAE3D,SAAS,yBAA0B;;;;;;;;AAgBnC,eAAe,eAAe,aAC5BA,WACAC,aAC+B;AAC/B,KAAI;EACF,MAAM,iBAAiB,MAAM,SAAS,aAAa,QAAQ;EAC3D,MAAMC,mBAA0C,KAAK,MAAM,eAAe;EAC1E,MAAM,cAAc,iBAAiB,IAAI,CAAC,WAAW,MAAM,OAAO,KAAK,CAAC;AAExE,SAAO,cACL,WACA,EAAE,MAAM,GAAI,GACZ,CAAC,OAAO,MAAM,QACZ,MAAM,IAAI,CAAC,SAAS;GAClB,MAAM,cAAc,KAAK,IAAI,MAAM,MAAM,KAAK,KAAK,CAAC;GACpD,MAAM,WAAW,KAAK,WAAW,KAAK,KAAK,UAAU,EAAE,MAAM,YAAa,EAAC,GAAG;AAE9E,UAAO,YAAY,KAAK,CAAC,UAAU,SAAS,MAAM,YAAY,CAAC,WAAW,KAAK,CAAC,GAC5E;IAAE,GAAG;IAAM,YAAY;IAAM;GAAU,IACvC;IAAE,GAAG;IAAM;GAAU;EAC1B,EAAC,CACL;CACF,SAAQC,GAAY;AACnB,MAAI,aAAa,SAAS,UAAU,KAAK,EAAE,SAAS,UAAU;AAC5D,UAAO;EACR;AAED,QAAM;CACP;AACF","names":["routeMeta: readonly RouteMeta[]","layoutsFile: URL","availableLayouts: readonly LayoutMeta[]","e: unknown"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/applyLayouts.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { join, relative } from 'node:path/posix';\nimport { transformTree } from '../shared/transformTree.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport { strip } from './utils.js';\n\n/**\n * The information about a particular server-side layout.\n */\nexport type LayoutMeta = Readonly<{\n path: string;\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) => strip(layout.path));\n\n return transformTree<readonly RouteMeta[], readonly RouteMeta[], { path: string }>(\n routeMeta,\n { path: '' },\n (metas, next, ctx) =>\n metas.map((meta) => {\n const currentPath = join(ctx.path, strip(meta.path));\n const children = meta.children ? next(meta.children, { path: currentPath }) : undefined;\n\n return layoutPaths.some((path) => !relative(path, currentPath).startsWith('..'))\n ? { ...meta, flowLayout: true, children }\n : { ...meta, children };\n }),\n );\n } catch (e: unknown) {\n if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {\n return routeMeta;\n }\n\n throw e;\n }\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"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","names":["url: URL | undefined","logger: Logger","dir: URL","children: RouteMeta[]","layout: URL | undefined"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/collectRoutesFromFS.ts"],"sourcesContent":["import { opendir, readFile } from 'node:fs/promises';\nimport { basename, extname, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Logger } from 'vite';\nimport { RouteParamType } from '../shared/routeParamType.js';\nimport type { ViewConfig } from '../types.js';\nimport { cleanUp, routeParamTypeMap } from './utils.js';\n\nexport type RouteMeta = Readonly<{\n path: string;\n file?: URL;\n layout?: URL;\n flowLayout?: boolean;\n config?: ViewConfig;\n children?: readonly RouteMeta[];\n}>;\n\n/**\n * Routes collector options.\n */\nexport type CollectRoutesOptions = Readonly<{\n /**\n * The list of extensions for files that will be collected as routes.\n */\n extensions: readonly string[];\n /**\n * The parent directory of the current directory. This is a\n * nested parameter used inside the function only.\n */\n parent?: URL;\n /**\n * The Vite logger instance.\n */\n logger: Logger;\n}>;\n\nasync function checkFile(url: URL | undefined, logger: Logger): Promise<URL | undefined> {\n if (url) {\n const contents = await readFile(url, 'utf-8');\n if (contents.trim() === '') {\n return undefined;\n } else if (!contents.includes('export default')) {\n logger.error(`The file \"${String(url)}\" should contain a default export of a component`);\n return undefined;\n }\n }\n\n return url;\n}\n\nconst collator = new Intl.Collator('en-US');\n\nconst warningFor = ['.ts', '.js'];\n\n/**\n * Collect route metadata from the file system and build a route tree.\n *\n * It accepts files that start with `@` as special files.\n * - `@layout` contains a component that wraps the child components.\n * - `@index` contains a component that will be used as the index page of the directory.\n *\n * It accepts files that start with `_` as private files. They will be ignored.\n *\n * @param dir - The directory to collect routes from.\n * @param options - The options object.\n *\n * @returns The route metadata array.\n */\nexport default async function collectRoutesFromFS(\n dir: URL,\n { extensions, logger, parent = dir }: CollectRoutesOptions,\n): Promise<readonly RouteMeta[]> {\n const path = relative(fileURLToPath(parent), fileURLToPath(dir));\n let children: RouteMeta[] = [];\n let layout: URL | undefined;\n\n for await (const d of await opendir(dir)) {\n if (d.name.startsWith('_')) {\n continue;\n }\n\n const extension = extname(d.name);\n const name = basename(d.name, extension);\n\n if (extension !== '' && !extensions.includes(extension)) {\n if (warningFor.includes(extension)) {\n logger.warn(\n `File System based router expects only JSX files in 'Frontend/views/' directory, such as '*.tsx' and '*.jsx'. The file '${d.name}' will be ignored by router, as it doesn't match this convention. Please consider storing it in another directory.`,\n );\n }\n continue;\n }\n\n if (children.some(({ path: p }) => p === name)) {\n throw new Error(`You cannot create a file and a directory with the same name (\"${name}\"). Use \"@index\" instead`);\n }\n\n if (d.isDirectory()) {\n const directoryRoutes = await collectRoutesFromFS(new URL(`${name}/`, dir), {\n extensions,\n logger,\n parent: dir,\n });\n if (directoryRoutes.length === 1 && directoryRoutes[0]?.layout) {\n const [layoutRoute] = directoryRoutes;\n children.push(layoutRoute);\n } else if (directoryRoutes.length > 0) {\n children.push({ path: name, children: directoryRoutes });\n }\n continue;\n }\n\n const file = new URL(d.name, dir);\n const url = await checkFile(file, logger);\n if (url === undefined) {\n continue;\n }\n const optionalParamType = routeParamTypeMap.get(RouteParamType.Optional)!;\n\n if (\n (name === '@index' && children.some(({ path: p }) => p.search(optionalParamType) >= 0)) ||\n (name.search(optionalParamType) >= 0 && children.some(({ path: p }) => p === ''))\n ) {\n throw new Error('You cannot create an `@index` file in a directory with optional parameters');\n } else if (name === '@layout') {\n layout = file;\n } else if (name === '@index') {\n children.push({\n path: '',\n file,\n });\n } else if (name.startsWith('@')) {\n throw new Error(\n 'Symbol \"@\" is reserved for special directories and files; only \"@layout\" and \"@index\" are allowed',\n );\n } else {\n children.push({\n path: name,\n file,\n });\n }\n }\n\n [children, layout] = await Promise.all([\n Promise.all(\n children.map(async (child) => ({\n ...child,\n file: child.file,\n layout: await checkFile(child.layout, logger),\n })),\n ),\n checkFile(layout, logger),\n ]);\n\n children = children.sort(({ path: a }, { path: b }) => collator.compare(cleanUp(a), cleanUp(b)));\n\n // If a layout was found, wrap the other routes with the layout route.\n return layout ? [{ path, layout, children }] : children;\n}\n"],"version":3}
1
+ {"mappings":"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","names":["url: URL | undefined","logger: Logger","dir: URL","children: RouteMeta[]","layout: URL | undefined"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/collectRoutesFromFS.ts"],"sourcesContent":["import { opendir, readFile } from 'node:fs/promises';\nimport { basename, extname, relative } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Logger } from 'vite';\nimport { RouteParamType } from '../shared/routeParamType.js';\nimport type { ViewConfig } from '../types.js';\nimport { cleanUp, routeParamTypeMap } from './utils.js';\n\nexport type RouteMeta = Readonly<{\n path: string;\n file?: URL;\n layout?: URL;\n flowLayout?: boolean;\n config?: ViewConfig;\n children?: readonly RouteMeta[];\n}>;\n\n/**\n * Routes collector options.\n */\nexport type CollectRoutesOptions = Readonly<{\n /**\n * The list of extensions for files that will be collected as routes.\n */\n extensions: readonly string[];\n /**\n * The parent directory of the current directory. This is a\n * nested parameter used inside the function only.\n */\n parent?: URL;\n /**\n * The Vite logger instance.\n */\n logger: Logger;\n}>;\n\nasync function checkFile(url: URL | undefined, logger: Logger): Promise<URL | undefined> {\n if (url) {\n const contents = await readFile(url, 'utf-8');\n if (contents.trim() === '') {\n return undefined;\n } else if (!contents.includes('export default')) {\n logger.error(`The file \"${String(url)}\" should contain a default export of a component`);\n return undefined;\n }\n }\n\n return url;\n}\n\nconst collator = new Intl.Collator('en-US');\n\nconst warningFor = ['.ts', '.js'];\n\n/**\n * Collect route metadata from the file system and build a route tree.\n *\n * It accepts files that start with `@` as special files.\n * - `@layout` contains a component that wraps the child components.\n * - `@index` contains a component that will be used as the index page of the directory.\n *\n * It accepts files that start with `_` as private files. They will be ignored.\n *\n * @param dir - The directory to collect routes from.\n * @param options - The options object.\n *\n * @returns The route metadata array.\n */\nexport default async function collectRoutesFromFS(\n dir: URL,\n { extensions, logger, parent = dir }: CollectRoutesOptions,\n): Promise<readonly RouteMeta[]> {\n const path = relative(fileURLToPath(parent), fileURLToPath(dir));\n let children: RouteMeta[] = [];\n let layout: URL | undefined;\n\n for await (const d of await opendir(dir)) {\n if (d.name.startsWith('_')) {\n continue;\n }\n\n const extension = extname(d.name);\n const name = basename(d.name, extension);\n\n if (extension !== '' && !extensions.includes(extension)) {\n if (warningFor.includes(extension)) {\n logger.warn(\n `File System based router expects only JSX files in 'Frontend/views/' directory, such as '*.tsx' and '*.jsx'. The file '${d.name}' will be ignored by router, as it doesn't match this convention. Please consider storing it in another directory.`,\n );\n }\n continue;\n }\n\n if (children.some(({ path: p }) => p === name)) {\n throw new Error(`You cannot create a file and a directory with the same name (\"${name}\"). Use \"@index\" instead`);\n }\n\n if (d.isDirectory()) {\n const directoryRoutes = await collectRoutesFromFS(new URL(`${name}/`, dir), {\n extensions,\n logger,\n parent: dir,\n });\n if (directoryRoutes.length === 1 && directoryRoutes[0]?.layout) {\n const [layoutRoute] = directoryRoutes;\n children.push(layoutRoute);\n } else if (directoryRoutes.length > 0) {\n children.push({ path: name, children: directoryRoutes });\n }\n continue;\n }\n\n const file = new URL(d.name, dir);\n const url = await checkFile(file, logger);\n if (url === undefined) {\n continue;\n }\n const optionalParamType = routeParamTypeMap.get(RouteParamType.Optional)!;\n\n if (\n (name === '@index' && children.some(({ path: p }) => p.search(optionalParamType) >= 0)) ||\n (name.search(optionalParamType) >= 0 && children.some(({ path: p }) => p === ''))\n ) {\n throw new Error('You cannot create an `@index` file in a directory with optional parameters');\n } else if (name === '@layout') {\n layout = file;\n } else if (name === '@index') {\n children.push({\n path: '',\n file,\n });\n } else if (name.startsWith('@')) {\n throw new Error(\n 'Symbol \"@\" is reserved for special directories and files; only \"@layout\" and \"@index\" are allowed',\n );\n } else {\n children.push({\n path: name,\n file,\n });\n }\n }\n\n [children, layout] = await Promise.all([\n Promise.all(\n children.map(async (child) => ({\n ...child,\n file: child.file,\n layout: await checkFile(child.layout, logger),\n })),\n ),\n checkFile(layout, logger),\n ]);\n\n children = children.sort(({ path: a }, { path: b }) => collator.compare(cleanUp(a), cleanUp(b)));\n\n // If a layout was found, wrap the other routes with the layout route.\n return layout ? [{ path, layout, children }] : children;\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,OAAO,yEAA0E;AACjF,OAAO,wFAAyF;AAChG,OAAO,4EAA6E;AACpF,OAAO,uBAAwB;AAC/B,SAEE,eACA,SAEA,+BAGkB;AAEpB,SAAS,iDAAkD;AAG3D,SAAS,2DAA4D;AAErE,MAAM,UAAU,cAAc,EAAE,SAAS,YAAY,SAAU,EAAC;AAEhE,MAAM,iBAAiB;CAAC;CAAO;CAAQ;CAAO;AAAO;AAErD,MAAM,oBAAoB;AAC1B,MAAM,6BAA6B,EAAE,kBAAkB;AACvD,MAAM,2BAA2B,EAAE,kBAAkB;AAcrD,SAAS,aAAaA,KAAgE;AACpF,UAAS,OAAO,UAAU;AAC3B;AAED,SAAS,YAAYC,aAAgCC,MAAcC,QAA6C;AAC9G,KAAI,OAAO,SAAS,WAAW;AAC7B,SAAO,OAAO;CACf;CAGD,MAAM,eAAe,YAAY,KAAK,QAAQ;CAC9C,MAAM,eAAe,gBAAgB,SAAS,MAAM,SAAS;AAC7D,SAAQ;AACT;AAED,MAAM,uBAAuB;CAC3B,AAASC;CACT,AAASC;CACT,AAASC;CAET,YACEC,OACAC,aACA,EAAE,MAAM,UAA2B,EACnC;AACA,OAAKH,SAAS;AACd,OAAKC,WAAW;EAEhB,MAAM,UAAU,IAAI,IAAI,MAAM;AAC9B,OAAKF,WAAW,IAAI,kBAAkB,IAAI,YAAY;GAAE,WAAW;GAAO,YAAY;EAAS;CAChG;;;;CAKD,UAAkB;EAChB,MAAM,EACJ,OACA,SAAS,EAAE,WAAW,OAAO,EAC9B,GAAG,KAAKA;EACT,MAAMK,SAAmB,CAAE;EAE3B,MAAM,SAAS,cAGb;GAAC,CAAE;GAAE,KAAKJ;GAAQ,KAAKC;EAAS,GAAE,MAAM,CAAC,CAAC,aAAa,OAAO,QAAQ,EAAE,SAAS;AACjF,UAAO,KACL,GAAG,MACA,IAAI,CAAC,UAAU,MAAM,KAAK,CAC1B,OAAO,CAAC,MAAM,OAAO,QAAQ,IAAI,QAAQ,KAAK,KAAK,MAAM,CACzD,IAAI,CAAC,SAAS,gDAAgD,IAAI,KAAK,CAC3E;AAED,UAAO,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,MAAM,UAAU,YAAY,EAAE,UAAU;IACxE,MAAM,SAAS,QAAQ;IACvB,IAAII;AAEJ,QAAI,UAAU;AAGZ,iBAAY,KAAK;MAAC,CAAC,GAAG,aAAa,IAAK;MAAE;MAAU,OAAO;KAAU,EAAC;IACvE;IAED,IAAIC;IAEJ,IAAIC;IACJ,IAAIC;AAEJ,QAAI,MAAM;KACR,MAAM,UAAU,eAAe,KAAK,CAAC,QAAQ,KAAK,SAAS,SAAS,IAAI,CAAC;AACzE,oBAAe,MAAM,mBAAmB,MAAM,QAAQ;AACtD,gBAAW;IACZ,WAAU,QAAQ;KACjB,MAAM,UAAU,eAAe,KAAK,CAAC,QAAQ,OAAO,SAAS,SAAS,IAAI,CAAC;AAC3E,oBAAe,MAAM,mBAAmB,QAAQ,QAAQ;AACxD,gBAAW;IACZ;AAED,QAAI,gBAAgB,UAAU;AAC5B,SAAI,YAAY,aAAa,MAAM,OAAO,EAAE;AAC1C,eAAS;OACP,MAAM;OACN;OACA,QAAQ,MAAM,cAAc,SAAS,OAAO,IAAI,MAAM,IAAI,SAAS,OAAO;MAC3E;KACF,OAAM;MACL,MAAM,MAAM,UAAU,IAAI,cAAc,SAAS;MACjD,MAAM,kBACJ,MAAM,cAAc,yBAAyB,cAAc,IAC3D,MAAM,IAAI,yBAAyB,eAAe,KAAK;AAEzD,eAAS;OACP,aAAa,IAAI,EAAE,IAAI,UAAU;OACjC,UAAU,IAAI,GAAG,IAAI,MAAM,gBAAgB,UAAU;OACrD;MACD;KACF;IACF;AAED,WAAO,KAAKC,iBAAiB,wCAAwC,KAAK,EAAE,QAAQ,UAAU;GAC/F,EAAC;EACH,EAAC;EAEF,MAAM,kBACJ,MAAM,cAAc,yBAAyB,gBAAgB,IAC7D,MAAM,IAAI,yBAAyB,iBAAiB,KAAK;EAC3D,MAAM,mBAAmB,CACvB,GAAG,KAAKV,SAAS,QAAQ,QAAQ,EACjC,GAAG,IAAI,EAAE,OAAO,KAAK,KAAK,CAAC;yBACR,gBAAgB,OAAO,QAAQ,6BAA6B,QAAQ,KAAK,CAAC;wBAC3E,OAAO,UAC1B;EAED,MAAM,OAAO,iBAAiB,kBAAkB,iBAAiB;AACjE,SAAO,QAAQ,UAAU,KAAK;CAC/B;;;;;;;;;CAUD,iBACEF,MACAS,QACAI,UACgB;EAChB,MAAM,EAAE,OAAO,GAAG,KAAKX,SAAS;EAEhC,MAAM,gBACJ,MAAM,cAAc,2BAA2B,cAAc,IAC7D,MAAM,IAAI,2BAA2B,cAAc;EAErD,IAAIY;EACJ,IAAIC;AAEJ,MAAI,aAAa,OAAO,EAAE;GACxB,MAAM,EAAE,UAAU,IAAI,QAAQ,GAAI,GAAG,YAAY,GAAG,OAAO;AAE3D,eAAY,IAAI,EAAE,OAAO,OAAO,iBAAiB,OAAO,KAAK,IAAI;AACjE,YAAS,OAAO,KAAK,WAAW,CAAC,SAAS,IAAI,KAAK,UAAU,WAAW,GAAG;EAC5E,WAAU,QAAQ;AACjB,eAAY,OAAO;AACnB,YAAS,OAAO,aACX,IAAI,oBAAoB,OAAO,SAAS,gBAAgB,OAAO,WAAW,UAAU,CAAC,OACnF,OACH,OAAO;EACZ;EAED,MAAM,YAAY,WAAW,QAAQ,6BAA6B,UAAU,KAAK,GAAG;AASpF,SAAO,IAAI,EAAE,cAAc,IAAI,KAAK,KAAK,aAAa,GAAG,IAAI,UAAU,GAAG,IAAI,UAAU,GAAG;CAC5F;AACF;AAED,eAAe,SAAS,qBACtBV,OACAC,aACAU,MACQ;AACR,QAAO,IAAI,uBAAuB,OAAO,aAAa,MAAM,SAAS;AACtE","names":["mod: LazyModule | RegularModule | undefined","pathContext: readonly string[]","path: string","config: Readonly<ServerViewConfig>","#manager","#views","#configs","views: readonly RouteMeta[]","viewConfigs: readonly ServerViewConfig[]","errors: string[]","_children: readonly CallExpression[] | undefined","module: LazyModule | RegularModule | undefined","relativePath: string | undefined","fileName: string | undefined","#createRouteData","children: readonly CallExpression[] | undefined","component: PropertyAccessExpression | CallExpression | undefined","config: PropertyAccessExpression | ObjectLiteralExpression | string | undefined","urls: RuntimeFileUrls"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/createRoutesFromMeta.ts"],"sourcesContent":["import 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 ast from 'tsc-template';\nimport {\n type CallExpression,\n createPrinter,\n factory,\n type Identifier,\n NewLineKind,\n type ObjectLiteralExpression,\n type PropertyAccessExpression,\n} from 'typescript';\nimport type { ServerViewConfig } from '../shared/internal.js';\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 = createPrinter({ newLine: NewLineKind.LineFeed });\n\nconst fileExtensions = ['.ts', '.tsx', '.js', '.jsx'];\n\nconst HILLA_FILE_ROUTER = '@vaadin/hilla-file-router';\nconst HILLA_FILE_ROUTER_RUNTIME = `${HILLA_FILE_ROUTER}/runtime.js`;\nconst HILLA_FILE_ROUTER_TYPES = `${HILLA_FILE_ROUTER}/types.js`;\n\ntype LazyModule = Readonly<{\n path: string;\n config: ServerViewConfig;\n lazyId: Identifier;\n}>;\n\ntype RegularModule = Readonly<{\n componentId: PropertyAccessExpression;\n configId: PropertyAccessExpression;\n flowLayout?: boolean;\n}>;\n\nfunction isLazyModule(mod: LazyModule | RegularModule | undefined): mod is LazyModule {\n return !!mod && 'path' in mod;\n}\n\nfunction isLazyRoute(pathContext: readonly string[], path: string, config: Readonly<ServerViewConfig>): boolean {\n if (config.lazy !== undefined) {\n return config.lazy;\n }\n\n // \"/\" and \"/login\" are eager by default\n const rootContext = !pathContext.some(Boolean);\n const eagerDefault = rootContext && (path === '' || path === 'login');\n return !eagerDefault;\n}\n\nclass RouteFromMetaProcessor {\n readonly #manager: DependencyManager;\n readonly #views: readonly RouteMeta[];\n readonly #configs: readonly ServerViewConfig[];\n\n constructor(\n views: readonly RouteMeta[],\n viewConfigs: readonly ServerViewConfig[],\n { code: codeFile }: RuntimeFileUrls,\n ) {\n this.#views = views;\n this.#configs = viewConfigs;\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 process(): string {\n const {\n paths,\n imports: { namespace, named },\n } = this.#manager;\n const errors: string[] = [];\n\n const routes = transformTree<\n [pathContext: readonly string[], metas: readonly RouteMeta[], configs: readonly ServerViewConfig[]],\n readonly CallExpression[]\n >([[], this.#views, this.#configs], null, ([pathContext, metas, configs], 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 }, index) => {\n const config = configs[index]!;\n let _children: readonly CallExpression[] | undefined;\n\n if (children) {\n // Assuming that if we have `children` in the route, we also have\n // `children` in the config.\n _children = next([[...pathContext, path], children, config.children!]);\n }\n\n let module: LazyModule | RegularModule | undefined;\n\n let relativePath: string | undefined;\n let fileName: string | undefined;\n\n if (file) {\n const fileExt = fileExtensions.find((ext) => file.pathname.endsWith(ext));\n relativePath = paths.createRelativePath(file, fileExt);\n fileName = 'Page';\n } else if (layout) {\n const fileExt = fileExtensions.find((ext) => layout.pathname.endsWith(ext));\n relativePath = paths.createRelativePath(layout, fileExt);\n fileName = 'Layout';\n }\n\n if (relativePath && fileName) {\n if (isLazyRoute(pathContext, path, config)) {\n module = {\n path: relativePath,\n config,\n lazyId: named.getIdentifier('react', 'lazy') ?? named.add('react', 'lazy'),\n };\n } else {\n const mod = namespace.add(relativePath, fileName);\n const reactModuleType =\n named.getIdentifier(HILLA_FILE_ROUTER_TYPES, 'RouteModule') ??\n named.add(HILLA_FILE_ROUTER_TYPES, 'RouteModule', true);\n\n module = {\n componentId: ast`${mod}.default`.node as PropertyAccessExpression,\n configId: ast`(${mod} as ${reactModuleType}).config`.node as PropertyAccessExpression,\n flowLayout,\n };\n }\n }\n\n return this.#createRouteData(convertFSRouteSegmentToURLPatternFormat(path), module, _children);\n });\n });\n\n const agnosticRouteId =\n named.getIdentifier(HILLA_FILE_ROUTER_TYPES, 'AgnosticRoute') ??\n named.add(HILLA_FILE_ROUTER_TYPES, 'AgnosticRoute', true);\n const routeDeclaration = [\n ...this.#manager.imports.toCode(),\n ...ast`${errors.join('\\n')}\nconst routes: readonly ${agnosticRouteId}[] = ${factory.createArrayLiteralExpression(routes, true)};\nexport default routes;`.source.statements,\n ];\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 module - The module to build route from.\n * @param children - The list of child route call expressions.\n */\n #createRouteData(\n path: string,\n module: LazyModule | RegularModule | undefined,\n children: readonly CallExpression[] | undefined,\n ): CallExpression {\n const { named } = this.#manager.imports;\n\n const createRouteId =\n named.getIdentifier(HILLA_FILE_ROUTER_RUNTIME, 'createRoute') ??\n named.add(HILLA_FILE_ROUTER_RUNTIME, 'createRoute');\n\n let component: PropertyAccessExpression | CallExpression | undefined;\n let config: PropertyAccessExpression | ObjectLiteralExpression | string | undefined;\n\n if (isLazyModule(module)) {\n const { children: _c, params: _p, ...viewConfig } = module.config;\n\n component = ast`${module.lazyId}(() => import('${module.path}')`.node as CallExpression;\n config = Object.keys(viewConfig).length > 0 ? JSON.stringify(viewConfig) : '';\n } else if (module) {\n component = module.componentId;\n config = module.flowLayout\n ? (ast`const a = %{ { ...${module.configId}, flowLayout: ${module.flowLayout.toString()} } }%`\n .node as ObjectLiteralExpression)\n : module.configId;\n }\n\n const _children = children ? factory.createArrayLiteralExpression(children, true) : '';\n\n // ```ts\n // createRoute(\"grandparent\", {...grandparentConfig, flowLayout: true}, [\n // createRoute(\"parent\", ParentPage, parentConfig, [\n // createRoute(\"child\", lazy(() => import('../ChildPage.js')), { title: 'Child Page' }),\n // ]),\n // ]),\n // ```\n return ast`${createRouteId}(\"${path}\", ${component ?? ''}, ${config ?? ''}, ${_children})`.node as CallExpression;\n }\n}\n\nexport default function createRoutesFromMeta(\n views: readonly RouteMeta[],\n viewConfigs: readonly ServerViewConfig[],\n urls: RuntimeFileUrls,\n): string {\n return new RouteFromMetaProcessor(views, viewConfigs, urls).process();\n}\n"],"version":3}
1
+ {"mappings":"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","names":["mod: LazyModule | RegularModule | undefined","pathContext: readonly string[]","path: string","config: Readonly<ServerViewConfig>","#manager","#views","#configs","views: readonly RouteMeta[]","viewConfigs: readonly ServerViewConfig[]","errors: string[]","_children: readonly CallExpression[] | undefined","module: LazyModule | RegularModule | undefined","relativePath: string | undefined","fileName: string | undefined","#createRouteData","children: readonly CallExpression[] | undefined","component: PropertyAccessExpression | CallExpression | undefined","config: PropertyAccessExpression | ObjectLiteralExpression | string | undefined","urls: RuntimeFileUrls"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/createRoutesFromMeta.ts"],"sourcesContent":["import 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 ast from 'tsc-template';\nimport {\n type CallExpression,\n createPrinter,\n factory,\n type Identifier,\n NewLineKind,\n type ObjectLiteralExpression,\n type PropertyAccessExpression,\n} from 'typescript';\nimport type { ServerViewConfig } from '../shared/internal.js';\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 = createPrinter({ newLine: NewLineKind.LineFeed });\n\nconst fileExtensions = ['.ts', '.tsx', '.js', '.jsx'];\n\nconst HILLA_FILE_ROUTER = '@vaadin/hilla-file-router';\nconst HILLA_FILE_ROUTER_RUNTIME = `${HILLA_FILE_ROUTER}/runtime.js`;\nconst HILLA_FILE_ROUTER_TYPES = `${HILLA_FILE_ROUTER}/types.js`;\n\ntype LazyModule = Readonly<{\n path: string;\n config: ServerViewConfig;\n lazyId: Identifier;\n}>;\n\ntype RegularModule = Readonly<{\n componentId: PropertyAccessExpression;\n configId: PropertyAccessExpression;\n flowLayout?: boolean;\n}>;\n\nfunction isLazyModule(mod: LazyModule | RegularModule | undefined): mod is LazyModule {\n return !!mod && 'path' in mod;\n}\n\nfunction isLazyRoute(pathContext: readonly string[], path: string, config: Readonly<ServerViewConfig>): boolean {\n if (config.lazy !== undefined) {\n return config.lazy;\n }\n\n // \"/\" and \"/login\" are eager by default\n const rootContext = !pathContext.some(Boolean);\n const eagerDefault = rootContext && (path === '' || path === 'login');\n return !eagerDefault;\n}\n\nclass RouteFromMetaProcessor {\n readonly #manager: DependencyManager;\n readonly #views: readonly RouteMeta[];\n readonly #configs: readonly ServerViewConfig[];\n\n constructor(\n views: readonly RouteMeta[],\n viewConfigs: readonly ServerViewConfig[],\n { code: codeFile }: RuntimeFileUrls,\n ) {\n this.#views = views;\n this.#configs = viewConfigs;\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 process(): string {\n const {\n paths,\n imports: { namespace, named },\n } = this.#manager;\n const errors: string[] = [];\n\n const routes = transformTree<\n [pathContext: readonly string[], metas: readonly RouteMeta[], configs: readonly ServerViewConfig[]],\n readonly CallExpression[]\n >([[], this.#views, this.#configs], null, ([pathContext, metas, configs], 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 }, index) => {\n const config = configs[index]!;\n let _children: readonly CallExpression[] | undefined;\n\n if (children) {\n // Assuming that if we have `children` in the route, we also have\n // `children` in the config.\n _children = next([[...pathContext, path], children, config.children!]);\n }\n\n let module: LazyModule | RegularModule | undefined;\n\n let relativePath: string | undefined;\n let fileName: string | undefined;\n\n if (file) {\n const fileExt = fileExtensions.find((ext) => file.pathname.endsWith(ext));\n relativePath = paths.createRelativePath(file, fileExt);\n fileName = 'Page';\n } else if (layout) {\n const fileExt = fileExtensions.find((ext) => layout.pathname.endsWith(ext));\n relativePath = paths.createRelativePath(layout, fileExt);\n fileName = 'Layout';\n }\n\n if (relativePath && fileName) {\n if (isLazyRoute(pathContext, path, config)) {\n module = {\n path: relativePath,\n config,\n lazyId: named.getIdentifier('react', 'lazy') ?? named.add('react', 'lazy'),\n };\n } else {\n const mod = namespace.add(relativePath, fileName);\n const reactModuleType =\n named.getIdentifier(HILLA_FILE_ROUTER_TYPES, 'RouteModule') ??\n named.add(HILLA_FILE_ROUTER_TYPES, 'RouteModule', true);\n\n module = {\n componentId: ast`${mod}.default`.node as PropertyAccessExpression,\n configId: ast`(${mod} as ${reactModuleType}).config`.node as PropertyAccessExpression,\n flowLayout,\n };\n }\n }\n\n return this.#createRouteData(convertFSRouteSegmentToURLPatternFormat(path), module, _children);\n });\n });\n\n const agnosticRouteId =\n named.getIdentifier(HILLA_FILE_ROUTER_TYPES, 'AgnosticRoute') ??\n named.add(HILLA_FILE_ROUTER_TYPES, 'AgnosticRoute', true);\n const routeDeclaration = [\n ...this.#manager.imports.toCode(),\n ...ast`${errors.join('\\n')}\nconst routes: readonly ${agnosticRouteId}[] = ${factory.createArrayLiteralExpression(routes, true)};\nexport default routes;`.source.statements,\n ];\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 module - The module to build route from.\n * @param children - The list of child route call expressions.\n */\n #createRouteData(\n path: string,\n module: LazyModule | RegularModule | undefined,\n children: readonly CallExpression[] | undefined,\n ): CallExpression {\n const { named } = this.#manager.imports;\n\n const createRouteId =\n named.getIdentifier(HILLA_FILE_ROUTER_RUNTIME, 'createRoute') ??\n named.add(HILLA_FILE_ROUTER_RUNTIME, 'createRoute');\n\n let component: PropertyAccessExpression | CallExpression | undefined;\n let config: PropertyAccessExpression | ObjectLiteralExpression | string | undefined;\n\n if (isLazyModule(module)) {\n const { children: _c, params: _p, ...viewConfig } = module.config;\n\n component = ast`${module.lazyId}(() => import('${module.path}')`.node as CallExpression;\n config = Object.keys(viewConfig).length > 0 ? JSON.stringify(viewConfig) : '';\n } else if (module) {\n component = module.componentId;\n config = module.flowLayout\n ? (ast`const a = %{ { ...${module.configId}, flowLayout: ${module.flowLayout.toString()} } }%`\n .node as ObjectLiteralExpression)\n : module.configId;\n }\n\n const _children = children ? factory.createArrayLiteralExpression(children, true) : '';\n\n // ```ts\n // createRoute(\"grandparent\", {...grandparentConfig, flowLayout: true}, [\n // createRoute(\"parent\", ParentPage, parentConfig, [\n // createRoute(\"child\", lazy(() => import('../ChildPage.js')), { title: 'Child Page' }),\n // ]),\n // ]),\n // ```\n return ast`${createRouteId}(\"${path}\", ${component ?? ''}, ${config ?? ''}, ${_children})`.node as CallExpression;\n }\n}\n\nexport default function createRoutesFromMeta(\n views: readonly RouteMeta[],\n viewConfigs: readonly ServerViewConfig[],\n urls: RuntimeFileUrls,\n): string {\n return new RouteFromMetaProcessor(views, viewConfigs, urls).process();\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,kCAAmC;AAC5C,SAAS,uBAAwB;AACjC,OAAO,oBAAoC;AAC3C,SAAS,6EAA8E;AAEvF,SAAS,iDAAkD;AAG3D,SAAS,yCAAyC,oDAAqD;;;;;;AAOvG,UAAU,QAAQA,MAA6B;AAC7C,OAAM;AAEN,MAAK,MAAM,SAAS,KAAK,aAAa,EAAE;AACtC,SAAO,QAAQ,MAAM;CACtB;AACF;;;;;;;;AASD,eAAe,eAAe,qBAAqBC,OAAmE;AACpH,QAAO,MAAM,cACX,OACA,MACA,OAAO,QAAQ,SACb,MAAM,QAAQ,IACZ,OAAO,IAAI,OAAO,EAAE,MAAM,MAAM,QAAQ,UAAU,YAAY,KAAK;EACjE,MAAM,cAAc,WAAW,MAAM,KAAK,SAAS,GAAG;AAEtD,OAAK,SAAS,QAAQ;AACpB,UAAO;IACL,OAAO,wCAAwC,KAAK;IACpD,QAAQ,iCAAiC,KAAK;IAC9C,UAAU;GACX;EACF;EAED,MAAM,aAAa,GAAG,iBACpB,QACA,MAAM,SAAS,QAAQ,QAAS,OAAO,EACvC,GAAG,aAAa,QAChB,KACD;EACD,IAAIC;EACJ,IAAI,uBAAuB;EAC3B,IAAIC;AAEJ,OAAK,MAAM,QAAQ,QAAQ,WAAW,EAAE;AACtC,OAAI,GAAG,sBAAsB,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,UAAU;AAC/F,QAAI,KAAK,eAAe,GAAG,0BAA0B,KAAK,YAAY,EAAE;KACtE,MAAM,OAAO,KAAK,YAAY,QAAQ,WAAW;KACjD,MAAM,SAAS,IAAI,QAAQ;;;;qBAItB,KAAK;;AAEV,cAAS,OAAO,kBAAkB;AAClC,SAAI,OAAO,eAAe,WAAW;MACnC,MAAM,OAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;AAE/C,WAAK,aAAa,cAAc;AAChC,eAAS;KACV;IACF;GACF,WAAU,KAAK,QAAQ,WAAW,CAAC,WAAW,iBAAiB,EAAE;AAChE,2BAAuB;GACxB,WAAU,wBAAwB,GAAG,aAAa,KAAK,EAAE;AACxD,oBAAgB,KAAK;AACrB,2BAAuB;GACxB;EACF;AAED,aAAW,EAAE,YAAY,cAAc,MAAO;EAE9C,IAAIC;AAEJ,MAAI,OAAO,OAAO;AAChB,IAAC,CAAE,MAAO,GAAG;EACd,OAAM;AACL,QAAK,eAAe;AAClB,UAAM,IAAI,OACP,YAAY,OAAO,QAAQ,OAAQ,CAAC;GAExC;AAED,WAAQ,4BAA4B,cAAc;EACnD;AAED,SAAO;GACL,OAAO,wCAAwC,KAAK;GACpD,GAAG;GACH,QAAQ,iCAAiC,OAAO,SAAS,KAAK;GAC9D;GACA,UAAU,gBAAgB,SAAS,CAAE,IAAG;EACzC;CACF,EAAC,CACH,CACJ;AACF","names":["node: Node","views: readonly RouteMeta[]","config: ViewConfig | undefined","componentName: string | undefined","title: string"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/createViewConfigJson.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { Script } from 'node:vm';\nimport ts, { type Node } from 'typescript';\nimport { convertComponentNameToTitle } from '../shared/convertComponentNameToTitle.js';\nimport type { ServerViewConfig } from '../shared/internal.js';\nimport { transformTree } from '../shared/transformTree.js';\nimport type { ViewConfig } from '../types.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport { convertFSRouteSegmentToURLPatternFormat, extractParameterFromRouteSegment } from './utils.js';\n\n/**\n * Walks the TypeScript AST using the deep-first search algorithm.\n *\n * @param node - The node to walk.\n */\nfunction* walkAST(node: Node): Generator<Node> {\n yield node;\n\n for (const child of node.getChildren()) {\n yield* walkAST(child);\n }\n}\n\n/**\n * Creates a map of all leaf routes to their configuration. This file is used by the server to provide server-side\n * routes along with managing the client-side routes.\n *\n * @param views - The route metadata tree.\n * @returns A view configuration tree.\n */\nexport default async function createViewConfigJson(views: readonly RouteMeta[]): Promise<readonly ServerViewConfig[]> {\n return await transformTree<readonly RouteMeta[], Promise<readonly ServerViewConfig[]>>(\n views,\n null,\n async (routes, next) =>\n await Promise.all(\n routes.map(async ({ path, file, layout, children, flowLayout }) => {\n const newChildren = children ? await next(children) : undefined;\n\n if (!file && !layout) {\n return {\n route: convertFSRouteSegmentToURLPatternFormat(path),\n params: extractParameterFromRouteSegment(path),\n children: newChildren,\n } satisfies ServerViewConfig;\n }\n\n const sourceFile = ts.createSourceFile(\n 'f.ts',\n await readFile(file ?? layout!, 'utf8'),\n ts.ScriptTarget.ESNext,\n true,\n );\n let config: ViewConfig | undefined;\n let waitingForIdentifier = false;\n let componentName: string | undefined;\n\n for (const node of walkAST(sourceFile)) {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === 'config') {\n if (node.initializer && ts.isObjectLiteralExpression(node.initializer)) {\n const code = node.initializer.getText(sourceFile);\n const script = new Script(`\n function key(x) {\n return x[0];\n }\n (${code})\n `);\n config = script.runInThisContext() as ViewConfig;\n if (config.flowLayout === undefined) {\n const copy = JSON.parse(JSON.stringify(config));\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n copy.flowLayout = flowLayout ?? false;\n config = copy;\n }\n }\n } else if (node.getText(sourceFile).startsWith('export default')) {\n waitingForIdentifier = true;\n } else if (waitingForIdentifier && ts.isIdentifier(node)) {\n componentName = node.text;\n waitingForIdentifier = false;\n }\n }\n\n config ??= { flowLayout: flowLayout ?? false };\n\n let title: string;\n\n if (config.title) {\n ({ title } = config);\n } else {\n if (!componentName) {\n throw new Error(\n `The file \"${String(file ?? layout!)}\" must contain a default export of a component whose name will be used as title by default`,\n );\n }\n\n title = convertComponentNameToTitle(componentName);\n }\n\n return {\n route: convertFSRouteSegmentToURLPatternFormat(path),\n ...config,\n params: extractParameterFromRouteSegment(config.route ?? path),\n title,\n children: newChildren ?? (layout ? [] : undefined),\n } satisfies ServerViewConfig;\n }),\n ),\n );\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,kCAAmC;AAC5C,SAAS,uBAAwB;AACjC,OAAO,oBAAoC;AAC3C,SAAS,6EAA8E;AAEvF,SAAS,iDAAkD;AAG3D,SAAS,yCAAyC,oDAAqD;;;;;;AAOvG,UAAU,QAAQA,MAA6B;AAC7C,OAAM;AAEN,MAAK,MAAM,SAAS,KAAK,aAAa,EAAE;AACtC,SAAO,QAAQ,MAAM;CACtB;AACF;;;;;;;;AASD,eAAe,eAAe,qBAAqBC,OAAmE;AACpH,QAAO,MAAM,cACX,OACA,MACA,OAAO,QAAQ,SACb,MAAM,QAAQ,IACZ,OAAO,IAAI,OAAO,EAAE,MAAM,MAAM,QAAQ,UAAU,YAAY,KAAK;EACjE,MAAM,cAAc,WAAW,MAAM,KAAK,SAAS,GAAG;AAEtD,OAAK,SAAS,QAAQ;AACpB,UAAO;IACL,OAAO,wCAAwC,KAAK;IACpD,QAAQ,iCAAiC,KAAK;IAC9C,UAAU;GACX;EACF;EAED,MAAM,aAAa,GAAG,iBACpB,QACA,MAAM,SAAS,QAAQ,QAAS,OAAO,EACvC,GAAG,aAAa,QAChB,KACD;EACD,IAAIC;EACJ,IAAI,uBAAuB;EAC3B,IAAIC;AAEJ,OAAK,MAAM,QAAQ,QAAQ,WAAW,EAAE;AACtC,OAAI,GAAG,sBAAsB,KAAK,IAAI,GAAG,aAAa,KAAK,KAAK,IAAI,KAAK,KAAK,SAAS,UAAU;AAC/F,QAAI,KAAK,eAAe,GAAG,0BAA0B,KAAK,YAAY,EAAE;KACtE,MAAM,OAAO,KAAK,YAAY,QAAQ,WAAW;KACjD,MAAM,SAAS,IAAI,QAAQ;;;;qBAItB,KAAK;;AAEV,cAAS,OAAO,kBAAkB;AAClC,SAAI,OAAO,eAAe,WAAW;MACnC,MAAM,OAAO,KAAK,MAAM,KAAK,UAAU,OAAO,CAAC;AAE/C,WAAK,aAAa,cAAc;AAChC,eAAS;KACV;IACF;GACF,WAAU,KAAK,QAAQ,WAAW,CAAC,WAAW,iBAAiB,EAAE;AAChE,2BAAuB;GACxB,WAAU,wBAAwB,GAAG,aAAa,KAAK,EAAE;AACxD,oBAAgB,KAAK;AACrB,2BAAuB;GACxB;EACF;AAED,aAAW,EAAE,YAAY,cAAc,MAAO;EAE9C,IAAIC;AAEJ,MAAI,OAAO,OAAO;AAChB,IAAC,CAAE,MAAO,GAAG;EACd,OAAM;AACL,QAAK,eAAe;AAClB,UAAM,IAAI,OACP,YAAY,OAAO,QAAQ,OAAQ,CAAC;GAExC;AAED,WAAQ,4BAA4B,cAAc;EACnD;AAED,SAAO;GACL,OAAO,wCAAwC,KAAK;GACpD,GAAG;GACH,QAAQ,iCAAiC,OAAO,SAAS,KAAK;GAC9D;GACA,UAAU,gBAAgB,SAAS,CAAE,IAAG;EACzC;CACF,EAAC,CACH,CACJ;AACF","names":["node: Node","views: readonly RouteMeta[]","config: ViewConfig | undefined","componentName: string | undefined","title: string"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/createViewConfigJson.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { Script } from 'node:vm';\nimport ts, { type Node } from 'typescript';\nimport { convertComponentNameToTitle } from '../shared/convertComponentNameToTitle.js';\nimport type { ServerViewConfig } from '../shared/internal.js';\nimport { transformTree } from '../shared/transformTree.js';\nimport type { ViewConfig } from '../types.js';\nimport type { RouteMeta } from './collectRoutesFromFS.js';\nimport { convertFSRouteSegmentToURLPatternFormat, extractParameterFromRouteSegment } from './utils.js';\n\n/**\n * Walks the TypeScript AST using the deep-first search algorithm.\n *\n * @param node - The node to walk.\n */\nfunction* walkAST(node: Node): Generator<Node> {\n yield node;\n\n for (const child of node.getChildren()) {\n yield* walkAST(child);\n }\n}\n\n/**\n * Creates a map of all leaf routes to their configuration. This file is used by the server to provide server-side\n * routes along with managing the client-side routes.\n *\n * @param views - The route metadata tree.\n * @returns A view configuration tree.\n */\nexport default async function createViewConfigJson(views: readonly RouteMeta[]): Promise<readonly ServerViewConfig[]> {\n return await transformTree<readonly RouteMeta[], Promise<readonly ServerViewConfig[]>>(\n views,\n null,\n async (routes, next) =>\n await Promise.all(\n routes.map(async ({ path, file, layout, children, flowLayout }) => {\n const newChildren = children ? await next(children) : undefined;\n\n if (!file && !layout) {\n return {\n route: convertFSRouteSegmentToURLPatternFormat(path),\n params: extractParameterFromRouteSegment(path),\n children: newChildren,\n } satisfies ServerViewConfig;\n }\n\n const sourceFile = ts.createSourceFile(\n 'f.ts',\n await readFile(file ?? layout!, 'utf8'),\n ts.ScriptTarget.ESNext,\n true,\n );\n let config: ViewConfig | undefined;\n let waitingForIdentifier = false;\n let componentName: string | undefined;\n\n for (const node of walkAST(sourceFile)) {\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === 'config') {\n if (node.initializer && ts.isObjectLiteralExpression(node.initializer)) {\n const code = node.initializer.getText(sourceFile);\n const script = new Script(`\n function key(x) {\n return x[0];\n }\n (${code})\n `);\n config = script.runInThisContext() as ViewConfig;\n if (config.flowLayout === undefined) {\n const copy = JSON.parse(JSON.stringify(config));\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n copy.flowLayout = flowLayout ?? false;\n config = copy;\n }\n }\n } else if (node.getText(sourceFile).startsWith('export default')) {\n waitingForIdentifier = true;\n } else if (waitingForIdentifier && ts.isIdentifier(node)) {\n componentName = node.text;\n waitingForIdentifier = false;\n }\n }\n\n config ??= { flowLayout: flowLayout ?? false };\n\n let title: string;\n\n if (config.title) {\n ({ title } = config);\n } else {\n if (!componentName) {\n throw new Error(\n `The file \"${String(file ?? layout!)}\" must contain a default export of a component whose name will be used as title by default`,\n );\n }\n\n title = convertComponentNameToTitle(componentName);\n }\n\n return {\n route: convertFSRouteSegmentToURLPatternFormat(path),\n ...config,\n params: extractParameterFromRouteSegment(config.route ?? path),\n title,\n children: newChildren ?? (layout ? [] : undefined),\n } satisfies ServerViewConfig;\n }),\n ),\n );\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,OAAO,UAAU,mCAAoC;AAE9D,OAAO,qCAAsC;AAC7C,OAAO,mDAAwE;AAC/E,OAAO,qDAAsD;AAC7D,OAAO,qDAAsD;;;;;;;;;;;AA+B7D,eAAe,oBAAoBA,KAAUC,MAAcC,YAAwC;AACjG,OAAM,MAAM,IAAI,IAAI,MAAM,MAAM,EAAE,WAAW,KAAM,EAAC;CACpD,IAAI,cAAc,cAAc;AAChC,MAAK,YAAY;EACf,IAAIC;AACJ,MAAI;AACF,cAAW,MAAM,SAAS,KAAK,QAAQ;EACxC,SAAQC,GAAY;AACnB,SAAM,KAAK,eAAe,MAAM,YAAY,UAAU,KAAK,EAAE,SAAS,WAAW;AAC/E,UAAM;GACP;EACF;AACD,gBAAc,aAAa;CAC5B;AACD,KAAI,aAAa;AACf,QAAM,UAAU,KAAK,MAAM,QAAQ;CACpC;AAED,QAAO;AACR;;;;;;;;;;AAYD,OAAO,eAAe,qBACpBC,UACAC,MACAC,YACAC,QACAC,OACkB;CAClB,IAAIC;AACJ,KAAI;AACF,cAAY,MAAM,oBAAoB,UAAU;GAAE;GAAY;EAAQ,EAAC;CACxE,SAAQN,GAAY;AACnB,MAAI,aAAa,SAAS,UAAU,KAAK,EAAE,SAAS,UAAU;AAC5D,eAAY,CAAE;EACf,OAAM;AACL,SAAM;EACP;CACF;AAED,KAAI,OAAO;AACT,SAAO,KAAK,8BAA8B;CAC3C;AACD,aAAY,MAAM,aAAa,WAAW,KAAK,QAAQ;CACvD,MAAM,iBAAiB,MAAM,qBAAqB,UAAU;CAC5D,MAAM,oBAAoB,qBAAqB,WAAW,gBAAgB,KAAK;CAE/E,MAAM,cAAc,MAAM,oBAAoB,KAAK,MAAM,KAAK,UAAU,gBAAgB,MAAM,EAAE,CAAC;AACjG,KAAI,OAAO;AACT,SAAO,MAAM,oCAAoC,OAAO,KAAK,KAAK,CAAC,EAAE;CACtE;CAID,MAAM,cAAc,MAAM,oBAAoB,KAAK,MAAM,mBAAmB,YAAY;AACxF,KAAI,OAAO;AACT,SAAO,MAAM,kCAAkC,OAAO,KAAK,KAAK,CAAC,EAAE;CACpE;AACD,QAAO;AACR","names":["url: URL","data: string","forceWrite?: boolean","contents: string | undefined","e: unknown","viewsDir: URL","urls: RuntimeFileUrls","extensions: readonly string[]","logger: Logger","debug: boolean","routeMeta: readonly RouteMeta[]"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/generateRuntimeFiles.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport type { Logger } from 'vite';\nimport applyLayouts from './applyLayouts.js';\nimport collectRoutesFromFS, { type RouteMeta } from './collectRoutesFromFS.js';\nimport createRoutesFromMeta from './createRoutesFromMeta.js';\nimport createViewConfigJson from './createViewConfigJson.js';\n\n/**\n * The URLs of the files to generate.\n */\nexport type RuntimeFileUrls = Readonly<{\n /**\n * The URL of the JSON file with the leaf routes and their metadata. This file\n * will be processed by the server to provide the final route configuration.\n */\n json: URL;\n /**\n * The URL of the module with the routes tree in a framework-agnostic format.\n */\n code: URL;\n /**\n * The URL of the JSON file containing server layout path information.\n */\n layouts: URL;\n}>;\n\n/**\n * Generates a file conditionally. If the file already exists and its content is the same as the\n * given data, the file will not be overwritten. It is useful to avoid unnecessary server\n * reboot during development.\n *\n * @param url - The URL of the file to generate.\n * @param data - The data to write to the file.\n * @param forceWrite - true to force writing the file even if there are no changes\n * @returns true if the file was written, false otherwise.\n */\nasync function generateRuntimeFile(url: URL, data: string, forceWrite?: boolean): Promise<boolean> {\n await mkdir(new URL('./', url), { recursive: true });\n let shouldWrite = forceWrite ?? false;\n if (!forceWrite) {\n let contents: string | undefined;\n try {\n contents = await readFile(url, 'utf-8');\n } catch (e: unknown) {\n if (!(e != null && typeof e === 'object' && 'code' in e && e.code === 'ENOENT')) {\n throw e;\n }\n }\n shouldWrite = contents !== data;\n }\n if (shouldWrite) {\n await writeFile(url, data, 'utf-8');\n }\n\n return shouldWrite;\n}\n\n/**\n * Collects all file-based routes from the given directory, and based on them generates two files\n * described by {@link RuntimeFileUrls} type.\n * @param viewsDir - The directory that contains file-based routes (views).\n * @param urls - The URLs of the files to generate.\n * @param extensions - The list of extensions that will be collected as routes.\n * @param logger - The Vite logger instance.\n * @param debug - true to debug\n */\n// eslint-disable-next-line @typescript-eslint/max-params\nexport async function generateRuntimeFiles(\n viewsDir: URL,\n urls: RuntimeFileUrls,\n extensions: readonly string[],\n logger: Logger,\n debug: boolean,\n): Promise<boolean> {\n let routeMeta: readonly RouteMeta[];\n try {\n routeMeta = await collectRoutesFromFS(viewsDir, { extensions, logger });\n } catch (e: unknown) {\n if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {\n routeMeta = [];\n } else {\n throw e;\n }\n }\n\n if (debug) {\n logger.info('Collected file-based routes');\n }\n routeMeta = await applyLayouts(routeMeta, urls.layouts);\n const viewConfigJson = await createViewConfigJson(routeMeta);\n const runtimeRoutesCode = createRoutesFromMeta(routeMeta, viewConfigJson, urls);\n\n const jsonWritten = await generateRuntimeFile(urls.json, JSON.stringify(viewConfigJson, null, 2));\n if (debug) {\n logger.info(`Frontend route list is generated: ${String(urls.json)}`);\n }\n // If the metadata has changed, we need to write the TS file also to make Vite HMR updates work properly.\n // Even though the contents of the TS file does not change, the contents of the files imported in the TS\n // files changes and the routes must be re-applied to the React router\n const codeWritten = await generateRuntimeFile(urls.code, runtimeRoutesCode, jsonWritten);\n if (debug) {\n logger.info(`File Route module is generated: ${String(urls.code)}`);\n }\n return codeWritten;\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,OAAO,UAAU,mCAAoC;AAE9D,OAAO,qCAAsC;AAC7C,OAAO,mDAAwE;AAC/E,OAAO,qDAAsD;AAC7D,OAAO,qDAAsD;;;;;;;;;;;AA+B7D,eAAe,oBAAoBA,KAAUC,MAAcC,YAAwC;AACjG,OAAM,MAAM,IAAI,IAAI,MAAM,MAAM,EAAE,WAAW,KAAM,EAAC;CACpD,IAAI,cAAc,cAAc;AAChC,MAAK,YAAY;EACf,IAAIC;AACJ,MAAI;AACF,cAAW,MAAM,SAAS,KAAK,QAAQ;EACxC,SAAQC,GAAY;AACnB,SAAM,KAAK,eAAe,MAAM,YAAY,UAAU,KAAK,EAAE,SAAS,WAAW;AAC/E,UAAM;GACP;EACF;AACD,gBAAc,aAAa;CAC5B;AACD,KAAI,aAAa;AACf,QAAM,UAAU,KAAK,MAAM,QAAQ;CACpC;AAED,QAAO;AACR;;;;;;;;;;AAYD,OAAO,eAAe,qBACpBC,UACAC,MACAC,YACAC,QACAC,OACkB;CAClB,IAAIC;AACJ,KAAI;AACF,cAAY,MAAM,oBAAoB,UAAU;GAAE;GAAY;EAAQ,EAAC;CACxE,SAAQN,GAAY;AACnB,MAAI,aAAa,SAAS,UAAU,KAAK,EAAE,SAAS,UAAU;AAC5D,eAAY,CAAE;EACf,OAAM;AACL,SAAM;EACP;CACF;AAED,KAAI,OAAO;AACT,SAAO,KAAK,8BAA8B;CAC3C;AACD,aAAY,MAAM,aAAa,WAAW,KAAK,QAAQ;CACvD,MAAM,iBAAiB,MAAM,qBAAqB,UAAU;CAC5D,MAAM,oBAAoB,qBAAqB,WAAW,gBAAgB,KAAK;CAE/E,MAAM,cAAc,MAAM,oBAAoB,KAAK,MAAM,KAAK,UAAU,gBAAgB,MAAM,EAAE,CAAC;AACjG,KAAI,OAAO;AACT,SAAO,MAAM,oCAAoC,OAAO,KAAK,KAAK,CAAC,EAAE;CACtE;CAID,MAAM,cAAc,MAAM,oBAAoB,KAAK,MAAM,mBAAmB,YAAY;AACxF,KAAI,OAAO;AACT,SAAO,MAAM,kCAAkC,OAAO,KAAK,KAAK,CAAC,EAAE;CACpE;AACD,QAAO;AACR","names":["url: URL","data: string","forceWrite?: boolean","contents: string | undefined","e: unknown","viewsDir: URL","urls: RuntimeFileUrls","extensions: readonly string[]","logger: Logger","debug: boolean","routeMeta: readonly RouteMeta[]"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/generateRuntimeFiles.ts"],"sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport type { Logger } from 'vite';\nimport applyLayouts from './applyLayouts.js';\nimport collectRoutesFromFS, { type RouteMeta } from './collectRoutesFromFS.js';\nimport createRoutesFromMeta from './createRoutesFromMeta.js';\nimport createViewConfigJson from './createViewConfigJson.js';\n\n/**\n * The URLs of the files to generate.\n */\nexport type RuntimeFileUrls = Readonly<{\n /**\n * The URL of the JSON file with the leaf routes and their metadata. This file\n * will be processed by the server to provide the final route configuration.\n */\n json: URL;\n /**\n * The URL of the module with the routes tree in a framework-agnostic format.\n */\n code: URL;\n /**\n * The URL of the JSON file containing server layout path information.\n */\n layouts: URL;\n}>;\n\n/**\n * Generates a file conditionally. If the file already exists and its content is the same as the\n * given data, the file will not be overwritten. It is useful to avoid unnecessary server\n * reboot during development.\n *\n * @param url - The URL of the file to generate.\n * @param data - The data to write to the file.\n * @param forceWrite - true to force writing the file even if there are no changes\n * @returns true if the file was written, false otherwise.\n */\nasync function generateRuntimeFile(url: URL, data: string, forceWrite?: boolean): Promise<boolean> {\n await mkdir(new URL('./', url), { recursive: true });\n let shouldWrite = forceWrite ?? false;\n if (!forceWrite) {\n let contents: string | undefined;\n try {\n contents = await readFile(url, 'utf-8');\n } catch (e: unknown) {\n if (!(e != null && typeof e === 'object' && 'code' in e && e.code === 'ENOENT')) {\n throw e;\n }\n }\n shouldWrite = contents !== data;\n }\n if (shouldWrite) {\n await writeFile(url, data, 'utf-8');\n }\n\n return shouldWrite;\n}\n\n/**\n * Collects all file-based routes from the given directory, and based on them generates two files\n * described by {@link RuntimeFileUrls} type.\n * @param viewsDir - The directory that contains file-based routes (views).\n * @param urls - The URLs of the files to generate.\n * @param extensions - The list of extensions that will be collected as routes.\n * @param logger - The Vite logger instance.\n * @param debug - true to debug\n */\n// eslint-disable-next-line @typescript-eslint/max-params\nexport async function generateRuntimeFiles(\n viewsDir: URL,\n urls: RuntimeFileUrls,\n extensions: readonly string[],\n logger: Logger,\n debug: boolean,\n): Promise<boolean> {\n let routeMeta: readonly RouteMeta[];\n try {\n routeMeta = await collectRoutesFromFS(viewsDir, { extensions, logger });\n } catch (e: unknown) {\n if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {\n routeMeta = [];\n } else {\n throw e;\n }\n }\n\n if (debug) {\n logger.info('Collected file-based routes');\n }\n routeMeta = await applyLayouts(routeMeta, urls.layouts);\n const viewConfigJson = await createViewConfigJson(routeMeta);\n const runtimeRoutesCode = createRoutesFromMeta(routeMeta, viewConfigJson, urls);\n\n const jsonWritten = await generateRuntimeFile(urls.json, JSON.stringify(viewConfigJson, null, 2));\n if (debug) {\n logger.info(`Frontend route list is generated: ${String(urls.json)}`);\n }\n // If the metadata has changed, we need to write the TS file also to make Vite HMR updates work properly.\n // Even though the contents of the TS file does not change, the contents of the files imported in the TS\n // files changes and the routes must be re-applied to the React router\n const codeWritten = await generateRuntimeFile(urls.code, runtimeRoutesCode, jsonWritten);\n if (debug) {\n logger.info(`File Route module is generated: ${String(urls.code)}`);\n }\n return codeWritten;\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"AAAA,SAAS,mDAAoD;AAE7D,OAAO,MAAMA,oBAAyD,IAAI,IAAI;CAC5E,CAAC,eAAe,UAAU,kBAAmB;CAC7C,CAAC,eAAe,UAAU,gBAAiB;CAC3C,CAAC,eAAe,UAAU,YAAa;AACxC;AAGD,SAAS,YAAYC,MAA8B;AAEjD,SAAQ,MAAR;EACE,KAAK,eAAe,SAClB,QAAO;EACT,KAAK,eAAe,SAClB,QAAO;EACT,KAAK,eAAe,SAClB,QAAO;CACV;AACF;;;;;;;;;;;;;;AAeD,OAAO,SAAS,wCAAwCC,SAAyB;CAC/E,IAAI,MAAM;AAEV,mBAAkB,QAAQ,CAAC,SAAS,SAAS;AAC3C,QAAM,IAAI,WAAW,SAAS,YAAY,KAAK,CAAC;CACjD,EAAC;AAEF,QAAO;AACR;;;;;;;AAQD,OAAO,SAAS,iCAAiCA,SAA2D;CAC1G,IAAI,WAAW;CACf,MAAMC,SAAyC,CAAE;AAEjD,MAAK,MAAM,CAAC,MAAM,QAAQ,IAAI,mBAAmB;EAC/C,MAAM,WAAW,IAAI,OAAO,QAAQ,QAAQ,QAAQ;AACpD,aAAW,SAAS,WAAW,UAAU,CAAC,UAAU;GAClD,MAAM,MAAM,MAAM,WAAW,SAAS,YAAY,KAAK,CAAC;AACxD,UAAO,OAAO;AACd,UAAO;EACR,EAAC;CACH;AAED,QAAO;AACR;;;;;AAMD,OAAO,SAAS,QAAQC,MAAsB;CAC5C,IAAI,MAAM;AAEV,MAAK,MAAM,WAAW,kBAAkB,QAAQ,EAAE;AAChD,QAAM,IAAI,WAAW,SAAS,KAAK;CACpC;AAED,QAAO;AACR;AAED,OAAO,SAAS,MAAMA,MAAsB;AAC1C,QAAO,KAAK,QAAQ,iBAAiB,KAAK;AAC3C","names":["routeParamTypeMap: ReadonlyMap<RouteParamType, RegExp>","type: RouteParamType","segment: string","params: Record<string, RouteParamType>","path: string"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin/utils.ts"],"sourcesContent":["import { RouteParamType } from '../shared/routeParamType.js';\n\nexport const routeParamTypeMap: ReadonlyMap<RouteParamType, RegExp> = new Map([\n [RouteParamType.Wildcard, /\\{\\.\\.\\.(.+)\\}/gu], // e.g. \"{...wildcard}\"\n [RouteParamType.Optional, /\\{\\{(.+)\\}\\}/gu], // e.g. \"{{param}}\"\n [RouteParamType.Required, /\\{(.+)\\}/gu], // e.g. \"{param}\"\n]);\n\n// eslint-disable-next-line @typescript-eslint/consistent-return\nfunction getReplacer(type: RouteParamType): string {\n // eslint-disable-next-line default-case\n switch (type) {\n case RouteParamType.Wildcard:\n return '*';\n case RouteParamType.Optional:\n return ':$1?';\n case RouteParamType.Required:\n return ':$1';\n }\n}\n\n/**\n * Converts a file system pattern to an URL pattern string.\n *\n * @param segment - a string representing a file system pattern:\n * - `{param}` - for a required single parameter;\n * - `{{param}}` - for an optional single parameter;\n * - `{...wildcard}` - for multiple parameters, including none.\n *\n * @returns a string representing a URL pattern, respectively:\n * - `:param`;\n * - `:param?`;\n * - `*`.\n */\nexport function convertFSRouteSegmentToURLPatternFormat(segment: string): string {\n let res = segment;\n\n routeParamTypeMap.forEach((pattern, type) => {\n res = res.replaceAll(pattern, getReplacer(type));\n });\n\n return res;\n}\n\n/**\n * Extracts the parameter name and its type from the route segment.\n *\n * @param segment - A part of the FS route URL.\n * @returns A map of parameter names and their types.\n */\nexport function extractParameterFromRouteSegment(segment: string): Readonly<Record<string, RouteParamType>> {\n let _segment = segment;\n const params: Record<string, RouteParamType> = {};\n\n for (const [type, pattern] of routeParamTypeMap) {\n const _pattern = new RegExp(pattern.source, pattern.flags);\n _segment = _segment.replaceAll(_pattern, (match) => {\n const key = match.replaceAll(pattern, getReplacer(type));\n params[key] = type;\n return '';\n });\n }\n\n return params;\n}\n\n/**\n * A small helper function that clears route path of the control characters in\n * order to sort the routes alphabetically.\n */\nexport function cleanUp(path: string): string {\n let res = path;\n\n for (const pattern of routeParamTypeMap.values()) {\n res = res.replaceAll(pattern, '$1');\n }\n\n return res;\n}\n\nexport function strip(path: string): string {\n return path.replace(/^\\/*(.+)\\/*$/u, '$1');\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,mDAAoD;AAE7D,OAAO,MAAMA,oBAAyD,IAAI,IAAI;CAC5E,CAAC,eAAe,UAAU,kBAAmB;CAC7C,CAAC,eAAe,UAAU,gBAAiB;CAC3C,CAAC,eAAe,UAAU,YAAa;AACxC;AAGD,SAAS,YAAYC,MAA8B;AAEjD,SAAQ,MAAR;EACE,KAAK,eAAe,SAClB,QAAO;EACT,KAAK,eAAe,SAClB,QAAO;EACT,KAAK,eAAe,SAClB,QAAO;CACV;AACF;;;;;;;;;;;;;;AAeD,OAAO,SAAS,wCAAwCC,SAAyB;CAC/E,IAAI,MAAM;AAEV,mBAAkB,QAAQ,CAAC,SAAS,SAAS;AAC3C,QAAM,IAAI,WAAW,SAAS,YAAY,KAAK,CAAC;CACjD,EAAC;AAEF,QAAO;AACR;;;;;;;AAQD,OAAO,SAAS,iCAAiCA,SAA2D;CAC1G,IAAI,WAAW;CACf,MAAMC,SAAyC,CAAE;AAEjD,MAAK,MAAM,CAAC,MAAM,QAAQ,IAAI,mBAAmB;EAC/C,MAAM,WAAW,IAAI,OAAO,QAAQ,QAAQ,QAAQ;AACpD,aAAW,SAAS,WAAW,UAAU,CAAC,UAAU;GAClD,MAAM,MAAM,MAAM,WAAW,SAAS,YAAY,KAAK,CAAC;AACxD,UAAO,OAAO;AACd,UAAO;EACR,EAAC;CACH;AAED,QAAO;AACR;;;;;AAMD,OAAO,SAAS,QAAQC,MAAsB;CAC5C,IAAI,MAAM;AAEV,MAAK,MAAM,WAAW,kBAAkB,QAAQ,EAAE;AAChD,QAAM,IAAI,WAAW,SAAS,KAAK;CACpC;AAED,QAAO;AACR;AAED,OAAO,SAAS,MAAMA,MAAsB;AAC1C,QAAO,KAAK,QAAQ,iBAAiB,KAAK;AAC3C","names":["routeParamTypeMap: ReadonlyMap<RouteParamType, RegExp>","type: RouteParamType","segment: string","params: Record<string, RouteParamType>","path: string"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin/utils.ts"],"sourcesContent":["import { RouteParamType } from '../shared/routeParamType.js';\n\nexport const routeParamTypeMap: ReadonlyMap<RouteParamType, RegExp> = new Map([\n [RouteParamType.Wildcard, /\\{\\.\\.\\.(.+)\\}/gu], // e.g. \"{...wildcard}\"\n [RouteParamType.Optional, /\\{\\{(.+)\\}\\}/gu], // e.g. \"{{param}}\"\n [RouteParamType.Required, /\\{(.+)\\}/gu], // e.g. \"{param}\"\n]);\n\n// eslint-disable-next-line @typescript-eslint/consistent-return\nfunction getReplacer(type: RouteParamType): string {\n // eslint-disable-next-line default-case\n switch (type) {\n case RouteParamType.Wildcard:\n return '*';\n case RouteParamType.Optional:\n return ':$1?';\n case RouteParamType.Required:\n return ':$1';\n }\n}\n\n/**\n * Converts a file system pattern to an URL pattern string.\n *\n * @param segment - a string representing a file system pattern:\n * - `{param}` - for a required single parameter;\n * - `{{param}}` - for an optional single parameter;\n * - `{...wildcard}` - for multiple parameters, including none.\n *\n * @returns a string representing a URL pattern, respectively:\n * - `:param`;\n * - `:param?`;\n * - `*`.\n */\nexport function convertFSRouteSegmentToURLPatternFormat(segment: string): string {\n let res = segment;\n\n routeParamTypeMap.forEach((pattern, type) => {\n res = res.replaceAll(pattern, getReplacer(type));\n });\n\n return res;\n}\n\n/**\n * Extracts the parameter name and its type from the route segment.\n *\n * @param segment - A part of the FS route URL.\n * @returns A map of parameter names and their types.\n */\nexport function extractParameterFromRouteSegment(segment: string): Readonly<Record<string, RouteParamType>> {\n let _segment = segment;\n const params: Record<string, RouteParamType> = {};\n\n for (const [type, pattern] of routeParamTypeMap) {\n const _pattern = new RegExp(pattern.source, pattern.flags);\n _segment = _segment.replaceAll(_pattern, (match) => {\n const key = match.replaceAll(pattern, getReplacer(type));\n params[key] = type;\n return '';\n });\n }\n\n return params;\n}\n\n/**\n * A small helper function that clears route path of the control characters in\n * order to sort the routes alphabetically.\n */\nexport function cleanUp(path: string): string {\n let res = path;\n\n for (const pattern of routeParamTypeMap.values()) {\n res = res.replaceAll(pattern, '$1');\n }\n\n return res;\n}\n\nexport function strip(path: string): string {\n return path.replace(/^\\/*(.+)\\/*$/u, '$1');\n}\n"],"version":3}
@@ -1 +1 @@
1
- {"mappings":"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","names":["_viewsDir: URL","_outDir: URL","_logger: Logger","runtimeUrls: RuntimeFileUrls","_generateRuntimeFiles: () => Promise<boolean>","_viewsDirPosix: string","e: unknown"],"sources":["/opt/agent/work/1af72d8adc613024/hilla/packages/ts/file-router/src/vite-plugin.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport type { TransformResult } from 'rollup';\nimport type { EnvironmentModuleNode, HotUpdateOptions, Logger, Plugin } from 'vite';\nimport { generateRuntimeFiles, type RuntimeFileUrls } from './vite-plugin/generateRuntimeFiles.js';\n\nconst INJECTION =\n \"if (Object.keys(nextExports).length === 2 && 'default' in nextExports && 'config' in nextExports) {nextExports = { ...nextExports, config: currentExports.config };}\";\n\n/**\n * The options for the Vite file-based router plugin.\n */\nexport type PluginOptions = Readonly<{\n /**\n * The base directory for the router. The folders and files in this directory\n * will be used as route paths.\n *\n * @defaultValue `frontend/views`\n */\n viewsDir?: URL | string;\n /**\n * The directory where the generated view file will be stored.\n *\n * @defaultValue `frontend/generated`\n */\n generatedDir?: URL | string;\n /**\n * The list of extensions that will be collected as routes of the file-based\n * router.\n *\n * @defaultValue `['.tsx', '.jsx']`\n */\n extensions?: readonly string[];\n /**\n * The flag to indicate whether the plugin is running in development mode.\n *\n * @defaultValue `false`\n */\n isDevMode?: boolean;\n /**\n * The flag to indicate whether to output debug information\n *\n * @defaultValue `false`\n */\n debug?: boolean;\n}>;\n\n/**\n * A Vite plugin that generates a router from the files in the specific directory.\n *\n * @param options - The plugin options.\n * @returns A Vite plugin.\n */\nexport default function vitePluginFileSystemRouter({\n viewsDir = 'frontend/views/',\n generatedDir = 'frontend/generated/',\n extensions = ['.tsx', '.jsx'],\n isDevMode = false,\n debug = false,\n}: PluginOptions = {}): Plugin {\n let _viewsDir: URL;\n let _outDir: URL;\n let _logger: Logger;\n let runtimeUrls: RuntimeFileUrls;\n let _generateRuntimeFiles: () => Promise<boolean>;\n let _viewsDirPosix: string;\n\n return {\n name: 'vite-plugin-file-router',\n enforce: 'pre',\n configResolved({ logger, root, build: { outDir } }) {\n const _root = pathToFileURL(root);\n const _generatedDir = new URL(generatedDir, _root);\n\n _viewsDir = new URL(viewsDir, _root);\n _viewsDirPosix = fileURLToPath(_viewsDir).replaceAll('\\\\', '/');\n _outDir = pathToFileURL(outDir);\n _logger = logger;\n\n if (debug) {\n _logger.info(`The directory of route files: ${String(_viewsDir)}`);\n _logger.info(`The directory of generated files: ${String(_generatedDir)}`);\n _logger.info(`The output directory: ${String(_outDir)}`);\n }\n runtimeUrls = {\n json: new URL('file-routes.json', isDevMode ? _generatedDir : _outDir),\n code: new URL('file-routes.ts', _generatedDir),\n layouts: new URL('layouts.json', _generatedDir),\n };\n _generateRuntimeFiles = async (): Promise<boolean> => {\n try {\n return await generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger, debug);\n } catch (e: unknown) {\n _logger.error(String(e));\n return true;\n }\n };\n },\n async buildStart() {\n await _generateRuntimeFiles();\n },\n async hotUpdate({ file, modules }: HotUpdateOptions): Promise<void | EnvironmentModuleNode[]> {\n const fileUrlString = String(pathToFileURL(file));\n\n if (fileUrlString === String(runtimeUrls.json)) {\n // Reload file routes JSON with a custom HMR event.\n this.environment.hot.send({ type: 'custom', event: 'fs-route-update' });\n return [];\n }\n\n if (fileUrlString === String(runtimeUrls.code)) {\n // Skip HMR for file routes from Vite builtin file change listener,\n // as we have our own HMR handling below.\n return [];\n }\n\n if (!file.startsWith(_viewsDirPosix)) {\n // Outside views folder, only changes to layouts file should trigger\n // files generation.\n if (fileUrlString !== String(runtimeUrls.layouts)) {\n return;\n }\n }\n\n // Check and update file routes if needed.\n if (await _generateRuntimeFiles()) {\n // The \"file-routes.ts\" file was changed at this point, so it should\n // be considered within the HMR update that caused the routes update.\n\n const mg = this.environment.moduleGraph;\n const fileRoutesModules = mg.getModulesByFile(fileURLToPath(runtimeUrls.code).replaceAll('\\\\', '/'))!;\n\n // Make eager update for file routes in Vite module graph\n // for consistency with the generated file contents.\n await Promise.all(\n Array.from(fileRoutesModules, async (fileRouteModule) => {\n mg.invalidateModule(fileRouteModule);\n await this.environment.fetchModule(fileRouteModule.id!, undefined, { cached: false });\n }),\n );\n\n const neverImported = modules.every((module) => module.importers.size === 0);\n if (neverImported) {\n // The current file is a not imported anywhere, however it caused\n // \"file-routes.ts\" update: possibly a route for this file\n // was removed, or we're processing \"layouts.json\".\n\n // Default Vite HMR behavior for not imported modules is a full page\n // reload. However, in this case, we could avoid it and only do HMR\n // for the file routes instead.\n return [...fileRoutesModules];\n }\n\n // Add \"file-routes.ts\" to current HMR module update list to reload\n // both at the same time.\n return [...fileRoutesModules, ...modules];\n }\n\n return undefined;\n },\n transform(code, id): Promise<TransformResult> | TransformResult {\n let modifiedCode = code;\n if (id.startsWith(_viewsDirPosix) && !basename(id).startsWith('_')) {\n if (isDevMode) {\n // To enable HMR for route files with exported configurations, we need\n // to address a limitation in `react-refresh`. This library requires\n // strict equality (`===`) for non-component exports. However, the\n // dynamic nature of HMR makes maintaining this equality between object\n // literals challenging.\n //\n // To work around this, we implement a strategy that preserves the\n // reference to the original configuration object (`currentExports.config`),\n // replacing any newly created configuration objects (`nextExports.config`)\n // with it. This ensures that the HMR mechanism perceives the\n // configuration as unchanged.\n const injectionPattern = /import\\.meta\\.hot\\.accept[\\s\\S]+if\\s\\(!nextExports\\)\\s+return;/gu;\n if (injectionPattern.test(modifiedCode)) {\n modifiedCode = `${modifiedCode.substring(0, injectionPattern.lastIndex)}${INJECTION}${modifiedCode.substring(\n injectionPattern.lastIndex,\n )}`;\n }\n } else {\n // In production mode, the function name is assigned as name to the function itself to avoid minification\n const functionNames = /export\\s+default\\s+(?:function\\s+)?(\\w+)/u.exec(modifiedCode);\n\n if (functionNames?.length) {\n const [, functionName] = functionNames;\n modifiedCode += `Object.defineProperty(${functionName}, 'name', { value: '${functionName}' });\\n`;\n }\n }\n\n return {\n code: modifiedCode,\n };\n }\n\n return undefined;\n },\n };\n}\n"],"version":3}
1
+ {"mappings":"AAAA,SAAS,2BAA4B;AACrC,SAAS,eAAe,+BAAgC;AAGxD,SAAS,mEAA0F;AAEnG,MAAM,YACJ;;;;;;;AA8CF,eAAe,SAAS,2BAA2B,EACjD,WAAW,mBACX,eAAe,uBACf,aAAa,CAAC,QAAQ,MAAO,GAC7B,YAAY,OACZ,QAAQ,OACM,GAAG,CAAE,GAAU;CAC7B,IAAIA;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;CACJ,IAAIC;AAEJ,QAAO;EACL,MAAM;EACN,SAAS;EACT,eAAe,EAAE,QAAQ,MAAM,OAAO,EAAE,QAAQ,EAAE,EAAE;GAClD,MAAM,QAAQ,cAAc,KAAK;GACjC,MAAM,gBAAgB,IAAI,IAAI,cAAc;AAE5C,eAAY,IAAI,IAAI,UAAU;AAC9B,oBAAiB,cAAc,UAAU,CAAC,WAAW,MAAM,IAAI;AAC/D,aAAU,cAAc,OAAO;AAC/B,aAAU;AAEV,OAAI,OAAO;AACT,YAAQ,MAAM,gCAAgC,OAAO,UAAU,CAAC,EAAE;AAClE,YAAQ,MAAM,oCAAoC,OAAO,cAAc,CAAC,EAAE;AAC1E,YAAQ,MAAM,wBAAwB,OAAO,QAAQ,CAAC,EAAE;GACzD;AACD,iBAAc;IACZ,MAAM,IAAI,IAAI,oBAAoB,YAAY,gBAAgB;IAC9D,MAAM,IAAI,IAAI,kBAAkB;IAChC,SAAS,IAAI,IAAI,gBAAgB;GAClC;AACD,2BAAwB,YAA8B;AACpD,QAAI;AACF,YAAO,MAAM,qBAAqB,WAAW,aAAa,YAAY,SAAS,MAAM;IACtF,SAAQC,GAAY;AACnB,aAAQ,MAAM,OAAO,EAAE,CAAC;AACxB,YAAO;IACR;GACF;EACF;EACD,MAAM,aAAa;AACjB,SAAM,uBAAuB;EAC9B;EACD,MAAM,UAAU,EAAE,MAAM,SAA2B,EAA2C;GAC5F,MAAM,gBAAgB,OAAO,cAAc,KAAK,CAAC;AAEjD,OAAI,kBAAkB,OAAO,YAAY,KAAK,EAAE;AAE9C,SAAK,YAAY,IAAI,KAAK;KAAE,MAAM;KAAU,OAAO;IAAmB,EAAC;AACvE,WAAO,CAAE;GACV;AAED,OAAI,kBAAkB,OAAO,YAAY,KAAK,EAAE;AAG9C,WAAO,CAAE;GACV;AAED,QAAK,KAAK,WAAW,eAAe,EAAE;AAGpC,QAAI,kBAAkB,OAAO,YAAY,QAAQ,EAAE;AACjD;IACD;GACF;AAGD,OAAI,MAAM,uBAAuB,EAAE;IAIjC,MAAM,KAAK,KAAK,YAAY;IAC5B,MAAM,oBAAoB,GAAG,iBAAiB,cAAc,YAAY,KAAK,CAAC,WAAW,MAAM,IAAI,CAAC;AAIpG,UAAM,QAAQ,IACZ,MAAM,KAAK,mBAAmB,OAAO,oBAAoB;AACvD,QAAG,iBAAiB,gBAAgB;AACpC,WAAM,KAAK,YAAY,YAAY,gBAAgB,IAAK,WAAW,EAAE,QAAQ,MAAO,EAAC;IACtF,EAAC,CACH;IAED,MAAM,gBAAgB,QAAQ,MAAM,CAAC,WAAW,OAAO,UAAU,SAAS,EAAE;AAC5E,QAAI,eAAe;AAQjB,YAAO,CAAC,GAAG,iBAAkB;IAC9B;AAID,WAAO,CAAC,GAAG,mBAAmB,GAAG,OAAQ;GAC1C;AAED,UAAO;EACR;EACD,UAAU,MAAM,IAAgD;GAC9D,IAAI,eAAe;AACnB,OAAI,GAAG,WAAW,eAAe,KAAK,SAAS,GAAG,CAAC,WAAW,IAAI,EAAE;AAClE,QAAI,WAAW;KAYb,MAAM,mBAAmB;AACzB,SAAI,iBAAiB,KAAK,aAAa,EAAE;AACvC,sBAAgB,EAAE,aAAa,UAAU,GAAG,iBAAiB,UAAU,CAAC,EAAE,UAAU,EAAE,aAAa,UACjG,iBAAiB,UAClB,CAAC;KACH;IACF,OAAM;KAEL,MAAM,gBAAgB,4CAA4C,KAAK,aAAa;AAEpF,SAAI,eAAe,QAAQ;MACzB,MAAM,GAAG,aAAa,GAAG;AACzB,uBAAiB,wBAAwB,aAAa,sBAAsB,aAAa;KAC1F;IACF;AAED,WAAO,EACL,MAAM,aACP;GACF;AAED,UAAO;EACR;CACF;AACF","names":["_viewsDir: URL","_outDir: URL","_logger: Logger","runtimeUrls: RuntimeFileUrls","_generateRuntimeFiles: () => Promise<boolean>","_viewsDirPosix: string","e: unknown"],"sources":["/opt/agent/work/649c11185a3798db/packages/ts/file-router/src/vite-plugin.ts"],"sourcesContent":["import { basename } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport type { TransformResult } from 'rollup';\nimport type { EnvironmentModuleNode, HotUpdateOptions, Logger, Plugin } from 'vite';\nimport { generateRuntimeFiles, type RuntimeFileUrls } from './vite-plugin/generateRuntimeFiles.js';\n\nconst INJECTION =\n \"if (Object.keys(nextExports).length === 2 && 'default' in nextExports && 'config' in nextExports) {nextExports = { ...nextExports, config: currentExports.config };}\";\n\n/**\n * The options for the Vite file-based router plugin.\n */\nexport type PluginOptions = Readonly<{\n /**\n * The base directory for the router. The folders and files in this directory\n * will be used as route paths.\n *\n * @defaultValue `frontend/views`\n */\n viewsDir?: URL | string;\n /**\n * The directory where the generated view file will be stored.\n *\n * @defaultValue `frontend/generated`\n */\n generatedDir?: URL | string;\n /**\n * The list of extensions that will be collected as routes of the file-based\n * router.\n *\n * @defaultValue `['.tsx', '.jsx']`\n */\n extensions?: readonly string[];\n /**\n * The flag to indicate whether the plugin is running in development mode.\n *\n * @defaultValue `false`\n */\n isDevMode?: boolean;\n /**\n * The flag to indicate whether to output debug information\n *\n * @defaultValue `false`\n */\n debug?: boolean;\n}>;\n\n/**\n * A Vite plugin that generates a router from the files in the specific directory.\n *\n * @param options - The plugin options.\n * @returns A Vite plugin.\n */\nexport default function vitePluginFileSystemRouter({\n viewsDir = 'frontend/views/',\n generatedDir = 'frontend/generated/',\n extensions = ['.tsx', '.jsx'],\n isDevMode = false,\n debug = false,\n}: PluginOptions = {}): Plugin {\n let _viewsDir: URL;\n let _outDir: URL;\n let _logger: Logger;\n let runtimeUrls: RuntimeFileUrls;\n let _generateRuntimeFiles: () => Promise<boolean>;\n let _viewsDirPosix: string;\n\n return {\n name: 'vite-plugin-file-router',\n enforce: 'pre',\n configResolved({ logger, root, build: { outDir } }) {\n const _root = pathToFileURL(root);\n const _generatedDir = new URL(generatedDir, _root);\n\n _viewsDir = new URL(viewsDir, _root);\n _viewsDirPosix = fileURLToPath(_viewsDir).replaceAll('\\\\', '/');\n _outDir = pathToFileURL(outDir);\n _logger = logger;\n\n if (debug) {\n _logger.info(`The directory of route files: ${String(_viewsDir)}`);\n _logger.info(`The directory of generated files: ${String(_generatedDir)}`);\n _logger.info(`The output directory: ${String(_outDir)}`);\n }\n runtimeUrls = {\n json: new URL('file-routes.json', isDevMode ? _generatedDir : _outDir),\n code: new URL('file-routes.ts', _generatedDir),\n layouts: new URL('layouts.json', _generatedDir),\n };\n _generateRuntimeFiles = async (): Promise<boolean> => {\n try {\n return await generateRuntimeFiles(_viewsDir, runtimeUrls, extensions, _logger, debug);\n } catch (e: unknown) {\n _logger.error(String(e));\n return true;\n }\n };\n },\n async buildStart() {\n await _generateRuntimeFiles();\n },\n async hotUpdate({ file, modules }: HotUpdateOptions): Promise<void | EnvironmentModuleNode[]> {\n const fileUrlString = String(pathToFileURL(file));\n\n if (fileUrlString === String(runtimeUrls.json)) {\n // Reload file routes JSON with a custom HMR event.\n this.environment.hot.send({ type: 'custom', event: 'fs-route-update' });\n return [];\n }\n\n if (fileUrlString === String(runtimeUrls.code)) {\n // Skip HMR for file routes from Vite builtin file change listener,\n // as we have our own HMR handling below.\n return [];\n }\n\n if (!file.startsWith(_viewsDirPosix)) {\n // Outside views folder, only changes to layouts file should trigger\n // files generation.\n if (fileUrlString !== String(runtimeUrls.layouts)) {\n return;\n }\n }\n\n // Check and update file routes if needed.\n if (await _generateRuntimeFiles()) {\n // The \"file-routes.ts\" file was changed at this point, so it should\n // be considered within the HMR update that caused the routes update.\n\n const mg = this.environment.moduleGraph;\n const fileRoutesModules = mg.getModulesByFile(fileURLToPath(runtimeUrls.code).replaceAll('\\\\', '/'))!;\n\n // Make eager update for file routes in Vite module graph\n // for consistency with the generated file contents.\n await Promise.all(\n Array.from(fileRoutesModules, async (fileRouteModule) => {\n mg.invalidateModule(fileRouteModule);\n await this.environment.fetchModule(fileRouteModule.id!, undefined, { cached: false });\n }),\n );\n\n const neverImported = modules.every((module) => module.importers.size === 0);\n if (neverImported) {\n // The current file is a not imported anywhere, however it caused\n // \"file-routes.ts\" update: possibly a route for this file\n // was removed, or we're processing \"layouts.json\".\n\n // Default Vite HMR behavior for not imported modules is a full page\n // reload. However, in this case, we could avoid it and only do HMR\n // for the file routes instead.\n return [...fileRoutesModules];\n }\n\n // Add \"file-routes.ts\" to current HMR module update list to reload\n // both at the same time.\n return [...fileRoutesModules, ...modules];\n }\n\n return undefined;\n },\n transform(code, id): Promise<TransformResult> | TransformResult {\n let modifiedCode = code;\n if (id.startsWith(_viewsDirPosix) && !basename(id).startsWith('_')) {\n if (isDevMode) {\n // To enable HMR for route files with exported configurations, we need\n // to address a limitation in `react-refresh`. This library requires\n // strict equality (`===`) for non-component exports. However, the\n // dynamic nature of HMR makes maintaining this equality between object\n // literals challenging.\n //\n // To work around this, we implement a strategy that preserves the\n // reference to the original configuration object (`currentExports.config`),\n // replacing any newly created configuration objects (`nextExports.config`)\n // with it. This ensures that the HMR mechanism perceives the\n // configuration as unchanged.\n const injectionPattern = /import\\.meta\\.hot\\.accept[\\s\\S]+if\\s\\(!nextExports\\)\\s+return;/gu;\n if (injectionPattern.test(modifiedCode)) {\n modifiedCode = `${modifiedCode.substring(0, injectionPattern.lastIndex)}${INJECTION}${modifiedCode.substring(\n injectionPattern.lastIndex,\n )}`;\n }\n } else {\n // In production mode, the function name is assigned as name to the function itself to avoid minification\n const functionNames = /export\\s+default\\s+(?:function\\s+)?(\\w+)/u.exec(modifiedCode);\n\n if (functionNames?.length) {\n const [, functionName] = functionNames;\n modifiedCode += `Object.defineProperty(${functionName}, 'name', { value: '${functionName}' });\\n`;\n }\n }\n\n return {\n code: modifiedCode,\n };\n }\n\n return undefined;\n },\n };\n}\n"],"version":3}