Files
jp 0917366cdf Separate JSON API backend (vm_api.py) + React+TanStack frontend scaffold
- vm_api.py: pure FastAPI JSON API on :8098 with CORS
- vm-api.service: systemd unit for API (replaces inline HTML vm_web.py for frontend)
- vm_web.py: kept intact as fallback; Apache now proxies /api/ -> :8098
- frontend/: Vite + React + TanStack Query scaffold
- Apache vhost updated: DocumentRoot -> frontend/dist, /api/ proxy, SPA fallback
- All original HTML pages still functional via :8099 during transition
2026-08-13 17:42:33 +01:00

1 line
14 KiB
Plaintext

{"version":3,"file":"Matches.cjs","names":[],"sources":["../../src/Matches.tsx"],"sourcesContent":["'use client'\n\nimport * as React from 'react'\nimport { useStore } from '@tanstack/react-store'\nimport { rootRouteId } from '@tanstack/router-core'\nimport { isServer } from '@tanstack/router-core/isServer'\nimport { CatchBoundary } from './CatchBoundary'\nimport { useRouter } from './useRouter'\nimport { useStructuralSharing } from './useMatch'\nimport { useLayoutEffect } from './utils'\nimport { Transitioner, settleOwner } from './Transitioner'\nimport { matchContext } from './matchContext'\nimport { Match, renderPending } from './Match'\nimport { SafeFragment } from './SafeFragment'\nimport type {\n StructuralSharingOption,\n ValidateSelected,\n} from './structuralSharing'\nimport type {\n AnyRoute,\n AnyRouter,\n DeepPartial,\n Expand,\n MakeOptionalPathParams,\n MakeOptionalSearchParams,\n MakeRouteMatchUnion,\n MaskOptions,\n MatchRouteOptions,\n RegisteredRouter,\n ResolveRoute,\n ToSubOptionsProps,\n} from '@tanstack/router-core'\n\ndeclare module '@tanstack/router-core' {\n export interface RouteMatchExtensions {\n meta?: Array<React.JSX.IntrinsicElements['meta'] | undefined>\n links?: Array<React.JSX.IntrinsicElements['link'] | undefined>\n scripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n styles?: Array<React.JSX.IntrinsicElements['style'] | undefined>\n headScripts?: Array<React.JSX.IntrinsicElements['script'] | undefined>\n }\n}\n\n/**\n * Internal component that renders the router's active match tree with\n * suspense, error, and not-found boundaries. Rendered by `RouterProvider`.\n */\nexport function Matches() {\n const router = useRouter()\n const rootRoute: AnyRoute = router.routesById[rootRouteId]\n\n const pendingElement = renderPending(router, rootRoute)\n\n // Do not render a root Suspense during SSR or hydrating from SSR\n const ResolvedSuspense =\n (isServer ?? router.isServer) || router.ssr ? SafeFragment : React.Suspense\n\n const inner = (\n <>\n {!(isServer ?? router.isServer) && (\n <Transitioner\n // The initial load publishes matches before MatchesInner's store\n // subscription is active. Storing the router here forces Matches to render\n // that first publication before paint. Later publications store the same\n // router object, so React skips the update.\n // eslint-disable-next-line react-hooks/rules-of-hooks -- server only, condition is static\n t={React.useState<AnyRouter>()[1]}\n />\n )}\n <ResolvedSuspense fallback={pendingElement}>\n <MatchesInner />\n </ResolvedSuspense>\n </>\n )\n\n return router.options.InnerWrap ? (\n <router.options.InnerWrap>{inner}</router.options.InnerWrap>\n ) : (\n inner\n )\n}\n\nfunction MatchesInner() {\n const router = useRouter()\n const acknowledgement = router._rendered!\n const matches =\n (isServer ?? router.isServer)\n ? router.stores.matches.get()\n : // eslint-disable-next-line react-hooks/rules-of-hooks\n useStore(\n router.stores.matches,\n (value) => acknowledgement[0 /* offered */] ?? value,\n )\n const match = matches[0]\n const routeId = match?.routeId\n\n useLayoutEffect(() => {\n if (acknowledgement[0 /* offered */] === matches) {\n settleOwner(acknowledgement, true)\n }\n }, [acknowledgement, matches])\n\n const matchComponent = routeId ? <Match routeId={routeId} /> : null\n\n return (\n <matchContext.Provider value={routeId}>\n {router.options.disableGlobalCatchBoundary ? (\n matchComponent\n ) : (\n <CatchBoundary\n getResetKey={() => match}\n onCatch={\n process.env.NODE_ENV !== 'production'\n ? (error) => {\n console.warn(\n `Warning: The following error wasn't caught by any route! At the very least, consider setting an 'errorComponent' in your RootRoute!`,\n )\n console.warn(`Warning: ${error.message || error.toString()}`)\n }\n : undefined\n }\n >\n {matchComponent}\n </CatchBoundary>\n )}\n </matchContext.Provider>\n )\n}\n\nexport type UseMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = ToSubOptionsProps<TRouter, TFrom, TTo> &\n DeepPartial<MakeOptionalSearchParams<TRouter, TFrom, TTo>> &\n DeepPartial<MakeOptionalPathParams<TRouter, TFrom, TTo>> &\n MaskOptions<TRouter, TMaskFrom, TMaskTo> &\n MatchRouteOptions\n\n/**\n * Create a matcher function for testing locations against route definitions.\n *\n * The returned function accepts standard navigation options (`to`, `params`,\n * `search`, etc.) and returns either `false` (no match) or the matched params\n * object when the route matches the current or pending location.\n *\n * Useful for conditional rendering and active UI states because it subscribes\n * the component to the router state used for matching. The returned function's\n * identity changes when that state changes. For imperative checks in event\n * handlers, get the router with `useRouter` and call `router.matchRoute(...)`\n * to avoid that subscription.\n *\n * @returns A `matchRoute(options)` function that returns `false` or params.\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/useMatchRouteHook\n */\nexport function useMatchRoute<TRouter extends AnyRouter = RegisteredRouter>(): <\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(\n opts: UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>,\n) => false | Expand<ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']> {\n const router = useRouter()\n if (isServer ?? router.isServer) {\n return (opts) => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n }\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks\n return React.useCallback(\n (opts) => {\n const { pending, caseSensitive, fuzzy, includeSearch, ...rest } = opts\n\n return router.matchRoute(rest as any, {\n pending,\n caseSensitive,\n fuzzy,\n includeSearch,\n })\n },\n [\n router,\n // eslint-disable-next-line react-hooks/rules-of-hooks, react-hooks/exhaustive-deps\n useStore(router.stores.location, (location) => location.href),\n // eslint-disable-next-line react-hooks/rules-of-hooks, react-hooks/exhaustive-deps\n useStore(router.stores.resolvedLocation, (location) => location?.href),\n // eslint-disable-next-line react-hooks/rules-of-hooks, react-hooks/exhaustive-deps\n useStore(router.stores.status, (status) => status),\n ],\n )\n}\n\nexport type MakeMatchRouteOptions<\n TRouter extends AnyRouter = RegisteredRouter,\n TFrom extends string = string,\n TTo extends string | undefined = undefined,\n TMaskFrom extends string = TFrom,\n TMaskTo extends string = '',\n> = UseMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo> & {\n // If a function is passed as a child, it will be given the `isActive` boolean to aid in further styling on the element it returns\n children?:\n | ((\n params?: Expand<\n ResolveRoute<TRouter, TFrom, TTo>['types']['allParams']\n >,\n ) => React.ReactNode)\n | React.ReactNode\n}\n\n/**\n * Component that conditionally renders its children based on whether a route\n * matches the provided `from`/`to` options. If `children` is a function, it\n * receives the matched params object.\n *\n * @link https://tanstack.com/router/latest/docs/framework/react/api/router/matchRouteComponent\n */\nexport function MatchRoute<\n TRouter extends AnyRouter = RegisteredRouter,\n const TFrom extends string = string,\n const TTo extends string | undefined = undefined,\n const TMaskFrom extends string = TFrom,\n const TMaskTo extends string = '',\n>(props: MakeMatchRouteOptions<TRouter, TFrom, TTo, TMaskFrom, TMaskTo>): any {\n const matchRoute = useMatchRoute()\n const params = matchRoute(props as any) as boolean\n\n if (typeof props.children === 'function') {\n return (props.children as any)(params)\n }\n\n return params ? props.children : null\n}\n\nexport interface UseMatchesBaseOptions<\n TRouter extends AnyRouter,\n TSelected,\n TStructuralSharing,\n> {\n select?: (\n matches: Array<MakeRouteMatchUnion<TRouter>>,\n ) => ValidateSelected<TRouter, TSelected, TStructuralSharing>\n}\n\nexport type UseMatchesResult<\n TRouter extends AnyRouter,\n TSelected,\n> = unknown extends TSelected ? Array<MakeRouteMatchUnion<TRouter>> : TSelected\n\nexport function useMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const router = useRouter<TRouter>()\n\n if (isServer ?? router.isServer) {\n const matches = router.stores.matches.get() as Array<\n MakeRouteMatchUnion<TRouter>\n >\n return (opts?.select ? opts.select(matches) : matches) as UseMatchesResult<\n TRouter,\n TSelected\n >\n }\n\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n return useStore(\n router.stores.matches,\n // eslint-disable-next-line react-hooks/rules-of-hooks -- condition is static\n useStructuralSharing(opts, router),\n ) as UseMatchesResult<TRouter, TSelected>\n}\n\n/**\n * Read the presented route matches above the current match, or select a\n * derived value from them.\n */\nexport function useParentMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextRouteId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n 0,\n matches.findIndex((d) => d.routeId === contextRouteId),\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n\n/**\n * Read the presented route matches below the current match, or select a\n * derived value from them.\n */\nexport function useChildMatches<\n TRouter extends AnyRouter = RegisteredRouter,\n TSelected = unknown,\n TStructuralSharing extends boolean = boolean,\n>(\n opts?: UseMatchesBaseOptions<TRouter, TSelected, TStructuralSharing> &\n StructuralSharingOption<TRouter, TSelected, TStructuralSharing>,\n): UseMatchesResult<TRouter, TSelected> {\n const contextRouteId = React.useContext(matchContext)\n\n return useMatches({\n select: (matches: Array<MakeRouteMatchUnion<TRouter>>) => {\n matches = matches.slice(\n matches.findIndex((d) => d.routeId === contextRouteId) + 1,\n )\n return opts?.select ? opts.select(matches) : matches\n },\n structuralSharing: opts?.structuralSharing,\n } as any)\n}\n"],"mappings":"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"}