@hyperspan/framework 0.1.2 → 0.1.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/build.ts +22 -20
- package/dist/assets.d.ts +1 -1
- package/dist/assets.js +3 -159
- package/dist/server.js +18 -242
- package/package.json +11 -7
- package/src/assets.ts +11 -10
- package/dist/index.d.ts +0 -132
- package/dist/index.js +0 -2477
- package/src/index.ts +0 -1
package/build.ts
CHANGED
|
@@ -1,27 +1,29 @@
|
|
|
1
1
|
import {build} from 'bun';
|
|
2
2
|
import dts from 'bun-plugin-dts';
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const entrypoints = ['./src/server.ts', './src/assets.ts'];
|
|
5
|
+
const external = ['@hyperspan/html'];
|
|
5
6
|
const outdir = './dist';
|
|
6
7
|
const target = 'node';
|
|
8
|
+
const splitting = true;
|
|
7
9
|
|
|
8
|
-
await Promise.all(
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
10
|
+
await Promise.all([
|
|
11
|
+
// Build JS
|
|
12
|
+
build({
|
|
13
|
+
entrypoints,
|
|
14
|
+
external,
|
|
15
|
+
outdir,
|
|
16
|
+
target,
|
|
17
|
+
splitting,
|
|
18
|
+
}),
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
]
|
|
26
|
-
)
|
|
27
|
-
);
|
|
20
|
+
// Build type files for TypeScript
|
|
21
|
+
build({
|
|
22
|
+
entrypoints,
|
|
23
|
+
external,
|
|
24
|
+
outdir,
|
|
25
|
+
target,
|
|
26
|
+
splitting,
|
|
27
|
+
plugins: [dts()],
|
|
28
|
+
}),
|
|
29
|
+
]);
|
package/dist/assets.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const clientJSFiles: Map<string, {
|
|
|
19
19
|
src: string;
|
|
20
20
|
type?: string;
|
|
21
21
|
}>;
|
|
22
|
-
export declare function buildClientJS(): Promise<
|
|
22
|
+
export declare function buildClientJS(): Promise<void>;
|
|
23
23
|
/**
|
|
24
24
|
* Find client CSS file built for end users
|
|
25
25
|
* @TODO: Build this in code here vs. relying on tailwindcss CLI tool from package scripts
|
package/dist/assets.js
CHANGED
|
@@ -1,161 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
|
|
3
|
-
* escape-html
|
|
4
|
-
* Copyright(c) 2012-2013 TJ Holowaychuk
|
|
5
|
-
* Copyright(c) 2015 Andreas Lubbe
|
|
6
|
-
* Copyright(c) 2015 Tiancheng "Timothy" Gu
|
|
7
|
-
* MIT Licensed
|
|
8
|
-
*/
|
|
9
|
-
var matchHtmlRegExp = /["'&<>]/;
|
|
10
|
-
function escapeHtml(string) {
|
|
11
|
-
const str = "" + string;
|
|
12
|
-
const match = matchHtmlRegExp.exec(str);
|
|
13
|
-
if (!match) {
|
|
14
|
-
return str;
|
|
15
|
-
}
|
|
16
|
-
let escape;
|
|
17
|
-
let html = "";
|
|
18
|
-
let index = 0;
|
|
19
|
-
let lastIndex = 0;
|
|
20
|
-
for (index = match.index;index < str.length; index++) {
|
|
21
|
-
switch (str.charCodeAt(index)) {
|
|
22
|
-
case 34:
|
|
23
|
-
escape = """;
|
|
24
|
-
break;
|
|
25
|
-
case 38:
|
|
26
|
-
escape = "&";
|
|
27
|
-
break;
|
|
28
|
-
case 39:
|
|
29
|
-
escape = "'";
|
|
30
|
-
break;
|
|
31
|
-
case 60:
|
|
32
|
-
escape = "<";
|
|
33
|
-
break;
|
|
34
|
-
case 62:
|
|
35
|
-
escape = ">";
|
|
36
|
-
break;
|
|
37
|
-
default:
|
|
38
|
-
continue;
|
|
39
|
-
}
|
|
40
|
-
if (lastIndex !== index) {
|
|
41
|
-
html += str.substring(lastIndex, index);
|
|
42
|
-
}
|
|
43
|
-
lastIndex = index + 1;
|
|
44
|
-
html += escape;
|
|
45
|
-
}
|
|
46
|
-
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
class TmplHtml {
|
|
50
|
-
_kind = "hstmpl";
|
|
51
|
-
content = "";
|
|
52
|
-
asyncContent;
|
|
53
|
-
constructor(props) {
|
|
54
|
-
this.content = props.content;
|
|
55
|
-
this.asyncContent = props.asyncContent;
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
var htmlId = 0;
|
|
59
|
-
function html(strings, ...values) {
|
|
60
|
-
const asyncContent = [];
|
|
61
|
-
let content = "";
|
|
62
|
-
for (let i = 0;i < strings.length; i++) {
|
|
63
|
-
const value = values[i];
|
|
64
|
-
const kind = _typeOf(value);
|
|
65
|
-
const renderValue = _renderValue(value, { kind, asyncContent }) || "";
|
|
66
|
-
content += strings[i] + (renderValue ? renderValue : "");
|
|
67
|
-
}
|
|
68
|
-
return new TmplHtml({ content, asyncContent });
|
|
69
|
-
}
|
|
70
|
-
html.raw = (content) => ({ _kind: "html_safe", content });
|
|
71
|
-
function _renderValue(value, opts = {
|
|
72
|
-
kind: undefined,
|
|
73
|
-
id: undefined,
|
|
74
|
-
asyncContent: []
|
|
75
|
-
}) {
|
|
76
|
-
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
77
|
-
return "";
|
|
78
|
-
}
|
|
79
|
-
const kind = opts.kind || _typeOf(value);
|
|
80
|
-
let id = opts.id;
|
|
81
|
-
switch (kind) {
|
|
82
|
-
case "array":
|
|
83
|
-
return value.map((v) => _renderValue(v, { id, asyncContent: opts.asyncContent })).join("");
|
|
84
|
-
case "object":
|
|
85
|
-
id = `async_loading_${htmlId++}`;
|
|
86
|
-
if (value instanceof TmplHtml || value.constructor.name === "TmplHtml" || value?._kind === "hstmpl") {
|
|
87
|
-
opts.asyncContent.push(...value.asyncContent);
|
|
88
|
-
return value.content;
|
|
89
|
-
}
|
|
90
|
-
if (value?._kind === "html_safe") {
|
|
91
|
-
return value?.content || "";
|
|
92
|
-
}
|
|
93
|
-
if (typeof value.renderAsync === "function") {
|
|
94
|
-
opts.asyncContent.push({
|
|
95
|
-
id,
|
|
96
|
-
promise: value.renderAsync().then((result) => ({
|
|
97
|
-
id,
|
|
98
|
-
value: result,
|
|
99
|
-
asyncContent: opts.asyncContent
|
|
100
|
-
}))
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
if (typeof value.render === "function") {
|
|
104
|
-
return render(_htmlPlaceholder(id, value.render()));
|
|
105
|
-
}
|
|
106
|
-
return JSON.stringify(value);
|
|
107
|
-
case "promise":
|
|
108
|
-
id = `async_loading_${htmlId++}`;
|
|
109
|
-
opts.asyncContent.push({
|
|
110
|
-
id,
|
|
111
|
-
promise: value.then((result) => ({
|
|
112
|
-
id,
|
|
113
|
-
value: result,
|
|
114
|
-
asyncContent: opts.asyncContent
|
|
115
|
-
}))
|
|
116
|
-
});
|
|
117
|
-
return render(_htmlPlaceholder(id));
|
|
118
|
-
case "generator":
|
|
119
|
-
throw new Error("Generators are not supported as a template value at this time. Sorry :(");
|
|
120
|
-
default:
|
|
121
|
-
console.log("_renderValue kind =", kind, value);
|
|
122
|
-
}
|
|
123
|
-
return escapeHtml(String(value));
|
|
124
|
-
}
|
|
125
|
-
function _htmlPlaceholder(id, content = "Loading...") {
|
|
126
|
-
return html`<!--hs:loading:${id}--><slot id="${id}">${content}</slot><!--/hs:loading:${id}-->`;
|
|
127
|
-
}
|
|
128
|
-
function render(tmpl) {
|
|
129
|
-
return tmpl.content;
|
|
130
|
-
}
|
|
131
|
-
function _typeOf(obj) {
|
|
132
|
-
if (obj instanceof Promise)
|
|
133
|
-
return "promise";
|
|
134
|
-
if (obj instanceof Date)
|
|
135
|
-
return "date";
|
|
136
|
-
if (obj instanceof String)
|
|
137
|
-
return "string";
|
|
138
|
-
if (obj instanceof Number)
|
|
139
|
-
return "number";
|
|
140
|
-
if (obj instanceof Boolean)
|
|
141
|
-
return "boolean";
|
|
142
|
-
if (obj instanceof Function)
|
|
143
|
-
return "function";
|
|
144
|
-
if (Array.isArray(obj))
|
|
145
|
-
return "array";
|
|
146
|
-
if (Number.isNaN(obj))
|
|
147
|
-
return "NaN";
|
|
148
|
-
if (obj === undefined)
|
|
149
|
-
return "undefined";
|
|
150
|
-
if (obj === null)
|
|
151
|
-
return "null";
|
|
152
|
-
if (isGenerator(obj))
|
|
153
|
-
return "generator";
|
|
154
|
-
return typeof obj;
|
|
155
|
-
}
|
|
156
|
-
function isGenerator(obj) {
|
|
157
|
-
return obj && typeof obj.next == "function" && typeof obj.throw == "function";
|
|
158
|
-
}
|
|
1
|
+
// src/assets.ts
|
|
2
|
+
import { html } from "@hyperspan/html";
|
|
159
3
|
|
|
160
4
|
// src/clientjs/md5.js
|
|
161
5
|
function md5cycle(x, k) {
|
|
@@ -307,7 +151,6 @@ async function buildClientJS() {
|
|
|
307
151
|
});
|
|
308
152
|
const jsFile = output.outputs[0].path.split("/").reverse()[0];
|
|
309
153
|
clientJSFiles.set("_hs", { src: "/_hs/js/" + jsFile });
|
|
310
|
-
return jsFile;
|
|
311
154
|
}
|
|
312
155
|
var clientCSSFiles = new Map;
|
|
313
156
|
async function buildClientCSS() {
|
|
@@ -391,3 +234,4 @@ export {
|
|
|
391
234
|
buildClientJS,
|
|
392
235
|
buildClientCSS
|
|
393
236
|
};
|
|
237
|
+
|
package/dist/server.js
CHANGED
|
@@ -1,194 +1,12 @@
|
|
|
1
|
+
import {
|
|
2
|
+
buildClientCSS,
|
|
3
|
+
buildClientJS
|
|
4
|
+
} from "./assets.js";
|
|
5
|
+
|
|
1
6
|
// src/server.ts
|
|
2
|
-
import { readdir
|
|
7
|
+
import { readdir } from "node:fs/promises";
|
|
3
8
|
import { basename, extname, join } from "node:path";
|
|
4
|
-
|
|
5
|
-
// ../html/dist/html.js
|
|
6
|
-
/*!
|
|
7
|
-
* escape-html
|
|
8
|
-
* Copyright(c) 2012-2013 TJ Holowaychuk
|
|
9
|
-
* Copyright(c) 2015 Andreas Lubbe
|
|
10
|
-
* Copyright(c) 2015 Tiancheng "Timothy" Gu
|
|
11
|
-
* MIT Licensed
|
|
12
|
-
*/
|
|
13
|
-
var matchHtmlRegExp = /["'&<>]/;
|
|
14
|
-
function escapeHtml(string) {
|
|
15
|
-
const str = "" + string;
|
|
16
|
-
const match = matchHtmlRegExp.exec(str);
|
|
17
|
-
if (!match) {
|
|
18
|
-
return str;
|
|
19
|
-
}
|
|
20
|
-
let escape;
|
|
21
|
-
let html = "";
|
|
22
|
-
let index = 0;
|
|
23
|
-
let lastIndex = 0;
|
|
24
|
-
for (index = match.index;index < str.length; index++) {
|
|
25
|
-
switch (str.charCodeAt(index)) {
|
|
26
|
-
case 34:
|
|
27
|
-
escape = """;
|
|
28
|
-
break;
|
|
29
|
-
case 38:
|
|
30
|
-
escape = "&";
|
|
31
|
-
break;
|
|
32
|
-
case 39:
|
|
33
|
-
escape = "'";
|
|
34
|
-
break;
|
|
35
|
-
case 60:
|
|
36
|
-
escape = "<";
|
|
37
|
-
break;
|
|
38
|
-
case 62:
|
|
39
|
-
escape = ">";
|
|
40
|
-
break;
|
|
41
|
-
default:
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (lastIndex !== index) {
|
|
45
|
-
html += str.substring(lastIndex, index);
|
|
46
|
-
}
|
|
47
|
-
lastIndex = index + 1;
|
|
48
|
-
html += escape;
|
|
49
|
-
}
|
|
50
|
-
return lastIndex !== index ? html + str.substring(lastIndex, index) : html;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
class TmplHtml {
|
|
54
|
-
_kind = "hstmpl";
|
|
55
|
-
content = "";
|
|
56
|
-
asyncContent;
|
|
57
|
-
constructor(props) {
|
|
58
|
-
this.content = props.content;
|
|
59
|
-
this.asyncContent = props.asyncContent;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
var htmlId = 0;
|
|
63
|
-
function html(strings, ...values) {
|
|
64
|
-
const asyncContent = [];
|
|
65
|
-
let content = "";
|
|
66
|
-
for (let i = 0;i < strings.length; i++) {
|
|
67
|
-
const value = values[i];
|
|
68
|
-
const kind = _typeOf(value);
|
|
69
|
-
const renderValue = _renderValue(value, { kind, asyncContent }) || "";
|
|
70
|
-
content += strings[i] + (renderValue ? renderValue : "");
|
|
71
|
-
}
|
|
72
|
-
return new TmplHtml({ content, asyncContent });
|
|
73
|
-
}
|
|
74
|
-
html.raw = (content) => ({ _kind: "html_safe", content });
|
|
75
|
-
function _renderValue(value, opts = {
|
|
76
|
-
kind: undefined,
|
|
77
|
-
id: undefined,
|
|
78
|
-
asyncContent: []
|
|
79
|
-
}) {
|
|
80
|
-
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
81
|
-
return "";
|
|
82
|
-
}
|
|
83
|
-
const kind = opts.kind || _typeOf(value);
|
|
84
|
-
let id = opts.id;
|
|
85
|
-
switch (kind) {
|
|
86
|
-
case "array":
|
|
87
|
-
return value.map((v) => _renderValue(v, { id, asyncContent: opts.asyncContent })).join("");
|
|
88
|
-
case "object":
|
|
89
|
-
id = `async_loading_${htmlId++}`;
|
|
90
|
-
if (value instanceof TmplHtml || value.constructor.name === "TmplHtml" || value?._kind === "hstmpl") {
|
|
91
|
-
opts.asyncContent.push(...value.asyncContent);
|
|
92
|
-
return value.content;
|
|
93
|
-
}
|
|
94
|
-
if (value?._kind === "html_safe") {
|
|
95
|
-
return value?.content || "";
|
|
96
|
-
}
|
|
97
|
-
if (typeof value.renderAsync === "function") {
|
|
98
|
-
opts.asyncContent.push({
|
|
99
|
-
id,
|
|
100
|
-
promise: value.renderAsync().then((result) => ({
|
|
101
|
-
id,
|
|
102
|
-
value: result,
|
|
103
|
-
asyncContent: opts.asyncContent
|
|
104
|
-
}))
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
if (typeof value.render === "function") {
|
|
108
|
-
return render(_htmlPlaceholder(id, value.render()));
|
|
109
|
-
}
|
|
110
|
-
return JSON.stringify(value);
|
|
111
|
-
case "promise":
|
|
112
|
-
id = `async_loading_${htmlId++}`;
|
|
113
|
-
opts.asyncContent.push({
|
|
114
|
-
id,
|
|
115
|
-
promise: value.then((result) => ({
|
|
116
|
-
id,
|
|
117
|
-
value: result,
|
|
118
|
-
asyncContent: opts.asyncContent
|
|
119
|
-
}))
|
|
120
|
-
});
|
|
121
|
-
return render(_htmlPlaceholder(id));
|
|
122
|
-
case "generator":
|
|
123
|
-
throw new Error("Generators are not supported as a template value at this time. Sorry :(");
|
|
124
|
-
default:
|
|
125
|
-
console.log("_renderValue kind =", kind, value);
|
|
126
|
-
}
|
|
127
|
-
return escapeHtml(String(value));
|
|
128
|
-
}
|
|
129
|
-
function _htmlPlaceholder(id, content = "Loading...") {
|
|
130
|
-
return html`<!--hs:loading:${id}--><slot id="${id}">${content}</slot><!--/hs:loading:${id}-->`;
|
|
131
|
-
}
|
|
132
|
-
function render(tmpl) {
|
|
133
|
-
return tmpl.content;
|
|
134
|
-
}
|
|
135
|
-
async function renderAsync(tmpl) {
|
|
136
|
-
let { content, asyncContent } = tmpl;
|
|
137
|
-
while (asyncContent.length !== 0) {
|
|
138
|
-
const resolvedHtml = await Promise.all(asyncContent.map((p) => p.promise));
|
|
139
|
-
asyncContent = [];
|
|
140
|
-
resolvedHtml.map((obj) => {
|
|
141
|
-
const r = new RegExp(`<!--hs:loading:${obj.id}-->(.*?)<!--/hs:loading:${obj.id}-->`);
|
|
142
|
-
const found = content.match(r);
|
|
143
|
-
if (found) {
|
|
144
|
-
content = content.replace(found[0], _renderValue(obj.value, { asyncContent }));
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
return content;
|
|
149
|
-
}
|
|
150
|
-
async function* renderStream(tmpl) {
|
|
151
|
-
yield render(tmpl);
|
|
152
|
-
let asyncContent = tmpl.asyncContent;
|
|
153
|
-
while (asyncContent.length > 0) {
|
|
154
|
-
const nextContent = await Promise.race(asyncContent.map((p) => p.promise));
|
|
155
|
-
asyncContent = asyncContent.filter((p) => p.id !== nextContent.id);
|
|
156
|
-
const id = nextContent.id;
|
|
157
|
-
const content = _renderValue(nextContent.value, {
|
|
158
|
-
asyncContent
|
|
159
|
-
});
|
|
160
|
-
const script = html`<template id="${id}_content">${html.raw(content)}<!--end--></template>`;
|
|
161
|
-
yield render(script);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
function _typeOf(obj) {
|
|
165
|
-
if (obj instanceof Promise)
|
|
166
|
-
return "promise";
|
|
167
|
-
if (obj instanceof Date)
|
|
168
|
-
return "date";
|
|
169
|
-
if (obj instanceof String)
|
|
170
|
-
return "string";
|
|
171
|
-
if (obj instanceof Number)
|
|
172
|
-
return "number";
|
|
173
|
-
if (obj instanceof Boolean)
|
|
174
|
-
return "boolean";
|
|
175
|
-
if (obj instanceof Function)
|
|
176
|
-
return "function";
|
|
177
|
-
if (Array.isArray(obj))
|
|
178
|
-
return "array";
|
|
179
|
-
if (Number.isNaN(obj))
|
|
180
|
-
return "NaN";
|
|
181
|
-
if (obj === undefined)
|
|
182
|
-
return "undefined";
|
|
183
|
-
if (obj === null)
|
|
184
|
-
return "null";
|
|
185
|
-
if (isGenerator(obj))
|
|
186
|
-
return "generator";
|
|
187
|
-
return typeof obj;
|
|
188
|
-
}
|
|
189
|
-
function isGenerator(obj) {
|
|
190
|
-
return obj && typeof obj.next == "function" && typeof obj.throw == "function";
|
|
191
|
-
}
|
|
9
|
+
import { TmplHtml, html, renderStream, renderAsync, render } from "@hyperspan/html";
|
|
192
10
|
|
|
193
11
|
// node_modules/isbot/index.mjs
|
|
194
12
|
var fullPattern = " daum[ /]| deusu/| yadirectfetcher|(?:^|[^g])news(?!sapphire)|(?<! (?:channel/|google/))google(?!(app|/google| pixel))|(?<! cu)bots?(?:\\b|_)|(?<!(?:lib))http|(?<![hg]m)score|@[a-z][\\w-]+\\.|\\(\\)|\\.com\\b|\\btime/|\\||^<|^[\\w \\.\\-\\(?:\\):%]+(?:/v?\\d+(?:\\.\\d+)?(?:\\.\\d{1,10})*?)?(?:,|$)|^[^ ]{50,}$|^\\d+\\b|^\\w*search\\b|^\\w+/[\\w\\(\\)]*$|^active|^ad muncher|^amaya|^avsdevicesdk/|^biglotron|^bot|^bw/|^clamav[ /]|^client/|^cobweb/|^custom|^ddg[_-]android|^discourse|^dispatch/\\d|^downcast/|^duckduckgo|^email|^facebook|^getright/|^gozilla/|^hobbit|^hotzonu|^hwcdn/|^igetter/|^jeode/|^jetty/|^jigsaw|^microsoft bits|^movabletype|^mozilla/\\d\\.\\d\\s[\\w\\.-]+$|^mozilla/\\d\\.\\d\\s\\(compatible;?(?:\\s\\w+\\/\\d+\\.\\d+)?\\)$|^navermailapp|^netsurf|^offline|^openai/|^owler|^php|^postman|^python|^rank|^read|^reed|^rest|^rss|^snapchat|^space bison|^svn|^swcd |^taringa|^thumbor/|^track|^w3c|^webbandit/|^webcopier|^wget|^whatsapp|^wordpress|^xenu link sleuth|^yahoo|^yandex|^zdm/\\d|^zoom marketplace/|^{{.*}}$|adscanner/|analyzer|archive|ask jeeves/teoma|audit|bit\\.ly/|bluecoat drtr|browsex|burpcollaborator|capture|catch|check\\b|checker|chrome-lighthouse|chromeframe|classifier|cloudflare|convertify|cookiehubscan|crawl|cypress/|dareboost|datanyze|dejaclick|detect|dmbrowser|download|evc-batch/|exaleadcloudview|feed|firephp|functionize|gomezagent|headless|httrack|hubspot marketing grader|hydra|ibisbrowser|infrawatch|insight|inspect|iplabel|ips-agent|java(?!;)|jsjcw_scanner|library|linkcheck|mail\\.ru/|manager|measure|neustar wpm|node|nutch|offbyone|onetrust|optimize|pageburst|pagespeed|parser|perl|phantomjs|pingdom|powermarks|preview|proxy|ptst[ /]\\d|retriever|rexx;|rigor|rss\\b|scanner\\.|scrape|server|sogou|sparkler/|speedcurve|spider|splash|statuscake|supercleaner|synapse|synthetic|tools|torrent|transcoder|url|validator|virtuoso|wappalyzer|webglance|webkit2png|whatcms/|zgrab";
|
|
@@ -209,48 +27,6 @@ function isbot(userAgent) {
|
|
|
209
27
|
return Boolean(userAgent) && getPattern().test(userAgent);
|
|
210
28
|
}
|
|
211
29
|
|
|
212
|
-
// src/clientjs/md5.js
|
|
213
|
-
var hex_chr = "0123456789abcdef".split("");
|
|
214
|
-
|
|
215
|
-
// src/assets.ts
|
|
216
|
-
import { readdir } from "node:fs/promises";
|
|
217
|
-
import { resolve } from "node:path";
|
|
218
|
-
var IS_PROD = false;
|
|
219
|
-
var PWD = import.meta.dir;
|
|
220
|
-
var clientJSFiles = new Map;
|
|
221
|
-
async function buildClientJS() {
|
|
222
|
-
const sourceFile = resolve(PWD, "../", "./src/clientjs/hyperspan-client.ts");
|
|
223
|
-
const output = await Bun.build({
|
|
224
|
-
entrypoints: [sourceFile],
|
|
225
|
-
outdir: `./public/_hs/js`,
|
|
226
|
-
naming: IS_PROD ? "[dir]/[name]-[hash].[ext]" : undefined,
|
|
227
|
-
minify: IS_PROD
|
|
228
|
-
});
|
|
229
|
-
const jsFile = output.outputs[0].path.split("/").reverse()[0];
|
|
230
|
-
clientJSFiles.set("_hs", { src: "/_hs/js/" + jsFile });
|
|
231
|
-
return jsFile;
|
|
232
|
-
}
|
|
233
|
-
var clientCSSFiles = new Map;
|
|
234
|
-
async function buildClientCSS() {
|
|
235
|
-
if (clientCSSFiles.has("_hs")) {
|
|
236
|
-
return clientCSSFiles.get("_hs");
|
|
237
|
-
}
|
|
238
|
-
const cssDir = "./public/_hs/css/";
|
|
239
|
-
const cssFiles = await readdir(cssDir);
|
|
240
|
-
let foundCSSFile = "";
|
|
241
|
-
for (const file of cssFiles) {
|
|
242
|
-
if (!file.endsWith(".css")) {
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
foundCSSFile = file.replace(cssDir, "");
|
|
246
|
-
clientCSSFiles.set("_hs", foundCSSFile);
|
|
247
|
-
break;
|
|
248
|
-
}
|
|
249
|
-
if (!foundCSSFile) {
|
|
250
|
-
console.log(`Unable to build CSS files from ${cssDir}`);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
30
|
// node_modules/hono/dist/compose.js
|
|
255
31
|
var compose = (middleware, onError, onNotFound) => {
|
|
256
32
|
return (context, next) => {
|
|
@@ -920,15 +696,15 @@ var Context = class {
|
|
|
920
696
|
this.#preparedHeaders["content-type"] = "application/json";
|
|
921
697
|
return typeof arg === "number" ? this.#newResponse(body, arg, headers) : this.#newResponse(body, arg);
|
|
922
698
|
};
|
|
923
|
-
html = (
|
|
699
|
+
html = (html, arg, headers) => {
|
|
924
700
|
this.#preparedHeaders ??= {};
|
|
925
701
|
this.#preparedHeaders["content-type"] = "text/html; charset=UTF-8";
|
|
926
|
-
if (typeof
|
|
927
|
-
return resolveCallback(
|
|
928
|
-
return typeof arg === "number" ? this.#newResponse(
|
|
702
|
+
if (typeof html === "object") {
|
|
703
|
+
return resolveCallback(html, HtmlEscapedCallbackPhase.Stringify, false, {}).then((html2) => {
|
|
704
|
+
return typeof arg === "number" ? this.#newResponse(html2, arg, headers) : this.#newResponse(html2, arg);
|
|
929
705
|
});
|
|
930
706
|
}
|
|
931
|
-
return typeof arg === "number" ? this.#newResponse(
|
|
707
|
+
return typeof arg === "number" ? this.#newResponse(html, arg, headers) : this.#newResponse(html, arg);
|
|
932
708
|
};
|
|
933
709
|
redirect = (location, status) => {
|
|
934
710
|
this.#headers ??= new Headers;
|
|
@@ -2190,7 +1966,7 @@ class ZodError extends $ZodError {
|
|
|
2190
1966
|
var parse = /* @__PURE__ */ _parse.bind({ Error: ZodError });
|
|
2191
1967
|
|
|
2192
1968
|
// src/server.ts
|
|
2193
|
-
var
|
|
1969
|
+
var IS_PROD = false;
|
|
2194
1970
|
var CWD = process.cwd();
|
|
2195
1971
|
function createRoute(handler) {
|
|
2196
1972
|
return new HSRoute(handler);
|
|
@@ -2330,7 +2106,7 @@ async function runAPIRoute(routeFn, context, middlewareResult) {
|
|
|
2330
2106
|
meta: { success: false },
|
|
2331
2107
|
data: {
|
|
2332
2108
|
message: e.message,
|
|
2333
|
-
stack:
|
|
2109
|
+
stack: IS_PROD ? undefined : e.stack?.split(`
|
|
2334
2110
|
`)
|
|
2335
2111
|
}
|
|
2336
2112
|
}, { status: 500 });
|
|
@@ -2341,7 +2117,7 @@ async function showErrorReponse(context, err) {
|
|
|
2341
2117
|
<main>
|
|
2342
2118
|
<h1>Error</h1>
|
|
2343
2119
|
<pre>${err.message}</pre>
|
|
2344
|
-
<pre>${!
|
|
2120
|
+
<pre>${!IS_PROD && err.stack ? err.stack.split(`
|
|
2345
2121
|
`).slice(1).join(`
|
|
2346
2122
|
`) : ""}</pre>
|
|
2347
2123
|
</main>
|
|
@@ -2354,7 +2130,7 @@ var ROUTE_SEGMENT = /(\[[a-zA-Z_\.]+\])/g;
|
|
|
2354
2130
|
async function buildRoutes(config2) {
|
|
2355
2131
|
const routesDir = join(config2.appDir, "routes");
|
|
2356
2132
|
console.log(routesDir);
|
|
2357
|
-
const files = await
|
|
2133
|
+
const files = await readdir(routesDir, { recursive: true });
|
|
2358
2134
|
const routes = [];
|
|
2359
2135
|
for (const file of files) {
|
|
2360
2136
|
if (!file.includes(".") || basename(file).startsWith(".")) {
|
|
@@ -2412,7 +2188,7 @@ async function createServer(config2) {
|
|
|
2412
2188
|
return context.text("No routes found. Add routes to app/routes. Example: `app/routes/index.ts`", { status: 404 });
|
|
2413
2189
|
});
|
|
2414
2190
|
}
|
|
2415
|
-
if (!
|
|
2191
|
+
if (!IS_PROD) {
|
|
2416
2192
|
console.log("[Hyperspan] File system routes (in app/routes):");
|
|
2417
2193
|
console.table(routeMap);
|
|
2418
2194
|
}
|
|
@@ -2469,7 +2245,7 @@ export {
|
|
|
2469
2245
|
createComponent,
|
|
2470
2246
|
buildRoutes,
|
|
2471
2247
|
StreamResponse,
|
|
2472
|
-
|
|
2248
|
+
IS_PROD,
|
|
2473
2249
|
HS_DEFAULT_LOADING,
|
|
2474
2250
|
HSRoute,
|
|
2475
2251
|
HSFormRoute,
|
package/package.json
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperspan/framework",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Hyperspan Web Framework",
|
|
5
|
-
"main": "dist/
|
|
5
|
+
"main": "dist/server.js",
|
|
6
6
|
"public": true,
|
|
7
7
|
"publishConfig": {
|
|
8
8
|
"access": "public"
|
|
9
9
|
},
|
|
10
10
|
"exports": {
|
|
11
11
|
".": {
|
|
12
|
-
"types": "./dist/
|
|
13
|
-
"default": "./dist/
|
|
12
|
+
"types": "./dist/server.d.ts",
|
|
13
|
+
"default": "./dist/server.js"
|
|
14
|
+
},
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/server.d.ts",
|
|
17
|
+
"default": "./dist/server.js"
|
|
14
18
|
},
|
|
15
19
|
"./assets": {
|
|
16
20
|
"types": "./dist/assets.d.ts",
|
|
@@ -38,10 +42,10 @@
|
|
|
38
42
|
"url": "https://github.com/vlucas/hyperspan/issues"
|
|
39
43
|
},
|
|
40
44
|
"scripts": {
|
|
41
|
-
"build": "bun ./build.ts",
|
|
45
|
+
"build": "bun ./build.ts && sed -i '' -e '$ d' dist/assets.js",
|
|
42
46
|
"clean": "rm -rf dist",
|
|
43
47
|
"test": "bun test",
|
|
44
|
-
"prepack": "
|
|
48
|
+
"prepack": "bun run clean && bun run build"
|
|
45
49
|
},
|
|
46
50
|
"devDependencies": {
|
|
47
51
|
"@types/bun": "^1.1.9",
|
|
@@ -55,7 +59,7 @@
|
|
|
55
59
|
"typescript": "^5.0.0"
|
|
56
60
|
},
|
|
57
61
|
"dependencies": {
|
|
58
|
-
"@hyperspan/html": "^0.1.
|
|
62
|
+
"@hyperspan/html": "^0.1.2",
|
|
59
63
|
"@preact/compat": "^18.3.1",
|
|
60
64
|
"hono": "^4.7.4",
|
|
61
65
|
"isbot": "^5.1.25",
|
package/src/assets.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {html} from '@hyperspan/html';
|
|
2
|
-
import {md5} from './clientjs/md5';
|
|
3
|
-
import {readdir} from 'node:fs/promises';
|
|
4
|
-
import {resolve} from 'node:path';
|
|
1
|
+
import { html } from '@hyperspan/html';
|
|
2
|
+
import { md5 } from './clientjs/md5';
|
|
3
|
+
import { readdir } from 'node:fs/promises';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
5
|
|
|
6
6
|
const IS_PROD = process.env.NODE_ENV === 'production';
|
|
7
7
|
const PWD = import.meta.dir;
|
|
@@ -9,7 +9,7 @@ const PWD = import.meta.dir;
|
|
|
9
9
|
/**
|
|
10
10
|
* Build client JS for end users (minimal JS for Hyperspan to work)
|
|
11
11
|
*/
|
|
12
|
-
export const clientJSFiles = new Map<string, {src: string; type?: string}>();
|
|
12
|
+
export const clientJSFiles = new Map<string, { src: string; type?: string }>();
|
|
13
13
|
export async function buildClientJS() {
|
|
14
14
|
const sourceFile = resolve(PWD, '../', './src/clientjs/hyperspan-client.ts');
|
|
15
15
|
const output = await Bun.build({
|
|
@@ -20,8 +20,8 @@ export async function buildClientJS() {
|
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
const jsFile = output.outputs[0].path.split('/').reverse()[0];
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
clientJSFiles.set('_hs', { src: '/_hs/js/' + jsFile });
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
/**
|
|
@@ -71,6 +71,7 @@ export function hyperspanStyleTags() {
|
|
|
71
71
|
*/
|
|
72
72
|
export function hyperspanScriptTags() {
|
|
73
73
|
const jsFiles = Array.from(clientJSFiles.entries());
|
|
74
|
+
|
|
74
75
|
return html`
|
|
75
76
|
<script type="importmap">
|
|
76
77
|
{
|
|
@@ -84,13 +85,13 @@ export function hyperspanScriptTags() {
|
|
|
84
85
|
}
|
|
85
86
|
</script>
|
|
86
87
|
${jsFiles.map(
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
([key, file]) =>
|
|
89
|
+
html`<script
|
|
89
90
|
id="js-${key}"
|
|
90
91
|
type="${file.type || 'text/javascript'}"
|
|
91
92
|
src="${file.src}"
|
|
92
93
|
></script>`
|
|
93
|
-
|
|
94
|
+
)}
|
|
94
95
|
`;
|
|
95
96
|
}
|
|
96
97
|
|