htmx-router 1.0.1 → 1.0.3
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/defer.d.ts +1 -1
- package/defer.js +2 -7
- package/endpoint.d.ts +1 -1
- package/endpoint.js +1 -6
- package/internal/router.d.ts +3 -1
- package/navigate.d.ts +1 -1
- package/navigate.js +18 -9
- package/package.json +1 -1
- package/response.d.ts +1 -0
- package/response.js +9 -0
- package/router.js +19 -4
- package/status.d.ts +69 -0
- package/status.js +91 -0
package/defer.d.ts
CHANGED
|
@@ -10,5 +10,5 @@ export declare const path = "_/defer/$";
|
|
|
10
10
|
export declare const parameters: {
|
|
11
11
|
$: StringConstructor;
|
|
12
12
|
};
|
|
13
|
-
export declare function loader(ctx: RouteContext<typeof parameters>): Promise<
|
|
13
|
+
export declare function loader(ctx: RouteContext<typeof parameters>): Promise<JSX.Element | null>;
|
|
14
14
|
export declare const action: typeof loader;
|
package/defer.js
CHANGED
|
@@ -68,13 +68,8 @@ export async function loader(ctx) {
|
|
|
68
68
|
console.warn(`Warn: Function ${endpoint.name} was not registered for defer use`);
|
|
69
69
|
return null;
|
|
70
70
|
}
|
|
71
|
-
const forward = new RouteContext(ctx, prelude, entry.shape);
|
|
72
|
-
const res = await endpoint(forward);
|
|
73
|
-
if (res instanceof Response)
|
|
74
|
-
return res;
|
|
75
|
-
if (res === null)
|
|
76
|
-
return null;
|
|
77
71
|
ctx.headers.set("X-Partial", "true");
|
|
78
|
-
|
|
72
|
+
const forward = new RouteContext(ctx, prelude, entry.shape);
|
|
73
|
+
return await endpoint(forward);
|
|
79
74
|
}
|
|
80
75
|
export const action = loader;
|
package/endpoint.d.ts
CHANGED
|
@@ -16,5 +16,5 @@ export declare const path = "_/endpoint/$";
|
|
|
16
16
|
export declare const parameters: {
|
|
17
17
|
$: StringConstructor;
|
|
18
18
|
};
|
|
19
|
-
export declare function loader(ctx: RouteContext<typeof parameters>): Promise<
|
|
19
|
+
export declare function loader(ctx: RouteContext<typeof parameters>): Promise<JSX.Element | null>;
|
|
20
20
|
export declare const action: typeof loader;
|
package/endpoint.js
CHANGED
|
@@ -30,11 +30,6 @@ export async function loader(ctx) {
|
|
|
30
30
|
const endpoint = registry.get(ctx.params["$"]);
|
|
31
31
|
if (!endpoint)
|
|
32
32
|
return null;
|
|
33
|
-
|
|
34
|
-
if (res === null)
|
|
35
|
-
return null;
|
|
36
|
-
if (res instanceof Response)
|
|
37
|
-
return res;
|
|
38
|
-
return ctx.render(res, ctx.headers);
|
|
33
|
+
return await endpoint.render(ctx);
|
|
39
34
|
}
|
|
40
35
|
export const action = loader;
|
package/internal/router.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ParameterShaper } from '../util/parameters.js';
|
|
2
2
|
import { RouteContext } from "../router.js";
|
|
3
3
|
import { Cookies } from '../cookies.js';
|
|
4
|
+
type Rendered = Response | BodyInit;
|
|
4
5
|
export declare class GenericContext {
|
|
5
6
|
request: Request;
|
|
6
7
|
headers: Headers;
|
|
@@ -9,7 +10,8 @@ export declare class GenericContext {
|
|
|
9
10
|
[key: string]: string;
|
|
10
11
|
};
|
|
11
12
|
url: URL;
|
|
12
|
-
render: (res: JSX.Element, headers: Headers) => Promise<
|
|
13
|
+
render: (res: JSX.Element, headers: Headers) => Promise<Rendered> | Rendered;
|
|
13
14
|
constructor(request: GenericContext["request"], url: GenericContext["url"], renderer: GenericContext["render"]);
|
|
14
15
|
shape<T extends ParameterShaper>(shape: T): RouteContext<T>;
|
|
15
16
|
}
|
|
17
|
+
export {};
|
package/navigate.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare function navigate(href: string,
|
|
1
|
+
export declare function navigate(href: string, pushHistory?: boolean): Promise<void>;
|
|
2
2
|
export declare function revalidate(): Promise<void>;
|
|
3
3
|
export declare function htmxAppend(href: string, verb?: string): Promise<void>;
|
package/navigate.js
CHANGED
|
@@ -4,20 +4,30 @@ function htmx() {
|
|
|
4
4
|
throw new Error("Missing htmx");
|
|
5
5
|
return htmx;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
const driver = (typeof document === "object" ? document.createElement("a") : null);
|
|
8
|
+
export async function navigate(href, pushHistory = true) {
|
|
8
9
|
if (typeof window !== "object")
|
|
9
10
|
return;
|
|
11
|
+
if (!driver)
|
|
12
|
+
return;
|
|
10
13
|
const url = new URL(href, window.location.href);
|
|
11
14
|
if (url.host !== window.location.host) {
|
|
12
15
|
window.location.assign(href);
|
|
13
16
|
return;
|
|
14
17
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
18
|
+
driver.setAttribute("hx-boost", "true");
|
|
19
|
+
driver.setAttribute("href", url.href);
|
|
20
|
+
if (pushHistory) {
|
|
21
|
+
driver.setAttribute("hx-push-url", "true");
|
|
22
|
+
driver.removeAttribute("hx-replace-url");
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
driver.setAttribute("hx-replace-url", "true");
|
|
26
|
+
driver.removeAttribute("hx-push-url");
|
|
27
|
+
}
|
|
28
|
+
document.body.appendChild(driver);
|
|
29
|
+
htmx().process(driver);
|
|
30
|
+
driver.click();
|
|
21
31
|
}
|
|
22
32
|
export function revalidate() {
|
|
23
33
|
return navigate("", false);
|
|
@@ -25,7 +35,6 @@ export function revalidate() {
|
|
|
25
35
|
export async function htmxAppend(href, verb = "GET") {
|
|
26
36
|
await htmx().ajax(verb, href, {
|
|
27
37
|
target: 'body',
|
|
28
|
-
swap: 'beforeend'
|
|
29
|
-
history: false
|
|
38
|
+
swap: 'beforeend'
|
|
30
39
|
});
|
|
31
40
|
}
|
package/package.json
CHANGED
package/response.d.ts
CHANGED
package/response.js
CHANGED
|
@@ -7,6 +7,15 @@ export function text(text, init) {
|
|
|
7
7
|
res.headers.set("X-Caught", "true");
|
|
8
8
|
return res;
|
|
9
9
|
}
|
|
10
|
+
export function html(text, init) {
|
|
11
|
+
init ||= {};
|
|
12
|
+
init.statusText ||= "ok";
|
|
13
|
+
init.status ||= 200;
|
|
14
|
+
const res = new Response(text, init);
|
|
15
|
+
res.headers.set("Content-Type", "text/html; charset=UTF-8");
|
|
16
|
+
res.headers.set("X-Caught", "true");
|
|
17
|
+
return res;
|
|
18
|
+
}
|
|
10
19
|
export function json(data, init) {
|
|
11
20
|
init ||= {};
|
|
12
21
|
init.statusText ||= "ok";
|
package/router.js
CHANGED
|
@@ -114,6 +114,8 @@ export class RouteTree {
|
|
|
114
114
|
|| await this.resolveWild(fragments, ctx)
|
|
115
115
|
|| await this.resolveSlug(fragments, ctx);
|
|
116
116
|
if (res instanceof Response) {
|
|
117
|
+
if (res.ok)
|
|
118
|
+
return res;
|
|
117
119
|
if (100 <= res.status && res.status <= 399)
|
|
118
120
|
return res;
|
|
119
121
|
if (res.headers.has("X-Caught"))
|
|
@@ -127,7 +129,10 @@ export class RouteTree {
|
|
|
127
129
|
return null;
|
|
128
130
|
if (!this.index)
|
|
129
131
|
return null;
|
|
130
|
-
|
|
132
|
+
const res = await this.index.resolve(ctx);
|
|
133
|
+
if (res instanceof Response)
|
|
134
|
+
return res;
|
|
135
|
+
return new Response(res, { headers: ctx.headers });
|
|
131
136
|
}
|
|
132
137
|
async resolveNext(fragments, ctx) {
|
|
133
138
|
if (fragments.length < 1)
|
|
@@ -152,14 +157,24 @@ export class RouteTree {
|
|
|
152
157
|
const res = this.slug.resolve
|
|
153
158
|
? await this.slug.resolve(ctx)
|
|
154
159
|
: null;
|
|
155
|
-
|
|
160
|
+
if (res instanceof Response)
|
|
161
|
+
return res;
|
|
162
|
+
return new Response(res, { headers: ctx.headers });
|
|
156
163
|
}
|
|
157
164
|
async unwrap(ctx, res) {
|
|
158
165
|
if (!this.slug)
|
|
159
166
|
throw res;
|
|
160
167
|
const caught = await this.slug.error(ctx, res);
|
|
161
|
-
caught
|
|
162
|
-
|
|
168
|
+
if (caught instanceof Response) {
|
|
169
|
+
caught.headers.set("X-Caught", "true");
|
|
170
|
+
return caught;
|
|
171
|
+
}
|
|
172
|
+
ctx.headers.set("X-Caught", "true");
|
|
173
|
+
return new Response(caught, res instanceof Response ? res : {
|
|
174
|
+
status: 500,
|
|
175
|
+
statusText: "Internal Server Error",
|
|
176
|
+
headers: ctx.headers
|
|
177
|
+
});
|
|
163
178
|
}
|
|
164
179
|
}
|
|
165
180
|
class RouteLeaf {
|
package/status.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
declare const definitions: {
|
|
2
|
+
100: "Continue";
|
|
3
|
+
101: "Switching Protocols";
|
|
4
|
+
102: "Processing";
|
|
5
|
+
103: "Early Hints";
|
|
6
|
+
200: "OK";
|
|
7
|
+
201: "Created";
|
|
8
|
+
202: "Accepted";
|
|
9
|
+
203: "Non-Authoritative Information";
|
|
10
|
+
204: "No Content";
|
|
11
|
+
205: "Reset Content";
|
|
12
|
+
206: "Partial Content";
|
|
13
|
+
207: "Multi-Status";
|
|
14
|
+
208: "Already Reported";
|
|
15
|
+
226: "IM Used";
|
|
16
|
+
300: "Multiple Choices";
|
|
17
|
+
301: "Moved Permanently";
|
|
18
|
+
302: "Found";
|
|
19
|
+
303: "See Other";
|
|
20
|
+
304: "Not Modified";
|
|
21
|
+
305: "Use Proxy";
|
|
22
|
+
306: "Switch Proxy";
|
|
23
|
+
308: "Permanent Redirect";
|
|
24
|
+
400: "Bad Request";
|
|
25
|
+
401: "Unauthorized";
|
|
26
|
+
402: "Payment Required";
|
|
27
|
+
403: "Forbidden";
|
|
28
|
+
405: "Method Not Allowed";
|
|
29
|
+
406: "Not Acceptable";
|
|
30
|
+
407: "Proxy Authentication Required";
|
|
31
|
+
408: "Request Timeout";
|
|
32
|
+
409: "Conflict";
|
|
33
|
+
410: "Gone";
|
|
34
|
+
411: "Length Required";
|
|
35
|
+
412: "Precondition Failed";
|
|
36
|
+
413: "Payload Too Large";
|
|
37
|
+
414: "URI Too Long";
|
|
38
|
+
415: "Unsupported Media Type";
|
|
39
|
+
416: "Range Not Satisfiable";
|
|
40
|
+
417: "Expectation Failed";
|
|
41
|
+
418: "I'm a teapot";
|
|
42
|
+
421: "Misdirected Request";
|
|
43
|
+
422: "Unprocessable Content";
|
|
44
|
+
423: "Locked";
|
|
45
|
+
424: "Failed Dependency";
|
|
46
|
+
425: "Too Early";
|
|
47
|
+
426: "Upgrade Required";
|
|
48
|
+
428: "Precondition Required";
|
|
49
|
+
429: "Too Many Requests";
|
|
50
|
+
431: "Request Header Fields Too Large";
|
|
51
|
+
451: "Unavailable For Legal Reasons";
|
|
52
|
+
500: "Internal Server Error";
|
|
53
|
+
501: "Not Implemented";
|
|
54
|
+
502: "Bad Gateway";
|
|
55
|
+
503: "Service Unavailable";
|
|
56
|
+
504: "Gateway Timeout";
|
|
57
|
+
505: "HTTP Version Not Supported";
|
|
58
|
+
506: "Variant Also Negotiates";
|
|
59
|
+
507: "Insufficient Storage";
|
|
60
|
+
508: "Loop Detected";
|
|
61
|
+
510: "Not Extended";
|
|
62
|
+
511: "Network Authentication Required";
|
|
63
|
+
};
|
|
64
|
+
export type StatusText = typeof definitions[keyof typeof definitions];
|
|
65
|
+
export declare function MakeStatus(lookup: number | StatusText | string): {
|
|
66
|
+
status: number;
|
|
67
|
+
statusText: string;
|
|
68
|
+
};
|
|
69
|
+
export {};
|
package/status.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const definitions = {
|
|
2
|
+
100: "Continue",
|
|
3
|
+
101: "Switching Protocols",
|
|
4
|
+
102: "Processing",
|
|
5
|
+
103: "Early Hints",
|
|
6
|
+
200: "OK",
|
|
7
|
+
201: "Created",
|
|
8
|
+
202: "Accepted",
|
|
9
|
+
203: "Non-Authoritative Information",
|
|
10
|
+
204: "No Content",
|
|
11
|
+
205: "Reset Content",
|
|
12
|
+
206: "Partial Content",
|
|
13
|
+
207: "Multi-Status",
|
|
14
|
+
208: "Already Reported",
|
|
15
|
+
226: "IM Used",
|
|
16
|
+
300: "Multiple Choices",
|
|
17
|
+
301: "Moved Permanently",
|
|
18
|
+
302: "Found",
|
|
19
|
+
303: "See Other",
|
|
20
|
+
304: "Not Modified",
|
|
21
|
+
305: "Use Proxy",
|
|
22
|
+
306: "Switch Proxy",
|
|
23
|
+
308: "Permanent Redirect",
|
|
24
|
+
400: "Bad Request",
|
|
25
|
+
401: "Unauthorized",
|
|
26
|
+
402: "Payment Required",
|
|
27
|
+
403: "Forbidden",
|
|
28
|
+
405: "Method Not Allowed",
|
|
29
|
+
406: "Not Acceptable",
|
|
30
|
+
407: "Proxy Authentication Required",
|
|
31
|
+
408: "Request Timeout",
|
|
32
|
+
409: "Conflict",
|
|
33
|
+
410: "Gone",
|
|
34
|
+
411: "Length Required",
|
|
35
|
+
412: "Precondition Failed",
|
|
36
|
+
413: "Payload Too Large",
|
|
37
|
+
414: "URI Too Long",
|
|
38
|
+
415: "Unsupported Media Type",
|
|
39
|
+
416: "Range Not Satisfiable",
|
|
40
|
+
417: "Expectation Failed",
|
|
41
|
+
418: "I'm a teapot",
|
|
42
|
+
421: "Misdirected Request",
|
|
43
|
+
422: "Unprocessable Content",
|
|
44
|
+
423: "Locked",
|
|
45
|
+
424: "Failed Dependency",
|
|
46
|
+
425: "Too Early",
|
|
47
|
+
426: "Upgrade Required",
|
|
48
|
+
428: "Precondition Required",
|
|
49
|
+
429: "Too Many Requests",
|
|
50
|
+
431: "Request Header Fields Too Large",
|
|
51
|
+
451: "Unavailable For Legal Reasons",
|
|
52
|
+
500: "Internal Server Error",
|
|
53
|
+
501: "Not Implemented",
|
|
54
|
+
502: "Bad Gateway",
|
|
55
|
+
503: "Service Unavailable",
|
|
56
|
+
504: "Gateway Timeout",
|
|
57
|
+
505: "HTTP Version Not Supported",
|
|
58
|
+
506: "Variant Also Negotiates",
|
|
59
|
+
507: "Insufficient Storage",
|
|
60
|
+
508: "Loop Detected",
|
|
61
|
+
510: "Not Extended",
|
|
62
|
+
511: "Network Authentication Required",
|
|
63
|
+
};
|
|
64
|
+
const lookup = new Array(500);
|
|
65
|
+
for (let i = 100; i < 600; i++) {
|
|
66
|
+
lookup[i - 100] = definitions[i]
|
|
67
|
+
|| definitions[i % 100];
|
|
68
|
+
}
|
|
69
|
+
const index = new Map();
|
|
70
|
+
for (const key in definitions) {
|
|
71
|
+
const code = Number(key);
|
|
72
|
+
index.set(definitions[code].toLowerCase(), code);
|
|
73
|
+
}
|
|
74
|
+
export function MakeStatus(lookup) {
|
|
75
|
+
if (typeof lookup === "number")
|
|
76
|
+
return lookupCode(lookup);
|
|
77
|
+
return lookupStatus(lookup);
|
|
78
|
+
}
|
|
79
|
+
function lookupCode(status) {
|
|
80
|
+
if (status < 100)
|
|
81
|
+
throw new TypeError(`Status ${status}<100`);
|
|
82
|
+
if (status > 599)
|
|
83
|
+
throw new TypeError(`Status ${status}>599`);
|
|
84
|
+
return { status, statusText: lookup[status] };
|
|
85
|
+
}
|
|
86
|
+
function lookupStatus(statusText) {
|
|
87
|
+
const status = index.get(statusText.toLowerCase());
|
|
88
|
+
if (!status)
|
|
89
|
+
throw new TypeError(`statusText ${statusText} is not of type StatusText`);
|
|
90
|
+
return { status, statusText };
|
|
91
|
+
}
|