@hyperspan/framework 0.1.4 → 0.1.6

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 CHANGED
@@ -1,5 +1,4 @@
1
1
  import {build} from 'bun';
2
- import dts from 'bun-plugin-dts';
3
2
 
4
3
  const entrypoints = ['./src/server.ts', './src/assets.ts'];
5
4
  const external = ['@hyperspan/html'];
@@ -7,23 +6,11 @@ const outdir = './dist';
7
6
  const target = 'node';
8
7
  const splitting = true;
9
8
 
10
- await Promise.all([
11
- // Build JS
12
- build({
13
- entrypoints,
14
- external,
15
- outdir,
16
- target,
17
- splitting,
18
- }),
19
-
20
- // Build type files for TypeScript
21
- build({
22
- entrypoints,
23
- external,
24
- outdir,
25
- target,
26
- splitting,
27
- plugins: [dts()],
28
- }),
29
- ]);
9
+ // Build JS
10
+ await build({
11
+ entrypoints,
12
+ external,
13
+ outdir,
14
+ target,
15
+ splitting,
16
+ });
package/dist/assets.js CHANGED
@@ -1,145 +1,10 @@
1
1
  // src/assets.ts
2
2
  import { html } from "@hyperspan/html";
3
-
4
- // src/clientjs/md5.js
5
- function md5cycle(x, k) {
6
- var a = x[0], b = x[1], c = x[2], d = x[3];
7
- a = ff(a, b, c, d, k[0], 7, -680876936);
8
- d = ff(d, a, b, c, k[1], 12, -389564586);
9
- c = ff(c, d, a, b, k[2], 17, 606105819);
10
- b = ff(b, c, d, a, k[3], 22, -1044525330);
11
- a = ff(a, b, c, d, k[4], 7, -176418897);
12
- d = ff(d, a, b, c, k[5], 12, 1200080426);
13
- c = ff(c, d, a, b, k[6], 17, -1473231341);
14
- b = ff(b, c, d, a, k[7], 22, -45705983);
15
- a = ff(a, b, c, d, k[8], 7, 1770035416);
16
- d = ff(d, a, b, c, k[9], 12, -1958414417);
17
- c = ff(c, d, a, b, k[10], 17, -42063);
18
- b = ff(b, c, d, a, k[11], 22, -1990404162);
19
- a = ff(a, b, c, d, k[12], 7, 1804603682);
20
- d = ff(d, a, b, c, k[13], 12, -40341101);
21
- c = ff(c, d, a, b, k[14], 17, -1502002290);
22
- b = ff(b, c, d, a, k[15], 22, 1236535329);
23
- a = gg(a, b, c, d, k[1], 5, -165796510);
24
- d = gg(d, a, b, c, k[6], 9, -1069501632);
25
- c = gg(c, d, a, b, k[11], 14, 643717713);
26
- b = gg(b, c, d, a, k[0], 20, -373897302);
27
- a = gg(a, b, c, d, k[5], 5, -701558691);
28
- d = gg(d, a, b, c, k[10], 9, 38016083);
29
- c = gg(c, d, a, b, k[15], 14, -660478335);
30
- b = gg(b, c, d, a, k[4], 20, -405537848);
31
- a = gg(a, b, c, d, k[9], 5, 568446438);
32
- d = gg(d, a, b, c, k[14], 9, -1019803690);
33
- c = gg(c, d, a, b, k[3], 14, -187363961);
34
- b = gg(b, c, d, a, k[8], 20, 1163531501);
35
- a = gg(a, b, c, d, k[13], 5, -1444681467);
36
- d = gg(d, a, b, c, k[2], 9, -51403784);
37
- c = gg(c, d, a, b, k[7], 14, 1735328473);
38
- b = gg(b, c, d, a, k[12], 20, -1926607734);
39
- a = hh(a, b, c, d, k[5], 4, -378558);
40
- d = hh(d, a, b, c, k[8], 11, -2022574463);
41
- c = hh(c, d, a, b, k[11], 16, 1839030562);
42
- b = hh(b, c, d, a, k[14], 23, -35309556);
43
- a = hh(a, b, c, d, k[1], 4, -1530992060);
44
- d = hh(d, a, b, c, k[4], 11, 1272893353);
45
- c = hh(c, d, a, b, k[7], 16, -155497632);
46
- b = hh(b, c, d, a, k[10], 23, -1094730640);
47
- a = hh(a, b, c, d, k[13], 4, 681279174);
48
- d = hh(d, a, b, c, k[0], 11, -358537222);
49
- c = hh(c, d, a, b, k[3], 16, -722521979);
50
- b = hh(b, c, d, a, k[6], 23, 76029189);
51
- a = hh(a, b, c, d, k[9], 4, -640364487);
52
- d = hh(d, a, b, c, k[12], 11, -421815835);
53
- c = hh(c, d, a, b, k[15], 16, 530742520);
54
- b = hh(b, c, d, a, k[2], 23, -995338651);
55
- a = ii(a, b, c, d, k[0], 6, -198630844);
56
- d = ii(d, a, b, c, k[7], 10, 1126891415);
57
- c = ii(c, d, a, b, k[14], 15, -1416354905);
58
- b = ii(b, c, d, a, k[5], 21, -57434055);
59
- a = ii(a, b, c, d, k[12], 6, 1700485571);
60
- d = ii(d, a, b, c, k[3], 10, -1894986606);
61
- c = ii(c, d, a, b, k[10], 15, -1051523);
62
- b = ii(b, c, d, a, k[1], 21, -2054922799);
63
- a = ii(a, b, c, d, k[8], 6, 1873313359);
64
- d = ii(d, a, b, c, k[15], 10, -30611744);
65
- c = ii(c, d, a, b, k[6], 15, -1560198380);
66
- b = ii(b, c, d, a, k[13], 21, 1309151649);
67
- a = ii(a, b, c, d, k[4], 6, -145523070);
68
- d = ii(d, a, b, c, k[11], 10, -1120210379);
69
- c = ii(c, d, a, b, k[2], 15, 718787259);
70
- b = ii(b, c, d, a, k[9], 21, -343485551);
71
- x[0] = add32(a, x[0]);
72
- x[1] = add32(b, x[1]);
73
- x[2] = add32(c, x[2]);
74
- x[3] = add32(d, x[3]);
75
- }
76
- function cmn(q, a, b, x, s, t) {
77
- a = add32(add32(a, q), add32(x, t));
78
- return add32(a << s | a >>> 32 - s, b);
79
- }
80
- function ff(a, b, c, d, x, s, t) {
81
- return cmn(b & c | ~b & d, a, b, x, s, t);
82
- }
83
- function gg(a, b, c, d, x, s, t) {
84
- return cmn(b & d | c & ~d, a, b, x, s, t);
85
- }
86
- function hh(a, b, c, d, x, s, t) {
87
- return cmn(b ^ c ^ d, a, b, x, s, t);
88
- }
89
- function ii(a, b, c, d, x, s, t) {
90
- return cmn(c ^ (b | ~d), a, b, x, s, t);
91
- }
92
- function md51(s) {
93
- var txt = "";
94
- var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
95
- for (i = 64;i <= s.length; i += 64) {
96
- md5cycle(state, md5blk(s.substring(i - 64, i)));
97
- }
98
- s = s.substring(i - 64);
99
- var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
100
- for (i = 0;i < s.length; i++)
101
- tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
102
- tail[i >> 2] |= 128 << (i % 4 << 3);
103
- if (i > 55) {
104
- md5cycle(state, tail);
105
- for (i = 0;i < 16; i++)
106
- tail[i] = 0;
107
- }
108
- tail[14] = n * 8;
109
- md5cycle(state, tail);
110
- return state;
111
- }
112
- function md5blk(s) {
113
- var md5blks = [], i;
114
- for (i = 0;i < 64; i += 4) {
115
- md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
116
- }
117
- return md5blks;
118
- }
119
- var hex_chr = "0123456789abcdef".split("");
120
- function rhex(n) {
121
- var s = "", j = 0;
122
- for (;j < 4; j++)
123
- s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
124
- return s;
125
- }
126
- function hex(x) {
127
- for (var i = 0;i < x.length; i++)
128
- x[i] = rhex(x[i]);
129
- return x.join("");
130
- }
131
- function add32(a, b) {
132
- return a + b & 4294967295;
133
- }
134
- function md5(s) {
135
- return hex(md51(s));
136
- }
137
-
138
- // src/assets.ts
139
3
  import { readdir } from "node:fs/promises";
