@hyperspan/framework 0.1.0 → 0.1.1
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 +27 -0
- package/dist/assets.d.ts +34 -0
- package/dist/assets.js +394 -0
- package/dist/index.d.ts +121 -0
- package/dist/index.js +2484 -0
- package/dist/server.d.ts +121 -0
- package/dist/server.js +2484 -0
- package/package.json +21 -8
- package/src/assets.ts +1 -1
- package/src/index.ts +1 -0
- package/src/server.ts +26 -96
package/build.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {build} from 'bun';
|
|
2
|
+
import dts from 'bun-plugin-dts';
|
|
3
|
+
|
|
4
|
+
const filesToBuild = ['./src/index.ts', './src/server.ts', './src/assets.ts'];
|
|
5
|
+
const outdir = './dist';
|
|
6
|
+
const target = 'node';
|
|
7
|
+
|
|
8
|
+
await Promise.all(
|
|
9
|
+
filesToBuild.map((file) =>
|
|
10
|
+
Promise.all([
|
|
11
|
+
// Build JS
|
|
12
|
+
build({
|
|
13
|
+
entrypoints: [file],
|
|
14
|
+
outdir,
|
|
15
|
+
target,
|
|
16
|
+
}),
|
|
17
|
+
|
|
18
|
+
// Build type files for TypeScript
|
|
19
|
+
build({
|
|
20
|
+
entrypoints: [file],
|
|
21
|
+
outdir,
|
|
22
|
+
target,
|
|
23
|
+
plugins: [dts()],
|
|
24
|
+
}),
|
|
25
|
+
])
|
|
26
|
+
)
|
|
27
|
+
);
|
package/dist/assets.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Build client JS for end users (minimal JS for Hyperspan to work)
|
|
5
|
+
*/
|
|
6
|
+
export declare const clientJSFiles: Map<string, {
|
|
7
|
+
src: string;
|
|
8
|
+
type?: string;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function buildClientJS(): Promise<string>;
|
|
11
|
+
/**
|
|
12
|
+
* Find client CSS file built for end users
|
|
13
|
+
* @TODO: Build this in code here vs. relying on tailwindcss CLI tool from package scripts
|
|
14
|
+
*/
|
|
15
|
+
export declare const clientCSSFiles: Map<string, string>;
|
|
16
|
+
export declare function buildClientCSS(): Promise<string | undefined>;
|
|
17
|
+
/**
|
|
18
|
+
* Output HTML style tag for Hyperspan app
|
|
19
|
+
*/
|
|
20
|
+
export declare function hyperspanStyleTags(): import("@hyperspan/html").TmplHtml;
|
|
21
|
+
/**
|
|
22
|
+
* Output HTML script tag for Hyperspan app
|
|
23
|
+
* Required for functioning streaming so content can pop into place properly once ready
|
|
24
|
+
*/
|
|
25
|
+
export declare function hyperspanScriptTags(): import("@hyperspan/html").TmplHtml;
|
|
26
|
+
/**
|
|
27
|
+
* Return a Preact component, mounted as an island in a <script> tag so it can be embedded into the page response.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createPreactIsland(file: string): Promise<(props: any) => {
|
|
30
|
+
_kind: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
export {};
|
package/dist/assets.js
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
// node_modules/@hyperspan/html/dist/html.js
|
|
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
|
+
content = "";
|
|
51
|
+
asyncContent;
|
|
52
|
+
constructor(props) {
|
|
53
|
+
this.content = props.content;
|
|
54
|
+
this.asyncContent = props.asyncContent;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
var htmlId = 0;
|
|
58
|
+
function html(strings, ...values) {
|
|
59
|
+
const asyncContent = [];
|
|
60
|
+
let content = "";
|
|
61
|
+
for (let i = 0;i < strings.length; i++) {
|
|
62
|
+
let value = values[i];
|
|
63
|
+
let renderValue;
|
|
64
|
+
if (value !== null && value !== undefined) {
|
|
65
|
+
let id = `async_loading_${htmlId++}`;
|
|
66
|
+
let kind = _typeOf(value);
|
|
67
|
+
if (!renderValue) {
|
|
68
|
+
renderValue = _renderValue(value, { id, kind, asyncContent }) || "";
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
content += strings[i] + (renderValue ? renderValue : "");
|
|
72
|
+
}
|
|
73
|
+
return new TmplHtml({ content, asyncContent });
|
|
74
|
+
}
|
|
75
|
+
html.raw = (content) => ({ _kind: "html_safe", content });
|
|
76
|
+
function _renderValue(value, opts = {
|
|
77
|
+
kind: undefined,
|
|
78
|
+
id: undefined,
|
|
79
|
+
asyncContent: []
|
|
80
|
+
}) {
|
|
81
|
+
if (value === null || value === undefined || Number.isNaN(value)) {
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
84
|
+
const kind = opts.kind || _typeOf(value);
|
|
85
|
+
const id = opts.id || "";
|
|
86
|
+
switch (kind) {
|
|
87
|
+
case "array":
|
|
88
|
+
return value.map((v) => _renderValue(v, { id, asyncContent: opts.asyncContent })).join("");
|
|
89
|
+
case "object":
|
|
90
|
+
if (value instanceof TmplHtml) {
|
|
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
|
+
opts.asyncContent.push({
|
|
113
|
+
id,
|
|
114
|
+
promise: value.then((result) => ({
|
|
115
|
+
id,
|
|
116
|
+
value: result,
|
|
117
|
+
asyncContent: opts.asyncContent
|
|
118
|
+
}))
|
|
119
|
+
});
|
|
120
|
+
return render(_htmlPlaceholder(id));
|
|
121
|
+
case "generator":
|
|
122
|
+
throw new Error("Generators are not supported as a template value at this time. Sorry :(");
|
|
123
|
+
}
|
|
124
|
+
return escapeHtml(String(value));
|
|
125
|
+
}
|
|
126
|
+
function _htmlPlaceholder(id, content = "Loading...") {
|
|
127
|
+
return html`<!--hs:loading:${id}--><slot id="${id}">${content}</slot><!--/hs:loading:${id}-->`;
|
|
128
|
+
}
|
|
129
|
+
function render(tmpl) {
|
|
130
|
+
return tmpl.content;
|
|
131
|
+
}
|
|
132
|
+
function _typeOf(obj) {
|
|
133
|
+
if (obj instanceof Promise)
|
|
134
|
+
return "promise";
|
|
135
|
+
if (obj instanceof Date)
|
|
136
|
+
return "date";
|
|
137
|
+
if (obj instanceof String)
|
|
138
|
+
return "string";
|
|
139
|
+
if (obj instanceof Number)
|
|
140
|
+
return "number";
|
|
141
|
+
if (obj instanceof Boolean)
|
|
142
|
+
return "boolean";
|
|
143
|
+
if (obj instanceof Function)
|
|
144
|
+
return "function";
|
|
145
|
+
if (Array.isArray(obj))
|
|
146
|
+
return "array";
|
|
147
|
+
if (Number.isNaN(obj))
|
|
148
|
+
return "NaN";
|
|
149
|
+
if (obj === undefined)
|
|
150
|
+
return "undefined";
|
|
151
|
+
if (obj === null)
|
|
152
|
+
return "null";
|
|
153
|
+
if (isGenerator(obj))
|
|
154
|
+
return "generator";
|
|
155
|
+
return typeof obj;
|
|
156
|
+
}
|
|
157
|
+
function isGenerator(obj) {
|
|
158
|
+
return obj && typeof obj.next == "function" && typeof obj.throw == "function";
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/clientjs/md5.js
|
|
162
|
+
function md5cycle(x, k) {
|
|
163
|
+
var a = x[0], b = x[1], c = x[2], d = x[3];
|
|
164
|
+
a = ff(a, b, c, d, k[0], 7, -680876936);
|
|
165
|
+
d = ff(d, a, b, c, k[1], 12, -389564586);
|
|
166
|
+
c = ff(c, d, a, b, k[2], 17, 606105819);
|
|
167
|
+
b = ff(b, c, d, a, k[3], 22, -1044525330);
|
|
168
|
+
a = ff(a, b, c, d, k[4], 7, -176418897);
|
|
169
|
+
d = ff(d, a, b, c, k[5], 12, 1200080426);
|
|
170
|
+
c = ff(c, d, a, b, k[6], 17, -1473231341);
|
|
171
|
+
b = ff(b, c, d, a, k[7], 22, -45705983);
|
|
172
|
+
a = ff(a, b, c, d, k[8], 7, 1770035416);
|
|
173
|
+
d = ff(d, a, b, c, k[9], 12, -1958414417);
|
|
174
|
+
c = ff(c, d, a, b, k[10], 17, -42063);
|
|
175
|
+
b = ff(b, c, d, a, k[11], 22, -1990404162);
|
|
176
|
+
a = ff(a, b, c, d, k[12], 7, 1804603682);
|
|
177
|
+
d = ff(d, a, b, c, k[13], 12, -40341101);
|
|
178
|
+
c = ff(c, d, a, b, k[14], 17, -1502002290);
|
|
179
|
+
b = ff(b, c, d, a, k[15], 22, 1236535329);
|
|
180
|
+
a = gg(a, b, c, d, k[1], 5, -165796510);
|
|
181
|
+
d = gg(d, a, b, c, k[6], 9, -1069501632);
|
|
182
|
+
c = gg(c, d, a, b, k[11], 14, 643717713);
|
|
183
|
+
b = gg(b, c, d, a, k[0], 20, -373897302);
|
|
184
|
+
a = gg(a, b, c, d, k[5], 5, -701558691);
|
|
185
|
+
d = gg(d, a, b, c, k[10], 9, 38016083);
|
|
186
|
+
c = gg(c, d, a, b, k[15], 14, -660478335);
|
|
187
|
+
b = gg(b, c, d, a, k[4], 20, -405537848);
|
|
188
|
+
a = gg(a, b, c, d, k[9], 5, 568446438);
|
|
189
|
+
d = gg(d, a, b, c, k[14], 9, -1019803690);
|
|
190
|
+
c = gg(c, d, a, b, k[3], 14, -187363961);
|
|
191
|
+
b = gg(b, c, d, a, k[8], 20, 1163531501);
|
|
192
|
+
a = gg(a, b, c, d, k[13], 5, -1444681467);
|
|
193
|
+
d = gg(d, a, b, c, k[2], 9, -51403784);
|
|
194
|
+
c = gg(c, d, a, b, k[7], 14, 1735328473);
|
|
195
|
+
b = gg(b, c, d, a, k[12], 20, -1926607734);
|
|
196
|
+
a = hh(a, b, c, d, k[5], 4, -378558);
|
|
197
|
+
d = hh(d, a, b, c, k[8], 11, -2022574463);
|
|
198
|
+
c = hh(c, d, a, b, k[11], 16, 1839030562);
|
|
199
|
+
b = hh(b, c, d, a, k[14], 23, -35309556);
|
|
200
|
+
a = hh(a, b, c, d, k[1], 4, -1530992060);
|
|
201
|
+
d = hh(d, a, b, c, k[4], 11, 1272893353);
|
|
202
|
+
c = hh(c, d, a, b, k[7], 16, -155497632);
|
|
203
|
+
b = hh(b, c, d, a, k[10], 23, -1094730640);
|
|
204
|
+
a = hh(a, b, c, d, k[13], 4, 681279174);
|
|
205
|
+
d = hh(d, a, b, c, k[0], 11, -358537222);
|
|
206
|
+
c = hh(c, d, a, b, k[3], 16, -722521979);
|
|
207
|
+
b = hh(b, c, d, a, k[6], 23, 76029189);
|
|
208
|
+
a = hh(a, b, c, d, k[9], 4, -640364487);
|
|
209
|
+
d = hh(d, a, b, c, k[12], 11, -421815835);
|
|
210
|
+
c = hh(c, d, a, b, k[15], 16, 530742520);
|
|
211
|
+
b = hh(b, c, d, a, k[2], 23, -995338651);
|
|
212
|
+
a = ii(a, b, c, d, k[0], 6, -198630844);
|
|
213
|
+
d = ii(d, a, b, c, k[7], 10, 1126891415);
|
|
214
|
+
c = ii(c, d, a, b, k[14], 15, -1416354905);
|
|
215
|
+
b = ii(b, c, d, a, k[5], 21, -57434055);
|
|
216
|
+
a = ii(a, b, c, d, k[12], 6, 1700485571);
|
|
217
|
+
d = ii(d, a, b, c, k[3], 10, -1894986606);
|
|
218
|
+
c = ii(c, d, a, b, k[10], 15, -1051523);
|
|
219
|
+
b = ii(b, c, d, a, k[1], 21, -2054922799);
|
|
220
|
+
a = ii(a, b, c, d, k[8], 6, 1873313359);
|
|
221
|
+
d = ii(d, a, b, c, k[15], 10, -30611744);
|
|
222
|
+
c = ii(c, d, a, b, k[6], 15, -1560198380);
|
|
223
|
+
b = ii(b, c, d, a, k[13], 21, 1309151649);
|
|
224
|
+
a = ii(a, b, c, d, k[4], 6, -145523070);
|
|
225
|
+
d = ii(d, a, b, c, k[11], 10, -1120210379);
|
|
226
|
+
c = ii(c, d, a, b, k[2], 15, 718787259);
|
|
227
|
+
b = ii(b, c, d, a, k[9], 21, -343485551);
|
|
228
|
+
x[0] = add32(a, x[0]);
|
|
229
|
+
x[1] = add32(b, x[1]);
|
|
230
|
+
x[2] = add32(c, x[2]);
|
|
231
|
+
x[3] = add32(d, x[3]);
|
|
232
|
+
}
|
|
233
|
+
function cmn(q, a, b, x, s, t) {
|
|
234
|
+
a = add32(add32(a, q), add32(x, t));
|
|
235
|
+
return add32(a << s | a >>> 32 - s, b);
|
|
236
|
+
}
|
|
237
|
+
function ff(a, b, c, d, x, s, t) {
|
|
238
|
+
return cmn(b & c | ~b & d, a, b, x, s, t);
|
|
239
|
+
}
|
|
240
|
+
function gg(a, b, c, d, x, s, t) {
|
|
241
|
+
return cmn(b & d | c & ~d, a, b, x, s, t);
|
|
242
|
+
}
|
|
243
|
+
function hh(a, b, c, d, x, s, t) {
|
|
244
|
+
return cmn(b ^ c ^ d, a, b, x, s, t);
|
|
245
|
+
}
|
|
246
|
+
function ii(a, b, c, d, x, s, t) {
|
|
247
|
+
return cmn(c ^ (b | ~d), a, b, x, s, t);
|
|
248
|
+
}
|
|
249
|
+
function md51(s) {
|
|
250
|
+
var txt = "";
|
|
251
|
+
var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
|
|
252
|
+
for (i = 64;i <= s.length; i += 64) {
|
|
253
|
+
md5cycle(state, md5blk(s.substring(i - 64, i)));
|
|
254
|
+
}
|
|
255
|
+
s = s.substring(i - 64);
|
|
256
|
+
var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
257
|
+
for (i = 0;i < s.length; i++)
|
|
258
|
+
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
|
|
259
|
+
tail[i >> 2] |= 128 << (i % 4 << 3);
|
|
260
|
+
if (i > 55) {
|
|
261
|
+
md5cycle(state, tail);
|
|
262
|
+
for (i = 0;i < 16; i++)
|
|
263
|
+
tail[i] = 0;
|
|
264
|
+
}
|
|
265
|
+
tail[14] = n * 8;
|
|
266
|
+
md5cycle(state, tail);
|
|
267
|
+
return state;
|
|
268
|
+
}
|
|
269
|
+
function md5blk(s) {
|
|
270
|
+
var md5blks = [], i;
|
|
271
|
+
for (i = 0;i < 64; i += 4) {
|
|
272
|
+
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
|
|
273
|
+
}
|
|
274
|
+
return md5blks;
|
|
275
|
+
}
|
|
276
|
+
var hex_chr = "0123456789abcdef".split("");
|
|
277
|
+
function rhex(n) {
|
|
278
|
+
var s = "", j = 0;
|
|
279
|
+
for (;j < 4; j++)
|
|
280
|
+
s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
|
|
281
|
+
return s;
|
|
282
|
+
}
|
|
283
|
+
function hex(x) {
|
|
284
|
+
for (var i = 0;i < x.length; i++)
|
|
285
|
+
x[i] = rhex(x[i]);
|
|
286
|
+
return x.join("");
|
|
287
|
+
}
|
|
288
|
+
function add32(a, b) {
|
|
289
|
+
return a + b & 4294967295;
|
|
290
|
+
}
|
|
291
|
+
function md5(s) {
|
|
292
|
+
return hex(md51(s));
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/assets.ts
|
|
296
|
+
import { readdir } from "node:fs/promises";
|
|
297
|
+
import { resolve } from "node:path";
|
|
298
|
+
var IS_PROD = false;
|
|
299
|
+
var PWD = import.meta.dir;
|
|
300
|
+
var clientJSFiles = new Map;
|
|
301
|
+
async function buildClientJS() {
|
|
302
|
+
const sourceFile = resolve(PWD, "../", "./hyperspan/clientjs/hyperspan-client.ts");
|
|
303
|
+
const output = await Bun.build({
|
|
304
|
+
entrypoints: [sourceFile],
|
|
305
|
+
outdir: `./public/_hs/js`,
|
|
306
|
+
naming: IS_PROD ? "[dir]/[name]-[hash].[ext]" : undefined,
|
|
307
|
+
minify: IS_PROD
|
|
308
|
+
});
|
|
309
|
+
const jsFile = output.outputs[0].path.split("/").reverse()[0];
|
|
310
|
+
clientJSFiles.set("_hs", { src: "/_hs/js/" + jsFile });
|
|
311
|
+
return jsFile;
|
|
312
|
+
}
|
|
313
|
+
var clientCSSFiles = new Map;
|
|
314
|
+
async function buildClientCSS() {
|
|
315
|
+
if (clientCSSFiles.has("_hs")) {
|
|
316
|
+
return clientCSSFiles.get("_hs");
|
|
317
|
+
}
|
|
318
|
+
const cssDir = "./public/_hs/css/";
|
|
319
|
+
const cssFiles = await readdir(cssDir);
|
|
320
|
+
let foundCSSFile = "";
|
|
321
|
+
for (const file of cssFiles) {
|
|
322
|
+
if (!file.endsWith(".css")) {
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
foundCSSFile = file.replace(cssDir, "");
|
|
326
|
+
clientCSSFiles.set("_hs", foundCSSFile);
|
|
327
|
+
break;
|
|
328
|
+
}
|
|
329
|
+
if (!foundCSSFile) {
|
|
330
|
+
console.log(`Unable to build CSS files from ${cssDir}`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
function hyperspanStyleTags() {
|
|
334
|
+
const cssFiles = Array.from(clientCSSFiles.entries());
|
|
335
|
+
return html`${cssFiles.map(([key, file]) => html`<link rel="stylesheet" href="/_hs/css/${file}" />`)}`;
|
|
336
|
+
}
|
|
337
|
+
function hyperspanScriptTags() {
|
|
338
|
+
const jsFiles = Array.from(clientJSFiles.entries());
|
|
339
|
+
return html`
|
|
340
|
+
<script type="importmap">
|
|
341
|
+
{
|
|
342
|
+
"imports": {
|
|
343
|
+
"preact": "https://esm.sh/preact@10.26.4",
|
|
344
|
+
"preact/": "https://esm.sh/preact@10.26.4/",
|
|
345
|
+
"react": "https://esm.sh/preact@10.26.4/compat",
|
|
346
|
+
"react/": "https://esm.sh/preact@10.26.4/compat/",
|
|
347
|
+
"react-dom": "https://esm.sh/preact@10.26.4/compat"
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
</script>
|
|
351
|
+
${jsFiles.map(([key, file]) => html`<script
|
|
352
|
+
id="js-${key}"
|
|
353
|
+
type="${file.type || "text/javascript"}"
|
|
354
|
+
src="${file.src}"
|
|
355
|
+
></script>`)}
|
|
356
|
+
`;
|
|
357
|
+
}
|
|
358
|
+
async function createPreactIsland(file) {
|
|
359
|
+
let filePath = file.replace("file://", "");
|
|
360
|
+
let resultStr = 'import{h,render}from"preact";';
|
|
361
|
+
const build = await Bun.build({
|
|
362
|
+
entrypoints: [filePath],
|
|
363
|
+
minify: true,
|
|
364
|
+
external: ["react", "preact"],
|
|
365
|
+
env: "APP_PUBLIC_*"
|
|
366
|
+
});
|
|
367
|
+
for (const output of build.outputs) {
|
|
368
|
+
resultStr += await output.text();
|
|
369
|
+
}
|
|
370
|
+
const r = /export\{([a-zA-Z]+) as default\}/g;
|
|
371
|
+
const matchExport = r.exec(resultStr);
|
|
372
|
+
const jsId = md5(resultStr);
|
|
373
|
+
if (!matchExport) {
|
|
374
|
+
throw new Error("File does not have a default export! Ensure a function has export default to use this.");
|
|
375
|
+
}
|
|
376
|
+
const fn = matchExport[1];
|
|
377
|
+
let _mounted = false;
|
|
378
|
+
return (props) => {
|
|
379
|
+
if (!_mounted) {
|
|
380
|
+
_mounted = true;
|
|
381
|
+
resultStr += `render(h(${fn}, ${JSON.stringify(props)}), document.getElementById("${jsId}"));`;
|
|
382
|
+
}
|
|
383
|
+
return html.raw(`<div id="${jsId}"></div><script type="module" data-source-id="${jsId}">${resultStr}</script>`);
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
export {
|
|
387
|
+
hyperspanStyleTags,
|
|
388
|
+
hyperspanScriptTags,
|
|
389
|
+
createPreactIsland,
|
|
390
|
+
clientJSFiles,
|
|
391
|
+
clientCSSFiles,
|
|
392
|
+
buildClientJS,
|
|
393
|
+
buildClientCSS
|
|
394
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// Generated by dts-bundle-generator v9.5.1
|
|
2
|
+
|
|
3
|
+
import { TmplHtml } from '@hyperspan/html';
|
|
4
|
+
import { Context, Handler, Hono } from 'hono';
|
|
5
|
+
|
|
6
|
+
export declare const IS_PROD: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Route
|
|
9
|
+
* Define a route that can handle a direct HTTP request
|
|
10
|
+
* Route handlers should return a Response or TmplHtml object
|
|
11
|
+
*/
|
|
12
|
+
export declare function createRoute(handler: Handler): HSRoute;
|
|
13
|
+
/**
|
|
14
|
+
* Component
|
|
15
|
+
* Define a component or partial with an optional loading placeholder
|
|
16
|
+
* These can be rendered anywhere inside other templates - even if async.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createComponent(render: () => THSComponentReturn | Promise<THSComponentReturn>): HSComponent;
|
|
19
|
+
/**
|
|
20
|
+
* Form + route handler
|
|
21
|
+
* Automatically handles and parses form data
|
|
22
|
+
*
|
|
23
|
+
* INITIAL IDEA OF HOW THIS WILL WORK:
|
|
24
|
+
* ---
|
|
25
|
+
* 1. Renders component as initial form markup for GET request
|
|
26
|
+
* 2. Bind form onSubmit function to custom client JS handling
|
|
27
|
+
* 3. Submits form with JavaScript fetch()
|
|
28
|
+
* 4. Replaces form content with content from server
|
|
29
|
+
* 5. All validation and save logic is on the server
|
|
30
|
+
* 6. Handles any Exception thrown on server as error displayed in client
|
|
31
|
+
*/
|
|
32
|
+
export declare function createForm(renderForm: (data?: any) => THSResponseTypes, schema?: z.ZodSchema | null): HSFormRoute;
|
|
33
|
+
/**
|
|
34
|
+
* Types
|
|
35
|
+
*/
|
|
36
|
+
export type THSComponentReturn = TmplHtml | string | number | null;
|
|
37
|
+
export type THSResponseTypes = TmplHtml | Response | string | null;
|
|
38
|
+
export declare const HS_DEFAULT_LOADING: () => TmplHtml;
|
|
39
|
+
/**
|
|
40
|
+
* Route handler helper
|
|
41
|
+
*/
|
|
42
|
+
export declare class HSComponent {
|
|
43
|
+
_kind: string;
|
|
44
|
+
_handlers: Record<string, Handler>;
|
|
45
|
+
_loading?: () => TmplHtml;
|
|
46
|
+
render: () => THSComponentReturn | Promise<THSComponentReturn>;
|
|
47
|
+
constructor(render: () => THSComponentReturn | Promise<THSComponentReturn>);
|
|
48
|
+
loading(fn: () => TmplHtml): this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Route handler helper
|
|
52
|
+
*/
|
|
53
|
+
export declare class HSRoute {
|
|
54
|
+
_kind: string;
|
|
55
|
+
_handlers: Record<string, Handler>;
|
|
56
|
+
_methods: null | string[];
|
|
57
|
+
constructor(handler: Handler);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Form route handler helper
|
|
61
|
+
*/
|
|
62
|
+
export type THSFormRenderer = (data?: any) => THSResponseTypes;
|
|
63
|
+
export declare class HSFormRoute {
|
|
64
|
+
_kind: string;
|
|
65
|
+
_handlers: Record<string, Handler>;
|
|
66
|
+
_form: THSFormRenderer;
|
|
67
|
+
_methods: null | string[];
|
|
68
|
+
_schema: null | z.ZodSchema;
|
|
69
|
+
constructor(renderForm: THSFormRenderer, schema?: z.ZodSchema | null);
|
|
70
|
+
getDefaultData(): unknown;
|
|
71
|
+
/**
|
|
72
|
+
* Get form renderer method
|
|
73
|
+
*/
|
|
74
|
+
renderForm(data?: any): THSResponseTypes;
|
|
75
|
+
get(handler: Handler): this;
|
|
76
|
+
patch(handler: Handler): this;
|
|
77
|
+
post(handler: Handler): this;
|
|
78
|
+
put(handler: Handler): this;
|
|
79
|
+
delete(handler: Handler): this;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Run route from file
|
|
83
|
+
*/
|
|
84
|
+
export declare function runFileRoute(RouteModule: any, context: Context): Promise<Response | false>;
|
|
85
|
+
export type THSServerConfig = {
|
|
86
|
+
appDir: string;
|
|
87
|
+
staticFileRoot: string;
|
|
88
|
+
rewrites?: Array<{
|
|
89
|
+
source: string;
|
|
90
|
+
destination: string;
|
|
91
|
+
}>;
|
|
92
|
+
beforeRoutesAdded?: (app: Hono) => void;
|
|
93
|
+
afterRoutesAdded?: (app: Hono) => void;
|
|
94
|
+
};
|
|
95
|
+
export type THSRouteMap = {
|
|
96
|
+
file: string;
|
|
97
|
+
route: string;
|
|
98
|
+
params: string[];
|
|
99
|
+
};
|
|
100
|
+
export declare function buildRoutes(config: THSServerConfig): Promise<THSRouteMap[]>;
|
|
101
|
+
/**
|
|
102
|
+
* Create and start Bun HTTP server
|
|
103
|
+
*/
|
|
104
|
+
export declare function createServer(config: THSServerConfig): Promise<Hono>;
|
|
105
|
+
/**
|
|
106
|
+
* Streaming HTML Response
|
|
107
|
+
*/
|
|
108
|
+
export declare class StreamResponse extends Response {
|
|
109
|
+
constructor(iterator: AsyncIterator<unknown>, options?: {});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Does what it says on the tin...
|
|
113
|
+
*/
|
|
114
|
+
export declare function createReadableStreamFromAsyncGenerator(output: AsyncGenerator): ReadableStream<any>;
|
|
115
|
+
/**
|
|
116
|
+
* Normalize URL path
|
|
117
|
+
* Removes trailing slash and lowercases path
|
|
118
|
+
*/
|
|
119
|
+
export declare function normalizePath(urlPath: string): string;
|
|
120
|
+
|
|
121
|
+
export {};
|