davaux 0.8.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/BASELINE.md +169 -0
- package/CLAUDE.md +518 -0
- package/LICENSE +21 -0
- package/README.md +36 -0
- package/ROADMAP.md +198 -0
- package/build.mjs +101 -0
- package/client/control.ts +247 -0
- package/client/hydrate.ts +37 -0
- package/client/index.ts +19 -0
- package/client/jsx-runtime.ts +209 -0
- package/client/resource.ts +122 -0
- package/client/signal.ts +211 -0
- package/client/store.ts +110 -0
- package/client/useHead.ts +63 -0
- package/dist/build/config.d.ts +3 -0
- package/dist/build/config.d.ts.map +1 -0
- package/dist/build/config.js +38 -0
- package/dist/build/config.js.map +7 -0
- package/dist/build/index.d.ts +2 -0
- package/dist/build/index.d.ts.map +1 -0
- package/dist/build/index.js +13 -0
- package/dist/build/index.js.map +7 -0
- package/dist/build/plugins.d.ts +7 -0
- package/dist/build/plugins.d.ts.map +1 -0
- package/dist/build/plugins.js +85 -0
- package/dist/build/plugins.js.map +7 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +427 -0
- package/dist/cli.js.map +7 -0
- package/dist/client/control.d.ts +49 -0
- package/dist/client/control.d.ts.map +1 -0
- package/dist/client/control.js +154 -0
- package/dist/client/control.js.map +7 -0
- package/dist/client/hydrate.d.ts +7 -0
- package/dist/client/hydrate.d.ts.map +1 -0
- package/dist/client/hydrate.js +23 -0
- package/dist/client/hydrate.js.map +7 -0
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +32 -0
- package/dist/client/index.js.map +7 -0
- package/dist/client/jsx-runtime.d.ts +40 -0
- package/dist/client/jsx-runtime.d.ts.map +1 -0
- package/dist/client/jsx-runtime.js +139 -0
- package/dist/client/jsx-runtime.js.map +7 -0
- package/dist/client/resource.d.ts +31 -0
- package/dist/client/resource.d.ts.map +1 -0
- package/dist/client/resource.js +64 -0
- package/dist/client/resource.js.map +7 -0
- package/dist/client/signal.d.ts +90 -0
- package/dist/client/signal.d.ts.map +1 -0
- package/dist/client/signal.js +115 -0
- package/dist/client/signal.js.map +7 -0
- package/dist/client/store.d.ts +26 -0
- package/dist/client/store.d.ts.map +1 -0
- package/dist/client/store.js +63 -0
- package/dist/client/store.js.map +7 -0
- package/dist/client/useHead.d.ts +28 -0
- package/dist/client/useHead.d.ts.map +1 -0
- package/dist/client/useHead.js +33 -0
- package/dist/client/useHead.js.map +7 -0
- package/dist/config.d.ts +182 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +21 -0
- package/dist/config.js.map +7 -0
- package/dist/create-multisite.d.ts +2 -0
- package/dist/create-multisite.d.ts.map +1 -0
- package/dist/create-multisite.js +291 -0
- package/dist/create-multisite.js.map +7 -0
- package/dist/create.d.ts +2 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +179 -0
- package/dist/create.js.map +7 -0
- package/dist/dev/blueprints.d.ts +11 -0
- package/dist/dev/blueprints.d.ts.map +1 -0
- package/dist/dev/blueprints.js +65 -0
- package/dist/dev/blueprints.js.map +7 -0
- package/dist/dev/components.d.ts +19 -0
- package/dist/dev/components.d.ts.map +1 -0
- package/dist/dev/components.js +87 -0
- package/dist/dev/components.js.map +7 -0
- package/dist/dev/insert.d.ts +11 -0
- package/dist/dev/insert.d.ts.map +1 -0
- package/dist/dev/insert.js +160 -0
- package/dist/dev/insert.js.map +7 -0
- package/dist/dev/remove.d.ts +53 -0
- package/dist/dev/remove.d.ts.map +1 -0
- package/dist/dev/remove.js +518 -0
- package/dist/dev/remove.js.map +7 -0
- package/dist/dev/watch.d.ts +26 -0
- package/dist/dev/watch.d.ts.map +1 -0
- package/dist/dev/watch.js +2905 -0
- package/dist/dev/watch.js.map +7 -0
- package/dist/errors.d.ts +6 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +63 -0
- package/dist/errors.js.map +7 -0
- package/dist/generate.d.ts +2 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +191 -0
- package/dist/generate.js.map +7 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +7 -0
- package/dist/island.d.ts +24 -0
- package/dist/island.d.ts.map +1 -0
- package/dist/island.js +15 -0
- package/dist/island.js.map +7 -0
- package/dist/jsx-runtime.d.ts +406 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +90 -0
- package/dist/jsx-runtime.js.map +7 -0
- package/dist/link.d.ts +27 -0
- package/dist/link.d.ts.map +1 -0
- package/dist/link.js +29 -0
- package/dist/link.js.map +7 -0
- package/dist/oml/fragment.d.ts +16 -0
- package/dist/oml/fragment.d.ts.map +1 -0
- package/dist/oml/fragment.js +26 -0
- package/dist/oml/fragment.js.map +7 -0
- package/dist/oml/index.d.ts +11 -0
- package/dist/oml/index.d.ts.map +1 -0
- package/dist/oml/index.js +21 -0
- package/dist/oml/index.js.map +7 -0
- package/dist/oml/jsx-runtime.d.ts +34 -0
- package/dist/oml/jsx-runtime.d.ts.map +1 -0
- package/dist/oml/jsx-runtime.js +59 -0
- package/dist/oml/jsx-runtime.js.map +7 -0
- package/dist/oml/jsx.d.ts +14 -0
- package/dist/oml/jsx.d.ts.map +1 -0
- package/dist/oml/jsx.js +96 -0
- package/dist/oml/jsx.js.map +7 -0
- package/dist/oml/page.d.ts +7 -0
- package/dist/oml/page.d.ts.map +1 -0
- package/dist/oml/page.js +6 -0
- package/dist/oml/page.js.map +7 -0
- package/dist/oml/render.d.ts +13 -0
- package/dist/oml/render.d.ts.map +1 -0
- package/dist/oml/render.js +117 -0
- package/dist/oml/render.js.map +7 -0
- package/dist/oml/types.d.ts +79 -0
- package/dist/oml/types.d.ts.map +1 -0
- package/dist/oml/types.js +64 -0
- package/dist/oml/types.js.map +7 -0
- package/dist/router/handler.d.ts +53 -0
- package/dist/router/handler.d.ts.map +1 -0
- package/dist/router/handler.js +342 -0
- package/dist/router/handler.js.map +7 -0
- package/dist/router/matcher.d.ts +21 -0
- package/dist/router/matcher.d.ts.map +1 -0
- package/dist/router/matcher.js +28 -0
- package/dist/router/matcher.js.map +7 -0
- package/dist/router/scanner.d.ts +17 -0
- package/dist/router/scanner.d.ts.map +1 -0
- package/dist/router/scanner.js +197 -0
- package/dist/router/scanner.js.map +7 -0
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +29 -0
- package/dist/server/index.js.map +7 -0
- package/dist/signal.d.ts +15 -0
- package/dist/signal.d.ts.map +1 -0
- package/dist/signal.js +29 -0
- package/dist/signal.js.map +7 -0
- package/dist/ssg.d.ts +45 -0
- package/dist/ssg.d.ts.map +1 -0
- package/dist/ssg.js +175 -0
- package/dist/ssg.js.map +7 -0
- package/dist/test/actions.test.d.ts +2 -0
- package/dist/test/actions.test.d.ts.map +1 -0
- package/dist/test/body-limits.test.d.ts +2 -0
- package/dist/test/body-limits.test.d.ts.map +1 -0
- package/dist/test/errors.test.d.ts +2 -0
- package/dist/test/errors.test.d.ts.map +1 -0
- package/dist/test/fixtures/routes/[id].page.d.ts +4 -0
- package/dist/test/fixtures/routes/[id].page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_error.d.ts +3 -0
- package/dist/test/fixtures/routes/_error.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_global.d.ts +3 -0
- package/dist/test/fixtures/routes/_global.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_layout-template.d.ts +3 -0
- package/dist/test/fixtures/routes/_layout-template.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_layout.d.ts +3 -0
- package/dist/test/fixtures/routes/_layout.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_layout_scripts.d.ts +3 -0
- package/dist/test/fixtures/routes/_layout_scripts.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_middleware.d.ts +3 -0
- package/dist/test/fixtures/routes/_middleware.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_redirect301_mw.d.ts +3 -0
- package/dist/test/fixtures/routes/_redirect301_mw.d.ts.map +1 -0
- package/dist/test/fixtures/routes/_redirect_mw.d.ts +3 -0
- package/dist/test/fixtures/routes/_redirect_mw.d.ts.map +1 -0
- package/dist/test/fixtures/routes/about.page.d.ts +3 -0
- package/dist/test/fixtures/routes/about.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/action.page.d.ts +6 -0
- package/dist/test/fixtures/routes/action.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/form-all.post.d.ts +3 -0
- package/dist/test/fixtures/routes/api/form-all.post.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/form-limited.post.d.ts +6 -0
- package/dist/test/fixtures/routes/api/form-limited.post.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/response-obj.get.d.ts +3 -0
- package/dist/test/fixtures/routes/api/response-obj.get.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/upload.post.d.ts +12 -0
- package/dist/test/fixtures/routes/api/upload.post.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/users.get.d.ts +6 -0
- package/dist/test/fixtures/routes/api/users.get.d.ts.map +1 -0
- package/dist/test/fixtures/routes/api/xml.get.d.ts +3 -0
- package/dist/test/fixtures/routes/api/xml.get.d.ts.map +1 -0
- package/dist/test/fixtures/routes/auth/_middleware.d.ts +3 -0
- package/dist/test/fixtures/routes/auth/_middleware.d.ts.map +1 -0
- package/dist/test/fixtures/routes/auth/protected.page.d.ts +3 -0
- package/dist/test/fixtures/routes/auth/protected.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/index.page.d.ts +3 -0
- package/dist/test/fixtures/routes/index.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/oml.page.d.ts +3 -0
- package/dist/test/fixtures/routes/oml.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/redirect.page.d.ts +3 -0
- package/dist/test/fixtures/routes/redirect.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/ssg/[slug].page.d.ts +5 -0
- package/dist/test/fixtures/routes/ssg/[slug].page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/ssg/server.page.d.ts +4 -0
- package/dist/test/fixtures/routes/ssg/server.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/state.page.d.ts +3 -0
- package/dist/test/fixtures/routes/state.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/throw.page.d.ts +3 -0
- package/dist/test/fixtures/routes/throw.page.d.ts.map +1 -0
- package/dist/test/fixtures/routes/wiki/[...slug].page.d.ts +3 -0
- package/dist/test/fixtures/routes/wiki/[...slug].page.d.ts.map +1 -0
- package/dist/test/helpers.d.ts +37 -0
- package/dist/test/helpers.d.ts.map +1 -0
- package/dist/test/layouts.test.d.ts +2 -0
- package/dist/test/layouts.test.d.ts.map +1 -0
- package/dist/test/middleware.test.d.ts +2 -0
- package/dist/test/middleware.test.d.ts.map +1 -0
- package/dist/test/multipart.test.d.ts +2 -0
- package/dist/test/multipart.test.d.ts.map +1 -0
- package/dist/test/oml-routing.test.d.ts +2 -0
- package/dist/test/oml-routing.test.d.ts.map +1 -0
- package/dist/test/oml.test.d.ts +2 -0
- package/dist/test/oml.test.d.ts.map +1 -0
- package/dist/test/redirects.test.d.ts +2 -0
- package/dist/test/redirects.test.d.ts.map +1 -0
- package/dist/test/routing.test.d.ts +2 -0
- package/dist/test/routing.test.d.ts.map +1 -0
- package/dist/test/ssg.test.d.ts +2 -0
- package/dist/test/ssg.test.d.ts.map +1 -0
- package/dist/test/web-response.test.d.ts +2 -0
- package/dist/test/web-response.test.d.ts.map +1 -0
- package/dist/types.d.ts +314 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +292 -0
- package/dist/types.js.map +7 -0
- package/package.json +103 -0
- package/pka.config.json +32 -0
- package/src/build/config.ts +42 -0
- package/src/build/index.ts +6 -0
- package/src/build/plugins.ts +118 -0
- package/src/cli.ts +502 -0
- package/src/config.ts +197 -0
- package/src/create-multisite.ts +310 -0
- package/src/create.ts +194 -0
- package/src/dev/blueprints.ts +75 -0
- package/src/dev/components.ts +108 -0
- package/src/dev/insert.ts +221 -0
- package/src/dev/remove.ts +677 -0
- package/src/dev/watch.ts +3098 -0
- package/src/env.d.ts +5 -0
- package/src/errors.ts +64 -0
- package/src/generate.ts +228 -0
- package/src/index.ts +67 -0
- package/src/island.ts +47 -0
- package/src/jsx-runtime.d.ts +408 -0
- package/src/jsx-runtime.d.ts.map +1 -0
- package/src/jsx-runtime.ts +536 -0
- package/src/link.ts +49 -0
- package/src/oml/fragment.ts +54 -0
- package/src/oml/index.ts +21 -0
- package/src/oml/jsx-runtime.ts +121 -0
- package/src/oml/jsx.ts +151 -0
- package/src/oml/page.ts +13 -0
- package/src/oml/render.ts +181 -0
- package/src/oml/types.ts +159 -0
- package/src/router/handler.ts +515 -0
- package/src/router/matcher.ts +52 -0
- package/src/router/scanner.ts +272 -0
- package/src/server/index.ts +49 -0
- package/src/signal.ts +39 -0
- package/src/ssg.ts +253 -0
- package/src/test/actions.test.ts +40 -0
- package/src/test/body-limits.test.ts +83 -0
- package/src/test/errors.test.ts +53 -0
- package/src/test/fixtures/routes/[id].page.ts +3 -0
- package/src/test/fixtures/routes/_error.ts +6 -0
- package/src/test/fixtures/routes/_global.ts +8 -0
- package/src/test/fixtures/routes/_layout-template.ts +7 -0
- package/src/test/fixtures/routes/_layout.ts +7 -0
- package/src/test/fixtures/routes/_layout_scripts.ts +8 -0
- package/src/test/fixtures/routes/_middleware.ts +8 -0
- package/src/test/fixtures/routes/_redirect301_mw.ts +5 -0
- package/src/test/fixtures/routes/_redirect_mw.ts +5 -0
- package/src/test/fixtures/routes/about.page.ts +6 -0
- package/src/test/fixtures/routes/action.page.ts +11 -0
- package/src/test/fixtures/routes/api/form-all.post.ts +5 -0
- package/src/test/fixtures/routes/api/form-limited.post.ts +6 -0
- package/src/test/fixtures/routes/api/response-obj.get.ts +17 -0
- package/src/test/fixtures/routes/api/upload.post.ts +14 -0
- package/src/test/fixtures/routes/api/users.get.ts +3 -0
- package/src/test/fixtures/routes/api/xml.get.ts +5 -0
- package/src/test/fixtures/routes/auth/_middleware.ts +11 -0
- package/src/test/fixtures/routes/auth/protected.page.ts +3 -0
- package/src/test/fixtures/routes/index.page.ts +3 -0
- package/src/test/fixtures/routes/oml.page.ts +7 -0
- package/src/test/fixtures/routes/redirect.page.ts +3 -0
- package/src/test/fixtures/routes/ssg/[slug].page.ts +8 -0
- package/src/test/fixtures/routes/ssg/server.page.ts +5 -0
- package/src/test/fixtures/routes/state.page.ts +4 -0
- package/src/test/fixtures/routes/throw.page.ts +5 -0
- package/src/test/fixtures/routes/wiki/[...slug].page.ts +3 -0
- package/src/test/helpers.ts +132 -0
- package/src/test/layouts.test.ts +76 -0
- package/src/test/middleware.test.ts +69 -0
- package/src/test/multipart.test.ts +91 -0
- package/src/test/oml-routing.test.ts +59 -0
- package/src/test/oml.test.ts +429 -0
- package/src/test/redirects.test.ts +32 -0
- package/src/test/routing.test.ts +118 -0
- package/src/test/ssg.test.ts +273 -0
- package/src/test/web-response.test.ts +33 -0
- package/src/types.ts +670 -0
- package/tsconfig.client.json +17 -0
- package/tsconfig.json +20 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { OmlNode } from './oml/types.js';
|
|
3
|
+
/** Options for the `Set-Cookie` header written by `ctx.cookies.set()`. */
|
|
4
|
+
export interface CookieOptions {
|
|
5
|
+
httpOnly?: boolean;
|
|
6
|
+
secure?: boolean;
|
|
7
|
+
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
8
|
+
/** Max age in seconds. */
|
|
9
|
+
maxAge?: number;
|
|
10
|
+
expires?: Date;
|
|
11
|
+
/** Defaults to `'/'` when not specified. */
|
|
12
|
+
path?: string;
|
|
13
|
+
domain?: string;
|
|
14
|
+
}
|
|
15
|
+
/** Reads incoming cookies and writes `Set-Cookie` response headers.
|
|
16
|
+
* Available as `ctx.cookies` in every handler, layout, and middleware. */
|
|
17
|
+
export declare class CookieJar {
|
|
18
|
+
private readonly incoming;
|
|
19
|
+
private readonly res;
|
|
20
|
+
constructor(req: IncomingMessage, res: ServerResponse);
|
|
21
|
+
private static parse;
|
|
22
|
+
/** Read a cookie sent by the browser. Returns `undefined` if absent. */
|
|
23
|
+
get(name: string): string | undefined;
|
|
24
|
+
/** Return all incoming cookies as a plain object. */
|
|
25
|
+
getAll(): Record<string, string>;
|
|
26
|
+
/** Write a `Set-Cookie` header on the response. */
|
|
27
|
+
set(name: string, value: string, options?: CookieOptions): void;
|
|
28
|
+
/** Expire a cookie by setting `Max-Age=0`. */
|
|
29
|
+
delete(name: string, options?: Pick<CookieOptions, 'path' | 'domain'>): void;
|
|
30
|
+
}
|
|
31
|
+
/** Schema interface satisfied by zod, valibot, arktype, and any library whose
|
|
32
|
+
* `.parse()` throws on invalid input. Pass a schema to `ctx.json()` or
|
|
33
|
+
* `ctx.form()` to validate and type the parsed body in one call. */
|
|
34
|
+
export interface Validator<T> {
|
|
35
|
+
parse(data: unknown): T;
|
|
36
|
+
}
|
|
37
|
+
/** Thrown when a body validator rejects the request data.
|
|
38
|
+
* Caught by the framework and sent as `400 { error, issues }`. */
|
|
39
|
+
export declare class ValidationError extends Error {
|
|
40
|
+
readonly isValidation = true;
|
|
41
|
+
constructor(cause: unknown);
|
|
42
|
+
}
|
|
43
|
+
/** Thrown when a request body exceeds the configured size limit.
|
|
44
|
+
* Caught by the framework and sent as `413 Payload Too Large`. */
|
|
45
|
+
export declare class PayloadTooLargeError extends Error {
|
|
46
|
+
readonly isPayloadTooLarge = true;
|
|
47
|
+
readonly status = 413;
|
|
48
|
+
constructor(limitBytes: number);
|
|
49
|
+
}
|
|
50
|
+
/** An uploaded file parsed from a `multipart/form-data` body. */
|
|
51
|
+
export interface MultipartFile {
|
|
52
|
+
filename: string;
|
|
53
|
+
mimetype: string;
|
|
54
|
+
data: Buffer;
|
|
55
|
+
}
|
|
56
|
+
/** Parsed result of `ctx.multipart()`. */
|
|
57
|
+
export interface MultipartResult {
|
|
58
|
+
fields: Record<string, string>;
|
|
59
|
+
files: Record<string, MultipartFile>;
|
|
60
|
+
}
|
|
61
|
+
/** Thrown by `redirect()`. Never construct directly. */
|
|
62
|
+
export declare class RedirectError extends Error {
|
|
63
|
+
readonly url: string;
|
|
64
|
+
readonly status: 301 | 302 | 307 | 308;
|
|
65
|
+
readonly isRedirect = true;
|
|
66
|
+
constructor(url: string, status?: 301 | 302 | 307 | 308);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Throw a redirect to the given URL.
|
|
70
|
+
*
|
|
71
|
+
* **Security note:** If `url` comes from user input (e.g. `ctx.query.get('next')`),
|
|
72
|
+
* validate it before passing it here to prevent open-redirect attacks. At minimum,
|
|
73
|
+
* ensure the value starts with `/` and does not contain `//` or a protocol.
|
|
74
|
+
*/
|
|
75
|
+
export declare function redirect(url: string, status?: 301 | 302 | 307 | 308): never;
|
|
76
|
+
/** Per-request `<head>` metadata. Set values in pages and layouts; the root
|
|
77
|
+
* layout renders them. Pages render before their layouts, so all values are
|
|
78
|
+
* populated by the time the root layout runs. */
|
|
79
|
+
export interface HeadContext {
|
|
80
|
+
title?: string;
|
|
81
|
+
description?: string;
|
|
82
|
+
/** Arbitrary `<meta name="..." content="...">` entries. */
|
|
83
|
+
meta: Record<string, string>;
|
|
84
|
+
/** CSS file URLs injected as `<link rel="stylesheet">`. */
|
|
85
|
+
stylesheets: string[];
|
|
86
|
+
/** JS module URLs injected as `<script type="module">`. */
|
|
87
|
+
scripts: string[];
|
|
88
|
+
}
|
|
89
|
+
type RouteParamNames<T extends string> = T extends `${string}[${infer Param}]${infer Rest}` ? Param | RouteParamNames<Rest> : never;
|
|
90
|
+
/**
|
|
91
|
+
* Infer typed route params from a file path pattern (relative to your routes
|
|
92
|
+
* directory, without the method suffix or extension).
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* // src/routes/blog/[slug].page.tsx
|
|
96
|
+
* export default definePage<ExtractParams<'blog/[slug]'>>(async (ctx) => {
|
|
97
|
+
* ctx.params.slug // string ✓ — TypeScript error if you typo the key
|
|
98
|
+
* })
|
|
99
|
+
*
|
|
100
|
+
* // src/routes/users/[id]/posts/[postId].get.ts
|
|
101
|
+
* export default defineHandler<unknown, ExtractParams<'users/[id]/posts/[postId]'>>(async (ctx) => {
|
|
102
|
+
* ctx.params.id // string ✓
|
|
103
|
+
* ctx.params.postId // string ✓
|
|
104
|
+
* })
|
|
105
|
+
*/
|
|
106
|
+
export type ExtractParams<T extends string> = {
|
|
107
|
+
[K in RouteParamNames<T>]: string;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Open interface for middleware-to-handler pass-through data.
|
|
111
|
+
* Ecosystem packages augment this via declaration merging to add typed properties:
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* declare module 'davaux' {
|
|
115
|
+
* interface State {
|
|
116
|
+
* session: Session
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
*/
|
|
120
|
+
export interface State extends Record<string, unknown> {
|
|
121
|
+
/** Result returned by `defineAction` before the page re-renders on form POST. */
|
|
122
|
+
actionResult?: unknown;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Context object passed to every page, API, layout, middleware, and error handler.
|
|
126
|
+
* @typeParam P - Typed URL params. Use `ExtractParams<'path/[param]'>` for compile-time safety.
|
|
127
|
+
*/
|
|
128
|
+
export interface RequestContext<P extends Record<string, string> = Record<string, string>> {
|
|
129
|
+
req: IncomingMessage;
|
|
130
|
+
res: ServerResponse;
|
|
131
|
+
params: P;
|
|
132
|
+
query: URLSearchParams;
|
|
133
|
+
url: URL;
|
|
134
|
+
/** Base path for subdirectory deployments (e.g. '/docs'). Empty string in dev/SSR. */
|
|
135
|
+
basePath: string;
|
|
136
|
+
cookies: CookieJar;
|
|
137
|
+
/** Mutable head metadata — set in pages/layouts, rendered by the root layout. */
|
|
138
|
+
head: HeadContext;
|
|
139
|
+
/** Pass-through bag for middleware → handler data. Augment via `State` interface merging. */
|
|
140
|
+
state: State;
|
|
141
|
+
/** Parse the request body as JSON. Pass a validator (zod schema, etc.) to
|
|
142
|
+
* validate and type the result; throws `ValidationError` (→ 400) on failure.
|
|
143
|
+
* Default body size limit: 4 MB. Override with `options.maxBytes`. */
|
|
144
|
+
json<T = Record<string, unknown>>(validator?: Validator<T>, options?: {
|
|
145
|
+
maxBytes?: number;
|
|
146
|
+
}): Promise<T>;
|
|
147
|
+
/** Parse the request body as URL-encoded form data. Pass a validator to
|
|
148
|
+
* validate and type the result; throws `ValidationError` (→ 400) on failure.
|
|
149
|
+
* Default body size limit: 1 MB. Override with `options.maxBytes`.
|
|
150
|
+
* When a field name appears more than once, the last value wins — use
|
|
151
|
+
* `ctx.formAll()` to collect all values for multi-select / checkbox groups. */
|
|
152
|
+
form<T = Record<string, string>>(validator?: Validator<T>, options?: {
|
|
153
|
+
maxBytes?: number;
|
|
154
|
+
}): Promise<T>;
|
|
155
|
+
/** Like `ctx.form()`, but returns every value for every key as a `string[]`.
|
|
156
|
+
* Use this for `<select multiple>` and repeated checkbox fields where
|
|
157
|
+
* `ctx.form()` would silently drop all but the last value. */
|
|
158
|
+
formAll<T = Record<string, string[]>>(validator?: Validator<T>, options?: {
|
|
159
|
+
maxBytes?: number;
|
|
160
|
+
}): Promise<T>;
|
|
161
|
+
/** Parse a multipart/form-data request body. Returns parsed text fields and
|
|
162
|
+
* uploaded files. Default body size limit: 10 MB. Override with `options.maxBytes`. */
|
|
163
|
+
multipart(options?: {
|
|
164
|
+
maxBytes?: number;
|
|
165
|
+
}): Promise<MultipartResult>;
|
|
166
|
+
/** Write a raw response with a custom content-type. The response is immediately
|
|
167
|
+
* sent; no further framework serialization occurs. */
|
|
168
|
+
send(body: string | Buffer, contentType: string, status?: number): void;
|
|
169
|
+
/** Write a one-time message that survives a single redirect. Requires @davaux/session. */
|
|
170
|
+
flash(key: string, value: string): void;
|
|
171
|
+
/** Read and consume a flash message set by a previous request. Returns undefined if absent. */
|
|
172
|
+
flash(key: string): string | undefined;
|
|
173
|
+
/**
|
|
174
|
+
* Register a named deferred HTML slot. Returns a `<?marker name="...">` placeholder node
|
|
175
|
+
* that renders inline; when the promise resolves the framework streams a
|
|
176
|
+
* `<template for="name">` element into the response to fill the slot.
|
|
177
|
+
* Polyfill scripts are injected automatically for browsers without native support.
|
|
178
|
+
*/
|
|
179
|
+
defer(name: string, content: Promise<OmlNode | string>): Promise<OmlNode>;
|
|
180
|
+
/** @internal Pending deferred slots registered via `ctx.defer()`. */
|
|
181
|
+
_deferredSlots: Map<string, Promise<OmlNode | string>>;
|
|
182
|
+
}
|
|
183
|
+
/** @internal Construct a `RequestContext` for a given request. Used by the router and SSG. */
|
|
184
|
+
export declare function makeContext(req: IncomingMessage, res: ServerResponse, params: Record<string, string>, url: URL, basePath?: string): RequestContext;
|
|
185
|
+
/** The HTTP method (or `'page'` for full-page SSR routes) a route file handles. */
|
|
186
|
+
export type RouteType = 'page' | 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head' | 'options';
|
|
187
|
+
/** A discovered route file and its compiled URL metadata. */
|
|
188
|
+
export interface RouteFile {
|
|
189
|
+
filePath: string;
|
|
190
|
+
urlPattern: string;
|
|
191
|
+
type: RouteType;
|
|
192
|
+
params: string[];
|
|
193
|
+
}
|
|
194
|
+
/** A discovered `_layout` file and the directory it covers. */
|
|
195
|
+
export interface LayoutFile {
|
|
196
|
+
/** Absolute path to the _layout.tsx file */
|
|
197
|
+
filePath: string;
|
|
198
|
+
/** Absolute path to the directory this layout covers */
|
|
199
|
+
dirPath: string;
|
|
200
|
+
}
|
|
201
|
+
/** A discovered `_middleware` file and the directory it covers. */
|
|
202
|
+
export interface MiddlewareFile {
|
|
203
|
+
/** Absolute path to the _middleware.ts file */
|
|
204
|
+
filePath: string;
|
|
205
|
+
/** Absolute path to the directory this middleware covers */
|
|
206
|
+
dirPath: string;
|
|
207
|
+
}
|
|
208
|
+
/** A discovered island component file and its derived hydration ID. */
|
|
209
|
+
export interface IslandFile {
|
|
210
|
+
/** Absolute path to the island source file */
|
|
211
|
+
filePath: string;
|
|
212
|
+
/** Island ID derived from filename — used as the key in the hydration manifest */
|
|
213
|
+
id: string;
|
|
214
|
+
}
|
|
215
|
+
/** The full result of scanning a routes directory. */
|
|
216
|
+
export interface ScanResult {
|
|
217
|
+
routes: RouteFile[];
|
|
218
|
+
layouts: LayoutFile[];
|
|
219
|
+
middlewares: MiddlewareFile[];
|
|
220
|
+
/** Absolute path to _error.tsx if one exists in the routes directory */
|
|
221
|
+
errorPage?: string;
|
|
222
|
+
}
|
|
223
|
+
/** Function signature for a `.page.*` route handler — receives context and returns HTML or an OmlNode. */
|
|
224
|
+
export type PageHandler<P extends Record<string, string> = Record<string, string>> = (ctx: RequestContext<P>) => string | OmlNode | Promise<string | OmlNode>;
|
|
225
|
+
/** Function signature for an API route handler — receives context and returns a JSON-serialisable value. */
|
|
226
|
+
export type ApiHandler<T = unknown, P extends Record<string, string> = Record<string, string>> = (ctx: RequestContext<P>) => T | Promise<T>;
|
|
227
|
+
/** Function signature for a `_layout.*` handler — receives rendered children and returns HTML or an OmlNode. */
|
|
228
|
+
export type LayoutHandler = (props: LayoutProps) => string | OmlNode | Promise<string | OmlNode>;
|
|
229
|
+
/** Props passed to every layout handler. */
|
|
230
|
+
export interface LayoutProps {
|
|
231
|
+
/** Already-rendered inner HTML. Use as a JSX child or template literal interpolation — it will not be escaped. */
|
|
232
|
+
children: Promise<string>;
|
|
233
|
+
ctx: RequestContext;
|
|
234
|
+
}
|
|
235
|
+
/** Props passed to the `_error.tsx` error page handler. */
|
|
236
|
+
export interface ErrorPageProps {
|
|
237
|
+
status: number;
|
|
238
|
+
message: string;
|
|
239
|
+
ctx: RequestContext;
|
|
240
|
+
}
|
|
241
|
+
/** Function signature for the `_error.*` handler — receives status/message and returns HTML or an OmlNode. */
|
|
242
|
+
export type ErrorPageHandler = (props: ErrorPageProps) => string | OmlNode | Promise<string | OmlNode>;
|
|
243
|
+
/**
|
|
244
|
+
* Wraps a page handler so TypeScript infers the correct return type.
|
|
245
|
+
* Handlers may return an HTML string or an OmlNode — both are handled transparently.
|
|
246
|
+
*
|
|
247
|
+
* export default definePage(async (ctx) => <Layout>...</Layout>)
|
|
248
|
+
*/
|
|
249
|
+
export declare function definePage<P extends Record<string, string> = Record<string, string>>(fn: PageHandler<P>): PageHandler<P>;
|
|
250
|
+
/**
|
|
251
|
+
* Wraps an API route handler.
|
|
252
|
+
*
|
|
253
|
+
* export default defineHandler(async (ctx) => ({ ok: true }))
|
|
254
|
+
*/
|
|
255
|
+
export declare function defineHandler<T = unknown, P extends Record<string, string> = Record<string, string>>(fn: ApiHandler<T, P>): ApiHandler<T, P>;
|
|
256
|
+
/**
|
|
257
|
+
* Wraps a layout component.
|
|
258
|
+
*
|
|
259
|
+
* export default defineLayout(({ children, ctx }) => <html>...</html>)
|
|
260
|
+
*/
|
|
261
|
+
export declare function defineLayout(fn: LayoutHandler): LayoutHandler;
|
|
262
|
+
/**
|
|
263
|
+
* Wraps the `_error.tsx` handler for type inference.
|
|
264
|
+
*
|
|
265
|
+
* export default defineError(({ status, message, ctx }) => (
|
|
266
|
+
* <div><h1>{status}</h1><p>{message}</p></div>
|
|
267
|
+
* ))
|
|
268
|
+
*/
|
|
269
|
+
export declare function defineError(fn: ErrorPageHandler): ErrorPageHandler;
|
|
270
|
+
/** A middleware function: runs code before and/or after the next handler in the chain. */
|
|
271
|
+
export type MiddlewareFn = (ctx: RequestContext, next: () => Promise<void>) => Promise<void>;
|
|
272
|
+
/**
|
|
273
|
+
* Wraps a middleware function for type inference.
|
|
274
|
+
*
|
|
275
|
+
* export default defineMiddleware(async (ctx, next) => {
|
|
276
|
+
* // run before the route handler
|
|
277
|
+
* await next()
|
|
278
|
+
* // run after
|
|
279
|
+
* })
|
|
280
|
+
*/
|
|
281
|
+
export declare function defineMiddleware(fn: MiddlewareFn): MiddlewareFn;
|
|
282
|
+
/**
|
|
283
|
+
* Function signature for a form action handler.
|
|
284
|
+
* The return value (if any) is set as `ctx.state.actionResult` before the
|
|
285
|
+
* page re-renders. Throw `redirect()` to skip re-rendering entirely.
|
|
286
|
+
*/
|
|
287
|
+
export type ActionFn<T = unknown> = (ctx: RequestContext) => T | Promise<T>;
|
|
288
|
+
/**
|
|
289
|
+
* Wraps a form action handler co-located with a page file.
|
|
290
|
+
*
|
|
291
|
+
* export const action = defineAction(async (ctx) => {
|
|
292
|
+
* const { email, password } = await ctx.form()
|
|
293
|
+
* const user = await db.authenticate(email, password)
|
|
294
|
+
* if (!user) return { error: 'Invalid credentials' }
|
|
295
|
+
* redirect('/dashboard')
|
|
296
|
+
* })
|
|
297
|
+
*/
|
|
298
|
+
export declare function defineAction<T = unknown>(fn: ActionFn<T>): ActionFn<T>;
|
|
299
|
+
/** A single set of params for a statically pre-rendered dynamic route. */
|
|
300
|
+
export type StaticPath = {
|
|
301
|
+
params: Record<string, string>;
|
|
302
|
+
};
|
|
303
|
+
/** Function signature for `getStaticPaths` — returns all param sets to render at build time. */
|
|
304
|
+
export type GetStaticPathsFn = () => StaticPath[] | Promise<StaticPath[]>;
|
|
305
|
+
/**
|
|
306
|
+
* Wraps a `getStaticPaths` export for type inference.
|
|
307
|
+
*
|
|
308
|
+
* export const getStaticPaths = defineStaticPaths(async () => [
|
|
309
|
+
* { params: { slug: 'hello-world' } },
|
|
310
|
+
* ])
|
|
311
|
+
*/
|
|
312
|
+
export declare function defineStaticPaths(fn: GetStaticPathsFn): GetStaticPathsFn;
|
|
313
|
+
export {};
|
|
314
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
function sanitizeCookieAttr(val) {
|
|
2
|
+
return val.replace(/[;\r\n]/g, "");
|
|
3
|
+
}
|
|
4
|
+
class CookieJar {
|
|
5
|
+
incoming;
|
|
6
|
+
res;
|
|
7
|
+
constructor(req, res) {
|
|
8
|
+
this.res = res;
|
|
9
|
+
this.incoming = CookieJar.parse(req.headers.cookie ?? "");
|
|
10
|
+
}
|
|
11
|
+
static parse(header) {
|
|
12
|
+
const out = {};
|
|
13
|
+
for (const pair of header.split(";")) {
|
|
14
|
+
const eq = pair.indexOf("=");
|
|
15
|
+
if (eq === -1) continue;
|
|
16
|
+
const name = pair.slice(0, eq).trim();
|
|
17
|
+
const value = pair.slice(eq + 1).trim();
|
|
18
|
+
if (name) out[name] = decodeURIComponent(value);
|
|
19
|
+
}
|
|
20
|
+
return out;
|
|
21
|
+
}
|
|
22
|
+
/** Read a cookie sent by the browser. Returns `undefined` if absent. */
|
|
23
|
+
get(name) {
|
|
24
|
+
return this.incoming[name];
|
|
25
|
+
}
|
|
26
|
+
/** Return all incoming cookies as a plain object. */
|
|
27
|
+
getAll() {
|
|
28
|
+
return { ...this.incoming };
|
|
29
|
+
}
|
|
30
|
+
/** Write a `Set-Cookie` header on the response. */
|
|
31
|
+
set(name, value, options = {}) {
|
|
32
|
+
const encoded = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
|
|
33
|
+
const parts = [encoded];
|
|
34
|
+
const path = sanitizeCookieAttr(options.path ?? "/");
|
|
35
|
+
if (options.maxAge != null) parts.push(`Max-Age=${options.maxAge}`);
|
|
36
|
+
if (options.expires) parts.push(`Expires=${options.expires.toUTCString()}`);
|
|
37
|
+
parts.push(`Path=${path}`);
|
|
38
|
+
if (options.domain) parts.push(`Domain=${sanitizeCookieAttr(options.domain)}`);
|
|
39
|
+
if (options.httpOnly) parts.push("HttpOnly");
|
|
40
|
+
if (options.secure) parts.push("Secure");
|
|
41
|
+
if (options.sameSite) parts.push(`SameSite=${options.sameSite}`);
|
|
42
|
+
const existing = this.res.getHeader("Set-Cookie");
|
|
43
|
+
const prev = existing ? Array.isArray(existing) ? existing : [String(existing)] : [];
|
|
44
|
+
this.res.setHeader("Set-Cookie", [...prev, parts.join("; ")]);
|
|
45
|
+
}
|
|
46
|
+
/** Expire a cookie by setting `Max-Age=0`. */
|
|
47
|
+
delete(name, options) {
|
|
48
|
+
this.set(name, "", { ...options, maxAge: 0, expires: /* @__PURE__ */ new Date(0) });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
class ValidationError extends Error {
|
|
52
|
+
isValidation = true;
|
|
53
|
+
constructor(cause) {
|
|
54
|
+
super(cause instanceof Error ? cause.message : "Validation failed", { cause });
|
|
55
|
+
this.name = "ValidationError";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
class PayloadTooLargeError extends Error {
|
|
59
|
+
isPayloadTooLarge = true;
|
|
60
|
+
status = 413;
|
|
61
|
+
constructor(limitBytes) {
|
|
62
|
+
super(`Payload Too Large \u2014 body exceeds ${limitBytes.toLocaleString()} bytes`);
|
|
63
|
+
this.name = "PayloadTooLargeError";
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
class RedirectError extends Error {
|
|
67
|
+
constructor(url, status = 302) {
|
|
68
|
+
super(`Redirect \u2192 ${url}`);
|
|
69
|
+
this.url = url;
|
|
70
|
+
this.status = status;
|
|
71
|
+
this.name = "RedirectError";
|
|
72
|
+
}
|
|
73
|
+
url;
|
|
74
|
+
status;
|
|
75
|
+
isRedirect = true;
|
|
76
|
+
}
|
|
77
|
+
function redirect(url, status = 302) {
|
|
78
|
+
throw new RedirectError(url, status);
|
|
79
|
+
}
|
|
80
|
+
const DEFAULT_FORM_LIMIT = 1e6;
|
|
81
|
+
const DEFAULT_JSON_LIMIT = 4e6;
|
|
82
|
+
const DEFAULT_MULTIPART_LIMIT = 1e7;
|
|
83
|
+
function readRawBuffer(req, maxBytes) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
const chunks = [];
|
|
86
|
+
let size = 0;
|
|
87
|
+
req.on("data", (chunk) => {
|
|
88
|
+
size += chunk.length;
|
|
89
|
+
if (size > maxBytes) {
|
|
90
|
+
req.destroy();
|
|
91
|
+
reject(new PayloadTooLargeError(maxBytes));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
chunks.push(chunk);
|
|
95
|
+
});
|
|
96
|
+
req.on("end", () => resolve(Buffer.concat(chunks)));
|
|
97
|
+
req.on("error", reject);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function splitBuffer(buf, sep) {
|
|
101
|
+
const parts = [];
|
|
102
|
+
let start = 0;
|
|
103
|
+
while (true) {
|
|
104
|
+
const idx = buf.indexOf(sep, start);
|
|
105
|
+
if (idx === -1) break;
|
|
106
|
+
parts.push(buf.subarray(start, idx));
|
|
107
|
+
start = idx + sep.length;
|
|
108
|
+
}
|
|
109
|
+
parts.push(buf.subarray(start));
|
|
110
|
+
return parts;
|
|
111
|
+
}
|
|
112
|
+
function extractMultipartParam(header, param) {
|
|
113
|
+
const rq = new RegExp(`(?:^|;)\\s*${param}="([^"]*)"`, "i");
|
|
114
|
+
const mq = header.match(rq);
|
|
115
|
+
if (mq) return mq[1];
|
|
116
|
+
const ru = new RegExp(`(?:^|;)\\s*${param}=([^;\\s]*)`, "i");
|
|
117
|
+
const mu = header.match(ru);
|
|
118
|
+
return mu ? mu[1] : void 0;
|
|
119
|
+
}
|
|
120
|
+
function parseMultipart(body, boundary) {
|
|
121
|
+
const fields = {};
|
|
122
|
+
const files = {};
|
|
123
|
+
const sep = Buffer.from(`\r
|
|
124
|
+
--${boundary}`);
|
|
125
|
+
const parts = splitBuffer(Buffer.concat([Buffer.from("\r\n"), body]), sep);
|
|
126
|
+
for (const part of parts) {
|
|
127
|
+
if (part.length < 2) continue;
|
|
128
|
+
const prefix = part.subarray(0, 2).toString("ascii");
|
|
129
|
+
if (prefix === "--") break;
|
|
130
|
+
if (prefix !== "\r\n") continue;
|
|
131
|
+
const content = part.subarray(2);
|
|
132
|
+
const headerEnd = content.indexOf("\r\n\r\n");
|
|
133
|
+
if (headerEnd === -1) continue;
|
|
134
|
+
const headerStr = content.subarray(0, headerEnd).toString("utf-8");
|
|
135
|
+
const partBody = content.subarray(headerEnd + 4);
|
|
136
|
+
const headers = {};
|
|
137
|
+
for (const line of headerStr.split("\r\n")) {
|
|
138
|
+
const colon = line.indexOf(":");
|
|
139
|
+
if (colon === -1) continue;
|
|
140
|
+
headers[line.slice(0, colon).trim().toLowerCase()] = line.slice(colon + 1).trim();
|
|
141
|
+
}
|
|
142
|
+
const disposition = headers["content-disposition"] ?? "";
|
|
143
|
+
const name = extractMultipartParam(disposition, "name");
|
|
144
|
+
if (!name) continue;
|
|
145
|
+
const filename = extractMultipartParam(disposition, "filename");
|
|
146
|
+
if (filename !== void 0) {
|
|
147
|
+
files[name] = {
|
|
148
|
+
filename,
|
|
149
|
+
mimetype: headers["content-type"] ?? "application/octet-stream",
|
|
150
|
+
data: partBody
|
|
151
|
+
};
|
|
152
|
+
} else {
|
|
153
|
+
fields[name] = partBody.toString("utf-8");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { fields, files };
|
|
157
|
+
}
|
|
158
|
+
function makeContext(req, res, params, url, basePath = "") {
|
|
159
|
+
let bodyCache;
|
|
160
|
+
function rawBuffer(maxBytes) {
|
|
161
|
+
if (bodyCache === void 0) bodyCache = readRawBuffer(req, maxBytes);
|
|
162
|
+
return bodyCache;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
req,
|
|
166
|
+
res,
|
|
167
|
+
params,
|
|
168
|
+
query: url.searchParams,
|
|
169
|
+
url,
|
|
170
|
+
basePath,
|
|
171
|
+
cookies: new CookieJar(req, res),
|
|
172
|
+
head: { meta: {}, stylesheets: [], scripts: [] },
|
|
173
|
+
state: {},
|
|
174
|
+
async json(validator, options) {
|
|
175
|
+
const raw = JSON.parse(
|
|
176
|
+
(await rawBuffer(options?.maxBytes ?? DEFAULT_JSON_LIMIT)).toString("utf-8")
|
|
177
|
+
);
|
|
178
|
+
if (!validator) return raw;
|
|
179
|
+
try {
|
|
180
|
+
return validator.parse(raw);
|
|
181
|
+
} catch (err) {
|
|
182
|
+
throw new ValidationError(err);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
async form(validator, options) {
|
|
186
|
+
const text = (await rawBuffer(options?.maxBytes ?? DEFAULT_FORM_LIMIT)).toString("utf-8");
|
|
187
|
+
const out = {};
|
|
188
|
+
for (const [k, v] of new URLSearchParams(text)) out[k] = v;
|
|
189
|
+
if (!validator) return out;
|
|
190
|
+
try {
|
|
191
|
+
return validator.parse(out);
|
|
192
|
+
} catch (err) {
|
|
193
|
+
throw new ValidationError(err);
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
async formAll(validator, options) {
|
|
197
|
+
const text = (await rawBuffer(options?.maxBytes ?? DEFAULT_FORM_LIMIT)).toString("utf-8");
|
|
198
|
+
const out = {};
|
|
199
|
+
for (const [k, v] of new URLSearchParams(text)) {
|
|
200
|
+
if (out[k] === void 0) out[k] = [];
|
|
201
|
+
out[k].push(v);
|
|
202
|
+
}
|
|
203
|
+
if (!validator) return out;
|
|
204
|
+
try {
|
|
205
|
+
return validator.parse(out);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
throw new ValidationError(err);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
async multipart(options) {
|
|
211
|
+
const ct = req.headers["content-type"] ?? "";
|
|
212
|
+
const boundary = extractMultipartParam(ct, "boundary");
|
|
213
|
+
if (!boundary)
|
|
214
|
+
throw new Error(
|
|
215
|
+
"[davaux] ctx.multipart() requires a multipart/form-data request with a boundary"
|
|
216
|
+
);
|
|
217
|
+
const buf = await rawBuffer(options?.maxBytes ?? DEFAULT_MULTIPART_LIMIT);
|
|
218
|
+
return parseMultipart(buf, boundary);
|
|
219
|
+
},
|
|
220
|
+
send(body, contentType, status = 200) {
|
|
221
|
+
if (!res.headersSent) {
|
|
222
|
+
res.writeHead(status, { "Content-Type": contentType });
|
|
223
|
+
res.end(body);
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
flash(key, value) {
|
|
227
|
+
const session = this.state.session;
|
|
228
|
+
if (!session)
|
|
229
|
+
throw new Error(
|
|
230
|
+
"[davaux] ctx.flash() requires @davaux/session \u2014 add sessionMiddleware to your middleware config"
|
|
231
|
+
);
|
|
232
|
+
const NS = "_flash";
|
|
233
|
+
if (value !== void 0) {
|
|
234
|
+
const bag2 = session.get(NS) ?? {};
|
|
235
|
+
session.set(NS, { ...bag2, [key]: value });
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
const bag = session.get(NS) ?? {};
|
|
239
|
+
const msg = bag[key];
|
|
240
|
+
if (msg !== void 0) {
|
|
241
|
+
const { [key]: _, ...rest } = bag;
|
|
242
|
+
Object.keys(rest).length > 0 ? session.set(NS, rest) : session.delete(NS);
|
|
243
|
+
}
|
|
244
|
+
return msg;
|
|
245
|
+
},
|
|
246
|
+
_deferredSlots: /* @__PURE__ */ new Map(),
|
|
247
|
+
defer(name, content) {
|
|
248
|
+
if (this._deferredSlots.size === 0) {
|
|
249
|
+
this.head.scripts.push("/_davaux/partial-updates.js");
|
|
250
|
+
}
|
|
251
|
+
this._deferredSlots.set(name, content);
|
|
252
|
+
return Promise.resolve({ type: "#raw", value: `<?marker name="${name}">` });
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function definePage(fn) {
|
|
257
|
+
return fn;
|
|
258
|
+
}
|
|
259
|
+
function defineHandler(fn) {
|
|
260
|
+
return fn;
|
|
261
|
+
}
|
|
262
|
+
function defineLayout(fn) {
|
|
263
|
+
return fn;
|
|
264
|
+
}
|
|
265
|
+
function defineError(fn) {
|
|
266
|
+
return fn;
|
|
267
|
+
}
|
|
268
|
+
function defineMiddleware(fn) {
|
|
269
|
+
return fn;
|
|
270
|
+
}
|
|
271
|
+
function defineAction(fn) {
|
|
272
|
+
return fn;
|
|
273
|
+
}
|
|
274
|
+
function defineStaticPaths(fn) {
|
|
275
|
+
return fn;
|
|
276
|
+
}
|
|
277
|
+
export {
|
|
278
|
+
CookieJar,
|
|
279
|
+
PayloadTooLargeError,
|
|
280
|
+
RedirectError,
|
|
281
|
+
ValidationError,
|
|
282
|
+
defineAction,
|
|
283
|
+
defineError,
|
|
284
|
+
defineHandler,
|
|
285
|
+
defineLayout,
|
|
286
|
+
defineMiddleware,
|
|
287
|
+
definePage,
|
|
288
|
+
defineStaticPaths,
|
|
289
|
+
makeContext,
|
|
290
|
+
redirect
|
|
291
|
+
};
|
|
292
|
+
//# sourceMappingURL=types.js.map
|