htmx-router 1.0.0-alpha.6 → 1.0.0-pre1
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/package.json +6 -8
- package/readme.md +20 -3
- package/cookies.d.ts +0 -25
- package/cookies.js +0 -60
- package/css.d.ts +0 -13
- package/css.js +0 -55
- package/dynamic.d.ts +0 -5
- package/dynamic.js +0 -42
- package/endpoint.d.ts +0 -13
- package/endpoint.js +0 -34
- package/event-source.d.ts +0 -26
- package/event-source.js +0 -123
- package/index.d.ts +0 -19
- package/index.js +0 -2
- package/internal/cli/config.d.ts +0 -13
- package/internal/cli/config.js +0 -11
- package/internal/cli/index.d.ts +0 -2
- package/internal/cli/index.js +0 -15
- package/internal/client.d.ts +0 -1
- package/internal/client.js +0 -14
- package/internal/compile/manifest.d.ts +0 -1
- package/internal/compile/manifest.js +0 -178
- package/internal/compile/router.d.ts +0 -1
- package/internal/compile/router.js +0 -51
- package/internal/component/dynamic.d.ts +0 -4
- package/internal/component/dynamic.js +0 -18
- package/internal/component/head.d.ts +0 -5
- package/internal/component/head.js +0 -22
- package/internal/component/scripts.d.ts +0 -4
- package/internal/component/scripts.js +0 -23
- package/internal/hash.d.ts +0 -4
- package/internal/hash.js +0 -10
- package/internal/mount.d.ts +0 -2
- package/internal/mount.js +0 -81
- package/internal/request/http.d.ts +0 -10
- package/internal/request/http.js +0 -61
- package/internal/request/index.d.ts +0 -16
- package/internal/request/index.js +0 -8
- package/internal/request/native.d.ts +0 -9
- package/internal/request/native.js +0 -48
- package/internal/util.d.ts +0 -4
- package/internal/util.js +0 -49
- package/request/http.d.ts +0 -10
- package/request/http.js +0 -59
- package/request/index.d.ts +0 -13
- package/request/index.js +0 -3
- package/request/native.d.ts +0 -9
- package/request/native.js +0 -46
- package/response.d.ts +0 -13
- package/response.js +0 -46
- package/router.d.ts +0 -51
- package/router.js +0 -231
- package/shell.d.ts +0 -120
- package/shell.js +0 -253
- package/util/parameters.d.ts +0 -7
- package/util/parameters.js +0 -14
- package/util/path-builder.d.ts +0 -1
- package/util/path-builder.js +0 -45
- package/util/route.d.ts +0 -2
- package/util/route.js +0 -58
- package/vite/bundle-splitter.d.ts +0 -4
- package/vite/bundle-splitter.js +0 -26
- package/vite/client-island.d.ts +0 -4
- package/vite/client-island.js +0 -14
- package/vite/code-splitting.d.ts +0 -4
- package/vite/code-splitting.js +0 -14
- package/vite/index.d.ts +0 -3
- package/vite/index.js +0 -3
- package/vite/router.d.ts +0 -2
- package/vite/router.js +0 -29
package/request/http.js
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Resolve } from "~/request/native.js";
|
|
2
|
-
export function createRequestHandler(config) {
|
|
3
|
-
return async (req, res) => {
|
|
4
|
-
try {
|
|
5
|
-
const mod = typeof config.build === "function" ? await config.build() : await config.build;
|
|
6
|
-
const request = NativeRequest(req);
|
|
7
|
-
let { response, headers } = await Resolve(request, mod.tree, config);
|
|
8
|
-
res.writeHead(response.status, headers);
|
|
9
|
-
if (response.body instanceof ReadableStream) {
|
|
10
|
-
const reader = response.body.getReader();
|
|
11
|
-
while (true) {
|
|
12
|
-
const { done, value } = await reader.read();
|
|
13
|
-
if (done)
|
|
14
|
-
break;
|
|
15
|
-
res.write(value); // `value` is a Uint8Array.
|
|
16
|
-
}
|
|
17
|
-
res.end();
|
|
18
|
-
}
|
|
19
|
-
else {
|
|
20
|
-
const rendered = await response.text();
|
|
21
|
-
res.end(rendered);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
catch (e) {
|
|
25
|
-
res.statusCode = 500;
|
|
26
|
-
if (e instanceof Error) {
|
|
27
|
-
console.error(e.stack);
|
|
28
|
-
config.viteDevServer?.ssrFixStacktrace(e);
|
|
29
|
-
res.end(e.stack);
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
console.error(e);
|
|
33
|
-
res.end(String(e));
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
function NativeRequest(req) {
|
|
39
|
-
const ctrl = new AbortController();
|
|
40
|
-
const headers = new Headers(req.headers);
|
|
41
|
-
const url = new URL(`http://${headers.get('host')}${req.originalUrl || req.url}`);
|
|
42
|
-
req.once('aborted', () => ctrl.abort());
|
|
43
|
-
const bodied = req.method !== "GET" && req.method !== "HEAD";
|
|
44
|
-
const request = new Request(url, {
|
|
45
|
-
headers,
|
|
46
|
-
method: req.method,
|
|
47
|
-
body: bodied ? req : undefined,
|
|
48
|
-
signal: ctrl.signal,
|
|
49
|
-
referrer: headers.get("referrer") || undefined,
|
|
50
|
-
// @ts-ignore
|
|
51
|
-
duplex: bodied ? 'half' : undefined
|
|
52
|
-
});
|
|
53
|
-
if (!request.headers.has("X-Real-IP")) {
|
|
54
|
-
const info = req.socket.address();
|
|
55
|
-
if ("address" in info)
|
|
56
|
-
request.headers.set("X-Real-IP", info.address);
|
|
57
|
-
}
|
|
58
|
-
return request;
|
|
59
|
-
}
|
package/request/index.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { ViteDevServer } from "vite";
|
|
2
|
-
import type { GenericContext, RouteTree } from '~/router.js';
|
|
3
|
-
import * as native from "~/request/native.js";
|
|
4
|
-
import * as http from "~/request/http.js";
|
|
5
|
-
export type Config = {
|
|
6
|
-
build: Promise<any> | (() => Promise<Record<string, any>>);
|
|
7
|
-
viteDevServer: ViteDevServer | null;
|
|
8
|
-
render: GenericContext["render"];
|
|
9
|
-
};
|
|
10
|
-
export type RouterModule = {
|
|
11
|
-
tree: RouteTree;
|
|
12
|
-
};
|
|
13
|
-
export { http, native };
|
package/request/index.js
DELETED
package/request/native.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type RouteTree } from '~/router.js';
|
|
2
|
-
import type { Config } from '~/request/index.js';
|
|
3
|
-
export declare function createRequestHandler(config: Config): (req: Request) => Promise<Response>;
|
|
4
|
-
export declare function Resolve(request: Request, tree: RouteTree, config: Config): Promise<{
|
|
5
|
-
response: Response;
|
|
6
|
-
headers: {
|
|
7
|
-
[key: string]: string | string[];
|
|
8
|
-
};
|
|
9
|
-
}>;
|
package/request/native.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { GenericContext } from '~/router.js';
|
|
2
|
-
export function createRequestHandler(config) {
|
|
3
|
-
return async (req) => {
|
|
4
|
-
try {
|
|
5
|
-
const mod = typeof config.build === "function" ? await config.build() : await config.build;
|
|
6
|
-
let { response } = await Resolve(req, mod.tree, config);
|
|
7
|
-
return response;
|
|
8
|
-
}
|
|
9
|
-
catch (e) {
|
|
10
|
-
if (e instanceof Error) {
|
|
11
|
-
console.error(e.stack);
|
|
12
|
-
config.viteDevServer?.ssrFixStacktrace(e);
|
|
13
|
-
return new Response(e.message + "\n" + e.stack, { status: 500, statusText: "Internal Server Error" });
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
console.error(e);
|
|
17
|
-
return new Response(String(e), { status: 500, statusText: "Internal Server Error" });
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
export async function Resolve(request, tree, config) {
|
|
23
|
-
const url = new URL(request.url);
|
|
24
|
-
const ctx = new GenericContext(request, url, config.render);
|
|
25
|
-
const x = ctx.url.pathname.endsWith("/") ? ctx.url.pathname.slice(0, -1) : ctx.url.pathname;
|
|
26
|
-
const fragments = x.split("/").slice(1);
|
|
27
|
-
let response = await tree.resolve(fragments, ctx);
|
|
28
|
-
if (response === null)
|
|
29
|
-
response = new Response("No Route Found", { status: 404, statusText: "Not Found", headers: ctx.headers });
|
|
30
|
-
// Override with context headers
|
|
31
|
-
if (response.headers !== ctx.headers) {
|
|
32
|
-
for (const [key, value] of ctx.headers) {
|
|
33
|
-
if (response.headers.has(key))
|
|
34
|
-
continue;
|
|
35
|
-
response.headers.set(key, value);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
// Merge cookie changes
|
|
39
|
-
const headers = Object.fromEntries(response.headers);
|
|
40
|
-
const cookies = ctx.cookie.export();
|
|
41
|
-
if (cookies.length > 0) {
|
|
42
|
-
headers['set-cookie'] = cookies;
|
|
43
|
-
response.headers.set("Set-Cookie", cookies[0]); // Response object doesn't support multi-header..[]
|
|
44
|
-
}
|
|
45
|
-
return { response, headers };
|
|
46
|
-
}
|
package/response.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export declare function text(text: string, init?: ResponseInit): Response;
|
|
2
|
-
export type TypedResponse<T> = Omit<Response, "json"> & {
|
|
3
|
-
json(): Promise<T>;
|
|
4
|
-
};
|
|
5
|
-
export type TypedJson<U extends TypedResponse<any>> = U extends TypedResponse<infer T> ? T : never;
|
|
6
|
-
export declare function json<T>(data: T, init?: ResponseInit): TypedResponse<T>;
|
|
7
|
-
export declare function redirect(url: string, init?: ResponseInit & {
|
|
8
|
-
clientOnly?: boolean;
|
|
9
|
-
}): Response;
|
|
10
|
-
export declare function revalidate(init?: ResponseInit): Response;
|
|
11
|
-
export declare function refresh(init?: ResponseInit & {
|
|
12
|
-
clientOnly?: boolean;
|
|
13
|
-
}): Response;
|
package/response.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
export function text(text, init) {
|
|
2
|
-
init ||= {};
|
|
3
|
-
init.statusText ||= "ok";
|
|
4
|
-
init.status ||= 200;
|
|
5
|
-
const res = new Response(text, init);
|
|
6
|
-
res.headers.set("Content-Type", "text/plain");
|
|
7
|
-
res.headers.set("X-Caught", "true");
|
|
8
|
-
return res;
|
|
9
|
-
}
|
|
10
|
-
export function json(data, init) {
|
|
11
|
-
init ||= {};
|
|
12
|
-
init.statusText ||= "ok";
|
|
13
|
-
init.status ||= 200;
|
|
14
|
-
const res = new Response(JSON.stringify(data), init);
|
|
15
|
-
res.headers.set("Content-Type", "application/json");
|
|
16
|
-
res.headers.set("X-Caught", "true");
|
|
17
|
-
return res;
|
|
18
|
-
}
|
|
19
|
-
export function redirect(url, init) {
|
|
20
|
-
init ||= {};
|
|
21
|
-
init.statusText ||= "Temporary Redirect";
|
|
22
|
-
init.status ||= 307;
|
|
23
|
-
const res = new Response("", init);
|
|
24
|
-
if (!init?.clientOnly)
|
|
25
|
-
res.headers.set("Location", url);
|
|
26
|
-
res.headers.set("HX-Location", url); // use hx-boost if applicable
|
|
27
|
-
return res;
|
|
28
|
-
}
|
|
29
|
-
export function revalidate(init) {
|
|
30
|
-
init ||= {};
|
|
31
|
-
init.statusText ||= "ok";
|
|
32
|
-
init.status ||= 200;
|
|
33
|
-
const res = new Response("", init);
|
|
34
|
-
res.headers.set("HX-Location", "");
|
|
35
|
-
return res;
|
|
36
|
-
}
|
|
37
|
-
export function refresh(init) {
|
|
38
|
-
init ||= {};
|
|
39
|
-
init.statusText ||= "ok";
|
|
40
|
-
init.status ||= 200;
|
|
41
|
-
const res = new Response("", init);
|
|
42
|
-
if (!init?.clientOnly)
|
|
43
|
-
res.headers.set("Refresh", "0"); // fallback
|
|
44
|
-
res.headers.set("HX-Refresh", "true");
|
|
45
|
-
return res;
|
|
46
|
-
}
|
package/router.d.ts
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { Parameterized, ParameterShaper } from './util/parameters.js';
|
|
2
|
-
import { RouteModule } from "./index.js";
|
|
3
|
-
import { Cookies } from './cookies.js';
|
|
4
|
-
export declare function GenerateRouteTree(modules: Record<string, unknown>): RouteTree;
|
|
5
|
-
export declare class GenericContext {
|
|
6
|
-
request: Request;
|
|
7
|
-
headers: Headers;
|
|
8
|
-
cookie: Cookies;
|
|
9
|
-
params: {
|
|
10
|
-
[key: string]: string;
|
|
11
|
-
};
|
|
12
|
-
url: URL;
|
|
13
|
-
render: (res: JSX.Element) => Response;
|
|
14
|
-
constructor(request: GenericContext["request"], url: GenericContext["url"], renderer: GenericContext["render"]);
|
|
15
|
-
shape<T extends ParameterShaper>(shape: T): RouteContext<T>;
|
|
16
|
-
}
|
|
17
|
-
export declare class RouteContext<T extends ParameterShaper = {}> {
|
|
18
|
-
request: Request;
|
|
19
|
-
headers: Headers;
|
|
20
|
-
cookie: Cookies;
|
|
21
|
-
params: Parameterized<T>;
|
|
22
|
-
url: URL;
|
|
23
|
-
render: (res: JSX.Element) => Response;
|
|
24
|
-
constructor(base: GenericContext, shape: T);
|
|
25
|
-
}
|
|
26
|
-
export declare class RouteTree {
|
|
27
|
-
root: boolean;
|
|
28
|
-
nested: Map<string, RouteTree>;
|
|
29
|
-
index: RouteLeaf | null;
|
|
30
|
-
slug: RouteLeaf | null;
|
|
31
|
-
wild: RouteTree | null;
|
|
32
|
-
wildCard: string;
|
|
33
|
-
constructor(root?: boolean);
|
|
34
|
-
ingest(path: string | string[], module: RouteModule<any>): void;
|
|
35
|
-
resolve(fragments: string[], ctx: GenericContext): Promise<Response | null>;
|
|
36
|
-
private _resolve;
|
|
37
|
-
private resolveIndex;
|
|
38
|
-
private resolveNext;
|
|
39
|
-
private resolveWild;
|
|
40
|
-
private resolveSlug;
|
|
41
|
-
private resolveNative;
|
|
42
|
-
private unwrap;
|
|
43
|
-
}
|
|
44
|
-
declare class RouteLeaf {
|
|
45
|
-
module: RouteModule<any>;
|
|
46
|
-
constructor(module: RouteModule<any>);
|
|
47
|
-
resolve(ctx: GenericContext): Promise<Response | null>;
|
|
48
|
-
error(ctx: GenericContext, e: unknown): Promise<Response>;
|
|
49
|
-
private renderWrapper;
|
|
50
|
-
}
|
|
51
|
-
export {};
|
package/router.js
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
import { ServerOnlyWarning } from "./internal/util.js";
|
|
2
|
-
ServerOnlyWarning("router");
|
|
3
|
-
import * as endpoint from './endpoint.js';
|
|
4
|
-
import * as dynamic from './dynamic.js';
|
|
5
|
-
import * as mount from './internal/mount.js';
|
|
6
|
-
import * as css from './css.js';
|
|
7
|
-
import { Parameterize } from './util/parameters.js';
|
|
8
|
-
import { Cookies } from './cookies.js';
|
|
9
|
-
export function GenerateRouteTree(modules) {
|
|
10
|
-
const tree = new RouteTree();
|
|
11
|
-
for (const path in modules) {
|
|
12
|
-
const mod = modules[path];
|
|
13
|
-
const tail = path.lastIndexOf(".");
|
|
14
|
-
const url = path.slice(9, tail);
|
|
15
|
-
tree.ingest(url, mod);
|
|
16
|
-
if (mod.route)
|
|
17
|
-
mod.route(url);
|
|
18
|
-
}
|
|
19
|
-
return tree;
|
|
20
|
-
}
|
|
21
|
-
export class GenericContext {
|
|
22
|
-
request;
|
|
23
|
-
headers; // response headers
|
|
24
|
-
cookie;
|
|
25
|
-
params;
|
|
26
|
-
url;
|
|
27
|
-
render;
|
|
28
|
-
constructor(request, url, renderer) {
|
|
29
|
-
this.cookie = new Cookies(request.headers);
|
|
30
|
-
this.headers = new Headers();
|
|
31
|
-
this.request = request;
|
|
32
|
-
this.params = {};
|
|
33
|
-
this.url = url;
|
|
34
|
-
this.render = renderer;
|
|
35
|
-
this.headers.set("x-powered-by", "htmx-router");
|
|
36
|
-
}
|
|
37
|
-
shape(shape) {
|
|
38
|
-
return new RouteContext(this, shape);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
export class RouteContext {
|
|
42
|
-
request;
|
|
43
|
-
headers; // response headers
|
|
44
|
-
cookie;
|
|
45
|
-
params;
|
|
46
|
-
url;
|
|
47
|
-
render;
|
|
48
|
-
constructor(base, shape) {
|
|
49
|
-
this.params = Parameterize(base.params, shape);
|
|
50
|
-
this.cookie = base.cookie;
|
|
51
|
-
this.headers = base.headers;
|
|
52
|
-
this.request = base.request;
|
|
53
|
-
this.render = base.render;
|
|
54
|
-
this.url = base.url;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
export class RouteTree {
|
|
58
|
-
root;
|
|
59
|
-
nested;
|
|
60
|
-
// Leaf nodes
|
|
61
|
-
index; // about._index
|
|
62
|
-
// Wild card route
|
|
63
|
-
slug; // $
|
|
64
|
-
wild; // e.g. $userID
|
|
65
|
-
wildCard;
|
|
66
|
-
constructor(root = true) {
|
|
67
|
-
this.root = root;
|
|
68
|
-
this.nested = new Map();
|
|
69
|
-
this.wildCard = "";
|
|
70
|
-
this.slug = null;
|
|
71
|
-
this.wild = null;
|
|
72
|
-
this.index = null;
|
|
73
|
-
}
|
|
74
|
-
ingest(path, module) {
|
|
75
|
-
if (!Array.isArray(path))
|
|
76
|
-
path = path.split("/");
|
|
77
|
-
if (path.length === 0 || (path.length == 1 && path[0] === "_index")) {
|
|
78
|
-
this.index = new RouteLeaf(module);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (path[0] === "$") {
|
|
82
|
-
this.slug = new RouteLeaf(module);
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
if (path[0][0] === "$") {
|
|
86
|
-
const wildCard = path[0].slice(1);
|
|
87
|
-
// Check wildcard isn't being changed
|
|
88
|
-
if (!this.wild) {
|
|
89
|
-
this.wildCard = wildCard;
|
|
90
|
-
this.wild = new RouteTree(false);
|
|
91
|
-
}
|
|
92
|
-
else if (wildCard !== this.wildCard) {
|
|
93
|
-
throw new Error(`Redefinition of wild card ${this.wildCard} to ${wildCard}`);
|
|
94
|
-
}
|
|
95
|
-
path.splice(0, 1);
|
|
96
|
-
this.wild.ingest(path, module);
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
let next = this.nested.get(path[0]);
|
|
100
|
-
if (!next) {
|
|
101
|
-
next = new RouteTree(false);
|
|
102
|
-
this.nested.set(path[0], next);
|
|
103
|
-
}
|
|
104
|
-
path.splice(0, 1);
|
|
105
|
-
next.ingest(path, module);
|
|
106
|
-
}
|
|
107
|
-
async resolve(fragments, ctx) {
|
|
108
|
-
if (!this.slug)
|
|
109
|
-
return await this._resolve(fragments, ctx);
|
|
110
|
-
try {
|
|
111
|
-
return await this._resolve(fragments, ctx);
|
|
112
|
-
}
|
|
113
|
-
catch (e) {
|
|
114
|
-
return this.unwrap(ctx, e);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
async _resolve(fragments, ctx) {
|
|
118
|
-
let res = await this.resolveNative(fragments, ctx)
|
|
119
|
-
|| await this.resolveIndex(fragments, ctx)
|
|
120
|
-
|| await this.resolveNext(fragments, ctx)
|
|
121
|
-
|| await this.resolveWild(fragments, ctx)
|
|
122
|
-
|| await this.resolveSlug(fragments, ctx);
|
|
123
|
-
if (res instanceof Response) {
|
|
124
|
-
if (100 <= res.status && res.status <= 399)
|
|
125
|
-
return res;
|
|
126
|
-
if (res.headers.has("X-Caught"))
|
|
127
|
-
return res;
|
|
128
|
-
return this.unwrap(ctx, res);
|
|
129
|
-
}
|
|
130
|
-
return res;
|
|
131
|
-
}
|
|
132
|
-
async resolveIndex(fragments, ctx) {
|
|
133
|
-
if (fragments.length > 0)
|
|
134
|
-
return null;
|
|
135
|
-
if (!this.index)
|
|
136
|
-
return null;
|
|
137
|
-
return await this.index.resolve(ctx);
|
|
138
|
-
}
|
|
139
|
-
async resolveNext(fragments, ctx) {
|
|
140
|
-
if (fragments.length < 1)
|
|
141
|
-
return null;
|
|
142
|
-
const next = this.nested.get(fragments[0]);
|
|
143
|
-
if (!next)
|
|
144
|
-
return null;
|
|
145
|
-
return await next.resolve(fragments.slice(1), ctx);
|
|
146
|
-
}
|
|
147
|
-
async resolveWild(fragments, ctx) {
|
|
148
|
-
if (!this.wild)
|
|
149
|
-
return null;
|
|
150
|
-
if (fragments.length < 1)
|
|
151
|
-
return null;
|
|
152
|
-
ctx.params[this.wildCard] = fragments[0];
|
|
153
|
-
return this.wild.resolve(fragments.slice(1), ctx);
|
|
154
|
-
}
|
|
155
|
-
async resolveSlug(fragments, ctx) {
|
|
156
|
-
if (!this.slug)
|
|
157
|
-
return null;
|
|
158
|
-
ctx.params["$"] = fragments.join("/");
|
|
159
|
-
const res = this.slug.resolve
|
|
160
|
-
? await this.slug.resolve(ctx)
|
|
161
|
-
: null;
|
|
162
|
-
return res;
|
|
163
|
-
}
|
|
164
|
-
async resolveNative(fragments, ctx) {
|
|
165
|
-
if (!this.root)
|
|
166
|
-
return null;
|
|
167
|
-
if (fragments.length < 2)
|
|
168
|
-
return null;
|
|
169
|
-
if (fragments[0] != "_")
|
|
170
|
-
return null;
|
|
171
|
-
return await ResolveNatively(fragments, ctx);
|
|
172
|
-
}
|
|
173
|
-
async unwrap(ctx, res) {
|
|
174
|
-
if (!this.slug)
|
|
175
|
-
throw res;
|
|
176
|
-
const caught = await this.slug.error(ctx, res);
|
|
177
|
-
caught.headers.set("X-Caught", "true");
|
|
178
|
-
return caught;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
class RouteLeaf {
|
|
182
|
-
module;
|
|
183
|
-
constructor(module) {
|
|
184
|
-
this.module = module;
|
|
185
|
-
}
|
|
186
|
-
async resolve(ctx) {
|
|
187
|
-
const res = await this.renderWrapper(ctx);
|
|
188
|
-
if (res === null)
|
|
189
|
-
return null;
|
|
190
|
-
if (res instanceof Response)
|
|
191
|
-
return res;
|
|
192
|
-
return ctx.render(res);
|
|
193
|
-
}
|
|
194
|
-
async error(ctx, e) {
|
|
195
|
-
if (!this.module.error)
|
|
196
|
-
throw e;
|
|
197
|
-
const res = await this.module.error(ctx, e);
|
|
198
|
-
if (res instanceof Response)
|
|
199
|
-
return res;
|
|
200
|
-
return ctx.render(res);
|
|
201
|
-
}
|
|
202
|
-
async renderWrapper(ctx) {
|
|
203
|
-
try {
|
|
204
|
-
if (!this.module.loader && !this.module.action)
|
|
205
|
-
return null;
|
|
206
|
-
const context = ctx.shape(this.module.parameters || {});
|
|
207
|
-
if (ctx.request.method === "HEAD" || ctx.request.method === "GET") {
|
|
208
|
-
if (this.module.loader)
|
|
209
|
-
return await this.module.loader(context);
|
|
210
|
-
else
|
|
211
|
-
return null;
|
|
212
|
-
}
|
|
213
|
-
if (this.module.action)
|
|
214
|
-
return await this.module.action(context);
|
|
215
|
-
throw new Response("Method not Allowed", { status: 405, statusText: "Method not Allowed", headers: ctx.headers });
|
|
216
|
-
}
|
|
217
|
-
catch (e) {
|
|
218
|
-
return await this.error(ctx, e);
|
|
219
|
-
}
|
|
220
|
-
return null;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
async function ResolveNatively(fragments, ctx) {
|
|
224
|
-
switch (fragments[1]) {
|
|
225
|
-
case "dynamic": return dynamic._resolve(fragments, ctx);
|
|
226
|
-
case "endpoint": return endpoint._resolve(fragments, ctx);
|
|
227
|
-
case "mount": return mount._resolve(fragments);
|
|
228
|
-
case "style": return css._resolve(fragments);
|
|
229
|
-
}
|
|
230
|
-
return null;
|
|
231
|
-
}
|
package/shell.d.ts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
export type ShellOptions<D = {}> = D & MetaDescriptor;
|
|
2
|
-
export declare function ApplyMetaDescriptorDefaults(options: ShellOptions, defaults: Readonly<Partial<ShellOptions>>): void;
|
|
3
|
-
export type InferShellOptions<F> = F extends (jsx: any, options: infer U) => any ? U : never;
|
|
4
|
-
export type MetaDescriptor = {
|
|
5
|
-
title?: string;
|
|
6
|
-
description?: string;
|
|
7
|
-
meta?: Record<string, string>;
|
|
8
|
-
og?: OpenGraph<string>;
|
|
9
|
-
jsonLD?: LdJsonObject[];
|
|
10
|
-
};
|
|
11
|
-
export declare function RenderMetaDescriptor<T>(options: ShellOptions<T>): string;
|
|
12
|
-
export type LdJsonObject = {
|
|
13
|
-
[Key in string]?: LdJsonValue | undefined;
|
|
14
|
-
};
|
|
15
|
-
type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[];
|
|
16
|
-
type LdJsonPrimitive = string | number | boolean | null;
|
|
17
|
-
type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
|
|
18
|
-
export type OpenGraphType = "website" | "article" | "book" | "profile" | "music.song" | "music.album" | "music.playlist" | "music.radio_station" | "video.movie" | "video.episode" | "video.tv_show" | "video.other" | string;
|
|
19
|
-
export type OpenGraph<T extends OpenGraphType = string> = {
|
|
20
|
-
type?: T;
|
|
21
|
-
title?: string;
|
|
22
|
-
description?: string;
|
|
23
|
-
determiner?: string;
|
|
24
|
-
url?: string;
|
|
25
|
-
secure_url?: string;
|
|
26
|
-
locale?: string | {
|
|
27
|
-
base: string;
|
|
28
|
-
alternative: string[];
|
|
29
|
-
};
|
|
30
|
-
image?: OpenGraphImage[];
|
|
31
|
-
video?: OpenGraphVideo[];
|
|
32
|
-
audio?: OpenGraphAudio[];
|
|
33
|
-
} & (T extends "music.song" ? OpenGraphSong : T extends "music.album" ? OpenGraphAlbum : T extends "music.playlist" ? OpenGraphPlaylist : T extends "music.radio_station" ? OpenGraphRadioStation : T extends "video.movie" ? OpenGraphMovie : T extends "video.episode" ? OpenGraphEpisode : T extends "video.tv_show" ? OpenGraphTvShow : T extends "video.other" ? OpenGraphVideoOther : T extends "article" ? OpenGraphArticle : T extends "book" ? OpenGraphBook : T extends "profile" ? OpenGraphProfile : {});
|
|
34
|
-
export type OpenGraphImage = {
|
|
35
|
-
url: string;
|
|
36
|
-
secure_url?: string;
|
|
37
|
-
type?: string;
|
|
38
|
-
width?: number;
|
|
39
|
-
height?: number;
|
|
40
|
-
alt?: string;
|
|
41
|
-
};
|
|
42
|
-
export type OpenGraphVideo = {
|
|
43
|
-
url: string;
|
|
44
|
-
type?: string;
|
|
45
|
-
secure_url?: string;
|
|
46
|
-
width?: number;
|
|
47
|
-
height?: number;
|
|
48
|
-
alt?: string;
|
|
49
|
-
};
|
|
50
|
-
export type OpenGraphAudio = {
|
|
51
|
-
url: string;
|
|
52
|
-
type?: string;
|
|
53
|
-
secure_url?: string;
|
|
54
|
-
};
|
|
55
|
-
type OpenGraphSong = {
|
|
56
|
-
duration?: number;
|
|
57
|
-
album?: Array<string | {
|
|
58
|
-
url: string;
|
|
59
|
-
disc?: number;
|
|
60
|
-
track?: number;
|
|
61
|
-
}>;
|
|
62
|
-
musician?: string[];
|
|
63
|
-
};
|
|
64
|
-
type OpenGraphAlbum = {
|
|
65
|
-
songs?: Array<string | {
|
|
66
|
-
url: string;
|
|
67
|
-
disc?: number;
|
|
68
|
-
track?: number;
|
|
69
|
-
}>;
|
|
70
|
-
musician?: string[];
|
|
71
|
-
release_date?: Date;
|
|
72
|
-
};
|
|
73
|
-
type OpenGraphPlaylist = {
|
|
74
|
-
songs?: Array<string | {
|
|
75
|
-
url: string;
|
|
76
|
-
disc?: number;
|
|
77
|
-
track?: number;
|
|
78
|
-
}>;
|
|
79
|
-
creator?: string[];
|
|
80
|
-
};
|
|
81
|
-
type OpenGraphRadioStation = {
|
|
82
|
-
creator?: string[];
|
|
83
|
-
};
|
|
84
|
-
type OpenGraphMovie = {
|
|
85
|
-
actors?: Array<string | {
|
|
86
|
-
url: string;
|
|
87
|
-
role: string;
|
|
88
|
-
}>;
|
|
89
|
-
directors?: string[];
|
|
90
|
-
writers?: string[];
|
|
91
|
-
duration?: number;
|
|
92
|
-
release_date?: Date;
|
|
93
|
-
tag: string[];
|
|
94
|
-
};
|
|
95
|
-
type OpenGraphEpisode = OpenGraphMovie & {
|
|
96
|
-
series?: string;
|
|
97
|
-
};
|
|
98
|
-
type OpenGraphTvShow = OpenGraphMovie;
|
|
99
|
-
type OpenGraphVideoOther = OpenGraphMovie;
|
|
100
|
-
type OpenGraphArticle = {
|
|
101
|
-
published_time?: Date;
|
|
102
|
-
modified_time?: Date;
|
|
103
|
-
expiration_time?: Date;
|
|
104
|
-
authors?: string[];
|
|
105
|
-
section?: string;
|
|
106
|
-
tag?: string;
|
|
107
|
-
};
|
|
108
|
-
type OpenGraphBook = {
|
|
109
|
-
authors?: string[];
|
|
110
|
-
isbn?: string;
|
|
111
|
-
release_date?: Date;
|
|
112
|
-
tag?: string;
|
|
113
|
-
};
|
|
114
|
-
type OpenGraphProfile = {
|
|
115
|
-
first_name?: string;
|
|
116
|
-
last_name?: string;
|
|
117
|
-
username?: string;
|
|
118
|
-
gender?: "male" | "female";
|
|
119
|
-
};
|
|
120
|
-
export {};
|