@devlusoft/devix 0.4.1-beta.8 → 0.4.1
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/dist/cli/build.js +130 -31
- package/dist/cli/build.js.map +4 -4
- package/dist/cli/dev-server.js +132 -33
- package/dist/cli/dev-server.js.map +4 -4
- package/dist/cli/generate.js +130 -31
- package/dist/cli/generate.js.map +4 -4
- package/dist/cli/index.js +131 -32
- package/dist/cli/index.js.map +4 -4
- package/dist/cli/start.js +1 -1
- package/dist/cli/start.js.map +3 -3
- package/dist/runtime/client-router.js +1 -1
- package/dist/runtime/client-router.js.map +3 -3
- package/dist/runtime/context.d.ts +1 -0
- package/dist/runtime/context.js.map +2 -2
- package/dist/runtime/fetch.d.ts +4 -35
- package/dist/runtime/fetch.js +1 -1
- package/dist/runtime/fetch.js.map +3 -3
- package/dist/runtime/index.d.ts +32 -4
- package/dist/runtime/index.js +1 -1
- package/dist/runtime/index.js.map +4 -4
- package/dist/runtime/link.d.ts +3 -2
- package/dist/runtime/link.js +1 -1
- package/dist/runtime/link.js.map +4 -4
- package/dist/runtime/router-provider.js +1 -1
- package/dist/runtime/router-provider.js.map +3 -3
- package/dist/runtime/server-app.js +1 -1
- package/dist/runtime/server-app.js.map +3 -3
- package/dist/server/api-router.d.ts +0 -1
- package/dist/server/api-router.js +1 -1
- package/dist/server/api-router.js.map +3 -3
- package/dist/server/api.js +1 -1
- package/dist/server/api.js.map +3 -3
- package/dist/server/index.js +1 -1
- package/dist/server/index.js.map +3 -3
- package/dist/server/pages-router.d.ts +0 -1
- package/dist/server/pages-router.js +1 -1
- package/dist/server/pages-router.js.map +3 -3
- package/dist/server/render.d.ts +15 -0
- package/dist/server/render.js +1 -1
- package/dist/server/render.js.map +3 -3
- package/dist/server/routes.js +1 -1
- package/dist/server/routes.js.map +3 -3
- package/dist/server/types.d.ts +4 -2
- package/dist/utils/banner.js +1 -1
- package/dist/utils/banner.js.map +1 -1
- package/dist/utils/load-config.js +1 -1
- package/dist/utils/load-config.js.map +3 -3
- package/dist/utils/response.d.ts +13 -2
- package/dist/utils/response.js +1 -1
- package/dist/utils/response.js.map +3 -3
- package/dist/vite/codegen/entry-client.js +14 -1
- package/dist/vite/codegen/entry-client.js.map +2 -2
- package/dist/vite/codegen/page-types.d.ts +5 -0
- package/dist/vite/codegen/page-types.js +14 -0
- package/dist/vite/codegen/page-types.js.map +7 -0
- package/dist/vite/codegen/routes-dts.js +13 -10
- package/dist/vite/codegen/routes-dts.js.map +2 -2
- package/dist/vite/codegen/scan-api.js +1 -1
- package/dist/vite/codegen/scan-api.js.map +1 -1
- package/dist/vite/codegen/server-entry.d.ts +9 -0
- package/dist/vite/codegen/server-entry.js +73 -0
- package/dist/vite/codegen/server-entry.js.map +7 -0
- package/dist/vite/index.js +131 -32
- package/dist/vite/index.js.map +4 -4
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/runtime/router-provider.tsx", "../../src/runtime/head.tsx", "../../src/runtime/context.tsx", "../../src/runtime/error-boundary.tsx"],
|
|
4
|
-
"sourcesContent": ["import { ComponentType, ReactNode, useCallback, useContext, useEffect, useRef, useState } from \"react\";\nimport { RouterContext } from 'virtual:devix/context'\nimport { ErrorProps, LayoutProps, PageProps } from \"../server/types\";\nimport { Metadata, Viewport } from \"../types\";\nimport { getDefaultErrorPage, loadErrorPage, matchClientRoute } from \"virtual:devix/client-routes\";\nimport { HeadSlot } from \"./head\";\nimport { NavigateOptions, PageMetaContext, RouteDataContext } from \"./context\";\nimport { DevixErrorBoundary } from \"./error-boundary\";\nimport type { Redirect } from \"../utils/response\";\n\ninterface RouteState {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n pendingError?: ErrorProps\n ErrorPage?: ComponentType<ErrorProps>\n}\n\nexport function useRouter() {\n return useContext(RouterContext)\n}\n\nconst noopNavigate = () => Promise.resolve()\nconst noopRevalidate = () => Promise.resolve()\n\nexport function useNavigate() {\n const ctx = useContext(RouterContext)\n return ctx?.navigate ?? noopNavigate\n}\n\nexport function useRevalidate() {\n const ctx = useContext(RouterContext)\n return ctx?.revalidate ?? noopRevalidate\n}\n\nexport function useParams<T extends Record<string, string>>() {\n const ctx = useContext(RouteDataContext)\n if (!ctx) throw new Error(\"useParams must be used within a route or layout\")\n return ctx.params as T\n}\n\ntype LoaderReturnType<T> = T extends (...args: any[]) => Promise<infer R>\n ? [Exclude<R, Redirect | void | undefined>] extends [never] ? undefined : Exclude<R, Redirect | void | undefined>\n : T extends (...args: any[]) => infer R\n ? [Exclude<R, Redirect | void | undefined>] extends [never] ? undefined : Exclude<R, Redirect | void | undefined>\n : T\n\nexport function useLoaderData<T>() {\n const ctx = useContext(RouteDataContext)\n if (!ctx) throw new Error(\"useLoaderData must be used within a route or layout\")\n return ctx.loaderData as LoaderReturnType<T>\n}\n\n\ninterface RouterProviderProps {\n initialData: unknown\n initialParams: Record<string, string>\n initialPage: ComponentType<PageProps>\n initialLayouts?: ComponentType<LayoutProps>[]\n initialLayoutsData?: unknown[]\n initialMeta?: Metadata | null\n initialViewport?: Viewport\n initialError?: ErrorProps\n initialErrorPage?: ComponentType<ErrorProps>\n clientEntry: string\n}\n\nexport function RouterProvider({\n initialData,\n initialParams,\n initialPage,\n initialLayouts = [],\n initialLayoutsData = [],\n initialMeta,\n initialViewport,\n initialError,\n initialErrorPage,\n clientEntry,\n}: RouterProviderProps) {\n\n const [state, setState] = useState<RouteState>({\n pathname: window.location.pathname,\n params: initialParams,\n loaderData: initialData,\n layoutsData: initialLayoutsData,\n Page: initialPage,\n layouts: initialLayouts,\n metadata: initialMeta ?? null,\n viewport: initialViewport,\n pendingError: initialError,\n ErrorPage: initialErrorPage,\n })\n\n const navigatingRef = useRef<AbortController | null>(null)\n const [isNavigating, setIsNavigating] = useState(false)\n\n const loadRoute = useCallback(async (to: string, controller: AbortController) => {\n const pathname = to.split('?')[0].split('#')[0]\n const matched = matchClientRoute(pathname)\n if (!matched) {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n setState(prev => ({\n ...prev,\n pathname: pathname,\n pendingError: { statusCode: 404, message: 'Not found' },\n ErrorPage: ErrorPage ?? undefined,\n }))\n return\n }\n\n const [pageMod, ...layoutMods] = await Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ])\n\n if (controller.signal.aborted) return\n if (!pageMod.default) return\n\n const dataRes = await fetch(`/_data${to}`, {\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n })\n\n if (controller.signal.aborted) return\n\n if (!dataRes.ok) {\n if (dataRes.status === 404) {\n window.location.href = to\n return\n }\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n setState(prev => ({\n ...prev,\n pathname,\n pendingError: { statusCode: dataRes.status, message: 'Server error' },\n ErrorPage: ErrorPage ?? undefined,\n }))\n return\n }\n\n const data = await dataRes.json()\n\n if (data.redirect) {\n if (data.redirectReplace) {\n window.history.replaceState(null, '', data.redirect)\n } else {\n window.history.pushState(null, '', data.redirect)\n }\n await loadRoute(data.redirect, controller)\n return\n }\n\n setState({\n pathname,\n params: data.params ?? {},\n loaderData: data.loaderData,\n layoutsData: (data.layouts ?? []).map((l: any) => l.loaderData),\n Page: pageMod.default,\n layouts: layoutMods.map(m => m.default),\n metadata: data.metadata ?? null,\n viewport: data.viewport,\n })\n\n const hash = to.includes('#') ? to.split('#')[1] : null\n const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior as ScrollBehavior\n if (hash) {\n requestAnimationFrame(() => {\n document.getElementById(hash)?.scrollIntoView({ behavior: scrollBehavior })\n })\n } else {\n window.scrollTo({ top: 0, behavior: scrollBehavior })\n }\n }, [])\n\n const navigate = useCallback(async (to: string, options?: NavigateOptions) => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n setIsNavigating(true)\n const run = async () => {\n window.history[options?.replace ? 'replaceState' : 'pushState'](null, '', to)\n await loadRoute(to, controller)\n }\n try {\n if (options?.viewTransition && 'startViewTransition' in document) {\n await (document as any).startViewTransition(run).finished\n } else {\n await run()\n }\n } finally {\n if (!controller.signal.aborted) setIsNavigating(false)\n }\n }, [loadRoute])\n\n const revalidate = useCallback(async () => {\n const to = window.location.pathname + window.location.search\n const controller = new AbortController()\n const dataRes = await fetch(`/_data${to}`, {\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n })\n if (!dataRes.ok) return\n const data = await dataRes.json()\n if (data.redirect) {\n await navigate(data.redirect, { replace: data.redirectReplace })\n return\n }\n setState(prev => ({\n ...prev,\n loaderData: data.loaderData,\n layoutsData: (data.layouts ?? []).map((l: any) => l.loaderData),\n params: data.params ?? prev.params,\n metadata: data.metadata ?? prev.metadata,\n viewport: data.viewport ?? prev.viewport,\n }))\n }, [navigate])\n\n useEffect(() => {\n const handlePop = () => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n const to = window.location.pathname + window.location.search\n loadRoute(to, controller).catch(err => {\n if (err.name !== 'AbortError') console.error('[router] popstate error:', err)\n })\n }\n window.addEventListener(\"popstate\", handlePop)\n return () => window.removeEventListener(\"popstate\", handlePop)\n }, [loadRoute])\n\n let content: ReactNode\n\n if (state.pendingError) {\n content = state.ErrorPage\n ? <state.ErrorPage {...state.pendingError} />\n : <h1>{state.pendingError.statusCode}</h1>\n } else {\n let tree: ReactNode = (\n <RouteDataContext value={{ loaderData: state.loaderData, params: state.params }}>\n <state.Page data={state.loaderData} params={state.params} url={state.pathname} />\n </RouteDataContext>\n )\n\n for (let i = state.layouts.length - 1; i >= 0; i--) {\n const Layout = state.layouts[i]\n const layoutData = state.layoutsData[i]\n tree = (\n <RouteDataContext value={{ loaderData: layoutData, params: state.params }}>\n <Layout data={layoutData} params={state.params}>{tree}</Layout>\n </RouteDataContext>\n )\n }\n\n content = (\n <DevixErrorBoundary key={state.pathname} ErrorPage={state.ErrorPage}>\n {tree}\n </DevixErrorBoundary>\n )\n }\n\n return (\n <PageMetaContext value={{\n metadata: state.metadata,\n viewport: state.viewport,\n clientEntry,\n }}>\n <HeadSlot metadata={state.metadata} viewport={state.viewport} />\n <RouterContext value={{ ...state, isNavigating, navigate, revalidate }}>\n {content}\n </RouterContext>\n </PageMetaContext>\n )\n}", "import { Metadata, MetadataIcon, Viewport } from \"../types\";\nimport { ReactNode } from \"react\";\n\ntype MetaTag =\n | { tag: 'title'; children: string }\n | { tag: 'meta'; name?: string; property?: string; content: string }\n | { tag: 'link'; rel: string; href: string; hrefLang?: string; type?: string; sizes?: string }\n\nfunction collectTags(metadata: Metadata, viewport?: Viewport): MetaTag[] {\n const tags: MetaTag[] = []\n\n if (metadata.title)\n tags.push({ tag: 'title', children: metadata.title })\n if (metadata.description)\n tags.push({ tag: 'meta', name: 'description', content: metadata.description })\n if (metadata.keywords?.length)\n tags.push({ tag: 'meta', name: 'keywords', content: metadata.keywords.join(', ') })\n\n const ogTitle = metadata.og?.title ?? metadata.title\n if (ogTitle) tags.push({ tag: 'meta', property: 'og:title', content: ogTitle })\n const ogDesc = metadata.og?.description ?? metadata.description\n if (ogDesc) tags.push({ tag: 'meta', property: 'og:description', content: ogDesc })\n if (metadata.og?.image) tags.push({ tag: 'meta', property: 'og:image', content: metadata.og.image })\n if (metadata.og?.type) tags.push({ tag: 'meta', property: 'og:type', content: metadata.og.type })\n if (metadata.og?.url) tags.push({ tag: 'meta', property: 'og:url', content: metadata.og.url })\n\n const twTitle = metadata.twitter?.title ?? metadata.title\n if (twTitle) tags.push({ tag: 'meta', name: 'twitter:title', content: twTitle })\n const twDesc = metadata.twitter?.description ?? metadata.description\n if (twDesc) tags.push({ tag: 'meta', name: 'twitter:description', content: twDesc })\n if (metadata.twitter?.card) tags.push({\n tag: 'meta', name: 'twitter:card', content:\n metadata.twitter.card\n })\n if (metadata.twitter?.image) tags.push({\n tag: 'meta', name: 'twitter:image', content:\n metadata.twitter.image\n })\n if (metadata.twitter?.creator) tags.push({\n tag: 'meta', name: 'twitter:creator', content:\n metadata.twitter.creator\n })\n\n if (metadata.canonical) tags.push({ tag: 'link', rel: 'canonical', href: metadata.canonical })\n if (metadata.robots) tags.push({ tag: 'meta', name: 'robots', content: metadata.robots })\n if (metadata.alternates) {\n for (const [lang, href] of Object.entries(metadata.alternates))\n tags.push({ tag: 'link', rel: 'alternate', href, hrefLang: lang })\n }\n\n if (metadata.icons) {\n const raw = Array.isArray(metadata.icons) ? metadata.icons : [metadata.icons]\n for (const icon of raw) {\n const resolved: MetadataIcon = typeof icon === 'string' ? { href: icon } : icon\n tags.push({\n tag: 'link',\n rel: resolved.rel ?? 'icon',\n href: resolved.href,\n ...(resolved.type && { type: resolved.type }),\n ...(resolved.sizes && { sizes: resolved.sizes }),\n })\n }\n }\n\n if (viewport) {\n const parts: string[] = []\n if (viewport.width !== undefined) parts.push(`width=${viewport.width}`)\n if (viewport.initialScale !== undefined) parts.push(`initial-scale=${viewport.initialScale}`)\n if (viewport.maximumScale !== undefined) parts.push(`maximum-scale=${viewport.maximumScale}`)\n if (viewport.userScalable !== undefined) parts.push(`user-scalable=${viewport.userScalable ? 'yes' :\n 'no'}`)\n if (parts.length) tags.push({ tag: 'meta', name: 'viewport', content: parts.join(', ') })\n if (viewport.themeColor) tags.push({\n tag: 'meta', name: 'theme-color', content: viewport.themeColor\n })\n }\n\n return tags\n}\n\nexport function HeadSlot({ metadata, viewport }: { metadata: Metadata | null, viewport?: Viewport }) {\n if (typeof window === 'undefined' || !metadata) return null\n return <>{buildHeadNodes(metadata, viewport)}</>\n}\n\nexport function buildHeadNodes(metadata: Metadata, viewport?: Viewport): ReactNode {\n const tags = collectTags(metadata, viewport)\n\n return <>\n {tags.map((t, i) => {\n if (t.tag === 'title') return <title key={i}>{t.children}</title>\n if (t.tag === 'link') return <link key={i} rel={t.rel} href={t.href} hrefLang={t.hrefLang} type={t.type} sizes={t.sizes} />\n return <meta key={i} name={t.name} property={t.property} content={t.content} />\n })}\n </>\n}", "import {createContext, Context, ComponentType} from \"react\";\nimport {Metadata, Viewport} from \"../types\";\nimport {LayoutProps, PageProps} from \"../server/types\";\n\nexport interface NavigateOptions {\n replace?: boolean\n viewTransition?: boolean\n}\n\nexport interface RouterContextValue {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n navigate: (to: string, options?: NavigateOptions) => Promise<void>\n revalidate: () => Promise<void>\n isNavigating: boolean\n}\n\nexport interface PageMetaContextValue {\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry?: string\n}\n\nexport interface RouteDataContextValue {\n loaderData: unknown\n params: Record<string, string>\n}\n\nconst g = globalThis as any\n\ng.__devix_RouterContext__ ??= createContext<RouterContextValue | null>(null)\nexport const RouterContext: Context<RouterContextValue | null> = g.__devix_RouterContext__\n\ng.__devix_PageMetaContext__ ??= createContext<PageMetaContextValue | null>(null)\ng.__devix_RouteDataContext__ ??= createContext<RouteDataContextValue | null>(null)\n\nexport const PageMetaContext: Context<PageMetaContextValue | null> = g.__devix_PageMetaContext__\nexport const RouteDataContext: Context<RouteDataContextValue | null> = g.__devix_RouteDataContext__\n\n", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAmC,eAAAA,EAAa,cAAAC,EAAY,aAAAC,
|
|
6
|
-
"names": ["useCallback", "useContext", "useEffect", "useRef", "useState", "RouterContext", "getDefaultErrorPage", "loadErrorPage", "matchClientRoute", "Fragment", "jsx", "collectTags", "metadata", "viewport", "tags", "ogTitle", "ogDesc", "twTitle", "twDesc", "lang", "href", "raw", "icon", "resolved", "parts", "HeadSlot", "buildHeadNodes", "t", "i", "createContext", "g", "RouterContext", "PageMetaContext", "RouteDataContext", "Component", "jsx", "DevixErrorBoundary", "err", "DevixError", "statusCode", "message", "jsx", "jsxs", "useRouter", "useContext", "RouterContext", "noopNavigate", "noopRevalidate", "useNavigate", "useRevalidate", "useParams", "ctx", "RouteDataContext", "useLoaderData", "RouterProvider", "initialData", "initialParams", "initialPage", "initialLayouts", "initialLayoutsData", "initialMeta", "initialViewport", "initialError", "initialErrorPage", "clientEntry", "state", "setState", "useState", "navigatingRef", "useRef", "isNavigating", "setIsNavigating", "
|
|
4
|
+
"sourcesContent": ["import { ComponentType, ReactNode, useCallback, useContext, useEffect, useRef, useState } from \"react\";\nimport { RouterContext } from 'virtual:devix/context'\nimport { ErrorProps, LayoutProps, PageProps } from \"../server/types\";\nimport { Metadata, Viewport } from \"../types\";\nimport { getDefaultErrorPage, loadErrorPage, matchClientRoute } from \"virtual:devix/client-routes\";\nimport { HeadSlot } from \"./head\";\nimport { NavigateOptions, PageMetaContext, RouteDataContext } from \"./context\";\nimport { DevixErrorBoundary } from \"./error-boundary\";\nimport type { Redirect } from \"../utils/response\";\n\ninterface RouteState {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n pendingError?: ErrorProps\n ErrorPage?: ComponentType<ErrorProps>\n}\n\nexport function useRouter() {\n return useContext(RouterContext)\n}\n\nconst noopNavigate = () => Promise.resolve()\nconst noopRevalidate = () => Promise.resolve()\n\nexport function useNavigate() {\n const ctx = useContext(RouterContext)\n return ctx?.navigate ?? noopNavigate\n}\n\nexport function useRevalidate() {\n const ctx = useContext(RouterContext)\n return ctx?.revalidate ?? noopRevalidate\n}\n\nexport function useParams<T extends Record<string, string>>() {\n const ctx = useContext(RouteDataContext)\n if (!ctx) throw new Error(\"useParams must be used within a route or layout\")\n return ctx.params as T\n}\n\ntype LoaderReturnType<T> = T extends (...args: any[]) => Promise<infer R>\n ? [Exclude<R, Redirect | void | undefined>] extends [never] ? undefined : Exclude<R, Redirect | void | undefined>\n : T extends (...args: any[]) => infer R\n ? [Exclude<R, Redirect | void | undefined>] extends [never] ? undefined : Exclude<R, Redirect | void | undefined>\n : T\n\nexport function useLoaderData<T>() {\n const ctx = useContext(RouteDataContext)\n if (!ctx) throw new Error(\"useLoaderData must be used within a route or layout\")\n return ctx.loaderData as LoaderReturnType<T>\n}\n\ninterface PrefetchEntry {\n promise: Promise<{ pageMod: any; layoutMods: any[]; data: any } | null>\n controller: AbortController\n}\n\ninterface RouterProviderProps {\n initialData: unknown\n initialParams: Record<string, string>\n initialPage: ComponentType<PageProps>\n initialLayouts?: ComponentType<LayoutProps>[]\n initialLayoutsData?: unknown[]\n initialMeta?: Metadata | null\n initialViewport?: Viewport\n initialError?: ErrorProps\n initialErrorPage?: ComponentType<ErrorProps>\n clientEntry: string\n}\n\nexport function RouterProvider({\n initialData,\n initialParams,\n initialPage,\n initialLayouts = [],\n initialLayoutsData = [],\n initialMeta,\n initialViewport,\n initialError,\n initialErrorPage,\n clientEntry,\n}: RouterProviderProps) {\n\n const [state, setState] = useState<RouteState>({\n pathname: window.location.pathname,\n params: initialParams,\n loaderData: initialData,\n layoutsData: initialLayoutsData,\n Page: initialPage,\n layouts: initialLayouts,\n metadata: initialMeta ?? null,\n viewport: initialViewport,\n pendingError: initialError,\n ErrorPage: initialErrorPage,\n })\n\n const navigatingRef = useRef<AbortController | null>(null)\n const [isNavigating, setIsNavigating] = useState(false)\n\n const prefetchCacheRef = useRef<Map<string, PrefetchEntry>>(new Map())\n\n const prefetchRoute = useCallback((href: string) => {\n if (prefetchCacheRef.current.has(href)) return\n const pathname = href.split('?')[0].split('#')[0]\n const matched = matchClientRoute(pathname)\n if (!matched) return\n\n const controller = new AbortController()\n const promise = Promise.all([\n Promise.all([matched.load(), ...matched.loadLayouts.map(l => l())]),\n fetch(`/_data${href}`, { headers: { Accept: 'application/json' }, signal: controller.signal })\n ]).then(async ([[pageMod, ...layoutMods], dataRes]) => {\n if (!dataRes.ok || !pageMod.default) return null\n const data = await dataRes.json()\n return { pageMod, layoutMods, data }\n }).catch(() => null)\n\n const expireTimer = setTimeout(() => {\n controller.abort()\n prefetchCacheRef.current.delete(href)\n }, 3000)\n promise.finally(() => clearTimeout(expireTimer))\n\n prefetchCacheRef.current.set(href, { promise, controller })\n }, [])\n\n const loadRoute = useCallback(async (to: string, controller: AbortController) => {\n const pathname = to.split('?')[0].split('#')[0]\n const matched = matchClientRoute(pathname)\n if (!matched) {\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n setState(prev => ({\n ...prev,\n pathname: pathname,\n pendingError: { statusCode: 404, message: 'Not found' },\n ErrorPage: ErrorPage ?? undefined,\n }))\n return\n }\n\n const cached = prefetchCacheRef.current.get(to)\n if (cached) prefetchCacheRef.current.delete(to)\n const prefetched = cached ? await cached.promise : null\n\n if (controller.signal.aborted) return\n\n let pageMod: any, layoutMods: any[], data: any\n\n if (prefetched) {\n ;({ pageMod, layoutMods, data } = prefetched)\n } else {\n const [[pm, ...lm], dataRes] = await Promise.all([\n Promise.all([\n matched.load(),\n ...matched.loadLayouts.map(l => l()),\n ]),\n fetch(`/_data${to}`, {\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n })\n ])\n\n if (controller.signal.aborted) return\n if (!pm.default) return\n\n if (!dataRes.ok) {\n const ct = dataRes.headers.get('Content-Type') ?? ''\n let errorBody: { statusCode?: number; message?: string; data?: unknown } | null = null\n try {\n if (ct.includes('application/json')) errorBody = await dataRes.json()\n else if (ct.includes('text/plain')) errorBody = { message: await dataRes.text() }\n } catch { /* ignorar errores de parsing */ }\n\n const headers: Record<string, string> = {}\n dataRes.headers.forEach((value, key) => { headers[key] = value })\n\n const ErrorPage = await loadErrorPage() ?? getDefaultErrorPage()\n setState(prev => ({\n ...prev,\n pathname,\n pendingError: {\n statusCode: errorBody?.statusCode ?? dataRes.status,\n message: errorBody?.message ?? 'Server error',\n data: errorBody?.data,\n headers,\n },\n ErrorPage: ErrorPage ?? undefined,\n }))\n return\n }\n\n pageMod = pm\n layoutMods = lm\n data = await dataRes.json()\n }\n\n if (data.redirect) {\n if (data.redirectReplace) {\n window.history.replaceState(null, '', data.redirect)\n } else {\n window.history.pushState(null, '', data.redirect)\n }\n await loadRoute(data.redirect, controller)\n return\n }\n\n setState({\n pathname,\n params: data.params ?? {},\n loaderData: data.loaderData,\n layoutsData: (data.layouts ?? []).map((l: any) => l.loaderData),\n Page: pageMod.default,\n layouts: layoutMods.map(m => m.default),\n metadata: data.metadata ?? null,\n viewport: data.viewport,\n })\n\n const hash = to.includes('#') ? to.split('#')[1] : null\n const scrollBehavior = getComputedStyle(document.documentElement).scrollBehavior as ScrollBehavior\n if (hash) {\n requestAnimationFrame(() => {\n document.getElementById(hash)?.scrollIntoView({ behavior: scrollBehavior })\n })\n } else {\n window.scrollTo({ top: 0, behavior: scrollBehavior })\n }\n }, [])\n\n const navigate = useCallback(async (to: string, options?: NavigateOptions) => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n setIsNavigating(true)\n const run = async () => {\n window.history[options?.replace ? 'replaceState' : 'pushState'](null, '', to)\n await loadRoute(to, controller)\n }\n try {\n if (options?.viewTransition && 'startViewTransition' in document) {\n await (document as any).startViewTransition(run).finished\n } else {\n await run()\n }\n } finally {\n if (!controller.signal.aborted) setIsNavigating(false)\n }\n }, [loadRoute])\n\n const revalidate = useCallback(async () => {\n const to = window.location.pathname + window.location.search\n const controller = new AbortController()\n const dataRes = await fetch(`/_data${to}`, {\n headers: { Accept: 'application/json' },\n signal: controller.signal,\n })\n if (!dataRes.ok) return\n const data = await dataRes.json()\n if (data.redirect) {\n await navigate(data.redirect, { replace: data.redirectReplace })\n return\n }\n setState(prev => ({\n ...prev,\n loaderData: data.loaderData,\n layoutsData: (data.layouts ?? []).map((l: any) => l.loaderData),\n params: data.params ?? prev.params,\n metadata: data.metadata ?? prev.metadata,\n viewport: data.viewport ?? prev.viewport,\n }))\n }, [navigate])\n\n useEffect(() => {\n const handlePop = () => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n const to = window.location.pathname + window.location.search\n loadRoute(to, controller).catch(err => {\n if (err.name !== 'AbortError') console.error('[router] popstate error:', err)\n })\n }\n window.addEventListener(\"popstate\", handlePop)\n return () => window.removeEventListener(\"popstate\", handlePop)\n }, [loadRoute])\n\n let content: ReactNode\n\n if (state.pendingError) {\n content = state.ErrorPage\n ? <state.ErrorPage {...state.pendingError} />\n : <h1>{state.pendingError.statusCode}</h1>\n } else {\n let tree: ReactNode = (\n <RouteDataContext value={{ loaderData: state.loaderData, params: state.params }}>\n <state.Page data={state.loaderData} params={state.params} url={state.pathname} />\n </RouteDataContext>\n )\n\n for (let i = state.layouts.length - 1; i >= 0; i--) {\n const Layout = state.layouts[i]\n const layoutData = state.layoutsData[i]\n tree = (\n <RouteDataContext value={{ loaderData: layoutData, params: state.params }}>\n <Layout data={layoutData} params={state.params}>{tree}</Layout>\n </RouteDataContext>\n )\n }\n\n content = (\n <DevixErrorBoundary key={state.pathname} ErrorPage={state.ErrorPage}>\n {tree}\n </DevixErrorBoundary>\n )\n }\n\n return (\n <PageMetaContext value={{\n metadata: state.metadata,\n viewport: state.viewport,\n clientEntry,\n }}>\n <HeadSlot metadata={state.metadata} viewport={state.viewport} />\n <RouterContext value={{ ...state, isNavigating, navigate, revalidate, prefetchRoute }}>\n {content}\n </RouterContext>\n </PageMetaContext>\n )\n}", "import { Metadata, MetadataIcon, Viewport } from \"../types\";\nimport { ReactNode } from \"react\";\n\ntype MetaTag =\n | { tag: 'title'; children: string }\n | { tag: 'meta'; name?: string; property?: string; content: string }\n | { tag: 'link'; rel: string; href: string; hrefLang?: string; type?: string; sizes?: string }\n\nfunction collectTags(metadata: Metadata, viewport?: Viewport): MetaTag[] {\n const tags: MetaTag[] = []\n\n if (metadata.title)\n tags.push({ tag: 'title', children: metadata.title })\n if (metadata.description)\n tags.push({ tag: 'meta', name: 'description', content: metadata.description })\n if (metadata.keywords?.length)\n tags.push({ tag: 'meta', name: 'keywords', content: metadata.keywords.join(', ') })\n\n const ogTitle = metadata.og?.title ?? metadata.title\n if (ogTitle) tags.push({ tag: 'meta', property: 'og:title', content: ogTitle })\n const ogDesc = metadata.og?.description ?? metadata.description\n if (ogDesc) tags.push({ tag: 'meta', property: 'og:description', content: ogDesc })\n if (metadata.og?.image) tags.push({ tag: 'meta', property: 'og:image', content: metadata.og.image })\n if (metadata.og?.type) tags.push({ tag: 'meta', property: 'og:type', content: metadata.og.type })\n if (metadata.og?.url) tags.push({ tag: 'meta', property: 'og:url', content: metadata.og.url })\n\n const twTitle = metadata.twitter?.title ?? metadata.title\n if (twTitle) tags.push({ tag: 'meta', name: 'twitter:title', content: twTitle })\n const twDesc = metadata.twitter?.description ?? metadata.description\n if (twDesc) tags.push({ tag: 'meta', name: 'twitter:description', content: twDesc })\n if (metadata.twitter?.card) tags.push({\n tag: 'meta', name: 'twitter:card', content:\n metadata.twitter.card\n })\n if (metadata.twitter?.image) tags.push({\n tag: 'meta', name: 'twitter:image', content:\n metadata.twitter.image\n })\n if (metadata.twitter?.creator) tags.push({\n tag: 'meta', name: 'twitter:creator', content:\n metadata.twitter.creator\n })\n\n if (metadata.canonical) tags.push({ tag: 'link', rel: 'canonical', href: metadata.canonical })\n if (metadata.robots) tags.push({ tag: 'meta', name: 'robots', content: metadata.robots })\n if (metadata.alternates) {\n for (const [lang, href] of Object.entries(metadata.alternates))\n tags.push({ tag: 'link', rel: 'alternate', href, hrefLang: lang })\n }\n\n if (metadata.icons) {\n const raw = Array.isArray(metadata.icons) ? metadata.icons : [metadata.icons]\n for (const icon of raw) {\n const resolved: MetadataIcon = typeof icon === 'string' ? { href: icon } : icon\n tags.push({\n tag: 'link',\n rel: resolved.rel ?? 'icon',\n href: resolved.href,\n ...(resolved.type && { type: resolved.type }),\n ...(resolved.sizes && { sizes: resolved.sizes }),\n })\n }\n }\n\n if (viewport) {\n const parts: string[] = []\n if (viewport.width !== undefined) parts.push(`width=${viewport.width}`)\n if (viewport.initialScale !== undefined) parts.push(`initial-scale=${viewport.initialScale}`)\n if (viewport.maximumScale !== undefined) parts.push(`maximum-scale=${viewport.maximumScale}`)\n if (viewport.userScalable !== undefined) parts.push(`user-scalable=${viewport.userScalable ? 'yes' :\n 'no'}`)\n if (parts.length) tags.push({ tag: 'meta', name: 'viewport', content: parts.join(', ') })\n if (viewport.themeColor) tags.push({\n tag: 'meta', name: 'theme-color', content: viewport.themeColor\n })\n }\n\n return tags\n}\n\nexport function HeadSlot({ metadata, viewport }: { metadata: Metadata | null, viewport?: Viewport }) {\n if (typeof window === 'undefined' || !metadata) return null\n return <>{buildHeadNodes(metadata, viewport)}</>\n}\n\nexport function buildHeadNodes(metadata: Metadata, viewport?: Viewport): ReactNode {\n const tags = collectTags(metadata, viewport)\n\n return <>\n {tags.map((t, i) => {\n if (t.tag === 'title') return <title key={i}>{t.children}</title>\n if (t.tag === 'link') return <link key={i} rel={t.rel} href={t.href} hrefLang={t.hrefLang} type={t.type} sizes={t.sizes} />\n return <meta key={i} name={t.name} property={t.property} content={t.content} />\n })}\n </>\n}", "import {createContext, Context, ComponentType} from \"react\";\nimport {Metadata, Viewport} from \"../types\";\nimport {LayoutProps, PageProps} from \"../server/types\";\n\nexport interface NavigateOptions {\n replace?: boolean\n viewTransition?: boolean\n}\n\nexport interface RouterContextValue {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n navigate: (to: string, options?: NavigateOptions) => Promise<void>\n revalidate: () => Promise<void>\n prefetchRoute: (href: string) => void\n isNavigating: boolean\n}\n\nexport interface PageMetaContextValue {\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry?: string\n}\n\nexport interface RouteDataContextValue {\n loaderData: unknown\n params: Record<string, string>\n}\n\nconst g = globalThis as any\n\ng.__devix_RouterContext__ ??= createContext<RouterContextValue | null>(null)\nexport const RouterContext: Context<RouterContextValue | null> = g.__devix_RouterContext__\n\ng.__devix_PageMetaContext__ ??= createContext<PageMetaContextValue | null>(null)\ng.__devix_RouteDataContext__ ??= createContext<RouteDataContextValue | null>(null)\n\nexport const PageMetaContext: Context<PageMetaContextValue | null> = g.__devix_PageMetaContext__\nexport const RouteDataContext: Context<RouteDataContextValue | null> = g.__devix_RouteDataContext__\n\n", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["useCallback", "useContext", "useEffect", "useRef", "useState", "RouterContext", "getDefaultErrorPage", "loadErrorPage", "matchClientRoute", "Fragment", "jsx", "collectTags", "metadata", "viewport", "tags", "ogTitle", "ogDesc", "twTitle", "twDesc", "lang", "href", "raw", "icon", "resolved", "parts", "HeadSlot", "buildHeadNodes", "t", "i", "createContext", "g", "RouterContext", "PageMetaContext", "RouteDataContext", "Component", "jsx", "DevixErrorBoundary", "err", "DevixError", "statusCode", "message", "jsx", "jsxs", "useRouter", "useContext", "RouterContext", "noopNavigate", "noopRevalidate", "useNavigate", "useRevalidate", "useParams", "ctx", "RouteDataContext", "useLoaderData", "RouterProvider", "initialData", "initialParams", "initialPage", "initialLayouts", "initialLayoutsData", "initialMeta", "initialViewport", "initialError", "initialErrorPage", "clientEntry", "state", "setState", "useState", "navigatingRef", "useRef", "isNavigating", "setIsNavigating", "prefetchCacheRef", "prefetchRoute", "useCallback", "href", "pathname", "matched", "matchClientRoute", "controller", "promise", "l", "pageMod", "layoutMods", "dataRes", "data", "expireTimer", "loadRoute", "to", "ErrorPage", "loadErrorPage", "getDefaultErrorPage", "prev", "cached", "prefetched", "pm", "lm", "ct", "errorBody", "headers", "value", "key", "m", "hash", "scrollBehavior", "navigate", "options", "run", "revalidate", "useEffect", "handlePop", "err", "content", "tree", "Layout", "layoutData", "DevixErrorBoundary", "PageMetaContext", "HeadSlot"]
|
|
7
7
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createContext as m}from"react";var g=globalThis;g.__devix_RouterContext__??=m(null);var C=g.__devix_RouterContext__;g.__devix_PageMetaContext__??=m(null);g.__devix_RouteDataContext__??=m(null);var
|
|
1
|
+
import{createContext as m}from"react";var g=globalThis;g.__devix_RouterContext__??=m(null);var C=g.__devix_RouterContext__;g.__devix_PageMetaContext__??=m(null);g.__devix_RouteDataContext__??=m(null);var P=g.__devix_PageMetaContext__,d=g.__devix_RouteDataContext__;import{Fragment as _,jsx as c}from"react/jsx-runtime";function M(t,e){let o=[];t.title&&o.push({tag:"title",children:t.title}),t.description&&o.push({tag:"meta",name:"description",content:t.description}),t.keywords?.length&&o.push({tag:"meta",name:"keywords",content:t.keywords.join(", ")});let r=t.og?.title??t.title;r&&o.push({tag:"meta",property:"og:title",content:r});let a=t.og?.description??t.description;a&&o.push({tag:"meta",property:"og:description",content:a}),t.og?.image&&o.push({tag:"meta",property:"og:image",content:t.og.image}),t.og?.type&&o.push({tag:"meta",property:"og:type",content:t.og.type}),t.og?.url&&o.push({tag:"meta",property:"og:url",content:t.og.url});let l=t.twitter?.title??t.title;l&&o.push({tag:"meta",name:"twitter:title",content:l});let u=t.twitter?.description??t.description;if(u&&o.push({tag:"meta",name:"twitter:description",content:u}),t.twitter?.card&&o.push({tag:"meta",name:"twitter:card",content:t.twitter.card}),t.twitter?.image&&o.push({tag:"meta",name:"twitter:image",content:t.twitter.image}),t.twitter?.creator&&o.push({tag:"meta",name:"twitter:creator",content:t.twitter.creator}),t.canonical&&o.push({tag:"link",rel:"canonical",href:t.canonical}),t.robots&&o.push({tag:"meta",name:"robots",content:t.robots}),t.alternates)for(let[n,s]of Object.entries(t.alternates))o.push({tag:"link",rel:"alternate",href:s,hrefLang:n});if(t.icons){let n=Array.isArray(t.icons)?t.icons:[t.icons];for(let s of n){let i=typeof s=="string"?{href:s}:s;o.push({tag:"link",rel:i.rel??"icon",href:i.href,...i.type&&{type:i.type},...i.sizes&&{sizes:i.sizes}})}}if(e){let n=[];e.width!==void 0&&n.push(`width=${e.width}`),e.initialScale!==void 0&&n.push(`initial-scale=${e.initialScale}`),e.maximumScale!==void 0&&n.push(`maximum-scale=${e.maximumScale}`),e.userScalable!==void 0&&n.push(`user-scalable=${e.userScalable?"yes":"no"}`),n.length&&o.push({tag:"meta",name:"viewport",content:n.join(", ")}),e.themeColor&&o.push({tag:"meta",name:"theme-color",content:e.themeColor})}return o}function w({metadata:t,viewport:e}){return typeof window>"u"||!t?null:c(_,{children:k(t,e)})}function k(t,e){let o=M(t,e);return c(_,{children:o.map((r,a)=>r.tag==="title"?c("title",{children:r.children},a):r.tag==="link"?c("link",{rel:r.rel,href:r.href,hrefLang:r.hrefLang,type:r.type,sizes:r.sizes},a):c("meta",{name:r.name,property:r.property,content:r.content},a))})}import{Component as V}from"react";import{jsx as R}from"react/jsx-runtime";var h=class extends V{state={error:null};static getDerivedStateFromError(e){return e instanceof y?{error:{statusCode:e.statusCode,message:e.message}}:{error:{statusCode:500,message:e instanceof Error?e.message:"Unknown error"}}}render(){return this.state.error&&this.props.ErrorPage?R(this.props.ErrorPage,{...this.state.error}):this.state.error?R("h1",{children:this.state.error.statusCode}):this.props.children}},y=class extends Error{statusCode;constructor(e,o){super(o),this.statusCode=e}};import{jsx as p,jsxs as b}from"react/jsx-runtime";var D=(t,e)=>Promise.resolve(),S=()=>Promise.resolve(),T=t=>{};function J({pathname:t,params:e,loaderData:o,layoutsData:r,Page:a,layouts:l,metadata:u,viewport:n,clientEntry:s}){let i=p(d,{value:{loaderData:o,params:e},children:p(a,{data:o,params:e,url:t})});for(let f=l.length-1;f>=0;f--){let v=l[f],x=r[f];i=p(d,{value:{loaderData:x,params:e},children:p(v,{data:x,params:e,children:i})})}return b(P,{value:{metadata:u,viewport:n,clientEntry:s},children:[p(w,{metadata:u,viewport:n}),p(C,{value:{pathname:t,params:e,loaderData:o,layoutsData:r,Page:a,layouts:l,metadata:u,viewport:n,isNavigating:!1,navigate:D,revalidate:S,prefetchRoute:T},children:p(h,{children:i},t)})]})}export{J as ServerApp};
|
|
2
2
|
//# sourceMappingURL=server-app.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/runtime/context.tsx", "../../src/runtime/head.tsx", "../../src/runtime/error-boundary.tsx", "../../src/runtime/server-app.tsx"],
|
|
4
|
-
"sourcesContent": ["import {createContext, Context, ComponentType} from \"react\";\nimport {Metadata, Viewport} from \"../types\";\nimport {LayoutProps, PageProps} from \"../server/types\";\n\nexport interface NavigateOptions {\n replace?: boolean\n viewTransition?: boolean\n}\n\nexport interface RouterContextValue {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n navigate: (to: string, options?: NavigateOptions) => Promise<void>\n revalidate: () => Promise<void>\n isNavigating: boolean\n}\n\nexport interface PageMetaContextValue {\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry?: string\n}\n\nexport interface RouteDataContextValue {\n loaderData: unknown\n params: Record<string, string>\n}\n\nconst g = globalThis as any\n\ng.__devix_RouterContext__ ??= createContext<RouterContextValue | null>(null)\nexport const RouterContext: Context<RouterContextValue | null> = g.__devix_RouterContext__\n\ng.__devix_PageMetaContext__ ??= createContext<PageMetaContextValue | null>(null)\ng.__devix_RouteDataContext__ ??= createContext<RouteDataContextValue | null>(null)\n\nexport const PageMetaContext: Context<PageMetaContextValue | null> = g.__devix_PageMetaContext__\nexport const RouteDataContext: Context<RouteDataContextValue | null> = g.__devix_RouteDataContext__\n\n", "import { Metadata, MetadataIcon, Viewport } from \"../types\";\nimport { ReactNode } from \"react\";\n\ntype MetaTag =\n | { tag: 'title'; children: string }\n | { tag: 'meta'; name?: string; property?: string; content: string }\n | { tag: 'link'; rel: string; href: string; hrefLang?: string; type?: string; sizes?: string }\n\nfunction collectTags(metadata: Metadata, viewport?: Viewport): MetaTag[] {\n const tags: MetaTag[] = []\n\n if (metadata.title)\n tags.push({ tag: 'title', children: metadata.title })\n if (metadata.description)\n tags.push({ tag: 'meta', name: 'description', content: metadata.description })\n if (metadata.keywords?.length)\n tags.push({ tag: 'meta', name: 'keywords', content: metadata.keywords.join(', ') })\n\n const ogTitle = metadata.og?.title ?? metadata.title\n if (ogTitle) tags.push({ tag: 'meta', property: 'og:title', content: ogTitle })\n const ogDesc = metadata.og?.description ?? metadata.description\n if (ogDesc) tags.push({ tag: 'meta', property: 'og:description', content: ogDesc })\n if (metadata.og?.image) tags.push({ tag: 'meta', property: 'og:image', content: metadata.og.image })\n if (metadata.og?.type) tags.push({ tag: 'meta', property: 'og:type', content: metadata.og.type })\n if (metadata.og?.url) tags.push({ tag: 'meta', property: 'og:url', content: metadata.og.url })\n\n const twTitle = metadata.twitter?.title ?? metadata.title\n if (twTitle) tags.push({ tag: 'meta', name: 'twitter:title', content: twTitle })\n const twDesc = metadata.twitter?.description ?? metadata.description\n if (twDesc) tags.push({ tag: 'meta', name: 'twitter:description', content: twDesc })\n if (metadata.twitter?.card) tags.push({\n tag: 'meta', name: 'twitter:card', content:\n metadata.twitter.card\n })\n if (metadata.twitter?.image) tags.push({\n tag: 'meta', name: 'twitter:image', content:\n metadata.twitter.image\n })\n if (metadata.twitter?.creator) tags.push({\n tag: 'meta', name: 'twitter:creator', content:\n metadata.twitter.creator\n })\n\n if (metadata.canonical) tags.push({ tag: 'link', rel: 'canonical', href: metadata.canonical })\n if (metadata.robots) tags.push({ tag: 'meta', name: 'robots', content: metadata.robots })\n if (metadata.alternates) {\n for (const [lang, href] of Object.entries(metadata.alternates))\n tags.push({ tag: 'link', rel: 'alternate', href, hrefLang: lang })\n }\n\n if (metadata.icons) {\n const raw = Array.isArray(metadata.icons) ? metadata.icons : [metadata.icons]\n for (const icon of raw) {\n const resolved: MetadataIcon = typeof icon === 'string' ? { href: icon } : icon\n tags.push({\n tag: 'link',\n rel: resolved.rel ?? 'icon',\n href: resolved.href,\n ...(resolved.type && { type: resolved.type }),\n ...(resolved.sizes && { sizes: resolved.sizes }),\n })\n }\n }\n\n if (viewport) {\n const parts: string[] = []\n if (viewport.width !== undefined) parts.push(`width=${viewport.width}`)\n if (viewport.initialScale !== undefined) parts.push(`initial-scale=${viewport.initialScale}`)\n if (viewport.maximumScale !== undefined) parts.push(`maximum-scale=${viewport.maximumScale}`)\n if (viewport.userScalable !== undefined) parts.push(`user-scalable=${viewport.userScalable ? 'yes' :\n 'no'}`)\n if (parts.length) tags.push({ tag: 'meta', name: 'viewport', content: parts.join(', ') })\n if (viewport.themeColor) tags.push({\n tag: 'meta', name: 'theme-color', content: viewport.themeColor\n })\n }\n\n return tags\n}\n\nexport function HeadSlot({ metadata, viewport }: { metadata: Metadata | null, viewport?: Viewport }) {\n if (typeof window === 'undefined' || !metadata) return null\n return <>{buildHeadNodes(metadata, viewport)}</>\n}\n\nexport function buildHeadNodes(metadata: Metadata, viewport?: Viewport): ReactNode {\n const tags = collectTags(metadata, viewport)\n\n return <>\n {tags.map((t, i) => {\n if (t.tag === 'title') return <title key={i}>{t.children}</title>\n if (t.tag === 'link') return <link key={i} rel={t.rel} href={t.href} hrefLang={t.hrefLang} type={t.type} sizes={t.sizes} />\n return <meta key={i} name={t.name} property={t.property} content={t.content} />\n })}\n </>\n}", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n", "import {ComponentType, ReactNode} from 'react'\nimport {RouterContext, PageMetaContext, RouteDataContext, NavigateOptions} from './context'\nimport {HeadSlot} from './head'\nimport {DevixErrorBoundary} from './error-boundary'\nimport {LayoutProps, PageProps} from '../server/types'\nimport {Metadata, Viewport} from '../types'\n\nconst noopNavigate = (_to: string, _opts?: NavigateOptions) => Promise.resolve()\nconst noopRevalidate = () => Promise.resolve()\n\nexport interface ServerAppProps {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry: string\n}\n\nexport function ServerApp({\n pathname, params, loaderData, layoutsData,\n Page, layouts, metadata, viewport, clientEntry,\n}: ServerAppProps) {\n let tree: ReactNode = (\n <RouteDataContext value={{loaderData, params}}>\n <Page data={loaderData as any} params={params} url={pathname}/>\n </RouteDataContext>\n )\n\n for (let i = layouts.length - 1; i >= 0; i--) {\n const Layout = layouts[i]\n const layoutData = layoutsData[i]\n tree = (\n <RouteDataContext value={{loaderData: layoutData, params}}>\n <Layout data={layoutData as any} params={params}>{tree}</Layout>\n </RouteDataContext>\n )\n }\n\n return (\n <PageMetaContext value={{metadata, viewport, clientEntry}}>\n <HeadSlot metadata={metadata} viewport={viewport}/>\n <RouterContext value={{\n pathname,\n params,\n loaderData,\n layoutsData,\n Page,\n layouts,\n metadata,\n viewport,\n isNavigating: false,\n navigate: noopNavigate,\n revalidate: noopRevalidate,\n }}>\n <DevixErrorBoundary key={pathname}>\n {tree}\n </DevixErrorBoundary>\n </RouterContext>\n </PageMetaContext>\n )\n}\n"],
|
|
5
|
-
"mappings": "AAAA,OAAQ,iBAAAA,MAA4C,
|
|
6
|
-
"names": ["createContext", "RouterContext", "PageMetaContext", "RouteDataContext", "Fragment", "jsx", "collectTags", "metadata", "viewport", "tags", "ogTitle", "ogDesc", "twTitle", "twDesc", "lang", "href", "raw", "icon", "resolved", "parts", "HeadSlot", "buildHeadNodes", "t", "i", "Component", "jsx", "DevixErrorBoundary", "err", "DevixError", "statusCode", "message", "jsx", "jsxs", "noopNavigate", "_to", "_opts", "noopRevalidate", "ServerApp", "pathname", "params", "loaderData", "layoutsData", "Page", "layouts", "metadata", "viewport", "clientEntry", "tree", "RouteDataContext", "i", "Layout", "layoutData", "PageMetaContext", "HeadSlot", "RouterContext", "DevixErrorBoundary"]
|
|
4
|
+
"sourcesContent": ["import {createContext, Context, ComponentType} from \"react\";\nimport {Metadata, Viewport} from \"../types\";\nimport {LayoutProps, PageProps} from \"../server/types\";\n\nexport interface NavigateOptions {\n replace?: boolean\n viewTransition?: boolean\n}\n\nexport interface RouterContextValue {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n navigate: (to: string, options?: NavigateOptions) => Promise<void>\n revalidate: () => Promise<void>\n prefetchRoute: (href: string) => void\n isNavigating: boolean\n}\n\nexport interface PageMetaContextValue {\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry?: string\n}\n\nexport interface RouteDataContextValue {\n loaderData: unknown\n params: Record<string, string>\n}\n\nconst g = globalThis as any\n\ng.__devix_RouterContext__ ??= createContext<RouterContextValue | null>(null)\nexport const RouterContext: Context<RouterContextValue | null> = g.__devix_RouterContext__\n\ng.__devix_PageMetaContext__ ??= createContext<PageMetaContextValue | null>(null)\ng.__devix_RouteDataContext__ ??= createContext<RouteDataContextValue | null>(null)\n\nexport const PageMetaContext: Context<PageMetaContextValue | null> = g.__devix_PageMetaContext__\nexport const RouteDataContext: Context<RouteDataContextValue | null> = g.__devix_RouteDataContext__\n\n", "import { Metadata, MetadataIcon, Viewport } from \"../types\";\nimport { ReactNode } from \"react\";\n\ntype MetaTag =\n | { tag: 'title'; children: string }\n | { tag: 'meta'; name?: string; property?: string; content: string }\n | { tag: 'link'; rel: string; href: string; hrefLang?: string; type?: string; sizes?: string }\n\nfunction collectTags(metadata: Metadata, viewport?: Viewport): MetaTag[] {\n const tags: MetaTag[] = []\n\n if (metadata.title)\n tags.push({ tag: 'title', children: metadata.title })\n if (metadata.description)\n tags.push({ tag: 'meta', name: 'description', content: metadata.description })\n if (metadata.keywords?.length)\n tags.push({ tag: 'meta', name: 'keywords', content: metadata.keywords.join(', ') })\n\n const ogTitle = metadata.og?.title ?? metadata.title\n if (ogTitle) tags.push({ tag: 'meta', property: 'og:title', content: ogTitle })\n const ogDesc = metadata.og?.description ?? metadata.description\n if (ogDesc) tags.push({ tag: 'meta', property: 'og:description', content: ogDesc })\n if (metadata.og?.image) tags.push({ tag: 'meta', property: 'og:image', content: metadata.og.image })\n if (metadata.og?.type) tags.push({ tag: 'meta', property: 'og:type', content: metadata.og.type })\n if (metadata.og?.url) tags.push({ tag: 'meta', property: 'og:url', content: metadata.og.url })\n\n const twTitle = metadata.twitter?.title ?? metadata.title\n if (twTitle) tags.push({ tag: 'meta', name: 'twitter:title', content: twTitle })\n const twDesc = metadata.twitter?.description ?? metadata.description\n if (twDesc) tags.push({ tag: 'meta', name: 'twitter:description', content: twDesc })\n if (metadata.twitter?.card) tags.push({\n tag: 'meta', name: 'twitter:card', content:\n metadata.twitter.card\n })\n if (metadata.twitter?.image) tags.push({\n tag: 'meta', name: 'twitter:image', content:\n metadata.twitter.image\n })\n if (metadata.twitter?.creator) tags.push({\n tag: 'meta', name: 'twitter:creator', content:\n metadata.twitter.creator\n })\n\n if (metadata.canonical) tags.push({ tag: 'link', rel: 'canonical', href: metadata.canonical })\n if (metadata.robots) tags.push({ tag: 'meta', name: 'robots', content: metadata.robots })\n if (metadata.alternates) {\n for (const [lang, href] of Object.entries(metadata.alternates))\n tags.push({ tag: 'link', rel: 'alternate', href, hrefLang: lang })\n }\n\n if (metadata.icons) {\n const raw = Array.isArray(metadata.icons) ? metadata.icons : [metadata.icons]\n for (const icon of raw) {\n const resolved: MetadataIcon = typeof icon === 'string' ? { href: icon } : icon\n tags.push({\n tag: 'link',\n rel: resolved.rel ?? 'icon',\n href: resolved.href,\n ...(resolved.type && { type: resolved.type }),\n ...(resolved.sizes && { sizes: resolved.sizes }),\n })\n }\n }\n\n if (viewport) {\n const parts: string[] = []\n if (viewport.width !== undefined) parts.push(`width=${viewport.width}`)\n if (viewport.initialScale !== undefined) parts.push(`initial-scale=${viewport.initialScale}`)\n if (viewport.maximumScale !== undefined) parts.push(`maximum-scale=${viewport.maximumScale}`)\n if (viewport.userScalable !== undefined) parts.push(`user-scalable=${viewport.userScalable ? 'yes' :\n 'no'}`)\n if (parts.length) tags.push({ tag: 'meta', name: 'viewport', content: parts.join(', ') })\n if (viewport.themeColor) tags.push({\n tag: 'meta', name: 'theme-color', content: viewport.themeColor\n })\n }\n\n return tags\n}\n\nexport function HeadSlot({ metadata, viewport }: { metadata: Metadata | null, viewport?: Viewport }) {\n if (typeof window === 'undefined' || !metadata) return null\n return <>{buildHeadNodes(metadata, viewport)}</>\n}\n\nexport function buildHeadNodes(metadata: Metadata, viewport?: Viewport): ReactNode {\n const tags = collectTags(metadata, viewport)\n\n return <>\n {tags.map((t, i) => {\n if (t.tag === 'title') return <title key={i}>{t.children}</title>\n if (t.tag === 'link') return <link key={i} rel={t.rel} href={t.href} hrefLang={t.hrefLang} type={t.type} sizes={t.sizes} />\n return <meta key={i} name={t.name} property={t.property} content={t.content} />\n })}\n </>\n}", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n", "import {ComponentType, ReactNode} from 'react'\nimport {RouterContext, PageMetaContext, RouteDataContext, NavigateOptions} from './context'\nimport {HeadSlot} from './head'\nimport {DevixErrorBoundary} from './error-boundary'\nimport {LayoutProps, PageProps} from '../server/types'\nimport {Metadata, Viewport} from '../types'\n\nconst noopNavigate = (_to: string, _opts?: NavigateOptions) => Promise.resolve()\nconst noopRevalidate = () => Promise.resolve()\nconst noopPrefetch = (_href: string) => {}\n\nexport interface ServerAppProps {\n pathname: string\n params: Record<string, string>\n loaderData: unknown\n layoutsData: unknown[]\n Page: ComponentType<PageProps>\n layouts: ComponentType<LayoutProps>[]\n metadata: Metadata | null\n viewport?: Viewport\n clientEntry: string\n}\n\nexport function ServerApp({\n pathname, params, loaderData, layoutsData,\n Page, layouts, metadata, viewport, clientEntry,\n}: ServerAppProps) {\n let tree: ReactNode = (\n <RouteDataContext value={{loaderData, params}}>\n <Page data={loaderData as any} params={params} url={pathname}/>\n </RouteDataContext>\n )\n\n for (let i = layouts.length - 1; i >= 0; i--) {\n const Layout = layouts[i]\n const layoutData = layoutsData[i]\n tree = (\n <RouteDataContext value={{loaderData: layoutData, params}}>\n <Layout data={layoutData as any} params={params}>{tree}</Layout>\n </RouteDataContext>\n )\n }\n\n return (\n <PageMetaContext value={{metadata, viewport, clientEntry}}>\n <HeadSlot metadata={metadata} viewport={viewport}/>\n <RouterContext value={{\n pathname,\n params,\n loaderData,\n layoutsData,\n Page,\n layouts,\n metadata,\n viewport,\n isNavigating: false,\n navigate: noopNavigate,\n revalidate: noopRevalidate,\n prefetchRoute: noopPrefetch,\n }}>\n <DevixErrorBoundary key={pathname}>\n {tree}\n </DevixErrorBoundary>\n </RouterContext>\n </PageMetaContext>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["createContext", "RouterContext", "PageMetaContext", "RouteDataContext", "Fragment", "jsx", "collectTags", "metadata", "viewport", "tags", "ogTitle", "ogDesc", "twTitle", "twDesc", "lang", "href", "raw", "icon", "resolved", "parts", "HeadSlot", "buildHeadNodes", "t", "i", "Component", "jsx", "DevixErrorBoundary", "err", "DevixError", "statusCode", "message", "jsx", "jsxs", "noopNavigate", "_to", "_opts", "noopRevalidate", "noopPrefetch", "_href", "ServerApp", "pathname", "params", "loaderData", "layoutsData", "Page", "layouts", "metadata", "viewport", "clientEntry", "tree", "RouteDataContext", "i", "Layout", "layoutData", "PageMetaContext", "HeadSlot", "RouterContext", "DevixErrorBoundary"]
|
|
7
7
|
}
|
|
@@ -13,7 +13,6 @@ export interface ApiResult {
|
|
|
13
13
|
middlewares: ApiMiddleware[];
|
|
14
14
|
}
|
|
15
15
|
export declare function keyToRoutePattern(key: string, apiDir: string): string;
|
|
16
|
-
export declare function invalidateApiCache(): void;
|
|
17
16
|
export declare function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult;
|
|
18
17
|
export declare function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[];
|
|
19
18
|
export declare function matchRoute(pathname: string, routes: ApiRoute[]): {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function c(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function u(e,o){let n=e.slice(o.length+1).replace(/\\/g,"/"),t=c(n);return t==="/"?"/api":`/api/${t}`.replace("/api//","/api/")}function g(e){return e.slice(0,e.lastIndexOf("/"))}function f(e,o,n){let t=[],s=[];for(let r of o)s.push({dir:g(r),key:r});for(let r of e){let i=u(r,n),a=[...i.matchAll(/:([^/]+)/g)].map(l=>l[1]),p=i.replace(/:[^/]+/g,"([^/]+)").replace(/\//g,"\\/");t.push({path:i,key:r,params:a,regex:new RegExp(`^${p}$`)})}return t.sort((r,i)=>{let a=(r.path.match(/:/g)||[]).length,p=(i.path.match(/:/g)||[]).length;return a!==p?a-p:i.path.length-r.path.length}),{routes:t,middlewares:s}}function x(e,o){let n=g(e);return o.filter(t=>n.startsWith(t.dir)).sort((t,s)=>t.dir.split("/").length-s.dir.split("/").length)}function m(e,o){for(let n of o){let t=e.match(n.regex);if(t){let s={};return n.params.forEach((r,i)=>{s[r]=decodeURIComponent(t[i+1])}),{route:n,params:s}}}return null}export{f as buildRoutes,x as collectMiddlewareChain,u as keyToRoutePattern,m as matchRoute};
|
|
2
2
|
//# sourceMappingURL=api-router.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/patterns.ts", "../../src/server/api-router.ts"],
|
|
4
|
-
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\
|
|
5
|
-
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,EAAkBC,EAAaC,EAAwB,CACnE,IAAMC,EAAMF,EAAI,MAAMC,EAAO,OAAS,CAAC,EAAE,QAAQ,MAAO,GAAG,EACrDE,EAAUC,EAAaF,CAAG,EAChC,OAAOC,IAAY,IAAM,OAAS,QAAQA,CAAO,GAAG,QAAQ,SAAU,OAAO,CACjF,CAEA,SAASE,EAASL,EAAqB,CACnC,OAAOA,EAAI,MAAM,EAAGA,EAAI,YAAY,GAAG,CAAC,CAC5C,
|
|
6
|
-
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "keyToDir", "
|
|
4
|
+
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n return {routes, middlewares}\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): { route: ApiRoute; params: Record<string, string> } | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n"],
|
|
5
|
+
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,EAAkBC,EAAaC,EAAwB,CACnE,IAAMC,EAAMF,EAAI,MAAMC,EAAO,OAAS,CAAC,EAAE,QAAQ,MAAO,GAAG,EACrDE,EAAUC,EAAaF,CAAG,EAChC,OAAOC,IAAY,IAAM,OAAS,QAAQA,CAAO,GAAG,QAAQ,SAAU,OAAO,CACjF,CAEA,SAASE,EAASL,EAAqB,CACnC,OAAOA,EAAI,MAAM,EAAGA,EAAI,YAAY,GAAG,CAAC,CAC5C,CAEO,SAASM,EAAYC,EAAqBC,EAA0BP,EAA2B,CAClG,IAAMQ,EAAqB,CAAC,EACtBC,EAA+B,CAAC,EAEtC,QAAWV,KAAOQ,EACdE,EAAY,KAAK,CAAC,IAAKL,EAASL,CAAG,EAAG,IAAAA,CAAG,CAAC,EAG9C,QAAWA,KAAOO,EAAW,CACzB,IAAMJ,EAAUJ,EAAkBC,EAAKC,CAAM,EACvCU,EAAS,CAAC,GAAGR,EAAQ,SAAS,WAAW,CAAC,EAAE,IAAIS,GAAKA,EAAE,CAAC,CAAC,EACzDC,EAAWV,EACZ,QAAQ,UAAW,SAAS,EAC5B,QAAQ,MAAO,KAAK,EACzBM,EAAO,KAAK,CAAC,KAAMN,EAAS,IAAAH,EAAK,OAAAW,EAAQ,MAAO,IAAI,OAAO,IAAIE,CAAQ,GAAG,CAAC,CAAC,CAChF,CACA,OAAAJ,EAAO,KAAK,CAACK,EAAGC,IAAM,CAClB,IAAMC,GAAUF,EAAE,KAAK,MAAM,IAAI,GAAK,CAAC,GAAG,OACpCG,GAAUF,EAAE,KAAK,MAAM,IAAI,GAAK,CAAC,GAAG,OAC1C,OAAIC,IAAWC,EAAeD,EAASC,EAChCF,EAAE,KAAK,OAASD,EAAE,KAAK,MAClC,CAAC,EAEM,CAAC,OAAAL,EAAQ,YAAAC,CAAW,CAC/B,CAEO,SAASQ,EAAuBC,EAAkBT,EAA+C,CACpG,IAAMU,EAAWf,EAASc,CAAQ,EAElC,OAAOT,EACF,OAAOW,GAAMD,EAAS,WAAWC,EAAG,GAAG,CAAC,EACxC,KAAK,CAACP,EAAGC,IAAMD,EAAE,IAAI,MAAM,GAAG,EAAE,OAASC,EAAE,IAAI,MAAM,GAAG,EAAE,MAAM,CACzE,CAEO,SAASO,EACZC,EACAd,EAC0D,CAC1D,QAAWe,KAASf,EAAQ,CACxB,IAAMgB,EAAQF,EAAS,MAAMC,EAAM,KAAK,EACxC,GAAIC,EAAO,CACP,IAAMd,EAAiC,CAAC,EACxC,OAAAa,EAAM,OAAO,QAAQ,CAACE,EAAM,IAAM,CAC9Bf,EAAOe,CAAI,EAAI,mBAAmBD,EAAM,EAAI,CAAC,CAAC,CAClD,CAAC,EACM,CAAC,MAAAD,EAAO,OAAAb,CAAM,CACzB,CACJ,CACA,OAAO,IACX",
|
|
6
|
+
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "keyToDir", "buildRoutes", "routeKeys", "middlewareKeys", "routes", "middlewares", "params", "m", "regexStr", "a", "b", "aScore", "bScore", "collectMiddlewareChain", "routeKey", "routeDir", "mw", "matchRoute", "pathname", "route", "match", "name"]
|
|
7
7
|
}
|
package/dist/server/api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function w(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function _(e,t){let r=e.slice(t.length+1).replace(/\\/g,"/"),n=w(r);return n==="/"?"/api":`/api/${n}`.replace("/api//","/api/")}function A(e){return e.slice(0,e.lastIndexOf("/"))}function T(e,t,r){let n=[],s=[];for(let o of t)s.push({dir:A(o),key:o});for(let o of e){let a=_(o,r),i=[...a.matchAll(/:([^/]+)/g)].map(c=>c[1]),u=a.replace(/:[^/]+/g,"([^/]+)").replace(/\//g,"\\/");n.push({path:a,key:o,params:i,regex:new RegExp(`^${u}$`)})}return n.sort((o,a)=>{let i=(o.path.match(/:/g)||[]).length,u=(a.path.match(/:/g)||[]).length;return i!==u?i-u:a.path.length-o.path.length}),{routes:n,middlewares:s}}function H(e,t){let r=A(e);return t.filter(n=>r.startsWith(n.dir)).sort((n,s)=>n.dir.split("/").length-s.dir.split("/").length)}function C(e,t){for(let r of t){let n=e.match(r.regex);if(n){let s={};return r.params.forEach((o,a)=>{s[o]=decodeURIComponent(n[a+1])}),{route:r,params:s}}}return null}var l=class{params;_state=new Map;constructor(t={}){this.params=t}set(t,r){this._state.set(t,r)}get(t){return this._state.get(t)}};import{Component as I}from"react";import{jsx as W}from"react/jsx-runtime";var p=class extends Error{statusCode;constructor(t,r){super(r),this.statusCode=t}};var S="__devix_handler__";import{AsyncLocalStorage as N}from"node:async_hooks";var R=Symbol.for("@devlusoft/devix.handlerStore"),g=globalThis;g[R]||(g[R]=new N);var b=g[R];function E(e,t){return b.run(e,t)}var y=null,k=null;function j(e){return typeof e=="object"&&e!==null&&S in e}async function B(e){let t=e.headers.get("Content-Type")??"";return t.includes("application/json")?e.json():t.includes("multipart/form-data")||t.includes("application/x-www-form-urlencoded")?e.formData():e.text()}function F(e){return e instanceof Response?e:e==null?new Response(null,{status:204}):new Response(JSON.stringify(e),{headers:{"Content-Type":"application/json"}})}async function oe(e,t,r){try{let{pathname:n}=new URL(e,"http://localhost"),s=Object.keys(r.routes).sort().join("\0")+"|"+Object.keys(r.middlewares).sort().join("\0");(!y||k!==s)&&(y=T(Object.keys(r.routes),Object.keys(r.middlewares),r.apiDir),k=s);let{routes:o,middlewares:a}=y,i=C(n,o);if(!i)return new Response("Not Found",{status:404});let{route:u,params:c}=i,f=new l(c),P=await E({request:t,ctx:f},async()=>{let D=H(u.key,a);for(let m of D){let x=await r.middlewares[m.key]();if(x.middleware){let h=await x.middleware(f,t);if(h instanceof Response)return h}}let M=await r.routes[u.key](),v=t.method.toUpperCase(),d=M[v];if(!d)return new Response("Method Not Allowed",{status:405});if(j(d)){if(d.fn.length===0)return d.fn();let m=await B(t);return d.fn(m)}return d(f,t)});return F(P)}catch(n){return console.error("[devix] api error:",n),n instanceof p?new Response(n.message,{status:n.statusCode}):new Response("Internal Server Error",{status:500})}}export{oe as handleApiRequest};
|
|
2
2
|
//# sourceMappingURL=api.js.map
|
package/dist/server/api.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/patterns.ts", "../../src/server/api-router.ts", "../../src/runtime/api-context.ts", "../../src/runtime/error-boundary.tsx", "../../src/runtime/create-handler.ts", "../../src/server/handler-store.ts", "../../src/server/api.ts"],
|
|
4
|
-
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nlet cache: ApiResult | null = null\n\nexport function invalidateApiCache() {\n cache = null\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n if (cache) return cache\n\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n cache = {routes, middlewares}\n return cache\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): {route: ApiRoute; params: Record<string, string>} | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "import type {DevixHandler} from './create-handler'\n\nexport class RouteContext {\n readonly params: Record<string, string>\n private _state = new Map<string, unknown>()\n\n constructor(params: Record<string, string> = {}) {\n this.params = params\n }\n\n set<T>(key: string, value: T): void {\n this._state.set(key, value)\n }\n\n get<T>(key: string): T | undefined {\n return this._state.get(key) as T\n }\n}\n\nexport type RouteResult = Response | Record<string, unknown> | unknown[] | null | void\n\nexport type RouteHandler = (ctx: RouteContext, req: Request) => Promise<RouteResult> | RouteResult\n\nexport interface MiddlewareModule {\n middleware: (ctx: RouteContext, req: Request) => Promise<Response | null> | Response | null\n}\n\ntype AnyHandler = RouteHandler | DevixHandler<any, any>\n\nexport interface RouteModule {\n GET?: AnyHandler\n POST?: AnyHandler\n PUT?: AnyHandler\n PATCH?: AnyHandler\n DELETE?: AnyHandler\n HEAD?: AnyHandler\n OPTIONS?: AnyHandler\n}\n", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n", "export const HANDLER_BRAND = '__devix_handler__' as const\n\nexport interface DevixHandler<TBody = undefined, TReturn = unknown> {\n readonly [HANDLER_BRAND]: true\n readonly fn: (...args: any[]) => any\n readonly __body: TBody\n readonly __return: TReturn\n}\n\ntype ExtractBody<TFn> = TFn extends (body: infer B) => any ? B : undefined\n\nexport function createHandler<TFn extends (...args: any[]) => any>(\n fn: TFn,\n): DevixHandler<ExtractBody<TFn>, Awaited<ReturnType<TFn>>> {\n return {[HANDLER_BRAND]: true, fn} as unknown as DevixHandler<ExtractBody<TFn>, Awaited<ReturnType<TFn>>>\n}\n", "import {AsyncLocalStorage} from 'node:async_hooks'\nimport type {RouteContext} from '../runtime/api-context'\n\ninterface HandlerStore {\n request: Request\n ctx: RouteContext\n}\n\nconst ALS_KEY = Symbol.for('@devlusoft/devix.handlerStore')\nconst g = globalThis as Record<symbol, unknown>\nif (!g[ALS_KEY]) g[ALS_KEY] = new AsyncLocalStorage<HandlerStore>()\nconst storage = g[ALS_KEY] as AsyncLocalStorage<HandlerStore>\n\nexport function withHandlerStore<T>(store: HandlerStore, fn: () => T): T {\n return storage.run(store, fn)\n}\n\nfunction getStore(hookName: string): HandlerStore {\n const store = storage.getStore()\n if (!store) throw new Error(`[devix] ${hookName}() called outside of a request handler`)\n return store\n}\n\nexport function useRequest(): Request {\n return getStore('useRequest').request\n}\n\nexport function useCtx(): RouteContext {\n return getStore('useCtx').ctx\n}\n\nexport function useParams(): Record<string, string> {\n return getStore('useParams').ctx.params\n}\n", "import {buildRoutes, matchRoute, collectMiddlewareChain} from './api-router'\nimport {RouteContext} from '../runtime/api-context'\nimport type {RouteModule, MiddlewareModule, RouteResult} from '../runtime/api-context'\nimport type {ApiGlob} from './types'\nimport {DevixError} from '../runtime/error-boundary'\nimport {HANDLER_BRAND, type DevixHandler} from '../runtime/create-handler'\nimport {withHandlerStore} from './handler-store'\n\nfunction isDevixHandler(h: unknown): h is DevixHandler<any, any> {\n return typeof h === 'object' && h !== null && HANDLER_BRAND in h\n}\n\nasync function parseBody(request: Request): Promise<unknown> {\n const ct = request.headers.get('Content-Type') ?? ''\n if (ct.includes('application/json')) return request.json()\n if (ct.includes('multipart/form-data') || ct.includes('application/x-www-form-urlencoded')) {\n return request.formData()\n }\n return request.text()\n}\n\nfunction resultToResponse(result: RouteResult): Response {\n if (result instanceof Response) return result\n if (result == null) return new Response(null, {status: 204})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n}\n\nexport async function handleApiRequest(\n url: string,\n request: Request,\n glob: ApiGlob,\n): Promise<Response> {\n try {\n const {pathname} = new URL(url, 'http://localhost')\n const {routes, middlewares} = buildRoutes(\n Object.keys(glob.routes),\n Object.keys(glob.middlewares),\n glob.apiDir,\n )\n const matched = matchRoute(pathname, routes)\n\n if (!matched) return new Response('Not Found', {status: 404})\n\n const {route, params} = matched\n const ctx = new RouteContext(params)\n\n const result = await withHandlerStore({request, ctx}, async () => {\n const middlewareChain = collectMiddlewareChain(route.key, middlewares)\n for (const mw of middlewareChain) {\n const mod = await glob.middlewares[mw.key]() as MiddlewareModule\n if (mod.middleware) {\n const mwResult = await mod.middleware(ctx, request)\n if (mwResult instanceof Response) return mwResult\n }\n }\n\n const mod = await glob.routes[route.key]() as RouteModule\n const method = request.method.toUpperCase() as keyof RouteModule\n const handler = mod[method]\n\n if (!handler) return new Response('Method Not Allowed', {status: 405})\n\n if (isDevixHandler(handler)) {\n if (handler.fn.length === 0) {\n return handler.fn() as Promise<RouteResult>\n }\n const body = await parseBody(request)\n return handler.fn(body) as Promise<RouteResult>\n }\n\n return handler(ctx, request)\n })\n\n return resultToResponse(result)\n } catch (err) {\n console.error('[devix] api error:', err)\n if (err instanceof DevixError) {\n return new Response(err.message, {status: err.statusCode})\n }\n return new Response('Internal Server Error', {status: 500})\n }\n}\n"],
|
|
5
|
-
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYO,SAASC,EAAkBC,EAAaC,EAAwB,CACnE,IAAMC,EAAMF,EAAI,MAAMC,EAAO,OAAS,CAAC,EAAE,QAAQ,MAAO,GAAG,EACrDE,EAAUC,EAAaF,CAAG,EAChC,OAAOC,IAAY,IAAM,OAAS,QAAQA,CAAO,GAAG,QAAQ,SAAU,OAAO,CACjF,CAEA,SAASE,EAASL,EAAqB,CACnC,OAAOA,EAAI,MAAM,EAAGA,EAAI,YAAY,GAAG,CAAC,CAC5C,
|
|
6
|
-
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "keyToDir", "
|
|
4
|
+
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n return {routes, middlewares}\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): { route: ApiRoute; params: Record<string, string> } | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "import type {DevixHandler} from './create-handler'\n\nexport class RouteContext {\n readonly params: Record<string, string>\n private _state = new Map<string, unknown>()\n\n constructor(params: Record<string, string> = {}) {\n this.params = params\n }\n\n set<T>(key: string, value: T): void {\n this._state.set(key, value)\n }\n\n get<T>(key: string): T | undefined {\n return this._state.get(key) as T\n }\n}\n\nexport type RouteResult = Response | Record<string, unknown> | unknown[] | null | void\n\nexport type RouteHandler = (ctx: RouteContext, req: Request) => Promise<RouteResult> | RouteResult\n\nexport interface MiddlewareModule {\n middleware: (ctx: RouteContext, req: Request) => Promise<Response | null> | Response | null\n}\n\ntype AnyHandler = RouteHandler | DevixHandler<any, any>\n\nexport interface RouteModule {\n GET?: AnyHandler\n POST?: AnyHandler\n PUT?: AnyHandler\n PATCH?: AnyHandler\n DELETE?: AnyHandler\n HEAD?: AnyHandler\n OPTIONS?: AnyHandler\n}\n", "import {Component, ComponentType, ReactNode} from \"react\";\nimport {ErrorProps} from \"../server/types\";\n\ninterface Props {\n ErrorPage?: ComponentType<ErrorProps>\n children: ReactNode\n}\n\ninterface State {\n error: ErrorProps | null\n}\n\nexport class DevixErrorBoundary extends Component<Props, State> {\n state: State = { error: null }\n\n static getDerivedStateFromError(err: unknown): State {\n if (err instanceof DevixError) {\n return {\n error: {statusCode: err.statusCode, message: err.message}\n }\n }\n return {\n error: {statusCode: 500, message: err instanceof Error ? err.message : 'Unknown error'}\n }\n }\n\n render() {\n if (this.state.error && this.props.ErrorPage) {\n return <this.props.ErrorPage {...this.state.error} />\n }\n if (this.state.error) {\n return <h1>{this.state.error.statusCode}</h1>\n }\n return this.props.children\n }\n}\n\nexport class DevixError extends Error {\n statusCode: number\n constructor(statusCode: number, message: string) {\n super(message)\n this.statusCode = statusCode\n }\n}\n", "export const HANDLER_BRAND = '__devix_handler__' as const\n\nexport interface DevixHandler<TBody = undefined, TReturn = unknown> {\n readonly [HANDLER_BRAND]: true\n readonly fn: (...args: any[]) => any\n readonly __body: TBody\n readonly __return: TReturn\n}\n\ntype ExtractBody<TFn> = TFn extends (body: infer B) => any ? B : undefined\n\nexport function createHandler<TFn extends (...args: any[]) => any>(\n fn: TFn,\n): DevixHandler<ExtractBody<TFn>, Awaited<ReturnType<TFn>>> {\n return {[HANDLER_BRAND]: true, fn} as unknown as DevixHandler<ExtractBody<TFn>, Awaited<ReturnType<TFn>>>\n}\n", "import {AsyncLocalStorage} from 'node:async_hooks'\nimport type {RouteContext} from '../runtime/api-context'\n\ninterface HandlerStore {\n request: Request\n ctx: RouteContext\n}\n\nconst ALS_KEY = Symbol.for('@devlusoft/devix.handlerStore')\nconst g = globalThis as Record<symbol, unknown>\nif (!g[ALS_KEY]) g[ALS_KEY] = new AsyncLocalStorage<HandlerStore>()\nconst storage = g[ALS_KEY] as AsyncLocalStorage<HandlerStore>\n\nexport function withHandlerStore<T>(store: HandlerStore, fn: () => T): T {\n return storage.run(store, fn)\n}\n\nfunction getStore(hookName: string): HandlerStore {\n const store = storage.getStore()\n if (!store) throw new Error(`[devix] ${hookName}() called outside of a request handler`)\n return store\n}\n\nexport function useRequest(): Request {\n return getStore('useRequest').request\n}\n\nexport function useCtx(): RouteContext {\n return getStore('useCtx').ctx\n}\n\nexport function useParams(): Record<string, string> {\n return getStore('useParams').ctx.params\n}\n", "import {buildRoutes, matchRoute, collectMiddlewareChain, ApiResult} from './api-router'\nimport {RouteContext} from '../runtime/api-context'\nimport type {RouteModule, MiddlewareModule, RouteResult} from '../runtime/api-context'\nimport type {ApiGlob} from './types'\nimport {DevixError} from '../runtime/error-boundary'\nimport {HANDLER_BRAND, type DevixHandler} from '../runtime/create-handler'\nimport {withHandlerStore} from './handler-store'\n\nlet apiCache: ApiResult | null = null\nlet apiCacheKey: string | null = null\n\nfunction isDevixHandler(h: unknown): h is DevixHandler<any, any> {\n return typeof h === 'object' && h !== null && HANDLER_BRAND in h\n}\n\nasync function parseBody(request: Request): Promise<unknown> {\n const ct = request.headers.get('Content-Type') ?? ''\n if (ct.includes('application/json')) return request.json()\n if (ct.includes('multipart/form-data') || ct.includes('application/x-www-form-urlencoded')) {\n return request.formData()\n }\n return request.text()\n}\n\nfunction resultToResponse(result: RouteResult): Response {\n if (result instanceof Response) return result\n if (result == null) return new Response(null, {status: 204})\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\n}\n\nexport async function handleApiRequest(\n url: string,\n request: Request,\n glob: ApiGlob,\n): Promise<Response> {\n try {\n const {pathname} = new URL(url, 'http://localhost')\n const cacheKey = Object.keys(glob.routes).sort().join('\\0') + '|' + Object.keys(glob.middlewares).sort().join('\\0')\n if (!apiCache || apiCacheKey !== cacheKey) {\n apiCache = buildRoutes(\n Object.keys(glob.routes),\n Object.keys(glob.middlewares),\n glob.apiDir,\n )\n apiCacheKey = cacheKey\n }\n const {routes, middlewares} = apiCache\n const matched = matchRoute(pathname, routes)\n\n if (!matched) return new Response('Not Found', {status: 404})\n\n const {route, params} = matched\n const ctx = new RouteContext(params)\n\n const result = await withHandlerStore({request, ctx}, async () => {\n const middlewareChain = collectMiddlewareChain(route.key, middlewares)\n for (const mw of middlewareChain) {\n const mod = await glob.middlewares[mw.key]() as MiddlewareModule\n if (mod.middleware) {\n const mwResult = await mod.middleware(ctx, request)\n if (mwResult instanceof Response) return mwResult\n }\n }\n\n const mod = await glob.routes[route.key]() as RouteModule\n const method = request.method.toUpperCase() as keyof RouteModule\n const handler = mod[method]\n\n if (!handler) return new Response('Method Not Allowed', {status: 405})\n\n if (isDevixHandler(handler)) {\n if (handler.fn.length === 0) {\n return handler.fn() as Promise<RouteResult>\n }\n const body = await parseBody(request)\n return handler.fn(body) as Promise<RouteResult>\n }\n\n return handler(ctx, request)\n })\n\n return resultToResponse(result)\n } catch (err) {\n console.error('[devix] api error:', err)\n if (err instanceof DevixError) {\n return new Response(err.message, {status: err.statusCode})\n }\n return new Response('Internal Server Error', {status: 500})\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "keyToDir", "buildRoutes", "routeKeys", "middlewareKeys", "routes", "middlewares", "params", "m", "regexStr", "a", "b", "aScore", "bScore", "collectMiddlewareChain", "routeKey", "routeDir", "mw", "matchRoute", "pathname", "route", "match", "name", "i", "RouteContext", "params", "key", "value", "Component", "jsx", "DevixError", "statusCode", "message", "HANDLER_BRAND", "AsyncLocalStorage", "ALS_KEY", "storage", "withHandlerStore", "store", "fn", "apiCache", "apiCacheKey", "isDevixHandler", "h", "HANDLER_BRAND", "parseBody", "request", "ct", "resultToResponse", "result", "handleApiRequest", "url", "glob", "pathname", "cacheKey", "buildRoutes", "routes", "middlewares", "matched", "matchRoute", "route", "params", "ctx", "RouteContext", "withHandlerStore", "middlewareChain", "collectMiddlewareChain", "mw", "mod", "mwResult", "method", "handler", "body", "err", "DevixError"]
|
|
7
7
|
}
|
package/dist/server/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function l(t){return t.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function m(t,r){let a=t.slice(r.length+1).replace(/\\/g,"/"),e=l(a);return e==="/"?"/":`/${e}`}function f(t){return t.slice(0,t.lastIndexOf("/"))}function x(t,r,a){let e=[],o=[];for(let n of r)o.push({dir:f(n),key:n});for(let n of t){let i=m(n,a),s=[...i.matchAll(/:([^/]+)/g)].map(c=>c[1]),p=i.replace(/:[^/]+/g,"([^/]+)").replace(/\//g,"\\/");e.push({path:i,key:n,params:s,regex:new RegExp(`^${p}$`)})}return e.sort((n,i)=>{let s=n.path.split("/").filter(Boolean),p=i.path.split("/").filter(Boolean),c=Math.max(s.length,p.length);for(let g=0;g<c;g++){let u=g<s.length?s[g].startsWith(":")?1:2:0,d=g<p.length?p[g].startsWith(":")?1:2:0;if(u!==d)return d-u}return i.path.length-n.path.length}),{pages:e,layouts:o}}function R(t,r){let a=f(t);return r.filter(e=>a.startsWith(e.dir)).sort((e,o)=>e.dir.split("/").length-o.dir.split("/").length)}function y(t,r){for(let a of r){let e=t.match(a.regex);if(e){let o={};return a.params.forEach((n,i)=>{o[n]=decodeURIComponent(e[i+1])}),{page:a,params:o}}}return null}function M(t,r){let a=t.slice(r.length+1).replace(/\\/g,"/"),e=l(a);return e==="/"?"/api":`/api/${e}`.replace("/api//","/api/")}function h(t){return t.slice(0,t.lastIndexOf("/"))}function w(t,r,a){let e=[],o=[];for(let n of r)o.push({dir:h(n),key:n});for(let n of t){let i=M(n,a),s=[...i.matchAll(/:([^/]+)/g)].map(c=>c[1]),p=i.replace(/:[^/]+/g,"([^/]+)").replace(/\//g,"\\/");e.push({path:i,key:n,params:s,regex:new RegExp(`^${p}$`)})}return e.sort((n,i)=>{let s=(n.path.match(/:/g)||[]).length,p=(i.path.match(/:/g)||[]).length;return s!==p?s-p:i.path.length-n.path.length}),{routes:e,middlewares:o}}function P(t,r){let a=h(t);return r.filter(e=>a.startsWith(e.dir)).sort((e,o)=>e.dir.split("/").length-o.dir.split("/").length)}function A(t,r){for(let a of r){let e=t.match(a.regex);if(e){let o={};return a.params.forEach((n,i)=>{o[n]=decodeURIComponent(e[i+1])}),{route:a,params:o}}}return null}async function L(t,r){let a=t.generateMetadata?await t.generateMetadata(r):t.metadata??{},e=t.generateViewport?await t.generateViewport(r):t.viewport;return{metadata:a,viewport:e}}function k(...t){let r={};for(let a of t){if(!a)continue;let{og:e,twitter:o,...n}=a;Object.assign(r,n),e&&(r.og={...r.og,...e}),o&&(r.twitter={...r.twitter,...o})}return r}export{x as buildPages,w as buildRoutes,R as collectLayoutChain,P as collectMiddlewareChain,y as matchPage,A as matchRoute,k as mergeMetadata,L as resolveMetadata};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/server/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/patterns.ts", "../../src/server/pages-router.ts", "../../src/server/api-router.ts", "../../src/runtime/metadata.ts"],
|
|
4
|
-
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\
|
|
5
|
-
"mappings": "AAAO,SAASA,EAAaC,EAAqB,CAC9C,OAAOA,EACE,QAAQ,qBAAsB,EAAE,EAChC,QAAQ,aAAc,EAAE,EACxB,QAAQ,mBAAoB,EAAE,EAC9B,QAAQ,eAAgB,KAAK,GAC/B,GACX,CCYA,SAASC,EAAkBC,EAAaC,EAA0B,CAC9D,IAAMC,EAAMF,EAAI,MAAMC,EAAS,OAAS,CAAC,EAAE,QAAQ,MAAO,GAAG,EACvDE,EAAUC,EAAaF,CAAG,EAChC,OAAOC,IAAY,IAAM,IAAM,IAAIA,CAAO,EAC9C,CAEA,SAASE,EAASL,EAAqB,CACnC,OAAOA,EAAI,MAAM,EAAGA,EAAI,YAAY,GAAG,CAAC,CAC5C,
|
|
6
|
-
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "pagesDir", "rel", "pattern", "routePattern", "keyToDir", "
|
|
4
|
+
"sourcesContent": ["export function routePattern(rel: string): string {\n return rel\n .replace(/\\.(tsx|ts|jsx|js)$/, '')\n .replace(/\\(.*?\\)\\//g, '')\n .replace(/^index$|\\/index$/, '')\n .replace(/\\[([^\\]]+)]/g, ':$1')\n || '/'\n}", "import {routePattern} from \"../utils/patterns\";\n\nexport interface Page {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface Layout {\n dir: string\n key: string\n}\n\nexport interface PagesResult {\n pages: Page[]\n layouts: Layout[]\n}\n\nfunction keyToRoutePattern(key: string, pagesDir: string): string {\n const rel = key.slice(pagesDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === \"/\" ? \"/\" : `/${pattern}`\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n const pages: Page[] = []\n const layouts: Layout[] = []\n\n for (const key of layoutKeys) {\n layouts.push({dir: keyToDir(key), key})\n }\n\n for (const key of pageKeys) {\n const pattern = keyToRoutePattern(key, pagesDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n pages.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n\n pages.sort((a, b) => {\n const aSegs = a.path.split('/').filter(Boolean)\n const bSegs = b.path.split('/').filter(Boolean)\n const len = Math.max(aSegs.length, bSegs.length)\n for (let i = 0; i < len; i++) {\n const aVal = i < aSegs.length ? (aSegs[i].startsWith(':') ? 1 : 2) : 0\n const bVal = i < bSegs.length ? (bSegs[i].startsWith(':') ? 1 : 2) : 0\n if (aVal !== bVal) return bVal - aVal\n }\n return b.path.length - a.path.length\n })\n\n return {pages, layouts}\n}\n\nexport function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[] {\n const pageDir = keyToDir(pageKey)\n\n return layouts\n .filter(layout => pageDir.startsWith(layout.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchPage(pathname: string, pages: Page[]): {\n page: Page\n params: Record<string, string>\n} | null {\n for (const page of pages) {\n const match = pathname.match(page.regex)\n if (match) {\n const params: Record<string, string> = {}\n page.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {page, params}\n }\n }\n return null\n}\n", "import {routePattern} from \"../utils/patterns\";\n\nexport interface ApiRoute {\n path: string\n key: string\n params: string[]\n regex: RegExp\n}\n\nexport interface ApiMiddleware {\n dir: string\n key: string\n}\n\nexport interface ApiResult {\n routes: ApiRoute[]\n middlewares: ApiMiddleware[]\n}\n\nexport function keyToRoutePattern(key: string, apiDir: string): string {\n const rel = key.slice(apiDir.length + 1).replace(/\\\\/g, '/')\n const pattern = routePattern(rel)\n return pattern === '/' ? '/api' : `/api/${pattern}`.replace('/api//', '/api/')\n}\n\nfunction keyToDir(key: string): string {\n return key.slice(0, key.lastIndexOf('/'))\n}\n\nexport function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult {\n const routes: ApiRoute[] = []\n const middlewares: ApiMiddleware[] = []\n\n for (const key of middlewareKeys) {\n middlewares.push({dir: keyToDir(key), key})\n }\n\n for (const key of routeKeys) {\n const pattern = keyToRoutePattern(key, apiDir)\n const params = [...pattern.matchAll(/:([^/]+)/g)].map(m => m[1])\n const regexStr = pattern\n .replace(/:[^/]+/g, '([^/]+)')\n .replace(/\\//g, '\\\\/')\n routes.push({path: pattern, key, params, regex: new RegExp(`^${regexStr}$`)})\n }\n routes.sort((a, b) => {\n const aScore = (a.path.match(/:/g) || []).length\n const bScore = (b.path.match(/:/g) || []).length\n if (aScore !== bScore) return aScore - bScore\n return b.path.length - a.path.length\n })\n\n return {routes, middlewares}\n}\n\nexport function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[] {\n const routeDir = keyToDir(routeKey)\n\n return middlewares\n .filter(mw => routeDir.startsWith(mw.dir))\n .sort((a, b) => a.dir.split('/').length - b.dir.split('/').length)\n}\n\nexport function matchRoute(\n pathname: string,\n routes: ApiRoute[]\n): { route: ApiRoute; params: Record<string, string> } | null {\n for (const route of routes) {\n const match = pathname.match(route.regex)\n if (match) {\n const params: Record<string, string> = {}\n route.params.forEach((name, i) => {\n params[name] = decodeURIComponent(match[i + 1])\n })\n return {route, params}\n }\n }\n return null\n}\n", "import {LayoutModule, PageModule} from \"../server\";\nimport {LoaderContext, Metadata, Viewport} from \"../types\"\n\nexport interface ResolvedMeta {\n metadata: Metadata\n viewport?: Viewport\n}\n\nexport async function resolveMetadata(module: PageModule | LayoutModule, ctx: LoaderContext & {\n loaderData: unknown\n}): Promise<ResolvedMeta> {\n const metadata = module.generateMetadata\n ? await module.generateMetadata(ctx)\n : module.metadata ?? {}\n\n const viewport = module.generateViewport\n ? await module.generateViewport(ctx)\n : module.viewport\n\n return {metadata, viewport}\n}\n\nexport function mergeMetadata(...sources: (Metadata | null | undefined)[]): Metadata {\n const result: Metadata = {}\n\n for (const source of sources) {\n if (!source) continue\n const { og, twitter, ...rest } = source\n Object.assign(result, rest)\n if (og) result.og = { ...result.og, ...og }\n if (twitter) result.twitter = { ...result.twitter, ...twitter }\n }\n\n return result\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["routePattern", "rel", "keyToRoutePattern", "key", "pagesDir", "rel", "pattern", "routePattern", "keyToDir", "buildPages", "pageKeys", "layoutKeys", "pages", "layouts", "params", "m", "regexStr", "a", "b", "aSegs", "bSegs", "len", "i", "aVal", "bVal", "collectLayoutChain", "pageKey", "pageDir", "layout", "matchPage", "pathname", "page", "match", "name", "keyToRoutePattern", "key", "apiDir", "rel", "pattern", "routePattern", "keyToDir", "buildRoutes", "routeKeys", "middlewareKeys", "routes", "middlewares", "params", "m", "regexStr", "a", "b", "aScore", "bScore", "collectMiddlewareChain", "routeKey", "routeDir", "mw", "matchRoute", "pathname", "route", "match", "name", "resolveMetadata", "module", "ctx", "metadata", "viewport", "mergeMetadata", "sources", "result", "source", "og", "twitter", "rest"]
|
|
7
7
|
}
|
|
@@ -12,7 +12,6 @@ export interface PagesResult {
|
|
|
12
12
|
pages: Page[];
|
|
13
13
|
layouts: Layout[];
|
|
14
14
|
}
|
|
15
|
-
export declare function invalidatePagesCache(): void;
|
|
16
15
|
export declare function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult;
|
|
17
16
|
export declare function collectLayoutChain(pageKey: string, layouts: Layout[]): Layout[];
|
|
18
17
|
export declare function matchPage(pathname: string, pages: Page[]): {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
function
|
|
1
|
+
function h(e){return e.replace(/\.(tsx|ts|jsx|js)$/,"").replace(/\(.*?\)\//g,"").replace(/^index$|\/index$/,"").replace(/\[([^\]]+)]/g,":$1")||"/"}function x(e,a){let n=e.slice(a.length+1).replace(/\\/g,"/"),t=h(n);return t==="/"?"/":`/${t}`}function f(e){return e.slice(0,e.lastIndexOf("/"))}function y(e,a,n){let t=[],o=[];for(let r of a)o.push({dir:f(r),key:r});for(let r of e){let s=x(r,n),i=[...s.matchAll(/:([^/]+)/g)].map(l=>l[1]),c=s.replace(/:[^/]+/g,"([^/]+)").replace(/\//g,"\\/");t.push({path:s,key:r,params:i,regex:new RegExp(`^${c}$`)})}return t.sort((r,s)=>{let i=r.path.split("/").filter(Boolean),c=s.path.split("/").filter(Boolean),l=Math.max(i.length,c.length);for(let g=0;g<l;g++){let p=g<i.length?i[g].startsWith(":")?1:2:0,u=g<c.length?c[g].startsWith(":")?1:2:0;if(p!==u)return u-p}return s.path.length-r.path.length}),{pages:t,layouts:o}}function P(e,a){let n=f(e);return a.filter(t=>n.startsWith(t.dir)).sort((t,o)=>t.dir.split("/").length-o.dir.split("/").length)}function R(e,a){for(let n of a){let t=e.match(n.regex);if(t){let o={};return n.params.forEach((r,s)=>{o[r]=decodeURIComponent(t[s+1])}),{page:n,params:o}}}return null}export{y as buildPages,P as collectLayoutChain,R as matchPage};
|
|
2
2
|
//# sourceMappingURL=pages-router.js.map
|