htmx-router 0.1.3 → 1.0.0-alpha.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/bin/cli/config.d.ts +10 -0
- package/bin/cli/config.js +4 -0
- package/bin/cli/index.js +54 -10
- package/bin/client/index.d.ts +4 -0
- package/bin/client/index.js +100 -0
- package/bin/client/mount.d.ts +2 -0
- package/bin/client/mount.js +75 -0
- package/bin/client/watch.d.ts +1 -0
- package/bin/client/watch.js +19 -0
- package/bin/helper.d.ts +1 -2
- package/bin/helper.js +25 -14
- package/bin/index.d.ts +8 -6
- package/bin/index.js +7 -16
- package/bin/request/http.d.ts +10 -0
- package/bin/request/http.js +46 -0
- package/bin/request/index.d.ts +16 -0
- package/bin/request/index.js +6 -0
- package/bin/request/native.d.ts +9 -0
- package/bin/request/native.js +56 -0
- package/bin/router.d.ts +41 -16
- package/bin/router.js +176 -236
- package/bin/types.d.ts +10 -0
- package/bin/types.js +1 -0
- package/bin/util/cookies.d.ts +22 -0
- package/bin/util/cookies.js +57 -0
- package/bin/util/css.d.ts +9 -0
- package/bin/util/css.js +47 -0
- package/bin/util/dynamic.d.ts +5 -0
- package/bin/util/dynamic.js +26 -0
- package/bin/util/endpoint.d.ts +9 -0
- package/bin/util/endpoint.js +28 -0
- package/bin/util/event-source.d.ts +16 -0
- package/bin/util/event-source.js +85 -0
- package/bin/util/hash.d.ts +1 -0
- package/bin/util/hash.js +7 -0
- package/bin/util/index.d.ts +1 -0
- package/bin/util/index.js +7 -0
- package/bin/util/parameters.d.ts +7 -0
- package/bin/util/parameters.js +14 -0
- package/bin/util/shell.d.ts +32 -0
- package/bin/util/shell.js +1 -0
- package/package.json +9 -7
- package/readme.md +149 -211
- package/bin/404-route.d.ts +0 -2
- package/bin/404-route.js +0 -8
- package/bin/cli/dynamic.d.ts +0 -2
- package/bin/cli/dynamic.js +0 -47
- package/bin/cli/static.d.ts +0 -2
- package/bin/cli/static.js +0 -49
- package/bin/components.d.ts +0 -6
- package/bin/components.js +0 -31
- package/bin/render-args.d.ts +0 -35
- package/bin/render-args.js +0 -140
- package/bin/shared.d.ts +0 -28
- package/bin/shared.js +0 -28
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { QuickHash } from "../util/hash.js";
|
|
2
|
+
const registry = new Map();
|
|
3
|
+
export class Endpoint {
|
|
4
|
+
render;
|
|
5
|
+
name;
|
|
6
|
+
url;
|
|
7
|
+
constructor(render, name) {
|
|
8
|
+
this.render = render;
|
|
9
|
+
name ||= render.constructor.name;
|
|
10
|
+
const hash = QuickHash(String(render));
|
|
11
|
+
this.name = name ? `${encodeURIComponent(name)}-${hash}` : hash;
|
|
12
|
+
this.url = `/_/endpoint/${this.name}`;
|
|
13
|
+
registry.set(this.name, this);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export async function _resolve(fragments, ctx) {
|
|
17
|
+
if (!fragments[2])
|
|
18
|
+
return null;
|
|
19
|
+
const endpoint = registry.get(fragments[2]);
|
|
20
|
+
if (!endpoint)
|
|
21
|
+
return null;
|
|
22
|
+
const res = await endpoint.render(ctx);
|
|
23
|
+
if (res === null)
|
|
24
|
+
return null;
|
|
25
|
+
if (res instanceof Response)
|
|
26
|
+
return res;
|
|
27
|
+
return ctx.render(res);
|
|
28
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a new SSE handler
|
|
3
|
+
* Includes auto keep-alive, and graceful shutdown
|
|
4
|
+
*/
|
|
5
|
+
export declare class EventSourceConnection {
|
|
6
|
+
private controller;
|
|
7
|
+
private stream;
|
|
8
|
+
private timer;
|
|
9
|
+
readonly createdAt: number;
|
|
10
|
+
constructor(request: Request, keepAlive?: number);
|
|
11
|
+
response(): Response;
|
|
12
|
+
private keepAlive;
|
|
13
|
+
send(type: string, data: string, timeStamp: number): boolean;
|
|
14
|
+
isClosed(): boolean;
|
|
15
|
+
close(unlink?: boolean): boolean;
|
|
16
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a new SSE handler
|
|
3
|
+
* Includes auto keep-alive, and graceful shutdown
|
|
4
|
+
*/
|
|
5
|
+
export class EventSourceConnection {
|
|
6
|
+
controller;
|
|
7
|
+
stream;
|
|
8
|
+
timer;
|
|
9
|
+
createdAt; // unix time
|
|
10
|
+
constructor(request, keepAlive = 30_000) {
|
|
11
|
+
this.createdAt = Date.now();
|
|
12
|
+
this.controller = null;
|
|
13
|
+
this.stream = new ReadableStream({
|
|
14
|
+
start: (c) => { this.controller = c; },
|
|
15
|
+
cancel: () => { this.close(); }
|
|
16
|
+
});
|
|
17
|
+
request.signal.addEventListener('abort', () => this.close());
|
|
18
|
+
this.timer = setInterval(() => this.keepAlive(), keepAlive);
|
|
19
|
+
register.push(this);
|
|
20
|
+
}
|
|
21
|
+
response() {
|
|
22
|
+
const headers = new Headers();
|
|
23
|
+
headers.set("Content-Type", "text/event-stream");
|
|
24
|
+
headers.set("Transfer-Encoding", "chunked");
|
|
25
|
+
headers.set("Connection", "keep-alive");
|
|
26
|
+
headers.set("Keep-Alive", `timeout=120`);
|
|
27
|
+
return new Response(this.stream, { headers });
|
|
28
|
+
}
|
|
29
|
+
keepAlive() {
|
|
30
|
+
if (!this.controller)
|
|
31
|
+
return;
|
|
32
|
+
try {
|
|
33
|
+
this.controller.enqueue("\n\n");
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
console.error(e);
|
|
37
|
+
this.close(); // unbind on failure
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
send(type, data, timeStamp) {
|
|
41
|
+
if (!this.controller)
|
|
42
|
+
return false;
|
|
43
|
+
try {
|
|
44
|
+
this.controller.enqueue(`event: ${type}\ndata: [${data},${timeStamp}]\n\n`);
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.error(e);
|
|
49
|
+
this.close(); // unbind on failure
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
isClosed() {
|
|
54
|
+
return this.controller === null;
|
|
55
|
+
}
|
|
56
|
+
close(unlink = true) {
|
|
57
|
+
clearInterval(this.timer);
|
|
58
|
+
if (!this.controller)
|
|
59
|
+
return false;
|
|
60
|
+
if (unlink) {
|
|
61
|
+
const i = register.indexOf(this);
|
|
62
|
+
if (i !== -1)
|
|
63
|
+
register.splice(i, 1);
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
this.controller?.close();
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
console.error(e);
|
|
70
|
+
this.controller = null;
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
this.controller = null;
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Auto close all SSE streams when shutdown requested
|
|
78
|
+
// Without this graceful shutdowns will hang indefinitely
|
|
79
|
+
const register = new Array();
|
|
80
|
+
function CloseAll() {
|
|
81
|
+
for (const connection of register)
|
|
82
|
+
connection.close(false); // don't waste time unregistering
|
|
83
|
+
}
|
|
84
|
+
process.on('SIGTERM', CloseAll);
|
|
85
|
+
process.on('SIGHUP', CloseAll);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function QuickHash(input: string): string;
|
package/bin/util/hash.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function MergeHeaders(base: Headers, extension: Headers, override: boolean): void;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type Parameterized<T extends ParameterShaper> = {
|
|
2
|
+
[K in keyof T]: ReturnType<T[K]>;
|
|
3
|
+
};
|
|
4
|
+
export type ParameterShaper = Record<string, (val: string) => any>;
|
|
5
|
+
export declare function Parameterize<T extends ParameterShaper>(params: {
|
|
6
|
+
[key: string]: string;
|
|
7
|
+
}, shape: T): Parameterized<T>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function Parameterize(params, shape) {
|
|
2
|
+
const out = {};
|
|
3
|
+
for (const key in shape) {
|
|
4
|
+
if (!(key in params))
|
|
5
|
+
console.warn(`Parameter ${key} not present in route, but defined in parameters`);
|
|
6
|
+
const func = shape[key];
|
|
7
|
+
const val = func(params[key] || "");
|
|
8
|
+
// NaN moment
|
|
9
|
+
if (func === Number && typeof val === "number" && isNaN(val))
|
|
10
|
+
throw new Error("Invalid Number");
|
|
11
|
+
out[key] = val;
|
|
12
|
+
}
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type MetaDescriptor = {
|
|
2
|
+
charSet: "utf-8";
|
|
3
|
+
} | {
|
|
4
|
+
title: string;
|
|
5
|
+
} | {
|
|
6
|
+
name: string;
|
|
7
|
+
content: string;
|
|
8
|
+
} | {
|
|
9
|
+
property: string;
|
|
10
|
+
content: string;
|
|
11
|
+
} | {
|
|
12
|
+
httpEquiv: string;
|
|
13
|
+
content: string;
|
|
14
|
+
} | {
|
|
15
|
+
"script:ld+json": LdJsonObject;
|
|
16
|
+
} | {
|
|
17
|
+
tagName: "meta" | "link";
|
|
18
|
+
[name: string]: string;
|
|
19
|
+
} | {
|
|
20
|
+
[name: string]: unknown;
|
|
21
|
+
};
|
|
22
|
+
type LdJsonObject = {
|
|
23
|
+
[Key in string]?: LdJsonValue | undefined;
|
|
24
|
+
};
|
|
25
|
+
type LdJsonArray = LdJsonValue[] | readonly LdJsonValue[];
|
|
26
|
+
type LdJsonPrimitive = string | number | boolean | null;
|
|
27
|
+
type LdJsonValue = LdJsonPrimitive | LdJsonObject | LdJsonArray;
|
|
28
|
+
export type ShellOptions = {
|
|
29
|
+
meta?: Array<MetaDescriptor>;
|
|
30
|
+
} | undefined;
|
|
31
|
+
export type ShellProps<T> = T & ShellOptions;
|
|
32
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "htmx-router",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "A
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
|
+
"description": "A simple SSR framework with dynamic+client islands",
|
|
5
5
|
"main": "./bin/index.js",
|
|
6
|
+
"type": "module",
|
|
6
7
|
"scripts": {
|
|
7
|
-
"build": "tsc"
|
|
8
|
+
"build": "tsc && tsc-alias"
|
|
8
9
|
},
|
|
9
10
|
"bin": {
|
|
10
11
|
"htmx-router": "bin/cli/index.js"
|
|
@@ -19,13 +20,14 @@
|
|
|
19
20
|
"url": "https://github.com/AjaniBilby/htmx-router/issues"
|
|
20
21
|
},
|
|
21
22
|
"homepage": "https://github.com/AjaniBilby/htmx-router#readme",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"vite": "^6.0.1"
|
|
25
|
+
},
|
|
22
26
|
"devDependencies": {
|
|
23
27
|
"@types/node": "^20.4.5",
|
|
28
|
+
"es-module-lexer": "^1.5.4",
|
|
24
29
|
"ts-node": "^10.9.1",
|
|
30
|
+
"tsc-alias": "^1.8.10",
|
|
25
31
|
"typescript": "^5.1.6"
|
|
26
|
-
},
|
|
27
|
-
"dependencies": {
|
|
28
|
-
"csstype": "^3.1.2",
|
|
29
|
-
"typed-html": "^3.0.1"
|
|
30
32
|
}
|
|
31
33
|
}
|