@shaferllc/keel 0.12.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/LICENSE +21 -0
- package/README.md +222 -0
- package/dist/core/application.d.ts +40 -0
- package/dist/core/application.js +115 -0
- package/dist/core/config.d.ts +17 -0
- package/dist/core/config.js +55 -0
- package/dist/core/container.d.ts +30 -0
- package/dist/core/container.js +59 -0
- package/dist/core/exceptions.d.ts +26 -0
- package/dist/core/exceptions.js +56 -0
- package/dist/core/helpers.d.ts +42 -0
- package/dist/core/helpers.js +55 -0
- package/dist/core/http/kernel.d.ts +29 -0
- package/dist/core/http/kernel.js +173 -0
- package/dist/core/http/router.d.ts +160 -0
- package/dist/core/http/router.js +344 -0
- package/dist/core/index.d.ts +21 -0
- package/dist/core/index.js +13 -0
- package/dist/core/inertia.d.ts +34 -0
- package/dist/core/inertia.js +68 -0
- package/dist/core/provider.d.ts +16 -0
- package/dist/core/provider.js +16 -0
- package/dist/core/request.d.ts +76 -0
- package/dist/core/request.js +151 -0
- package/dist/core/validation.d.ts +32 -0
- package/dist/core/validation.js +33 -0
- package/dist/core/view.d.ts +29 -0
- package/dist/core/view.js +27 -0
- package/package.json +57 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global helpers — convenience functions for reaching the active application.
|
|
3
|
+
*
|
|
4
|
+
* These resolve against the "current" application, which is registered
|
|
5
|
+
* automatically when an Application is constructed. In a normal single-app
|
|
6
|
+
* process (Node server or one Worker isolate) that's exactly what you want:
|
|
7
|
+
* call `config('app.name')` from anywhere without threading the container
|
|
8
|
+
* through every function.
|
|
9
|
+
*/
|
|
10
|
+
import type { Application } from "./application.js";
|
|
11
|
+
import type { Token, Factory } from "./container.js";
|
|
12
|
+
import { type Renderable } from "./view.js";
|
|
13
|
+
/** Register the active application. Called by the Application constructor. */
|
|
14
|
+
export declare function setApplication(app: Application): void;
|
|
15
|
+
/** The active application container. Throws if none has been created. */
|
|
16
|
+
export declare function app(): Application;
|
|
17
|
+
/**
|
|
18
|
+
* Read configuration with dot notation: `config('app.name')`, or with a
|
|
19
|
+
* fallback: `config('app.port', 3000)`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function config<T = unknown>(key: string, fallback?: T): T;
|
|
22
|
+
/** Register a transient binding — a fresh value every resolve. */
|
|
23
|
+
export declare function bind<T>(token: Token<T>, factory: Factory<T>): void;
|
|
24
|
+
/** Register a shared binding — resolved once, then cached. */
|
|
25
|
+
export declare function singleton<T>(token: Token<T>, factory: Factory<T>): void;
|
|
26
|
+
/** Register an already-constructed value as a shared instance. */
|
|
27
|
+
export declare function instance<T>(token: Token<T>, value: T): T;
|
|
28
|
+
/** Resolve a token out of the container. */
|
|
29
|
+
export declare function make<T>(token: Token<T>): T;
|
|
30
|
+
/** Whether a token is bound or has a cached instance. */
|
|
31
|
+
export declare function bound(token: Token): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Render a view component through the View service, in one call:
|
|
34
|
+
*
|
|
35
|
+
* return view(WelcomePage, { appName }); // component with props
|
|
36
|
+
* return view(HomePage); // component with no props
|
|
37
|
+
*
|
|
38
|
+
* Props are type-checked against the component. Returns a full HTML document
|
|
39
|
+
* (Promise<string>) — return it straight from a route handler.
|
|
40
|
+
*/
|
|
41
|
+
export declare function view<P>(component: (props: P, ...rest: any[]) => Renderable, props: P): Promise<string>;
|
|
42
|
+
export declare function view(component: (...rest: any[]) => Renderable): Promise<string>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global helpers — convenience functions for reaching the active application.
|
|
3
|
+
*
|
|
4
|
+
* These resolve against the "current" application, which is registered
|
|
5
|
+
* automatically when an Application is constructed. In a normal single-app
|
|
6
|
+
* process (Node server or one Worker isolate) that's exactly what you want:
|
|
7
|
+
* call `config('app.name')` from anywhere without threading the container
|
|
8
|
+
* through every function.
|
|
9
|
+
*/
|
|
10
|
+
import { Config } from "./config.js";
|
|
11
|
+
import { View } from "./view.js";
|
|
12
|
+
let current;
|
|
13
|
+
/** Register the active application. Called by the Application constructor. */
|
|
14
|
+
export function setApplication(app) {
|
|
15
|
+
current = app;
|
|
16
|
+
}
|
|
17
|
+
/** The active application container. Throws if none has been created. */
|
|
18
|
+
export function app() {
|
|
19
|
+
if (!current) {
|
|
20
|
+
throw new Error("No Keel application has been bootstrapped. Create an Application first.");
|
|
21
|
+
}
|
|
22
|
+
return current;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read configuration with dot notation: `config('app.name')`, or with a
|
|
26
|
+
* fallback: `config('app.port', 3000)`.
|
|
27
|
+
*/
|
|
28
|
+
export function config(key, fallback) {
|
|
29
|
+
return app().make(Config).get(key, fallback);
|
|
30
|
+
}
|
|
31
|
+
/* --------------------------- container helpers --------------------------- */
|
|
32
|
+
/* Bind and resolve against the active application from anywhere — no `this.app`. */
|
|
33
|
+
/** Register a transient binding — a fresh value every resolve. */
|
|
34
|
+
export function bind(token, factory) {
|
|
35
|
+
app().bind(token, factory);
|
|
36
|
+
}
|
|
37
|
+
/** Register a shared binding — resolved once, then cached. */
|
|
38
|
+
export function singleton(token, factory) {
|
|
39
|
+
app().singleton(token, factory);
|
|
40
|
+
}
|
|
41
|
+
/** Register an already-constructed value as a shared instance. */
|
|
42
|
+
export function instance(token, value) {
|
|
43
|
+
return app().instance(token, value);
|
|
44
|
+
}
|
|
45
|
+
/** Resolve a token out of the container. */
|
|
46
|
+
export function make(token) {
|
|
47
|
+
return app().make(token);
|
|
48
|
+
}
|
|
49
|
+
/** Whether a token is bound or has a cached instance. */
|
|
50
|
+
export function bound(token) {
|
|
51
|
+
return app().bound(token);
|
|
52
|
+
}
|
|
53
|
+
export function view(component, props) {
|
|
54
|
+
return app().make(View).render(component(props));
|
|
55
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP kernel. Owns the global middleware stack, compiles the Router's
|
|
3
|
+
* collected routes onto a Hono instance, and turns thrown errors (and
|
|
4
|
+
* unmatched routes) into proper responses.
|
|
5
|
+
*/
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import type { Context, MiddlewareHandler } from "hono";
|
|
8
|
+
import type { Application } from "../application.js";
|
|
9
|
+
type ErrorHandler = (err: unknown, c: Context) => Response | Promise<Response>;
|
|
10
|
+
export declare class HttpKernel {
|
|
11
|
+
protected app: Application;
|
|
12
|
+
/** Global middleware, run on every request in order. */
|
|
13
|
+
protected middleware: MiddlewareHandler[];
|
|
14
|
+
/** Optional app-supplied error handler, taking precedence over the default. */
|
|
15
|
+
protected customErrorHandler?: ErrorHandler;
|
|
16
|
+
constructor(app: Application);
|
|
17
|
+
use(mw: MiddlewareHandler): this;
|
|
18
|
+
/** Register a custom error handler (overrides the default rendering). */
|
|
19
|
+
onError(handler: ErrorHandler): this;
|
|
20
|
+
/** Build the Hono app: mount routes, dispatch domain routes by host. */
|
|
21
|
+
build(): Hono;
|
|
22
|
+
/** Compile a set of routes onto a fresh Hono instance. */
|
|
23
|
+
private compile;
|
|
24
|
+
private handle;
|
|
25
|
+
/** Default rendering: HTML for browsers, JSON otherwise; details in debug. */
|
|
26
|
+
protected renderException(err: unknown, c: Context): Response;
|
|
27
|
+
private errorPage;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP kernel. Owns the global middleware stack, compiles the Router's
|
|
3
|
+
* collected routes onto a Hono instance, and turns thrown errors (and
|
|
4
|
+
* unmatched routes) into proper responses.
|
|
5
|
+
*/
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import { contextStorage } from "hono/context-storage";
|
|
8
|
+
import { Config } from "../config.js";
|
|
9
|
+
import { HttpException, NotFoundException, ValidationException, STATUS_TEXT, } from "../exceptions.js";
|
|
10
|
+
import { Router } from "./router.js";
|
|
11
|
+
/** Per-request stash of subdomain params, keyed by the raw Request. */
|
|
12
|
+
const SUBDOMAINS = new WeakMap();
|
|
13
|
+
/** Compile a host pattern like ":tenant.example.com" into a matcher. */
|
|
14
|
+
function domainMatcher(pattern) {
|
|
15
|
+
const keys = [];
|
|
16
|
+
const source = pattern
|
|
17
|
+
.split(".")
|
|
18
|
+
.map((seg) => {
|
|
19
|
+
if (seg.startsWith(":")) {
|
|
20
|
+
keys.push(seg.slice(1));
|
|
21
|
+
return "([^.]+)";
|
|
22
|
+
}
|
|
23
|
+
return seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
24
|
+
})
|
|
25
|
+
.join("\\.");
|
|
26
|
+
return { regex: new RegExp(`^${source}$`), keys };
|
|
27
|
+
}
|
|
28
|
+
export class HttpKernel {
|
|
29
|
+
app;
|
|
30
|
+
/** Global middleware, run on every request in order. */
|
|
31
|
+
middleware = [];
|
|
32
|
+
/** Optional app-supplied error handler, taking precedence over the default. */
|
|
33
|
+
customErrorHandler;
|
|
34
|
+
constructor(app) {
|
|
35
|
+
this.app = app;
|
|
36
|
+
}
|
|
37
|
+
use(mw) {
|
|
38
|
+
this.middleware.push(mw);
|
|
39
|
+
return this;
|
|
40
|
+
}
|
|
41
|
+
/** Register a custom error handler (overrides the default rendering). */
|
|
42
|
+
onError(handler) {
|
|
43
|
+
this.customErrorHandler = handler;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
/** Build the Hono app: mount routes, dispatch domain routes by host. */
|
|
47
|
+
build() {
|
|
48
|
+
const router = this.app.make(Router);
|
|
49
|
+
const routes = router.all();
|
|
50
|
+
const domainRoutes = routes.filter((r) => r.domain);
|
|
51
|
+
const defaultRoutes = routes.filter((r) => !r.domain);
|
|
52
|
+
// No domain routing — the common case.
|
|
53
|
+
if (domainRoutes.length === 0) {
|
|
54
|
+
return this.compile(defaultRoutes);
|
|
55
|
+
}
|
|
56
|
+
// Compile a Hono per distinct host pattern, plus a host dispatcher that
|
|
57
|
+
// runs before everything else on the default app.
|
|
58
|
+
const byDomain = new Map();
|
|
59
|
+
for (const r of domainRoutes) {
|
|
60
|
+
const list = byDomain.get(r.domain) ?? [];
|
|
61
|
+
list.push(r);
|
|
62
|
+
byDomain.set(r.domain, list);
|
|
63
|
+
}
|
|
64
|
+
const compiled = [...byDomain.entries()].map(([pattern, rs]) => ({
|
|
65
|
+
...domainMatcher(pattern),
|
|
66
|
+
hono: this.compile(rs),
|
|
67
|
+
}));
|
|
68
|
+
const dispatch = async (c, next) => {
|
|
69
|
+
const host = (c.req.header("host") ?? "").split(":")[0];
|
|
70
|
+
for (const d of compiled) {
|
|
71
|
+
const m = host.match(d.regex);
|
|
72
|
+
if (m) {
|
|
73
|
+
const subs = {};
|
|
74
|
+
d.keys.forEach((k, i) => (subs[k] = m[i + 1]));
|
|
75
|
+
SUBDOMAINS.set(c.req.raw, subs);
|
|
76
|
+
return d.hono.fetch(c.req.raw, c.env);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
await next();
|
|
80
|
+
};
|
|
81
|
+
return this.compile(defaultRoutes, dispatch);
|
|
82
|
+
}
|
|
83
|
+
/** Compile a set of routes onto a fresh Hono instance. */
|
|
84
|
+
compile(routes, firstMiddleware) {
|
|
85
|
+
const hono = new Hono();
|
|
86
|
+
const router = this.app.make(Router);
|
|
87
|
+
if (firstMiddleware)
|
|
88
|
+
hono.use("*", firstMiddleware);
|
|
89
|
+
// Store the context per-request so the request helpers reach it.
|
|
90
|
+
hono.use("*", contextStorage());
|
|
91
|
+
// Bind the container and any subdomain params onto the context.
|
|
92
|
+
hono.use("*", async (c, next) => {
|
|
93
|
+
c.set("app", this.app);
|
|
94
|
+
const subs = SUBDOMAINS.get(c.req.raw);
|
|
95
|
+
if (subs)
|
|
96
|
+
c.set("subdomains", subs);
|
|
97
|
+
await next();
|
|
98
|
+
});
|
|
99
|
+
for (const mw of this.middleware) {
|
|
100
|
+
hono.use("*", mw);
|
|
101
|
+
}
|
|
102
|
+
for (const route of routes) {
|
|
103
|
+
const fn = router.resolve(route.handler);
|
|
104
|
+
const honoHandler = async (c) => {
|
|
105
|
+
c.set("route", { name: route.name, pattern: route.path, methods: route.methods });
|
|
106
|
+
const result = await fn(c);
|
|
107
|
+
return typeof result === "string" ? c.html(result) : result;
|
|
108
|
+
};
|
|
109
|
+
// Compile param constraints into Hono's regex-param syntax (:id{\d+}).
|
|
110
|
+
let path = route.path;
|
|
111
|
+
for (const [param, rgx] of Object.entries(route.wheres)) {
|
|
112
|
+
path = path.replace(new RegExp(`:${param}(\\??)`), `:${param}{${rgx}}$1`);
|
|
113
|
+
}
|
|
114
|
+
hono.on(route.methods, [path], ...route.middleware, honoHandler);
|
|
115
|
+
}
|
|
116
|
+
hono.notFound((c) => this.handle(new NotFoundException(`No route for ${c.req.method} ${c.req.path}`), c));
|
|
117
|
+
hono.onError((err, c) => this.handle(err, c));
|
|
118
|
+
return hono;
|
|
119
|
+
}
|
|
120
|
+
handle(err, c) {
|
|
121
|
+
if (this.customErrorHandler)
|
|
122
|
+
return this.customErrorHandler(err, c);
|
|
123
|
+
return this.renderException(err, c);
|
|
124
|
+
}
|
|
125
|
+
/** Default rendering: HTML for browsers, JSON otherwise; details in debug. */
|
|
126
|
+
renderException(err, c) {
|
|
127
|
+
const isHttp = err instanceof HttpException;
|
|
128
|
+
const status = isHttp ? err.status : 500;
|
|
129
|
+
const debug = Boolean(this.app.make(Config).get("app.debug", false));
|
|
130
|
+
const title = STATUS_TEXT[status] ?? "Error";
|
|
131
|
+
// Hide internal messages for unexpected 500s in production.
|
|
132
|
+
const message = isHttp || debug ? (err instanceof Error ? err.message : String(err)) : title;
|
|
133
|
+
if (isHttp && err.headers) {
|
|
134
|
+
for (const [k, v] of Object.entries(err.headers))
|
|
135
|
+
c.header(k, v);
|
|
136
|
+
}
|
|
137
|
+
const wantsHtml = (c.req.header("accept") ?? "").includes("text/html");
|
|
138
|
+
const code = status;
|
|
139
|
+
if (wantsHtml) {
|
|
140
|
+
return c.html(this.errorPage(status, title, message, err, debug, c), code);
|
|
141
|
+
}
|
|
142
|
+
const body = { error: message, status };
|
|
143
|
+
if (err instanceof ValidationException)
|
|
144
|
+
body.errors = err.errors;
|
|
145
|
+
if (debug && !isHttp && err instanceof Error) {
|
|
146
|
+
body.exception = err.name;
|
|
147
|
+
body.stack = (err.stack ?? "").split("\n").map((l) => l.trim());
|
|
148
|
+
}
|
|
149
|
+
return c.json(body, code);
|
|
150
|
+
}
|
|
151
|
+
errorPage(status, title, message, err, debug, c) {
|
|
152
|
+
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
153
|
+
const stack = debug && err instanceof Error && err.stack ? esc(err.stack) : "";
|
|
154
|
+
const req = `${c.req.method} ${c.req.path}`;
|
|
155
|
+
return `<!DOCTYPE html><html lang="en"><head><meta charset="utf-8">
|
|
156
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
157
|
+
<title>${status} ${esc(title)}</title><style>
|
|
158
|
+
body{margin:0;background:#0b1120;color:#e2e8f0;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;display:flex;min-height:100vh;align-items:center;justify-content:center;padding:2rem}
|
|
159
|
+
.box{max-width:52rem;width:100%}
|
|
160
|
+
.status{font-size:4rem;font-weight:700;line-height:1;color:#f87171}
|
|
161
|
+
.title{font-size:1.1rem;color:#94a3b8;margin:.3rem 0 1.2rem;text-transform:uppercase;letter-spacing:.1em}
|
|
162
|
+
.msg{font-size:1.25rem;margin:0 0 1rem}
|
|
163
|
+
.req{color:#64748b;font-size:.9rem;margin-bottom:1.5rem}
|
|
164
|
+
pre{background:#020617;border:1px solid #1e293b;border-radius:.5rem;padding:1.1rem;overflow-x:auto;font-size:.82rem;line-height:1.7;color:#cbd5e1;white-space:pre-wrap}
|
|
165
|
+
</style></head><body><div class="box">
|
|
166
|
+
<div class="status">${status}</div>
|
|
167
|
+
<div class="title">${esc(title)}</div>
|
|
168
|
+
<p class="msg">${esc(message)}</p>
|
|
169
|
+
<div class="req">${esc(req)}</div>
|
|
170
|
+
${stack ? `<pre>${stack}</pre>` : ""}
|
|
171
|
+
</div></body></html>`;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router facade. Collects route definitions declaratively; the HTTP kernel
|
|
3
|
+
* compiles them onto the underlying Hono instance at boot.
|
|
4
|
+
*
|
|
5
|
+
* Fluent, AdonisJS-inspired API: named routes, per-route and group middleware,
|
|
6
|
+
* prefixes, param constraints, resource routes, and URL generation.
|
|
7
|
+
*/
|
|
8
|
+
import type { Context as HonoContext, MiddlewareHandler } from "hono";
|
|
9
|
+
import type { Container, Constructor } from "../container.js";
|
|
10
|
+
/** The request context handed to every route handler and middleware. */
|
|
11
|
+
export type Ctx = HonoContext;
|
|
12
|
+
/** A route-parameter constraint: a regex, a source string, or `{ match }`. */
|
|
13
|
+
export type Matcher = RegExp | string | {
|
|
14
|
+
match: RegExp;
|
|
15
|
+
};
|
|
16
|
+
/** Built-in parameter matchers, à la `router.matchers.number()`. */
|
|
17
|
+
export declare const matchers: {
|
|
18
|
+
number: () => RegExp;
|
|
19
|
+
uuid: () => RegExp;
|
|
20
|
+
slug: () => RegExp;
|
|
21
|
+
alpha: () => RegExp;
|
|
22
|
+
};
|
|
23
|
+
export type HandlerFn = (c: Ctx) => Response | string | Promise<Response | string>;
|
|
24
|
+
/** A controller class, or a lazy `() => import(...)` loader of one. */
|
|
25
|
+
export type LazyController = () => Promise<{
|
|
26
|
+
default: Constructor;
|
|
27
|
+
} | Constructor>;
|
|
28
|
+
export type ControllerRef = Constructor | LazyController;
|
|
29
|
+
/**
|
|
30
|
+
* A controller action: `[Controller, "method"]`, or `[Controller]` for a
|
|
31
|
+
* single-action controller (calls `handle`). The controller may be a lazy
|
|
32
|
+
* `() => import(...)` loader.
|
|
33
|
+
*/
|
|
34
|
+
export type ControllerAction = [ControllerRef] | [ControllerRef, string];
|
|
35
|
+
/** A function, a controller action, or a ready-made Response. */
|
|
36
|
+
export type RouteHandler = HandlerFn | ControllerAction | Response;
|
|
37
|
+
export type Method = "GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS" | "HEAD";
|
|
38
|
+
export interface RouteDefinition {
|
|
39
|
+
methods: Method[];
|
|
40
|
+
path: string;
|
|
41
|
+
handler: RouteHandler;
|
|
42
|
+
name?: string;
|
|
43
|
+
middleware: MiddlewareHandler[];
|
|
44
|
+
wheres: Record<string, string>;
|
|
45
|
+
/** Host pattern this route is bound to, e.g. ":tenant.example.com". */
|
|
46
|
+
domain?: string;
|
|
47
|
+
}
|
|
48
|
+
/** A single registered route — chain to name it, guard it, or constrain params. */
|
|
49
|
+
export declare class Route {
|
|
50
|
+
readonly def: RouteDefinition;
|
|
51
|
+
constructor(def: RouteDefinition);
|
|
52
|
+
/** Give the route a name for URL generation. */
|
|
53
|
+
name(name: string): this;
|
|
54
|
+
/** Alias for name(). */
|
|
55
|
+
as(name: string): this;
|
|
56
|
+
/** Attach middleware that runs only for this route (after group middleware). */
|
|
57
|
+
middleware(mw: MiddlewareHandler | MiddlewareHandler[]): this;
|
|
58
|
+
/** Alias for middleware(), matching AdonisJS. */
|
|
59
|
+
use(mw: MiddlewareHandler | MiddlewareHandler[]): this;
|
|
60
|
+
/** Constrain a route parameter with a regex, source string, or matcher. */
|
|
61
|
+
where(param: string, matcher: Matcher): this;
|
|
62
|
+
/** Bind this route to a host pattern (supports `:subdomain` segments). */
|
|
63
|
+
domain(pattern: string): this;
|
|
64
|
+
}
|
|
65
|
+
/** A group of routes sharing a prefix, middleware, and/or name prefix. */
|
|
66
|
+
export declare class RouteGroup {
|
|
67
|
+
private routes;
|
|
68
|
+
constructor(routes: RouteDefinition[]);
|
|
69
|
+
prefix(prefix: string): this;
|
|
70
|
+
middleware(mw: MiddlewareHandler | MiddlewareHandler[]): this;
|
|
71
|
+
/** Alias for middleware(), matching AdonisJS. */
|
|
72
|
+
use(mw: MiddlewareHandler | MiddlewareHandler[]): this;
|
|
73
|
+
/** Constrain a parameter across every route in the group. */
|
|
74
|
+
where(param: string, matcher: Matcher): this;
|
|
75
|
+
as(namePrefix: string): this;
|
|
76
|
+
/** Bind every route in the group to a host pattern. */
|
|
77
|
+
domain(pattern: string): this;
|
|
78
|
+
}
|
|
79
|
+
/** RESTful resource routes; chain to trim, rename, or guard actions. */
|
|
80
|
+
export declare class RouteResource {
|
|
81
|
+
private byAction;
|
|
82
|
+
private resourceName;
|
|
83
|
+
private child;
|
|
84
|
+
constructor(byAction: Map<string, RouteDefinition>, resourceName: string, child: string);
|
|
85
|
+
only(actions: string[]): this;
|
|
86
|
+
except(actions: string[]): this;
|
|
87
|
+
/** Drop the HTML-form actions (create, edit). */
|
|
88
|
+
apiOnly(): this;
|
|
89
|
+
/** Rename the route-name prefix, e.g. `.as("articles")` → `articles.index`. */
|
|
90
|
+
as(name: string): this;
|
|
91
|
+
/** Rename a route parameter, e.g. `.params({ posts: "post" })`. */
|
|
92
|
+
params(map: Record<string, string>): this;
|
|
93
|
+
/** Attach middleware to specific actions (or "*" for all). */
|
|
94
|
+
use(actions: string[] | "*", mw: MiddlewareHandler | MiddlewareHandler[]): this;
|
|
95
|
+
}
|
|
96
|
+
/** Fluent matcher for `on(path)` convenience routes. */
|
|
97
|
+
declare class RouteMatcher {
|
|
98
|
+
private router;
|
|
99
|
+
private path;
|
|
100
|
+
constructor(router: Router, path: string);
|
|
101
|
+
/** Redirect to a path or URL. */
|
|
102
|
+
redirect(to: string, status?: number): Route;
|
|
103
|
+
/** Alias for redirect(), matching AdonisJS. */
|
|
104
|
+
redirectToPath(to: string, status?: number): Route;
|
|
105
|
+
/** Redirect to a named route, optionally with params and a query string. */
|
|
106
|
+
redirectToRoute(name: string, params?: Record<string, string | number>, options?: {
|
|
107
|
+
qs?: Record<string, string | number>;
|
|
108
|
+
status?: number;
|
|
109
|
+
}): Route;
|
|
110
|
+
/** Render a view component directly. */
|
|
111
|
+
render(component: (props?: any) => unknown, props?: any): Route;
|
|
112
|
+
/** Render an Inertia page component directly. */
|
|
113
|
+
renderInertia(component: string, props?: Record<string, unknown>): Route;
|
|
114
|
+
}
|
|
115
|
+
export declare class Router {
|
|
116
|
+
private container;
|
|
117
|
+
private routes;
|
|
118
|
+
private group_prefix;
|
|
119
|
+
private group_mw;
|
|
120
|
+
private globalWheres;
|
|
121
|
+
/** Built-in parameter matchers: `router.matchers.number()`. */
|
|
122
|
+
readonly matchers: {
|
|
123
|
+
number: () => RegExp;
|
|
124
|
+
uuid: () => RegExp;
|
|
125
|
+
slug: () => RegExp;
|
|
126
|
+
alpha: () => RegExp;
|
|
127
|
+
};
|
|
128
|
+
constructor(container: Container);
|
|
129
|
+
get(path: string, handler: RouteHandler): Route;
|
|
130
|
+
post(path: string, handler: RouteHandler): Route;
|
|
131
|
+
put(path: string, handler: RouteHandler): Route;
|
|
132
|
+
patch(path: string, handler: RouteHandler): Route;
|
|
133
|
+
delete(path: string, handler: RouteHandler): Route;
|
|
134
|
+
/** Match any HTTP verb. */
|
|
135
|
+
any(path: string, handler: RouteHandler): Route;
|
|
136
|
+
/** Match a specific set of verbs. */
|
|
137
|
+
route(methods: Method[], path: string, handler: RouteHandler): Route;
|
|
138
|
+
/** A fluent matcher: `router.on("/").redirect("/home")`. */
|
|
139
|
+
on(path: string): RouteMatcher;
|
|
140
|
+
/**
|
|
141
|
+
* Group routes under a shared prefix / middleware / name prefix:
|
|
142
|
+
* router.group(() => { … }).prefix("/api").middleware([auth]).as("api");
|
|
143
|
+
*/
|
|
144
|
+
group(callback: () => void): RouteGroup;
|
|
145
|
+
/**
|
|
146
|
+
* RESTful resource routes for a controller:
|
|
147
|
+
* index, create, store, show, edit, update, destroy.
|
|
148
|
+
*/
|
|
149
|
+
resource(name: string, controller: ControllerRef): RouteResource;
|
|
150
|
+
private add;
|
|
151
|
+
/** Register a global parameter constraint, applied to every matching route. */
|
|
152
|
+
where(param: string, matcher: Matcher): this;
|
|
153
|
+
/** All registered routes (excluding those trimmed to zero methods). */
|
|
154
|
+
all(): RouteDefinition[];
|
|
155
|
+
/** Generate a URL for a named route, substituting `:params`. */
|
|
156
|
+
url(name: string, params?: Record<string, string | number>): string;
|
|
157
|
+
/** Turn a route handler into an executable function, resolving controllers. */
|
|
158
|
+
resolve(handler: RouteHandler): HandlerFn;
|
|
159
|
+
}
|
|
160
|
+
export {};
|