@devlusoft/devix 0.1.0 → 0.2.0
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/README.md +6 -4
- package/dist/cli/build.js +145 -6
- package/dist/cli/build.js.map +4 -4
- package/dist/cli/dev.js +155 -4
- package/dist/cli/dev.js.map +4 -4
- package/dist/cli/generate.js +174 -12
- package/dist/cli/generate.js.map +4 -4
- package/dist/cli/index.js +200 -18
- package/dist/cli/index.js.map +4 -4
- package/dist/cli/start.js +12 -0
- package/dist/cli/start.js.map +3 -3
- package/dist/runtime/api-context.d.ts +3 -2
- package/dist/runtime/api-context.js.map +1 -1
- package/dist/runtime/fetch.d.ts +19 -0
- package/dist/runtime/fetch.js +35 -0
- package/dist/runtime/fetch.js.map +7 -0
- package/dist/runtime/index.d.ts +6 -1
- package/dist/runtime/index.js +68 -0
- package/dist/runtime/index.js.map +3 -3
- package/dist/server/api-router.d.ts +1 -0
- package/dist/server/api-router.js +1 -0
- package/dist/server/api-router.js.map +2 -2
- package/dist/server/api.js +1 -0
- package/dist/server/api.js.map +2 -2
- package/dist/server/index.js.map +2 -2
- package/dist/utils/cookies.d.ts +12 -0
- package/dist/utils/cookies.js +29 -0
- package/dist/utils/cookies.js.map +7 -0
- package/dist/utils/env.d.ts +1 -0
- package/dist/utils/env.js +14 -0
- package/dist/utils/env.js.map +7 -0
- package/dist/utils/response.d.ts +3 -0
- package/dist/utils/response.js +10 -0
- package/dist/utils/response.js.map +7 -0
- package/dist/vite/codegen/extract-methods.d.ts +4 -0
- package/dist/vite/codegen/extract-methods.js +16 -0
- package/dist/vite/codegen/extract-methods.js.map +7 -0
- package/dist/vite/codegen/routes-dts.d.ts +10 -0
- package/dist/vite/codegen/routes-dts.js +61 -0
- package/dist/vite/codegen/routes-dts.js.map +7 -0
- package/dist/vite/codegen/scan-api.d.ts +2 -0
- package/dist/vite/codegen/scan-api.js +78 -0
- package/dist/vite/codegen/scan-api.js.map +7 -0
- package/dist/vite/codegen/write-routes-dts.d.ts +1 -0
- package/dist/vite/codegen/write-routes-dts.js +17 -0
- package/dist/vite/codegen/write-routes-dts.js.map +7 -0
- package/dist/vite/index.js +143 -4
- package/dist/vite/index.js.map +4 -4
- package/package.json +1 -1
|
@@ -5,9 +5,10 @@ export declare class RouteContext {
|
|
|
5
5
|
set<T>(key: string, value: T): void;
|
|
6
6
|
get<T>(key: string): T | undefined;
|
|
7
7
|
}
|
|
8
|
-
export type
|
|
8
|
+
export type RouteResult = Response | Record<string, unknown> | unknown[] | null | void;
|
|
9
|
+
export type RouteHandler = (ctx: RouteContext, req: Request) => Promise<RouteResult> | RouteResult;
|
|
9
10
|
export interface MiddlewareModule {
|
|
10
|
-
middleware: (ctx: RouteContext,
|
|
11
|
+
middleware: (ctx: RouteContext, req: Request) => Promise<Response | null> | Response | null;
|
|
11
12
|
}
|
|
12
13
|
export interface RouteModule {
|
|
13
14
|
GET?: RouteHandler;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/runtime/api-context.ts"],
|
|
4
|
-
"sourcesContent": ["export 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 RouteHandler = (ctx: RouteContext,
|
|
4
|
+
"sourcesContent": ["export 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\nexport interface RouteModule {\n GET?: RouteHandler\n POST?: RouteHandler\n PUT?: RouteHandler\n PATCH?: RouteHandler\n DELETE?: RouteHandler\n HEAD?: RouteHandler\n OPTIONS?: RouteHandler\n}\n"],
|
|
5
5
|
"mappings": ";AAAO,IAAM,eAAN,MAAmB;AAAA,EACb;AAAA,EACD,SAAS,oBAAI,IAAqB;AAAA,EAE1C,YAAY,SAAiC,CAAC,GAAG;AAC7C,SAAK,SAAS;AAAA,EAClB;AAAA,EAEA,IAAO,KAAa,OAAgB;AAChC,SAAK,OAAO,IAAI,KAAK,KAAK;AAAA,EAC9B;AAAA,EAEA,IAAO,KAA4B;AAC/B,WAAO,KAAK,OAAO,IAAI,GAAG;AAAA,EAC9B;AACJ;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ApiRoutes {
|
|
2
|
+
}
|
|
3
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS';
|
|
4
|
+
export interface FetchOptions<M extends HttpMethod = 'GET'> {
|
|
5
|
+
method?: M;
|
|
6
|
+
body?: unknown;
|
|
7
|
+
headers?: HeadersInit;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
type ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`;
|
|
11
|
+
type InferResult<M extends HttpMethod, P extends string> = ApiKey<M, P> extends keyof ApiRoutes ? ApiRoutes[ApiKey<M, P>] : unknown;
|
|
12
|
+
export declare class FetchError extends Error {
|
|
13
|
+
readonly status: number;
|
|
14
|
+
readonly statusText: string;
|
|
15
|
+
readonly response: Response;
|
|
16
|
+
constructor(status: number, statusText: string, response: Response);
|
|
17
|
+
}
|
|
18
|
+
export declare function $fetch<P extends string, M extends HttpMethod = 'GET'>(path: P, options?: FetchOptions<M>): Promise<InferResult<M, P>>;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// src/runtime/fetch.ts
|
|
2
|
+
var FetchError = class extends Error {
|
|
3
|
+
constructor(status, statusText, response) {
|
|
4
|
+
super(`HTTP ${status}: ${statusText}`);
|
|
5
|
+
this.status = status;
|
|
6
|
+
this.statusText = statusText;
|
|
7
|
+
this.response = response;
|
|
8
|
+
this.name = "FetchError";
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
async function $fetch(path, options) {
|
|
12
|
+
const method = options?.method ?? "GET";
|
|
13
|
+
const headers = new Headers(options?.headers);
|
|
14
|
+
let body;
|
|
15
|
+
if (options?.body !== void 0) {
|
|
16
|
+
body = JSON.stringify(options.body);
|
|
17
|
+
if (!headers.has("Content-Type")) {
|
|
18
|
+
headers.set("Content-Type", "application/json");
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const response = await fetch(path, { method, headers, body, signal: options?.signal });
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new FetchError(response.status, response.statusText, response);
|
|
24
|
+
}
|
|
25
|
+
const contentType = response.headers.get("Content-Type") ?? "";
|
|
26
|
+
if (contentType.includes("application/json")) {
|
|
27
|
+
return response.json();
|
|
28
|
+
}
|
|
29
|
+
return response.text();
|
|
30
|
+
}
|
|
31
|
+
export {
|
|
32
|
+
$fetch,
|
|
33
|
+
FetchError
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=fetch.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/runtime/fetch.ts"],
|
|
4
|
+
"sourcesContent": ["export interface ApiRoutes {}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\nexport interface FetchOptions<M extends HttpMethod = 'GET'> {\n method?: M\n body?: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\ntype ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`\n\ntype InferResult<M extends HttpMethod, P extends string> =\n ApiKey<M, P> extends keyof ApiRoutes\n ? ApiRoutes[ApiKey<M, P>]\n : unknown\n\nexport class FetchError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly response: Response,\n ) {\n super(`HTTP ${status}: ${statusText}`)\n this.name = 'FetchError'\n }\n}\n\nexport async function $fetch<\n P extends string,\n M extends HttpMethod = 'GET',\n>(path: P, options?: FetchOptions<M>): Promise<InferResult<M, P>> {\n const method = (options?.method ?? 'GET') as string\n const headers = new Headers(options?.headers)\n\n let body: BodyInit | undefined\n if (options?.body !== undefined) {\n body = JSON.stringify(options.body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n }\n\n const response = await fetch(path, {method, headers, body, signal: options?.signal})\n\n if (!response.ok) {\n throw new FetchError(response.status, response.statusText, response)\n }\n\n const contentType = response.headers.get('Content-Type') ?? ''\n if (contentType.includes('application/json')) {\n return response.json() as Promise<InferResult<M, P>>\n }\n\n return response.text() as unknown as Promise<InferResult<M, P>>\n}\n"],
|
|
5
|
+
"mappings": ";AAkBO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAClC,YACoB,QACA,YACA,UAClB;AACE,UAAM,QAAQ,MAAM,KAAK,UAAU,EAAE;AAJrB;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EAChB;AACJ;AAEA,eAAsB,OAGpB,MAAS,SAAuD;AAC9D,QAAM,SAAU,SAAS,UAAU;AACnC,QAAM,UAAU,IAAI,QAAQ,SAAS,OAAO;AAE5C,MAAI;AACJ,MAAI,SAAS,SAAS,QAAW;AAC7B,WAAO,KAAK,UAAU,QAAQ,IAAI;AAClC,QAAI,CAAC,QAAQ,IAAI,cAAc,GAAG;AAC9B,cAAQ,IAAI,gBAAgB,kBAAkB;AAAA,IAClD;AAAA,EACJ;AAEA,QAAM,WAAW,MAAM,MAAM,MAAM,EAAC,QAAQ,SAAS,MAAM,QAAQ,SAAS,OAAM,CAAC;AAEnF,MAAI,CAAC,SAAS,IAAI;AACd,UAAM,IAAI,WAAW,SAAS,QAAQ,SAAS,YAAY,QAAQ;AAAA,EACvE;AAEA,QAAM,cAAc,SAAS,QAAQ,IAAI,cAAc,KAAK;AAC5D,MAAI,YAAY,SAAS,kBAAkB,GAAG;AAC1C,WAAO,SAAS,KAAK;AAAA,EACzB;AAEA,SAAO,SAAS,KAAK;AACzB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -2,4 +2,9 @@ export { useRouter, useNavigate, useParams, useLoaderData, RouterProvider } from
|
|
|
2
2
|
export { Link } from "./link";
|
|
3
3
|
export type { Metadata, Viewport, LoaderContext, LoaderFunction, GuardFunction } from '../types';
|
|
4
4
|
export type { PageProps, LayoutProps, PageModule, LayoutModule, ErrorProps } from '../server/types';
|
|
5
|
-
export type { RouteHandler } from './api-context';
|
|
5
|
+
export type { RouteHandler, RouteResult } from './api-context';
|
|
6
|
+
export { getCookie, setCookie, deleteCookie } from '../utils/cookies';
|
|
7
|
+
export type { CookieOptions } from '../utils/cookies';
|
|
8
|
+
export { json, text, redirect } from '../utils/response';
|
|
9
|
+
export { $fetch, FetchError } from './fetch';
|
|
10
|
+
export type { ApiRoutes, FetchOptions } from './fetch';
|
package/dist/runtime/index.js
CHANGED
|
@@ -289,9 +289,77 @@ function Link({ href, prefetch = false, viewTransition = false, children, ...pro
|
|
|
289
289
|
};
|
|
290
290
|
return /* @__PURE__ */ jsx4("a", { href, onClick: handleClick, onMouseEnter: handleMouseEnter, ...props, children });
|
|
291
291
|
}
|
|
292
|
+
|
|
293
|
+
// src/utils/cookies.ts
|
|
294
|
+
function getCookie(req, name) {
|
|
295
|
+
const header = req.headers.get("cookie");
|
|
296
|
+
if (!header) return void 0;
|
|
297
|
+
for (const part of header.split(";")) {
|
|
298
|
+
const [key, ...rest] = part.trim().split("=");
|
|
299
|
+
if (key.trim() === name) return decodeURIComponent(rest.join("="));
|
|
300
|
+
}
|
|
301
|
+
return void 0;
|
|
302
|
+
}
|
|
303
|
+
function setCookie(headers, name, value, options = {}) {
|
|
304
|
+
let cookie = `${name}=${encodeURIComponent(value)}; Path=${options.path ?? "/"}`;
|
|
305
|
+
if (options.domain) cookie += `; Domain=${options.domain}`;
|
|
306
|
+
if (options.maxAge !== void 0) cookie += `; Max-Age=${options.maxAge}`;
|
|
307
|
+
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
308
|
+
if (options.httpOnly) cookie += `; HttpOnly`;
|
|
309
|
+
if (options.secure) cookie += `; Secure`;
|
|
310
|
+
if (options.sameSite) cookie += `; SameSite=${options.sameSite}`;
|
|
311
|
+
headers.append("Set-Cookie", cookie);
|
|
312
|
+
}
|
|
313
|
+
function deleteCookie(headers, name, options = {}) {
|
|
314
|
+
setCookie(headers, name, "", { ...options, maxAge: 0, expires: /* @__PURE__ */ new Date(0) });
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/utils/response.ts
|
|
318
|
+
var json = (data, status = 200) => Response.json(data, { status });
|
|
319
|
+
var text = (body, status = 200) => new Response(body, { status, headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
320
|
+
var redirect = (url, status = 302) => new Response(null, { status, headers: { Location: url } });
|
|
321
|
+
|
|
322
|
+
// src/runtime/fetch.ts
|
|
323
|
+
var FetchError = class extends Error {
|
|
324
|
+
constructor(status, statusText, response) {
|
|
325
|
+
super(`HTTP ${status}: ${statusText}`);
|
|
326
|
+
this.status = status;
|
|
327
|
+
this.statusText = statusText;
|
|
328
|
+
this.response = response;
|
|
329
|
+
this.name = "FetchError";
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
async function $fetch(path, options) {
|
|
333
|
+
const method = options?.method ?? "GET";
|
|
334
|
+
const headers = new Headers(options?.headers);
|
|
335
|
+
let body;
|
|
336
|
+
if (options?.body !== void 0) {
|
|
337
|
+
body = JSON.stringify(options.body);
|
|
338
|
+
if (!headers.has("Content-Type")) {
|
|
339
|
+
headers.set("Content-Type", "application/json");
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const response = await fetch(path, { method, headers, body, signal: options?.signal });
|
|
343
|
+
if (!response.ok) {
|
|
344
|
+
throw new FetchError(response.status, response.statusText, response);
|
|
345
|
+
}
|
|
346
|
+
const contentType = response.headers.get("Content-Type") ?? "";
|
|
347
|
+
if (contentType.includes("application/json")) {
|
|
348
|
+
return response.json();
|
|
349
|
+
}
|
|
350
|
+
return response.text();
|
|
351
|
+
}
|
|
292
352
|
export {
|
|
353
|
+
$fetch,
|
|
354
|
+
FetchError,
|
|
293
355
|
Link,
|
|
294
356
|
RouterProvider,
|
|
357
|
+
deleteCookie,
|
|
358
|
+
getCookie,
|
|
359
|
+
json,
|
|
360
|
+
redirect,
|
|
361
|
+
setCookie,
|
|
362
|
+
text,
|
|
295
363
|
useLoaderData,
|
|
296
364
|
useNavigate,
|
|
297
365
|
useParams,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../../src/runtime/router-provider.tsx", "../../src/runtime/head.tsx", "../../src/runtime/context.tsx", "../../src/runtime/error-boundary.tsx", "../../src/runtime/link.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 {buildHeadNodes} from \"./head\";\nimport {PageMetaContext, RouteDataContext} from \"./context\";\nimport {DevixErrorBoundary} from \"./error-boundary\";\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\nexport function useNavigate() {\n const ctx = useContext(RouterContext)\n if (!ctx) throw new Error(\"useNavigate must be used within a RouterProvider\")\n return ctx.navigate\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 ? R\n : T extends (...args: any[]) => infer R\n ? R\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]\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 console.error(`/_data${to} returned ${dataRes.status}`)\n return\n }\n\n const data = await dataRes.json()\n\n window.scrollTo(0, 0)\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\n const navigate = useCallback(async (to: string) => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n setIsNavigating(true)\n try {\n window.history.pushState(null, \"\", to)\n await loadRoute(to, controller)\n } finally {\n if (!controller.signal.aborted) setIsNavigating(false)\n }\n }, [loadRoute])\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 {state.metadata && buildHeadNodes(state.metadata, state.viewport)}\n <RouterContext value={{...state, isNavigating, navigate}}>\n {content}\n </RouterContext>\n </PageMetaContext>\n )\n}", "import {Metadata, 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 }\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 (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 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}/>\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 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) => 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", "import {AnchorHTMLAttributes, MouseEventHandler, useCallback, useContext} from \"react\";\nimport {matchClientRoute} from \"virtual:devix/client-routes\";\nimport {RouterContext} from 'virtual:devix/context'\n\ninterface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n prefetch?: boolean\n viewTransition?: boolean\n}\n\nfunction resolveHref(href: string): string {\n if (href.startsWith('/') || href.startsWith('http')) return href\n const base = window.location.pathname.endsWith('/')\n ? window.location.href\n : window.location.href + '/'\n const resolved = new URL(href, base).pathname\n return resolved.length > 1 ? resolved.replace(/\\/$/, '') : resolved\n}\n\nexport function Link({ href, prefetch = false, viewTransition = false, children, ...props }: LinkProps) {\n const router = useContext(RouterContext)\n\n const handleMouseEnter = useCallback(() => {\n if (!prefetch) return\n const resolved = resolveHref(href)\n const pathname = resolved.split('?')[0]\n const matched = matchClientRoute(pathname)\n if (matched) {\n matched.load().catch(() => {})\n fetch(`/_data${resolved}`, { headers: { Accept: 'application/json' } }).catch(() => {})\n }\n }, [href, prefetch])\n\n const handleClick: MouseEventHandler<HTMLAnchorElement> = (e) => {\n if (!router) return\n if (!e.ctrlKey && !e.metaKey && !e.shiftKey && e.button === 0) {\n e.preventDefault()\n const resolved = resolveHref(href)\n if (viewTransition && typeof document.startViewTransition === 'function') {\n document.startViewTransition(() => router.navigate(resolved))\n } else {\n router.navigate(resolved)\n }\n }\n }\n\n return (\n <a href={href} onClick={handleClick} onMouseEnter={handleMouseEnter} {...props}>\n {children}\n </a>\n )\n}"],
|
|
5
|
-
"mappings": "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",
|
|
3
|
+
"sources": ["../../src/runtime/router-provider.tsx", "../../src/runtime/head.tsx", "../../src/runtime/context.tsx", "../../src/runtime/error-boundary.tsx", "../../src/runtime/link.tsx", "../../src/utils/cookies.ts", "../../src/utils/response.ts", "../../src/runtime/fetch.ts"],
|
|
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 {buildHeadNodes} from \"./head\";\nimport {PageMetaContext, RouteDataContext} from \"./context\";\nimport {DevixErrorBoundary} from \"./error-boundary\";\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\nexport function useNavigate() {\n const ctx = useContext(RouterContext)\n if (!ctx) throw new Error(\"useNavigate must be used within a RouterProvider\")\n return ctx.navigate\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 ? R\n : T extends (...args: any[]) => infer R\n ? R\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]\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 console.error(`/_data${to} returned ${dataRes.status}`)\n return\n }\n\n const data = await dataRes.json()\n\n window.scrollTo(0, 0)\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\n const navigate = useCallback(async (to: string) => {\n navigatingRef.current?.abort()\n const controller = new AbortController()\n navigatingRef.current = controller\n\n setIsNavigating(true)\n try {\n window.history.pushState(null, \"\", to)\n await loadRoute(to, controller)\n } finally {\n if (!controller.signal.aborted) setIsNavigating(false)\n }\n }, [loadRoute])\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 {state.metadata && buildHeadNodes(state.metadata, state.viewport)}\n <RouterContext value={{...state, isNavigating, navigate}}>\n {content}\n </RouterContext>\n </PageMetaContext>\n )\n}", "import {Metadata, 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 }\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 (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 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}/>\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 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) => 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", "import {AnchorHTMLAttributes, MouseEventHandler, useCallback, useContext} from \"react\";\nimport {matchClientRoute} from \"virtual:devix/client-routes\";\nimport {RouterContext} from 'virtual:devix/context'\n\ninterface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string\n prefetch?: boolean\n viewTransition?: boolean\n}\n\nfunction resolveHref(href: string): string {\n if (href.startsWith('/') || href.startsWith('http')) return href\n const base = window.location.pathname.endsWith('/')\n ? window.location.href\n : window.location.href + '/'\n const resolved = new URL(href, base).pathname\n return resolved.length > 1 ? resolved.replace(/\\/$/, '') : resolved\n}\n\nexport function Link({ href, prefetch = false, viewTransition = false, children, ...props }: LinkProps) {\n const router = useContext(RouterContext)\n\n const handleMouseEnter = useCallback(() => {\n if (!prefetch) return\n const resolved = resolveHref(href)\n const pathname = resolved.split('?')[0]\n const matched = matchClientRoute(pathname)\n if (matched) {\n matched.load().catch(() => {})\n fetch(`/_data${resolved}`, { headers: { Accept: 'application/json' } }).catch(() => {})\n }\n }, [href, prefetch])\n\n const handleClick: MouseEventHandler<HTMLAnchorElement> = (e) => {\n if (!router) return\n if (!e.ctrlKey && !e.metaKey && !e.shiftKey && e.button === 0) {\n e.preventDefault()\n const resolved = resolveHref(href)\n if (viewTransition && typeof document.startViewTransition === 'function') {\n document.startViewTransition(() => router.navigate(resolved))\n } else {\n router.navigate(resolved)\n }\n }\n }\n\n return (\n <a href={href} onClick={handleClick} onMouseEnter={handleMouseEnter} {...props}>\n {children}\n </a>\n )\n}", "export interface CookieOptions {\n httpOnly?: boolean\n secure?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n maxAge?: number\n expires?: Date\n path?: string\n domain?: string\n}\n\nexport function getCookie(req: Request, name: string): string | undefined {\n const header = req.headers.get('cookie')\n if (!header) return undefined\n for (const part of header.split(';')) {\n const [key, ...rest] = part.trim().split('=')\n if (key.trim() === name) return decodeURIComponent(rest.join('='))\n }\n return undefined\n}\n\nexport function setCookie(headers: Headers, name: string, value: string, options: CookieOptions = {}): void {\n let cookie = `${name}=${encodeURIComponent(value)}; Path=${options.path ?? '/'}`\n if (options.domain) cookie += `; Domain=${options.domain}`\n if (options.maxAge !== undefined) cookie += `; Max-Age=${options.maxAge}`\n if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`\n if (options.httpOnly) cookie += `; HttpOnly`\n if (options.secure) cookie += `; Secure`\n if (options.sameSite) cookie += `; SameSite=${options.sameSite}`\n headers.append('Set-Cookie', cookie)\n}\n\nexport function deleteCookie(headers: Headers, name: string, options: Pick<CookieOptions, 'path' | 'domain'> = {}): void {\n setCookie(headers, name, '', {...options, maxAge: 0, expires: new Date(0)})\n}\n", "export const json = (data: unknown, status = 200): Response =>\n Response.json(data, {status})\n\nexport const text = (body: string, status = 200): Response =>\n new Response(body, {status, headers: {'Content-Type': 'text/plain; charset=utf-8'}})\n\nexport const redirect = (url: string, status = 302): Response =>\n new Response(null, {status, headers: {Location: url}})\n", "export interface ApiRoutes {}\n\ntype HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'\n\nexport interface FetchOptions<M extends HttpMethod = 'GET'> {\n method?: M\n body?: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n}\n\ntype ApiKey<M extends HttpMethod, P extends string> = `${M} ${P}`\n\ntype InferResult<M extends HttpMethod, P extends string> =\n ApiKey<M, P> extends keyof ApiRoutes\n ? ApiRoutes[ApiKey<M, P>]\n : unknown\n\nexport class FetchError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly response: Response,\n ) {\n super(`HTTP ${status}: ${statusText}`)\n this.name = 'FetchError'\n }\n}\n\nexport async function $fetch<\n P extends string,\n M extends HttpMethod = 'GET',\n>(path: P, options?: FetchOptions<M>): Promise<InferResult<M, P>> {\n const method = (options?.method ?? 'GET') as string\n const headers = new Headers(options?.headers)\n\n let body: BodyInit | undefined\n if (options?.body !== undefined) {\n body = JSON.stringify(options.body)\n if (!headers.has('Content-Type')) {\n headers.set('Content-Type', 'application/json')\n }\n }\n\n const response = await fetch(path, {method, headers, body, signal: options?.signal})\n\n if (!response.ok) {\n throw new FetchError(response.status, response.statusText, response)\n }\n\n const contentType = response.headers.get('Content-Type') ?? ''\n if (contentType.includes('application/json')) {\n return response.json() as Promise<InferResult<M, P>>\n }\n\n return response.text() as unknown as Promise<InferResult<M, P>>\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["RouterContext", "jsx", "jsx", "RouterContext", "useCallback", "useContext", "matchClientRoute", "RouterContext", "jsx"]
|
|
7
7
|
}
|
|
@@ -12,6 +12,7 @@ export interface ApiResult {
|
|
|
12
12
|
routes: ApiRoute[];
|
|
13
13
|
middlewares: ApiMiddleware[];
|
|
14
14
|
}
|
|
15
|
+
export declare function keyToRoutePattern(key: string, apiDir: string): string;
|
|
15
16
|
export declare function invalidateApiCache(): void;
|
|
16
17
|
export declare function buildRoutes(routeKeys: string[], middlewareKeys: string[], apiDir: string): ApiResult;
|
|
17
18
|
export declare function collectMiddlewareChain(routeKey: string, middlewares: ApiMiddleware[]): ApiMiddleware[];
|
|
@@ -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\
|
|
5
|
-
"mappings": ";AAAO,SAAS,aAAa,KAAqB;AAC9C,SAAO,IACE,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,cAAc,EAAE,EACxB,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gBAAgB,KAAK,KAC/B;AACX;;;
|
|
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"],
|
|
5
|
+
"mappings": ";AAAO,SAAS,aAAa,KAAqB;AAC9C,SAAO,IACE,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,cAAc,EAAE,EACxB,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gBAAgB,KAAK,KAC/B;AACX;;;ACYO,SAAS,kBAAkB,KAAa,QAAwB;AACnE,QAAM,MAAM,IAAI,MAAM,OAAO,SAAS,CAAC,EAAE,QAAQ,OAAO,GAAG;AAC3D,QAAM,UAAU,aAAa,GAAG;AAChC,SAAO,YAAY,MAAM,SAAS,QAAQ,OAAO,GAAG,QAAQ,UAAU,OAAO;AACjF;AAEA,SAAS,SAAS,KAAqB;AACnC,SAAO,IAAI,MAAM,GAAG,IAAI,YAAY,GAAG,CAAC;AAC5C;AAEA,IAAI,QAA0B;AAEvB,SAAS,qBAAqB;AACjC,UAAQ;AACZ;AAEO,SAAS,YAAY,WAAqB,gBAA0B,QAA2B;AAClG,MAAI,MAAO,QAAO;AAElB,QAAM,SAAqB,CAAC;AAC5B,QAAM,cAA+B,CAAC;AAEtC,aAAW,OAAO,gBAAgB;AAC9B,gBAAY,KAAK,EAAC,KAAK,SAAS,GAAG,GAAG,IAAG,CAAC;AAAA,EAC9C;AAEA,aAAW,OAAO,WAAW;AACzB,UAAM,UAAU,kBAAkB,KAAK,MAAM;AAC7C,UAAM,SAAS,CAAC,GAAG,QAAQ,SAAS,WAAW,CAAC,EAAE,IAAI,OAAK,EAAE,CAAC,CAAC;AAC/D,UAAM,WAAW,QACZ,QAAQ,WAAW,SAAS,EAC5B,QAAQ,OAAO,KAAK;AACzB,WAAO,KAAK,EAAC,MAAM,SAAS,KAAK,QAAQ,OAAO,IAAI,OAAO,IAAI,QAAQ,GAAG,EAAC,CAAC;AAAA,EAChF;AACA,SAAO,KAAK,CAAC,GAAG,MAAM;AAClB,UAAM,UAAU,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG;AAC1C,UAAM,UAAU,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG;AAC1C,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,KAAK,SAAS,EAAE,KAAK;AAAA,EAClC,CAAC;AAED,UAAQ,EAAC,QAAQ,YAAW;AAC5B,SAAO;AACX;AAEO,SAAS,uBAAuB,UAAkB,aAA+C;AACpG,QAAM,WAAW,SAAS,QAAQ;AAElC,SAAO,YACF,OAAO,QAAM,SAAS,WAAW,GAAG,GAAG,CAAC,EACxC,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,MAAM,GAAG,EAAE,MAAM;AACzE;AAEO,SAAS,WACZ,UACA,QACwD;AACxD,aAAW,SAAS,QAAQ;AACxB,UAAM,QAAQ,SAAS,MAAM,MAAM,KAAK;AACxC,QAAI,OAAO;AACP,YAAM,SAAiC,CAAC;AACxC,YAAM,OAAO,QAAQ,CAAC,MAAM,MAAM;AAC9B,eAAO,IAAI,IAAI,mBAAmB,MAAM,IAAI,CAAC,CAAC;AAAA,MAClD,CAAC;AACD,aAAO,EAAC,OAAO,OAAM;AAAA,IACzB;AAAA,EACJ;AACA,SAAO;AACX;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/server/api.js
CHANGED
|
@@ -106,6 +106,7 @@ async function handleApiRequest(url, request, glob) {
|
|
|
106
106
|
if (!handler) return new Response("Method Not Allowed", { status: 405 });
|
|
107
107
|
const result = await handler(ctx, request);
|
|
108
108
|
if (result instanceof Response) return result;
|
|
109
|
+
if (result == null) return new Response(null, { status: 204 });
|
|
109
110
|
return new Response(JSON.stringify(result), {
|
|
110
111
|
headers: { "Content-Type": "application/json" }
|
|
111
112
|
});
|
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/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\
|
|
5
|
-
"mappings": ";AAAO,SAAS,aAAa,KAAqB;AAC9C,SAAO,IACE,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,cAAc,EAAE,EACxB,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gBAAgB,KAAK,KAC/B;AACX;;;
|
|
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", "export 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\nexport interface RouteModule {\n GET?: RouteHandler\n POST?: RouteHandler\n PUT?: RouteHandler\n PATCH?: RouteHandler\n DELETE?: RouteHandler\n HEAD?: RouteHandler\n OPTIONS?: RouteHandler\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 {buildRoutes, matchRoute, collectMiddlewareChain} from './api-router'\nimport {RouteContext} from '../runtime/api-context'\nimport type {RouteModule, MiddlewareModule} from '../runtime/api-context'\nimport type {ApiGlob} from './types'\nimport {DevixError} from '../runtime/error-boundary'\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 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 result = await mod.middleware(ctx, request)\n if (result instanceof Response) return result\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 const result = await handler(ctx, request)\n if (result instanceof Response) return result\n if (result == null) return new Response(null, {status: 204})\n\n return new Response(JSON.stringify(result), {\n headers: {'Content-Type': 'application/json'},\n })\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}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["mod", "result"]
|
|
7
7
|
}
|
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\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\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 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 = {pages, layouts}\n return cache\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\
|
|
5
|
-
"mappings": ";AAAO,SAAS,aAAa,KAAqB;AAC9C,SAAO,IACE,QAAQ,sBAAsB,EAAE,EAChC,QAAQ,cAAc,EAAE,EACxB,QAAQ,oBAAoB,EAAE,EAC9B,QAAQ,gBAAgB,KAAK,KAC/B;AACX;;;ACYA,SAAS,kBAAkB,KAAa,UAA0B;AAC9D,QAAM,MAAM,IAAI,MAAM,SAAS,SAAS,CAAC,EAAE,QAAQ,OAAO,GAAG;AAC7D,QAAM,UAAU,aAAa,GAAG;AAChC,SAAO,YAAY,MAAM,MAAM,IAAI,OAAO;AAC9C;AAEA,SAAS,SAAS,KAAqB;AACnC,SAAO,IAAI,MAAM,GAAG,IAAI,YAAY,GAAG,CAAC;AAC5C;AAEA,IAAI,QAA4B;AAMzB,SAAS,WAAW,UAAoB,YAAsB,UAA+B;AAChG,MAAI,MAAO,QAAO;AAElB,QAAM,QAAgB,CAAC;AACvB,QAAM,UAAoB,CAAC;AAE3B,aAAW,OAAO,YAAY;AAC1B,YAAQ,KAAK,EAAC,KAAK,SAAS,GAAG,GAAG,IAAG,CAAC;AAAA,EAC1C;AAEA,aAAW,OAAO,UAAU;AACxB,UAAM,UAAU,kBAAkB,KAAK,QAAQ;AAC/C,UAAM,SAAS,CAAC,GAAG,QAAQ,SAAS,WAAW,CAAC,EAAE,IAAI,OAAK,EAAE,CAAC,CAAC;AAC/D,UAAM,WAAW,QACZ,QAAQ,WAAW,SAAS,EAC5B,QAAQ,OAAO,KAAK;AACzB,UAAM,KAAK,EAAC,MAAM,SAAS,KAAK,QAAQ,OAAO,IAAI,OAAO,IAAI,QAAQ,GAAG,EAAC,CAAC;AAAA,EAC/E;AAEA,QAAM,KAAK,CAAC,GAAG,MAAM;AACjB,UAAM,UAAU,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG;AAC1C,UAAM,UAAU,EAAE,KAAK,MAAM,IAAI,KAAK,CAAC,GAAG;AAC1C,QAAI,WAAW,OAAQ,QAAO,SAAS;AACvC,WAAO,EAAE,KAAK,SAAS,EAAE,KAAK;AAAA,EAClC,CAAC;AAED,UAAQ,EAAC,OAAO,QAAO;AACvB,SAAO;AACX;AAEO,SAAS,mBAAmB,SAAiB,SAA6B;AAC7E,QAAM,UAAU,SAAS,OAAO;AAEhC,SAAO,QACF,OAAO,YAAU,QAAQ,WAAW,OAAO,GAAG,CAAC,EAC/C,KAAK,CAAC,GAAG,MAAM,EAAE,IAAI,MAAM,GAAG,EAAE,SAAS,EAAE,IAAI,MAAM,GAAG,EAAE,MAAM;AACzE;AAEO,SAAS,UAAU,UAAkB,OAGnC;AACL,aAAW,QAAQ,OAAO;AACtB,UAAM,QAAQ,SAAS,MAAM,KAAK,KAAK;AACvC,QAAI,OAAO;AACP,YAAM,SAAiC,CAAC;AACxC,WAAK,OAAO,QAAQ,CAAC,MAAM,MAAM;AAC7B,eAAO,IAAI,IAAI,mBAAmB,MAAM,IAAI,CAAC,CAAC;AAAA,MAClD,CAAC;AACD,aAAO,EAAC,MAAM,OAAM;AAAA,IACxB;AAAA,EACJ;AACA,SAAO;AACX;;;
|
|
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\nlet cache: PagesResult | null = null\n\nexport function invalidatePagesCache() {\n cache = null\n}\n\nexport function buildPages(pageKeys: string[], layoutKeys: string[], pagesDir: string): PagesResult {\n if (cache) return cache\n\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 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 = {pages, layouts}\n return cache\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\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 {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
6
|
"names": ["keyToRoutePattern", "keyToDir", "cache", "cache", "keyToDir", "keyToRoutePattern"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CookieOptions {
|
|
2
|
+
httpOnly?: boolean;
|
|
3
|
+
secure?: boolean;
|
|
4
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
5
|
+
maxAge?: number;
|
|
6
|
+
expires?: Date;
|
|
7
|
+
path?: string;
|
|
8
|
+
domain?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function getCookie(req: Request, name: string): string | undefined;
|
|
11
|
+
export declare function setCookie(headers: Headers, name: string, value: string, options?: CookieOptions): void;
|
|
12
|
+
export declare function deleteCookie(headers: Headers, name: string, options?: Pick<CookieOptions, 'path' | 'domain'>): void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/utils/cookies.ts
|
|
2
|
+
function getCookie(req, name) {
|
|
3
|
+
const header = req.headers.get("cookie");
|
|
4
|
+
if (!header) return void 0;
|
|
5
|
+
for (const part of header.split(";")) {
|
|
6
|
+
const [key, ...rest] = part.trim().split("=");
|
|
7
|
+
if (key.trim() === name) return decodeURIComponent(rest.join("="));
|
|
8
|
+
}
|
|
9
|
+
return void 0;
|
|
10
|
+
}
|
|
11
|
+
function setCookie(headers, name, value, options = {}) {
|
|
12
|
+
let cookie = `${name}=${encodeURIComponent(value)}; Path=${options.path ?? "/"}`;
|
|
13
|
+
if (options.domain) cookie += `; Domain=${options.domain}`;
|
|
14
|
+
if (options.maxAge !== void 0) cookie += `; Max-Age=${options.maxAge}`;
|
|
15
|
+
if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`;
|
|
16
|
+
if (options.httpOnly) cookie += `; HttpOnly`;
|
|
17
|
+
if (options.secure) cookie += `; Secure`;
|
|
18
|
+
if (options.sameSite) cookie += `; SameSite=${options.sameSite}`;
|
|
19
|
+
headers.append("Set-Cookie", cookie);
|
|
20
|
+
}
|
|
21
|
+
function deleteCookie(headers, name, options = {}) {
|
|
22
|
+
setCookie(headers, name, "", { ...options, maxAge: 0, expires: /* @__PURE__ */ new Date(0) });
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
deleteCookie,
|
|
26
|
+
getCookie,
|
|
27
|
+
setCookie
|
|
28
|
+
};
|
|
29
|
+
//# sourceMappingURL=cookies.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/cookies.ts"],
|
|
4
|
+
"sourcesContent": ["export interface CookieOptions {\n httpOnly?: boolean\n secure?: boolean\n sameSite?: 'Strict' | 'Lax' | 'None'\n maxAge?: number\n expires?: Date\n path?: string\n domain?: string\n}\n\nexport function getCookie(req: Request, name: string): string | undefined {\n const header = req.headers.get('cookie')\n if (!header) return undefined\n for (const part of header.split(';')) {\n const [key, ...rest] = part.trim().split('=')\n if (key.trim() === name) return decodeURIComponent(rest.join('='))\n }\n return undefined\n}\n\nexport function setCookie(headers: Headers, name: string, value: string, options: CookieOptions = {}): void {\n let cookie = `${name}=${encodeURIComponent(value)}; Path=${options.path ?? '/'}`\n if (options.domain) cookie += `; Domain=${options.domain}`\n if (options.maxAge !== undefined) cookie += `; Max-Age=${options.maxAge}`\n if (options.expires) cookie += `; Expires=${options.expires.toUTCString()}`\n if (options.httpOnly) cookie += `; HttpOnly`\n if (options.secure) cookie += `; Secure`\n if (options.sameSite) cookie += `; SameSite=${options.sameSite}`\n headers.append('Set-Cookie', cookie)\n}\n\nexport function deleteCookie(headers: Headers, name: string, options: Pick<CookieOptions, 'path' | 'domain'> = {}): void {\n setCookie(headers, name, '', {...options, maxAge: 0, expires: new Date(0)})\n}\n"],
|
|
5
|
+
"mappings": ";AAUO,SAAS,UAAU,KAAc,MAAkC;AACtE,QAAM,SAAS,IAAI,QAAQ,IAAI,QAAQ;AACvC,MAAI,CAAC,OAAQ,QAAO;AACpB,aAAW,QAAQ,OAAO,MAAM,GAAG,GAAG;AAClC,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,KAAK,KAAK,EAAE,MAAM,GAAG;AAC5C,QAAI,IAAI,KAAK,MAAM,KAAM,QAAO,mBAAmB,KAAK,KAAK,GAAG,CAAC;AAAA,EACrE;AACA,SAAO;AACX;AAEO,SAAS,UAAU,SAAkB,MAAc,OAAe,UAAyB,CAAC,GAAS;AACxG,MAAI,SAAS,GAAG,IAAI,IAAI,mBAAmB,KAAK,CAAC,UAAU,QAAQ,QAAQ,GAAG;AAC9E,MAAI,QAAQ,OAAoB,WAAU,YAAY,QAAQ,MAAM;AACpE,MAAI,QAAQ,WAAW,OAAW,WAAU,aAAa,QAAQ,MAAM;AACvE,MAAI,QAAQ,QAAoB,WAAU,aAAa,QAAQ,QAAQ,YAAY,CAAC;AACpF,MAAI,QAAQ,SAAoB,WAAU;AAC1C,MAAI,QAAQ,OAAoB,WAAU;AAC1C,MAAI,QAAQ,SAAoB,WAAU,cAAc,QAAQ,QAAQ;AACxE,UAAQ,OAAO,cAAc,MAAM;AACvC;AAEO,SAAS,aAAa,SAAkB,MAAc,UAAkD,CAAC,GAAS;AACrH,YAAU,SAAS,MAAM,IAAI,EAAC,GAAG,SAAS,QAAQ,GAAG,SAAS,oBAAI,KAAK,CAAC,EAAC,CAAC;AAC9E;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function loadDotenv(mode: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// src/utils/env.ts
|
|
2
|
+
import { loadEnv } from "vite";
|
|
3
|
+
function loadDotenv(mode) {
|
|
4
|
+
const env = loadEnv(mode, process.cwd(), "");
|
|
5
|
+
for (const [key, value] of Object.entries(env)) {
|
|
6
|
+
if (process.env[key] === void 0) {
|
|
7
|
+
process.env[key] = value;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
loadDotenv
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/env.ts"],
|
|
4
|
+
"sourcesContent": ["import {loadEnv} from 'vite'\n\nexport function loadDotenv(mode: string) {\n const env = loadEnv(mode, process.cwd(), '')\n for (const [key, value] of Object.entries(env)) {\n if (process.env[key] === undefined) {\n process.env[key] = value\n }\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAQ,eAAc;AAEf,SAAS,WAAW,MAAc;AACrC,QAAM,MAAM,QAAQ,MAAM,QAAQ,IAAI,GAAG,EAAE;AAC3C,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC5C,QAAI,QAAQ,IAAI,GAAG,MAAM,QAAW;AAChC,cAAQ,IAAI,GAAG,IAAI;AAAA,IACvB;AAAA,EACJ;AACJ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// src/utils/response.ts
|
|
2
|
+
var json = (data, status = 200) => Response.json(data, { status });
|
|
3
|
+
var text = (body, status = 200) => new Response(body, { status, headers: { "Content-Type": "text/plain; charset=utf-8" } });
|
|
4
|
+
var redirect = (url, status = 302) => new Response(null, { status, headers: { Location: url } });
|
|
5
|
+
export {
|
|
6
|
+
json,
|
|
7
|
+
redirect,
|
|
8
|
+
text
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=response.js.map
|