140
4
  import { resolve } from "node:path";
141
5
  var IS_PROD = false;
142
6
  var PWD = import.meta.dir;
7
+ var clientImportMap = new Map;
143
8
  var clientJSFiles = new Map;
144
9
  async function buildClientJS() {
145
10
  const sourceFile = resolve(PWD, "../", "./src/clientjs/hyperspan-client.ts");
@@ -197,39 +62,11 @@ function hyperspanScriptTags() {
197
62
  ></script>`)}
198
63
  `;
199
64
  }
200
- async function createPreactIsland(file) {
201
- let filePath = file.replace("file://", "");
202
- let resultStr = 'import{h,render}from"preact";';
203
- const build = await Bun.build({
204
- entrypoints: [filePath],
205
- minify: true,
206
- external: ["react", "preact"],
207
- env: "APP_PUBLIC_*"
208
- });
209
- for (const output of build.outputs) {
210
- resultStr += await output.text();
211
- }
212
- const r = /export\{([a-zA-Z]+) as default\}/g;
213
- const matchExport = r.exec(resultStr);
214
- const jsId = md5(resultStr);
215
- if (!matchExport) {
216
- throw new Error("File does not have a default export! Ensure a function has export default to use this.");
217
- }
218
- const fn = matchExport[1];
219
- let _mounted = false;
220
- return (props) => {
221
- if (!_mounted) {
222
- _mounted = true;
223
- resultStr += `render(h(${fn}, ${JSON.stringify(props)}), document.getElementById("${jsId}"));`;
224
- }
225
- return html.raw(`<div id="${jsId}"></div><script type="module" data-source-id="${jsId}">${resultStr}</script>`);
226
- };
227
- }
228
65
  export {
229
66
  hyperspanStyleTags,
230
67
  hyperspanScriptTags,
231
- createPreactIsland,
232
68
  clientJSFiles,
69
+ clientImportMap,
233
70
  clientCSSFiles,
234
71
  buildClientJS,
235
72
  buildClientCSS
package/dist/server.js CHANGED
@@ -1931,7 +1931,7 @@ function createAPIRoute(handler) {
1931
1931
  return api;
1932
1932
  }
1933
1933
  function getRunnableRoute(route) {
1934
- if (isRouteRunnable(route)) {
1934
+ if (isRunnableRoute(route)) {
1935
1935
  return route;
1936
1936
  }
1937
1937
  const kind = typeof route;
@@ -1943,7 +1943,7 @@ function getRunnableRoute(route) {
1943
1943
  }
1944
1944
  throw new Error('Route not runnable. Use "export default createRoute()" to create a Hyperspan route.');
1945
1945
  }
1946
- function isRouteRunnable(route) {
1946
+ function isRunnableRoute(route) {
1947
1947
  return typeof route === "object" && "run" in route;
1948
1948
  }
1949
1949
  async function showErrorReponse(context, err) {
@@ -2024,8 +2024,7 @@ async function createServer(config) {
2024
2024
  const fullRouteFile = join(CWD, route.file);
2025
2025
  const routePattern = normalizePath(route.route);
2026
2026
  routeMap.push({ route: routePattern, file: route.file });
2027
- const routeModule = await import(fullRouteFile);
2028
- app.all(routePattern, createRouteFromModule(routeModule));
2027
+ app.all(routePattern, createRouteFromModule(await import(fullRouteFile)));
2029
2028
  }
2030
2029
  if (routeMap.length === 0) {
2031
2030
  app.get("/", (context) => {
@@ -2085,7 +2084,7 @@ function normalizePath(urlPath) {
2085
2084
  }
2086
2085
  export {
2087
2086
  normalizePath,
2088
- isRouteRunnable,
2087
+ isRunnableRoute,
2089
2088
  getRunnableRoute,
2090
2089
  createServer,
2091
2090
  createRouteFromModule,
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@hyperspan/framework",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Hyperspan Web Framework",
5
5
  "main": "dist/server.js",
6
+ "types": "src/server.ts",
6
7
  "public": true,
7
8
  "publishConfig": {
8
9
  "access": "public"
@@ -63,7 +64,7 @@
63
64
  "typescript": "^5.0.0"
64
65
  },
65
66
  "dependencies": {
66
- "@hyperspan/html": "^0.1.4",
67
+ "@hyperspan/html": "^0.1.5",
67
68
  "@preact/compat": "^18.3.1",
68
69
  "hono": "^4.7.4",
69
70
  "isbot": "^5.1.25",
@@ -1,16 +1,16 @@
1
1
  import z from 'zod';
2
- import { createAction, THSFormData } from './actions';
2
+ import { createAction } from './actions';
3
3
  import { describe, it, expect } from 'bun:test';
4
4
  import { html, render, type TmplHtml } from '@hyperspan/html';
5
5
  import type { Context } from 'hono';
6
6
 
7
7
  describe('createAction', () => {
8
- const formWithNameOnly = ({ data }: THSFormData) => {
8
+ const formWithNameOnly = ({ data }: { data?: { name: string } }) => {
9
9
  return html`
10
10
  <form>
11
11
  <p>
12
12
  Name:
13
- <input type="text" name="name" value="${data.name || ''}" />
13
+ <input type="text" name="name" value="${data?.name || ''}" />
14
14
  </p>
15
15
  <button type="submit">Submit</button>
16
16
  </form>
@@ -22,7 +22,7 @@ describe('createAction', () => {
22
22
  const schema = z.object({
23
23
  name: z.string(),
24
24
  });
25
- const action = createAction(schema).form(formWithNameOnly);
25
+ const action = createAction(schema, formWithNameOnly);
26
26
 
27
27
  const formResponse = render(action.render({ data: { name: 'John' } }) as TmplHtml);
28
28
  expect(formResponse).toContain('value="John"');
@@ -34,10 +34,9 @@ describe('createAction', () => {
34
34
  const schema = z.object({
35
35
  name: z.string().nonempty(),
36
36
  });
37
- const action = createAction(schema)
38
- .form(formWithNameOnly)
39
- .handler((c, { data }) => {
40
- return html`<div>Thanks for submitting the form, ${data.name}!</div>`;
37
+ const action = createAction(schema, formWithNameOnly)
38
+ .post((c, { data }) => {
39
+ return html`<div>Thanks for submitting the form, ${data?.name}!</div>`;
41
40
  })
42
41
  .error((c, { error }) => {
43
42
  return html`<div>There was an error! ${error?.message}</div>`;
@@ -68,8 +67,8 @@ describe('createAction', () => {
68
67
  });
69
68
  const action = createAction(schema)
70
69
  .form(formWithNameOnly)
71
- .handler((c, { data }) => {
72
- return html`<div>Thanks for submitting the form, ${data.name}!</div>`;
70
+ .post((c, { data }) => {
71
+ return html`<div>Thanks for submitting the form, ${data?.name}!</div>`;
73
72
  })
74
73
  .error((c, { error }) => {
75
74
  return html`<div>There was an error! ${error?.message}</div>`;
package/src/actions.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { html } from '@hyperspan/html';
1
+ import { html, TmplHtml } from '@hyperspan/html';
2
2
  import * as z from 'zod';
3
3
  import { HTTPException } from 'hono/http-exception';
4
4
 
@@ -20,21 +20,24 @@ import type { Context } from 'hono';
20
20
  */
21
21
  export interface HSAction<T extends z.ZodTypeAny> {
22
22
  _kind: string;
23
- form(renderForm: (data: z.infer<T>) => THSResponseTypes): HSAction<T>;
24
- handler(handler: (c: Context, { data }: { data: z.infer<T> }) => THSResponseTypes): HSAction<T>;
23
+ form(renderForm: ({ data }: { data?: z.infer<T> }) => TmplHtml): HSAction<T>;
24
+ post(handler: (c: Context, { data }: { data?: z.infer<T> }) => THSResponseTypes): HSAction<T>;
25
25
  error(
26
26
  handler: (
27
27
  c: Context,
28
- { data, error }: { data: z.infer<T>; error?: z.ZodError | Error }
28
+ { data, error }: { data?: z.infer<T>; error?: z.ZodError | Error }
29
29
  ) => THSResponseTypes
30
30
  ): HSAction<T>;
31
- render(props?: { data: z.infer<T>; error?: z.ZodError | Error }): THSResponseTypes;
31
+ render(props?: { data?: z.infer<T>; error?: z.ZodError | Error }): THSResponseTypes;
32
32
  run(method: 'GET' | 'POST', c: Context): Promise<THSResponseTypes>;
33
33
  }
34
34
 
35
- export function createAction<T extends z.ZodTypeAny>(schema: T | null = null) {
36
- let _handler: Parameters<HSAction<T>['handler']>[0] | null = null,
37
- _form: Parameters<HSAction<T>['form']>[0] | null = null,
35
+ export function createAction<T extends z.ZodTypeAny>(
36
+ schema: T | null = null,
37
+ form: Parameters<HSAction<T>['form']>[0] | null = null
38
+ ) {
39
+ let _handler: Parameters<HSAction<T>['post']>[0] | null = null,
40
+ _form: Parameters<HSAction<T>['form']>[0] | null = form,
38
41
  _errorHandler: Parameters<HSAction<T>['error']>[0] | null = null;
39
42
 
40
43
  const api: HSAction<T> = {
@@ -50,7 +53,7 @@ export function createAction<T extends z.ZodTypeAny>(schema: T | null = null) {
50
53
  * Returns result from form processing if successful
51
54
  * Re-renders form with data and error information otherwise
52
55
  */
53
- handler(handler) {
56
+ post(handler) {
54
57
  _handler = handler;
55
58
  return api;
56
59
  },
@@ -63,8 +66,8 @@ export function createAction<T extends z.ZodTypeAny>(schema: T | null = null) {
63
66
  /**
64
67
  * Get form renderer method
65
68
  */
66
- render(data) {
67
- const form = _form ? _form(data || { data: {} }) : null;
69
+ render(formState?: { data?: z.infer<T>; error?: z.ZodError | Error }) {
70
+ const form = _form ? _form(formState || {}) : null;
68
71
  return form ? html`<hs-action>${form}</hs-action>` : null;
69
72
  },
70
73
 
@@ -86,7 +89,7 @@ export function createAction<T extends z.ZodTypeAny>(schema: T | null = null) {
86
89
  const formData = await c.req.formData();
87
90
  const jsonData = formDataToJSON(formData);
88
91
  const schemaData = schema ? schema.safeParse(jsonData) : null;
89
- const data = schemaData?.success ? (schemaData.data as z.infer<T>) : {};
92
+ const data = schemaData?.success ? (schemaData.data as z.infer<T>) : undefined;
90
93
  let error: z.ZodError | Error | null = null;
91
94
 
92
95
  try {
@@ -95,7 +98,7 @@ export function createAction<T extends z.ZodTypeAny>(schema: T | null = null) {
95
98
  }
96
99
 
97
100
  if (!_handler) {
98
- throw new Error('Action handler not set! Every action must have a handler.');
101
+ throw new Error('Action POST handler not set! Every action must have a POST handler.');
99
102
  }
100
103
 
101
104
  return _handler(c, { data });
package/src/assets.ts CHANGED
@@ -1,11 +1,12 @@
1
1
  import { html } from '@hyperspan/html';
2
- import { md5 } from './clientjs/md5';
3
2
  import { readdir } from 'node:fs/promises';
4
3
  import { resolve } from 'node:path';
5
4
 
6
5
  const IS_PROD = process.env.NODE_ENV === 'production';
7
6
  const PWD = import.meta.dir;
8
7
 
8
+ export const clientImportMap = new Map<string, string>();
9
+
9
10
  /**
10
11
  * Build client JS for end users (minimal JS for Hyperspan to work)
11
12
  */
@@ -94,49 +95,3 @@ export function hyperspanScriptTags() {
94
95
  )}
95
96
  `;
96
97
  }
97
-
98
- /**
99
- * Return a Preact component, mounted as an island in a <script> tag so it can be embedded into the page response.
100
- */
101
- export async function createPreactIsland(file: string) {
102
- let filePath = file.replace('file://', '');
103
-
104
- let resultStr = 'import{h,render}from"preact";';
105
- const build = await Bun.build({
106
- entrypoints: [filePath],
107
- minify: true,
108
- external: ['react', 'preact'],
109
- // @ts-ignore
110
- env: 'APP_PUBLIC_*', // Inlines any ENV that starts with 'APP_PUBLIC_'
111
- });
112
-
113
- for (const output of build.outputs) {
114
- resultStr += await output.text(); // string
115
- }
116
-
117
- // Find default export - this is our component
118
- const r = /export\{([a-zA-Z]+) as default\}/g;
119
- const matchExport = r.exec(resultStr);
120
- const jsId = md5(resultStr);
121
-
122
- if (!matchExport) {
123
- throw new Error(
124
- 'File does not have a default export! Ensure a function has export default to use this.'
125
- );
126
- }
127
-
128
- // Preact render/mount component
129
- const fn = matchExport[1];
130
- let _mounted = false;
131
-
132
- // Return HTML that will embed this component
133
- return (props: any) => {
134
- if (!_mounted) {
135
- _mounted = true;
136
- resultStr += `render(h(${fn}, ${JSON.stringify(props)}), document.getElementById("${jsId}"));`;
137
- }
138
- return html.raw(
139
- `<div id="${jsId}"></div><script type="module" data-source-id="${jsId}">${resultStr}</script>`
140
- );
141
- };
142
- }
package/src/server.ts CHANGED
@@ -3,11 +3,9 @@ import { basename, extname, join } from 'node:path';
3
3
  import { TmplHtml, html, renderStream, renderAsync, render } from '@hyperspan/html';
4
4
  import { isbot } from 'isbot';
5
5
  import { buildClientJS, buildClientCSS } from './assets';
6
- import { Hono } from 'hono';
6
+ import { Hono, type Context } from 'hono';
7
7
  import { serveStatic } from 'hono/bun';
8
- import type { Context, Handler } from 'hono';
9
8
  import { HTTPException } from 'hono/http-exception';
10
- import { create } from 'node:domain';
11
9
 
12
10
  export const IS_PROD = process.env.NODE_ENV === 'production';
13
11
  const CWD = process.cwd();
@@ -18,19 +16,28 @@ const CWD = process.cwd();
18
16
  export type THSResponseTypes = TmplHtml | Response | string | null;
19
17
  export type THSRouteHandler = (context: Context) => THSResponseTypes | Promise<THSResponseTypes>;
20
18
 
19
+ export type THSRoute = {
20
+ _kind: 'hsRoute';
21
+ get: (handler: THSRouteHandler) => THSRoute;
22
+ post: (handler: THSRouteHandler) => THSRoute;
23
+ put: (handler: THSRouteHandler) => THSRoute;
24
+ delete: (handler: THSRouteHandler) => THSRoute;
25
+ patch: (handler: THSRouteHandler) => THSRoute;
26
+ run: (method: string, context: Context) => Promise<Response>;
27
+ };
28
+
21
29
  /**
22
- * Route
23
- * Define a route that can handle a direct HTTP request
24
- * Route handlers should return a Response or TmplHtml object
30
+ * Define a route that can handle a direct HTTP request.
31
+ * Route handlers should return a TmplHtml or Response object
25
32
  */
26
- export function createRoute(handler?: THSRouteHandler) {
33
+ export function createRoute(handler?: THSRouteHandler): THSRoute {
27
34
  let _handlers: Record<string, THSRouteHandler> = {};
28
35
 
29
36
  if (handler) {
30
37
  _handlers['GET'] = handler;
31
38
  }
32
39
 
33
- const api = {
40
+ const api: THSRoute = {
34
41
  _kind: 'hsRoute',
35
42
  get(handler: THSRouteHandler) {
36
43
  _handlers['GET'] = handler;
@@ -95,20 +102,19 @@ export function createRoute(handler?: THSRouteHandler) {
95
102
 
96
103
  return api;
97
104
  }
98
- export type THSRoute = ReturnType<typeof createRoute>;
99
105
 
100
106
  /**
101
107
  * Create new API Route
102
108
  * API Route handlers should return a JSON object or a Response
103
109
  */
104
- export function createAPIRoute(handler?: THSRouteHandler) {
110
+ export function createAPIRoute(handler?: THSRouteHandler): THSRoute {
105
111
  let _handlers: Record<string, THSRouteHandler> = {};
106
112
 
107
113
  if (handler) {
108
114
  _handlers['GET'] = handler;
109
115
  }
110
116
 
111
- const api = {
117
+ const api: THSRoute = {
112
118
  _kind: 'hsRoute',
113
119
  get(handler: THSRouteHandler) {
114
120
  _handlers['GET'] = handler;
@@ -168,7 +174,6 @@ export function createAPIRoute(handler?: THSRouteHandler) {
168
174
 
169
175
  return api;
170
176
  }
171
- export type THSAPIRoute = ReturnType<typeof createAPIRoute>;
172
177
 
173
178
  /**
174
179
  * Get a Hyperspan runnable route from a module import
@@ -176,7 +181,7 @@ export type THSAPIRoute = ReturnType<typeof createAPIRoute>;
176
181
  */
177
182
  export function getRunnableRoute(route: unknown): THSRoute {
178
183
  // Runnable already? Just return it
179
- if (isRouteRunnable(route)) {
184
+ if (isRunnableRoute(route)) {
180
185
  return route as THSRoute;
181
186
  }
182
187
 
@@ -199,7 +204,7 @@ export function getRunnableRoute(route: unknown): THSRoute {
199
204
  );
200
205
  }
201
206
 
202
- export function isRouteRunnable(route: unknown): boolean {
207
+ export function isRunnableRoute(route: unknown): boolean {
203
208
  // @ts-ignore
204
209
  return typeof route === 'object' && 'run' in route;
205
210
  }
@@ -337,9 +342,7 @@ export async function createServer(config: THSServerConfig): Promise<Hono> {
337
342
  routeMap.push({ route: routePattern, file: route.file });
338
343
 
339
344
  // Import route
340
- const routeModule = await import(fullRouteFile);
341
-
342
- app.all(routePattern, createRouteFromModule(routeModule));
345
+ app.all(routePattern, createRouteFromModule(await import(fullRouteFile)));
343
346
  }
344
347
 
345
348
  // Help route if no routes found
package/dist/assets.d.ts DELETED
@@ -1,46 +0,0 @@
1
- // Generated by dts-bundle-generator v9.5.1
2
-
3
- declare class TmplHtml {
4
- _kind: string;
5
- content: string;
6
- asyncContent: Array<{
7
- id: string;
8
- promise: Promise<{
9
- id: string;
10
- value: unknown;
11
- }>;
12
- }>;
13
- constructor(props: Pick<TmplHtml, "content" | "asyncContent">);
14
- }
15
- /**
16
- * Build client JS for end users (minimal JS for Hyperspan to work)
17
- */
18
- export declare const clientJSFiles: Map<string, {
19
- src: string;
20
- type?: string;
21
- }>;
22
- export declare function buildClientJS(): Promise<void>;
23
- /**
24
- * Find client CSS file built for end users
25
- * @TODO: Build this in code here vs. relying on tailwindcss CLI tool from package scripts
26
- */
27
- export declare const clientCSSFiles: Map<string, string>;
28
- export declare function buildClientCSS(): Promise<string | undefined>;
29
- /**
30
- * Output HTML style tag for Hyperspan app
31
- */
32
- export declare function hyperspanStyleTags(): TmplHtml;
33
- /**
34
- * Output HTML script tag for Hyperspan app
35
- * Required for functioning streaming so content can pop into place properly once ready
36
- */
37
- export declare function hyperspanScriptTags(): TmplHtml;
38
- /**
39
- * Return a Preact component, mounted as an island in a <script> tag so it can be embedded into the page response.
40
- */
41
- export declare function createPreactIsland(file: string): Promise<(props: any) => {
42
- _kind: string;
43
- content: string;
44
- }>;
45
-
46
- export {};
package/dist/server.d.ts DELETED
@@ -1,98 +0,0 @@
1
- // Generated by dts-bundle-generator v9.5.1
2
-
3
- import { Context, Hono } from 'hono';
4
-
5
- declare class TmplHtml {
6
- _kind: string;
7
- content: string;
8
- asyncContent: Array<{
9
- id: string;
10
- promise: Promise<{
11
- id: string;
12
- value: unknown;
13
- }>;
14
- }>;
15
- constructor(props: Pick<TmplHtml, "content" | "asyncContent">);
16
- }
17
- export declare const IS_PROD: boolean;
18
- /**
19
- * Types
20
- */
21
- export type THSResponseTypes = TmplHtml | Response | string | null;
22
- export type THSRouteHandler = (context: Context) => THSResponseTypes | Promise<THSResponseTypes>;
23
- /**
24
- * Route
25
- * Define a route that can handle a direct HTTP request
26
- * Route handlers should return a Response or TmplHtml object
27
- */
28
- export declare function createRoute(handler?: THSRouteHandler): {
29
- _kind: string;
30
- get(handler: THSRouteHandler): any;
31
- post(handler: THSRouteHandler): any;
32
- put(handler: THSRouteHandler): any;
33
- delete(handler: THSRouteHandler): any;
34
- patch(handler: THSRouteHandler): any;
35
- run(method: string, context: Context): Promise<Response>;
36
- };
37
- export type THSRoute = ReturnType<typeof createRoute>;
38
- /**
39
- * Create new API Route
40
- * API Route handlers should return a JSON object or a Response
41
- */
42
- export declare function createAPIRoute(handler?: THSRouteHandler): {
43
- _kind: string;
44
- get(handler: THSRouteHandler): any;
45
- post(handler: THSRouteHandler): any;
46
- put(handler: THSRouteHandler): any;
47
- delete(handler: THSRouteHandler): any;
48
- patch(handler: THSRouteHandler): any;
49
- run(method: string, context: Context): Promise<Response>;
50
- };
51
- export type THSAPIRoute = ReturnType<typeof createAPIRoute>;
52
- /**
53
- * Get a Hyperspan runnable route from a module import
54
- * @throws Error if no runnable route found
55
- */
56
- export declare function getRunnableRoute(route: unknown): THSRoute;
57
- export declare function isRouteRunnable(route: unknown): boolean;
58
- export type THSServerConfig = {
59
- appDir: string;
60
- staticFileRoot: string;
61
- rewrites?: Array<{
62
- source: string;
63
- destination: string;
64
- }>;
65
- beforeRoutesAdded?: (app: Hono) => void;
66
- afterRoutesAdded?: (app: Hono) => void;
67
- };
68
- export type THSRouteMap = {
69
- file: string;
70
- route: string;
71
- params: string[];
72
- };
73
- export declare function buildRoutes(config: THSServerConfig): Promise<THSRouteMap[]>;
74
- /**
75
- * Run route from file
76
- */
77
- export declare function createRouteFromModule(RouteModule: any): (context: Context) => Promise<Response>;
78
- /**
79
- * Create and start Bun HTTP server
80
- */
81
- export declare function createServer(config: THSServerConfig): Promise<Hono>;
82
- /**
83
- * Streaming HTML Response
84
- */
85
- export declare class StreamResponse extends Response {
86
- constructor(iterator: AsyncIterator<unknown>, options?: {});
87
- }
88
- /**
89
- * Does what it says on the tin...
90
- */
91
- export declare function createReadableStreamFromAsyncGenerator(output: AsyncGenerator): ReadableStream<any>;
92
- /**
93
- * Normalize URL path
94
- * Removes trailing slash and lowercases path
95
- */
96
- export declare function normalizePath(urlPath: string): string;
97
-
98
- export {};