honox 0.0.0 → 0.0.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/LICENSE +21 -0
- package/README.md +629 -0
- package/dist/client/client.d.ts +11 -0
- package/dist/client/client.js +32 -0
- package/dist/client/index.d.ts +2 -0
- package/dist/client/index.js +4 -0
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +6 -0
- package/dist/factory/factory.d.ts +19 -0
- package/dist/factory/factory.js +11 -0
- package/dist/factory/index.d.ts +3 -0
- package/dist/factory/index.js +5 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +0 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +4 -0
- package/dist/server/server.d.ts +32 -0
- package/dist/server/server.js +124 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.js +0 -0
- package/dist/utils/file.d.ts +7 -0
- package/dist/utils/file.js +77 -0
- package/dist/vite/index.d.ts +15 -0
- package/dist/vite/index.js +39 -0
- package/dist/vite/island-components.d.ts +6 -0
- package/dist/vite/island-components.js +128 -0
- package/package.json +114 -4
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as hono_types from 'hono/types';
|
|
2
|
+
import * as hono from 'hono';
|
|
3
|
+
import { Env, Hono } from 'hono';
|
|
4
|
+
|
|
5
|
+
declare const createRoute: {
|
|
6
|
+
<I extends hono.Input = {}>(handler1: hono_types.H<Env, any, I>): [hono_types.H<Env, any, I>];
|
|
7
|
+
<I_1 extends hono.Input = {}, I2 extends hono.Input = I_1, R extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_1, R>, handler2: hono_types.H<Env, any, I2, R>): [hono_types.H<Env, any, I_1, R>, hono_types.H<Env, any, I2, R>];
|
|
8
|
+
<I_2 extends hono.Input = {}, I2_1 extends hono.Input = I_2, I3 extends hono.Input = I_2 & I2_1, R_1 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_2, R_1>, handler2: hono_types.H<Env, any, I2_1, R_1>, handler3: hono_types.H<Env, any, I3, R_1>): [hono_types.H<Env, any, I_2, R_1>, hono_types.H<Env, any, I2_1, R_1>, hono_types.H<Env, any, I3, R_1>];
|
|
9
|
+
<I_3 extends hono.Input = {}, I2_2 extends hono.Input = I_3, I3_1 extends hono.Input = I_3 & I2_2, I4 extends hono.Input = I_3 & I2_2 & I3_1, R_2 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_3, R_2>, handler2: hono_types.H<Env, any, I2_2, R_2>, handler3: hono_types.H<Env, any, I3_1, R_2>, handler4: hono_types.H<Env, any, I4, R_2>): [hono_types.H<Env, any, I_3, R_2>, hono_types.H<Env, any, I2_2, R_2>, hono_types.H<Env, any, I3_1, R_2>, hono_types.H<Env, any, I4, R_2>];
|
|
10
|
+
<I_4 extends hono.Input = {}, I2_3 extends hono.Input = I_4, I3_2 extends hono.Input = I_4 & I2_3, I4_1 extends hono.Input = I_4 & I2_3 & I3_2, I5 extends hono.Input = I_4 & I2_3 & I3_2 & I4_1, R_3 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_4, R_3>, handler2: hono_types.H<Env, any, I2_3, R_3>, handler3: hono_types.H<Env, any, I3_2, R_3>, handler4: hono_types.H<Env, any, I4_1, R_3>, handler5: hono_types.H<Env, any, I5, R_3>): [hono_types.H<Env, any, I_4, R_3>, hono_types.H<Env, any, I2_3, R_3>, hono_types.H<Env, any, I3_2, R_3>, hono_types.H<Env, any, I4_1, R_3>, hono_types.H<Env, any, I5, R_3>];
|
|
11
|
+
<I_5 extends hono.Input = {}, I2_4 extends hono.Input = I_5, I3_3 extends hono.Input = I_5 & I2_4, I4_2 extends hono.Input = I_5 & I2_4 & I3_3, I5_1 extends hono.Input = I_5 & I2_4 & I3_3 & I4_2, I6 extends hono.Input = I_5 & I2_4 & I3_3 & I4_2 & I5_1, R_4 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_5, R_4>, handler2: hono_types.H<Env, any, I2_4, R_4>, handler3: hono_types.H<Env, any, I3_3, R_4>, handler4: hono_types.H<Env, any, I4_2, R_4>, handler5: hono_types.H<Env, any, I5_1, R_4>, handler6: hono_types.H<Env, any, I6, R_4>): [hono_types.H<Env, any, I_5, R_4>, hono_types.H<Env, any, I2_4, R_4>, hono_types.H<Env, any, I3_3, R_4>, hono_types.H<Env, any, I4_2, R_4>, hono_types.H<Env, any, I5_1, R_4>, hono_types.H<Env, any, I6, R_4>];
|
|
12
|
+
<I_6 extends hono.Input = {}, I2_5 extends hono.Input = I_6, I3_4 extends hono.Input = I_6 & I2_5, I4_3 extends hono.Input = I_6 & I2_5 & I3_4, I5_2 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3, I6_1 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3 & I5_2, I7 extends hono.Input = I_6 & I2_5 & I3_4 & I4_3 & I5_2 & I6_1, R_5 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_6, R_5>, handler2: hono_types.H<Env, any, I2_5, R_5>, handler3: hono_types.H<Env, any, I3_4, R_5>, handler4: hono_types.H<Env, any, I4_3, R_5>, handler5: hono_types.H<Env, any, I5_2, R_5>, handler6: hono_types.H<Env, any, I6_1, R_5>, handler7: hono_types.H<Env, any, I7, R_5>): [hono_types.H<Env, any, I_6, R_5>, hono_types.H<Env, any, I2_5, R_5>, hono_types.H<Env, any, I3_4, R_5>, hono_types.H<Env, any, I4_3, R_5>, hono_types.H<Env, any, I5_2, R_5>, hono_types.H<Env, any, I6_1, R_5>, hono_types.H<Env, any, I7, R_5>];
|
|
13
|
+
<I_7 extends hono.Input = {}, I2_6 extends hono.Input = I_7, I3_5 extends hono.Input = I_7 & I2_6, I4_4 extends hono.Input = I_7 & I2_6 & I3_5, I5_3 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4, I6_2 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3, I7_1 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3 & I6_2, I8 extends hono.Input = I_7 & I2_6 & I3_5 & I4_4 & I5_3 & I6_2 & I7_1, R_6 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_7, R_6>, handler2: hono_types.H<Env, any, I2_6, R_6>, handler3: hono_types.H<Env, any, I3_5, R_6>, handler4: hono_types.H<Env, any, I4_4, R_6>, handler5: hono_types.H<Env, any, I5_3, R_6>, handler6: hono_types.H<Env, any, I6_2, R_6>, handler7: hono_types.H<Env, any, I7_1, R_6>, handler8: hono_types.H<Env, any, I8, R_6>): [hono_types.H<Env, any, I_7, R_6>, hono_types.H<Env, any, I2_6, R_6>, hono_types.H<Env, any, I3_5, R_6>, hono_types.H<Env, any, I4_4, R_6>, hono_types.H<Env, any, I5_3, R_6>, hono_types.H<Env, any, I6_2, R_6>, hono_types.H<Env, any, I7_1, R_6>, hono_types.H<Env, any, I8, R_6>];
|
|
14
|
+
<I_8 extends hono.Input = {}, I2_7 extends hono.Input = I_8, I3_6 extends hono.Input = I_8 & I2_7, I4_5 extends hono.Input = I_8 & I2_7 & I3_6, I5_4 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5, I6_3 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4, I7_2 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3, I8_1 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3 & I7_2, I9 extends hono.Input = I_8 & I2_7 & I3_6 & I4_5 & I5_4 & I6_3 & I7_2 & I8_1, R_7 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_8, R_7>, handler2: hono_types.H<Env, any, I2_7, R_7>, handler3: hono_types.H<Env, any, I3_6, R_7>, handler4: hono_types.H<Env, any, I4_5, R_7>, handler5: hono_types.H<Env, any, I5_4, R_7>, handler6: hono_types.H<Env, any, I6_3, R_7>, handler7: hono_types.H<Env, any, I7_2, R_7>, handler8: hono_types.H<Env, any, I8_1, R_7>, handler9: hono_types.H<Env, any, I9, R_7>): [hono_types.H<Env, any, I_8, R_7>, hono_types.H<Env, any, I2_7, R_7>, hono_types.H<Env, any, I3_6, R_7>, hono_types.H<Env, any, I4_5, R_7>, hono_types.H<Env, any, I5_4, R_7>, hono_types.H<Env, any, I6_3, R_7>, hono_types.H<Env, any, I7_2, R_7>, hono_types.H<Env, any, I8_1, R_7>, hono_types.H<Env, any, I9, R_7>];
|
|
15
|
+
<I_9 extends hono.Input = {}, I2_8 extends hono.Input = I_9, I3_7 extends hono.Input = I_9 & I2_8, I4_6 extends hono.Input = I_9 & I2_8 & I3_7, I5_5 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6, I6_4 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5, I7_3 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4, I8_2 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3, I9_1 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3 & I8_2, I10 extends hono.Input = I_9 & I2_8 & I3_7 & I4_6 & I5_5 & I6_4 & I7_3 & I8_2 & I9_1, R_8 extends hono_types.HandlerResponse<any> = any>(handler1: hono_types.H<Env, any, I_9, R_8>, handler2: hono_types.H<Env, any, I2_8, R_8>, handler3: hono_types.H<Env, any, I3_7, R_8>, handler4: hono_types.H<Env, any, I4_6, R_8>, handler5: hono_types.H<Env, any, I5_5, R_8>, handler6: hono_types.H<Env, any, I6_4, R_8>, handler7: hono_types.H<Env, any, I7_3, R_8>, handler8: hono_types.H<Env, any, I8_2, R_8>, handler9: hono_types.H<Env, any, I9_1, R_8>, handler10: hono_types.H<Env, any, I10, R_8>): [hono_types.H<Env, any, I_9, R_8>, hono_types.H<Env, any, I2_8, R_8>, hono_types.H<Env, any, I3_7, R_8>, hono_types.H<Env, any, I4_6, R_8>, hono_types.H<Env, any, I5_5, R_8>, hono_types.H<Env, any, I6_4, R_8>, hono_types.H<Env, any, I7_3, R_8>, hono_types.H<Env, any, I8_2, R_8>, hono_types.H<Env, any, I9_1, R_8>, hono_types.H<Env, any, I10, R_8>];
|
|
16
|
+
};
|
|
17
|
+
declare const createHono: () => Hono<Env, hono_types.BlankSchema, "/">;
|
|
18
|
+
|
|
19
|
+
export { createHono, createRoute };
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as hono_types from 'hono/types';
|
|
2
|
+
import { H } from 'hono/types';
|
|
3
|
+
import { Env, Hono, MiddlewareHandler, NotFoundHandler, ErrorHandler } from 'hono';
|
|
4
|
+
|
|
5
|
+
declare const METHODS: readonly ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"];
|
|
6
|
+
type RouteFile = {
|
|
7
|
+
default?: Function;
|
|
8
|
+
} & {
|
|
9
|
+
[M in (typeof METHODS)[number]]?: H[];
|
|
10
|
+
};
|
|
11
|
+
type RendererFile = {
|
|
12
|
+
default: MiddlewareHandler;
|
|
13
|
+
};
|
|
14
|
+
type NotFoundFile = {
|
|
15
|
+
default: NotFoundHandler;
|
|
16
|
+
};
|
|
17
|
+
type ErrorFile = {
|
|
18
|
+
default: ErrorHandler;
|
|
19
|
+
};
|
|
20
|
+
type InitFunction<E extends Env = Env> = (app: Hono<E>) => void;
|
|
21
|
+
type ServerOptions<E extends Env = Env> = {
|
|
22
|
+
ROUTES?: Record<string, RouteFile>;
|
|
23
|
+
RENDERER?: Record<string, RendererFile>;
|
|
24
|
+
NOT_FOUND?: Record<string, NotFoundFile>;
|
|
25
|
+
ERROR?: Record<string, ErrorFile>;
|
|
26
|
+
root?: string;
|
|
27
|
+
app?: Hono<E>;
|
|
28
|
+
init?: InitFunction<E>;
|
|
29
|
+
};
|
|
30
|
+
declare const createApp: <E extends Env>(options?: ServerOptions<E> | undefined) => Hono<E, hono_types.BlankSchema, "/">;
|
|
31
|
+
|
|
32
|
+
export { type ServerOptions, createApp };
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import {
|
|
3
|
+
filePathToPath,
|
|
4
|
+
groupByDirectory,
|
|
5
|
+
listByDirectory,
|
|
6
|
+
pathToDirectoryPath,
|
|
7
|
+
sortDirectoriesByDepth
|
|
8
|
+
} from "../utils/file.js";
|
|
9
|
+
const NOTFOUND_FILENAME = "_404.tsx";
|
|
10
|
+
const ERROR_FILENAME = "_error.tsx";
|
|
11
|
+
const METHODS = ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"];
|
|
12
|
+
const createApp = (options) => {
|
|
13
|
+
const root = options?.root ?? "/app/routes";
|
|
14
|
+
const rootRegExp = new RegExp(`^${root}`);
|
|
15
|
+
const app = options?.app ?? new Hono();
|
|
16
|
+
if (options?.init) {
|
|
17
|
+
options.init(app);
|
|
18
|
+
}
|
|
19
|
+
const NOT_FOUND_FILE = options?.NOT_FOUND ?? import.meta.glob("/app/routes/**/_404.(ts|tsx)", {
|
|
20
|
+
eager: true
|
|
21
|
+
});
|
|
22
|
+
const notFoundMap = groupByDirectory(NOT_FOUND_FILE);
|
|
23
|
+
const ERROR_FILE = options?.ERROR ?? import.meta.glob("/app/routes/**/_error.(ts|tsx)", {
|
|
24
|
+
eager: true
|
|
25
|
+
});
|
|
26
|
+
const errorMap = groupByDirectory(ERROR_FILE);
|
|
27
|
+
const RENDERER_FILE = options?.RENDERER ?? import.meta.glob("/app/routes/**/_renderer.tsx", {
|
|
28
|
+
eager: true
|
|
29
|
+
});
|
|
30
|
+
const rendererList = listByDirectory(RENDERER_FILE);
|
|
31
|
+
const applyRenderer = (rendererFile) => {
|
|
32
|
+
const renderer = RENDERER_FILE[rendererFile];
|
|
33
|
+
const path = pathToDirectoryPath(rendererFile).replace(rootRegExp, "");
|
|
34
|
+
app.all(`${filePathToPath(path)}*`, renderer.default);
|
|
35
|
+
};
|
|
36
|
+
const ROUTES_FILE = options?.ROUTES ?? import.meta.glob("/app/routes/**/[!_]*.(ts|tsx|mdx)", {
|
|
37
|
+
eager: true
|
|
38
|
+
});
|
|
39
|
+
const routesMap = sortDirectoriesByDepth(groupByDirectory(ROUTES_FILE));
|
|
40
|
+
for (const map of routesMap) {
|
|
41
|
+
for (const [dir, content] of Object.entries(map)) {
|
|
42
|
+
const subApp = new Hono();
|
|
43
|
+
let rendererFiles = rendererList[dir];
|
|
44
|
+
if (rendererFiles) {
|
|
45
|
+
applyRenderer(rendererFiles[0]);
|
|
46
|
+
}
|
|
47
|
+
if (!rendererFiles) {
|
|
48
|
+
const dirPaths = dir.split("/");
|
|
49
|
+
const getRendererPaths = (paths) => {
|
|
50
|
+
rendererFiles = rendererList[paths.join("/")];
|
|
51
|
+
if (!rendererFiles) {
|
|
52
|
+
paths.pop();
|
|
53
|
+
if (paths.length) {
|
|
54
|
+
getRendererPaths(paths);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return rendererFiles;
|
|
58
|
+
};
|
|
59
|
+
rendererFiles = getRendererPaths(dirPaths);
|
|
60
|
+
if (rendererFiles) {
|
|
61
|
+
applyRenderer(rendererFiles[0]);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
let rootPath = dir.replace(rootRegExp, "");
|
|
65
|
+
rootPath = filePathToPath(rootPath);
|
|
66
|
+
for (const [filename, route] of Object.entries(content)) {
|
|
67
|
+
const routeDefault = route.default;
|
|
68
|
+
const path = filePathToPath(filename);
|
|
69
|
+
if (routeDefault && "fetch" in routeDefault) {
|
|
70
|
+
subApp.route(path, routeDefault);
|
|
71
|
+
}
|
|
72
|
+
for (const m of METHODS) {
|
|
73
|
+
const handlers = route[m];
|
|
74
|
+
if (handlers) {
|
|
75
|
+
subApp.on(m, path, ...handlers);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (routeDefault && Array.isArray(routeDefault)) {
|
|
79
|
+
subApp.get(path, ...routeDefault);
|
|
80
|
+
}
|
|
81
|
+
if (typeof routeDefault === "function") {
|
|
82
|
+
subApp.get(path, (c) => {
|
|
83
|
+
return c.render(routeDefault(), route);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
applyNotFound(subApp, dir, notFoundMap);
|
|
88
|
+
applyError(subApp, dir, errorMap);
|
|
89
|
+
app.route(rootPath, subApp);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return app;
|
|
93
|
+
};
|
|
94
|
+
function applyNotFound(app, dir, map) {
|
|
95
|
+
for (const [mapDir, content] of Object.entries(map)) {
|
|
96
|
+
if (dir === mapDir) {
|
|
97
|
+
const notFound = content[NOTFOUND_FILENAME];
|
|
98
|
+
if (notFound) {
|
|
99
|
+
const notFoundHandler = notFound.default;
|
|
100
|
+
app.get("*", (c) => {
|
|
101
|
+
c.status(404);
|
|
102
|
+
return notFoundHandler(c);
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function applyError(app, dir, map) {
|
|
109
|
+
for (const [mapDir, content] of Object.entries(map)) {
|
|
110
|
+
if (dir === mapDir) {
|
|
111
|
+
const error = content[ERROR_FILENAME];
|
|
112
|
+
if (error) {
|
|
113
|
+
const errorHandler = error.default;
|
|
114
|
+
app.onError((error2, c) => {
|
|
115
|
+
c.status(500);
|
|
116
|
+
return errorHandler(error2, c);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
createApp
|
|
124
|
+
};
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
File without changes
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
declare const filePathToPath: (filePath: string) => string;
|
|
2
|
+
declare const groupByDirectory: <T = unknown>(files: Record<string, T>) => Record<string, Record<string, T>>;
|
|
3
|
+
declare const sortDirectoriesByDepth: <T>(directories: Record<string, T>) => Record<string, T>[];
|
|
4
|
+
declare const listByDirectory: <T = unknown>(files: Record<string, T>) => Record<string, string[]>;
|
|
5
|
+
declare const pathToDirectoryPath: (path: string) => string;
|
|
6
|
+
|
|
7
|
+
export { filePathToPath, groupByDirectory, listByDirectory, pathToDirectoryPath, sortDirectoriesByDepth };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const filePathToPath = (filePath) => {
|
|
2
|
+
filePath = filePath.replace(/\.tsx?$/g, "").replace(/\.mdx$/g, "").replace(/^\/?index/, "/").replace(/\/index/, "").replace(/\[\.{3}.+\]/, "*").replace(/\[(.+)\]/, ":$1");
|
|
3
|
+
return /^\//.test(filePath) ? filePath : "/" + filePath;
|
|
4
|
+
};
|
|
5
|
+
const groupByDirectory = (files) => {
|
|
6
|
+
const organizedFiles = {};
|
|
7
|
+
for (const [path, content] of Object.entries(files)) {
|
|
8
|
+
const pathParts = path.split("/");
|
|
9
|
+
const fileName = pathParts.pop();
|
|
10
|
+
const directory = pathParts.join("/");
|
|
11
|
+
if (!organizedFiles[directory]) {
|
|
12
|
+
organizedFiles[directory] = {};
|
|
13
|
+
}
|
|
14
|
+
if (fileName) {
|
|
15
|
+
organizedFiles[directory][fileName] = content;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const [directory, files2] of Object.entries(organizedFiles)) {
|
|
19
|
+
const sortedEntries = Object.entries(files2).sort(([keyA], [keyB]) => {
|
|
20
|
+
if (keyA[0] === "[" && keyB[0] !== "[") {
|
|
21
|
+
return 1;
|
|
22
|
+
}
|
|
23
|
+
if (keyA[0] !== "[" && keyB[0] === "[") {
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
return keyA.localeCompare(keyB);
|
|
27
|
+
});
|
|
28
|
+
organizedFiles[directory] = Object.fromEntries(sortedEntries);
|
|
29
|
+
}
|
|
30
|
+
return organizedFiles;
|
|
31
|
+
};
|
|
32
|
+
const sortDirectoriesByDepth = (directories) => {
|
|
33
|
+
const sortedKeys = Object.keys(directories).sort((a, b) => {
|
|
34
|
+
const depthA = a.split("/").length;
|
|
35
|
+
const depthB = b.split("/").length;
|
|
36
|
+
return depthB - depthA;
|
|
37
|
+
});
|
|
38
|
+
const sortedDirectories = sortedKeys.map((key) => {
|
|
39
|
+
return { [key]: directories[key] };
|
|
40
|
+
});
|
|
41
|
+
return sortedDirectories;
|
|
42
|
+
};
|
|
43
|
+
const listByDirectory = (files) => {
|
|
44
|
+
const organizedFiles = {};
|
|
45
|
+
for (const path of Object.keys(files)) {
|
|
46
|
+
const pathParts = path.split("/");
|
|
47
|
+
pathParts.pop();
|
|
48
|
+
const directory = pathParts.join("/");
|
|
49
|
+
if (!organizedFiles[directory]) {
|
|
50
|
+
organizedFiles[directory] = [];
|
|
51
|
+
}
|
|
52
|
+
if (!organizedFiles[directory].includes(path)) {
|
|
53
|
+
organizedFiles[directory].push(path);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const directories = Object.keys(organizedFiles).sort((a, b) => b.length - a.length);
|
|
57
|
+
for (const dir of directories) {
|
|
58
|
+
for (const subDir of directories) {
|
|
59
|
+
if (subDir.startsWith(dir) && subDir !== dir) {
|
|
60
|
+
const uniqueFiles = /* @__PURE__ */ new Set([...organizedFiles[subDir], ...organizedFiles[dir]]);
|
|
61
|
+
organizedFiles[subDir] = [...uniqueFiles];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return organizedFiles;
|
|
66
|
+
};
|
|
67
|
+
const pathToDirectoryPath = (path) => {
|
|
68
|
+
const dirPath = path.replace(/[^\/]+$/, "");
|
|
69
|
+
return dirPath;
|
|
70
|
+
};
|
|
71
|
+
export {
|
|
72
|
+
filePathToPath,
|
|
73
|
+
groupByDirectory,
|
|
74
|
+
listByDirectory,
|
|
75
|
+
pathToDirectoryPath,
|
|
76
|
+
sortDirectoriesByDepth
|
|
77
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DevServerOptions } from '@hono/vite-dev-server';
|
|
2
|
+
export { defaultOptions as devServerDefaultOptions } from '@hono/vite-dev-server';
|
|
3
|
+
import { PluginOption } from 'vite';
|
|
4
|
+
export { islandComponents } from './island-components.js';
|
|
5
|
+
|
|
6
|
+
type HonoXOptions = {
|
|
7
|
+
islands?: boolean;
|
|
8
|
+
entry?: string;
|
|
9
|
+
devServer?: DevServerOptions;
|
|
10
|
+
external?: string[];
|
|
11
|
+
};
|
|
12
|
+
declare const defaultOptions: HonoXOptions;
|
|
13
|
+
declare function honox(options?: HonoXOptions): PluginOption[];
|
|
14
|
+
|
|
15
|
+
export { honox as default, defaultOptions };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import devServer, { defaultOptions as devServerDefaultOptions } from "@hono/vite-dev-server";
|
|
3
|
+
import { islandComponents } from "./island-components.js";
|
|
4
|
+
const defaultOptions = {
|
|
5
|
+
islands: true,
|
|
6
|
+
entry: path.join(process.cwd(), "./app/server.ts")
|
|
7
|
+
};
|
|
8
|
+
function honox(options) {
|
|
9
|
+
const plugins = [];
|
|
10
|
+
const entry = options?.entry ?? defaultOptions.entry;
|
|
11
|
+
plugins.push(
|
|
12
|
+
devServer({
|
|
13
|
+
entry,
|
|
14
|
+
exclude: [
|
|
15
|
+
...devServerDefaultOptions.exclude,
|
|
16
|
+
/^\/app\/.+/,
|
|
17
|
+
/^\/favicon.ico/,
|
|
18
|
+
/^\/static\/.+/
|
|
19
|
+
],
|
|
20
|
+
...options?.devServer
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
if (options?.islands !== false) {
|
|
24
|
+
plugins.push(islandComponents());
|
|
25
|
+
}
|
|
26
|
+
return [
|
|
27
|
+
{
|
|
28
|
+
name: "honox-vite-config"
|
|
29
|
+
},
|
|
30
|
+
...plugins
|
|
31
|
+
];
|
|
32
|
+
}
|
|
33
|
+
var vite_default = honox;
|
|
34
|
+
export {
|
|
35
|
+
vite_default as default,
|
|
36
|
+
defaultOptions,
|
|
37
|
+
devServerDefaultOptions,
|
|
38
|
+
islandComponents
|
|
39
|
+
};
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import fs from "fs/promises";
|
|
2
|
+
import _generate from "@babel/generator";
|
|
3
|
+
const generate = _generate.default ?? _generate;
|
|
4
|
+
import { parse } from "@babel/parser";
|
|
5
|
+
import _traverse from "@babel/traverse";
|
|
6
|
+
const traverse = _traverse.default ?? _traverse;
|
|
7
|
+
import {
|
|
8
|
+
identifier,
|
|
9
|
+
jsxAttribute,
|
|
10
|
+
jsxClosingElement,
|
|
11
|
+
jsxElement,
|
|
12
|
+
jsxIdentifier,
|
|
13
|
+
jsxOpeningElement,
|
|
14
|
+
stringLiteral,
|
|
15
|
+
callExpression,
|
|
16
|
+
variableDeclarator,
|
|
17
|
+
variableDeclaration,
|
|
18
|
+
functionExpression,
|
|
19
|
+
blockStatement,
|
|
20
|
+
returnStatement,
|
|
21
|
+
jsxSpreadAttribute,
|
|
22
|
+
jsxExpressionContainer,
|
|
23
|
+
exportDefaultDeclaration,
|
|
24
|
+
conditionalExpression,
|
|
25
|
+
memberExpression
|
|
26
|
+
} from "@babel/types";
|
|
27
|
+
import { COMPONENT_NAME, DATA_SERIALIZED_PROPS } from "../constants.js";
|
|
28
|
+
function addSSRCheck(funcName, componentName, isAsync = false) {
|
|
29
|
+
const isSSR = memberExpression(
|
|
30
|
+
memberExpression(identifier("import"), identifier("meta")),
|
|
31
|
+
identifier("env.SSR")
|
|
32
|
+
);
|
|
33
|
+
const serializedProps = callExpression(identifier("JSON.stringify"), [identifier("props")]);
|
|
34
|
+
const ssrElement = jsxElement(
|
|
35
|
+
jsxOpeningElement(
|
|
36
|
+
jsxIdentifier("honox-island"),
|
|
37
|
+
[
|
|
38
|
+
jsxAttribute(jsxIdentifier(COMPONENT_NAME), stringLiteral(componentName)),
|
|
39
|
+
jsxAttribute(jsxIdentifier(DATA_SERIALIZED_PROPS), jsxExpressionContainer(serializedProps))
|
|
40
|
+
],
|
|
41
|
+
false
|
|
42
|
+
),
|
|
43
|
+
jsxClosingElement(jsxIdentifier("honox-island")),
|
|
44
|
+
[
|
|
45
|
+
jsxElement(
|
|
46
|
+
jsxOpeningElement(
|
|
47
|
+
jsxIdentifier(funcName),
|
|
48
|
+
[jsxSpreadAttribute(identifier("props"))],
|
|
49
|
+
false
|
|
50
|
+
),
|
|
51
|
+
jsxClosingElement(jsxIdentifier(funcName)),
|
|
52
|
+
[]
|
|
53
|
+
)
|
|
54
|
+
]
|
|
55
|
+
);
|
|
56
|
+
const clientElement = jsxElement(
|
|
57
|
+
jsxOpeningElement(jsxIdentifier(funcName), [jsxSpreadAttribute(identifier("props"))], false),
|
|
58
|
+
jsxClosingElement(jsxIdentifier(funcName)),
|
|
59
|
+
[]
|
|
60
|
+
);
|
|
61
|
+
const returnStmt = returnStatement(conditionalExpression(isSSR, ssrElement, clientElement));
|
|
62
|
+
const functionExpr = functionExpression(null, [identifier("props")], blockStatement([returnStmt]));
|
|
63
|
+
if (isAsync) {
|
|
64
|
+
functionExpr.async = true;
|
|
65
|
+
}
|
|
66
|
+
return functionExpr;
|
|
67
|
+
}
|
|
68
|
+
const transformJsxTags = (contents, componentName) => {
|
|
69
|
+
const ast = parse(contents, {
|
|
70
|
+
sourceType: "module",
|
|
71
|
+
plugins: ["typescript", "jsx"]
|
|
72
|
+
});
|
|
73
|
+
if (ast) {
|
|
74
|
+
traverse(ast, {
|
|
75
|
+
ExportDefaultDeclaration(path) {
|
|
76
|
+
if (path.node.declaration.type === "FunctionDeclaration") {
|
|
77
|
+
const functionId = path.node.declaration.id;
|
|
78
|
+
if (!functionId)
|
|
79
|
+
return;
|
|
80
|
+
const isAsync = path.node.declaration.async;
|
|
81
|
+
const originalFunctionId = identifier(functionId.name + "Original");
|
|
82
|
+
const originalFunction = functionExpression(
|
|
83
|
+
null,
|
|
84
|
+
path.node.declaration.params,
|
|
85
|
+
path.node.declaration.body
|
|
86
|
+
);
|
|
87
|
+
if (isAsync) {
|
|
88
|
+
originalFunction.async = true;
|
|
89
|
+
}
|
|
90
|
+
path.insertBefore(
|
|
91
|
+
variableDeclaration("const", [variableDeclarator(originalFunctionId, originalFunction)])
|
|
92
|
+
);
|
|
93
|
+
const wrappedFunction = addSSRCheck(originalFunctionId.name, componentName, isAsync);
|
|
94
|
+
const wrappedFunctionId = identifier("Wrapped" + functionId.name);
|
|
95
|
+
path.replaceWith(
|
|
96
|
+
variableDeclaration("const", [variableDeclarator(wrappedFunctionId, wrappedFunction)])
|
|
97
|
+
);
|
|
98
|
+
path.insertAfter(exportDefaultDeclaration(wrappedFunctionId));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
const { code } = generate(ast);
|
|
103
|
+
return code;
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
function islandComponents() {
|
|
107
|
+
return {
|
|
108
|
+
name: "transform-island-components",
|
|
109
|
+
async load(id) {
|
|
110
|
+
const match = id.match(/\/islands\/(.+?\.tsx)$/);
|
|
111
|
+
if (match) {
|
|
112
|
+
const componentName = match[1];
|
|
113
|
+
const contents = await fs.readFile(id, "utf-8");
|
|
114
|
+
const code = transformJsxTags(contents, componentName);
|
|
115
|
+
if (code) {
|
|
116
|
+
return {
|
|
117
|
+
code,
|
|
118
|
+
map: null
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
islandComponents,
|
|
127
|
+
transformJsxTags
|
|
128
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,116 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "honox",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "index.js",
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "bun typecheck && bun test:unit && bun test:integration && bun test:e2e",
|
|
8
|
+
"test:unit": "vitest --run test/unit",
|
|
9
|
+
"test:integration": "bun test:integration:api && bun test:integration:hono-jsx",
|
|
10
|
+
"test:integration:hono-jsx": "vitest run -c ./test/hono-jsx/vitest.config.ts ./test/hono-jsx/integration.test.ts",
|
|
11
|
+
"test:integration:api": "vitest run -c ./test/api/vitest.config.ts ./test/api/integration.test.ts",
|
|
12
|
+
"test:e2e": "playwright test -c ./test/hono-jsx/playwright.config.ts ./test/hono-jsx/e2e.test.ts",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
14
|
+
"build": "tsup && publint",
|
|
15
|
+
"watch": "tsup --watch",
|
|
16
|
+
"lint": "eslint src/**.ts",
|
|
17
|
+
"lint:fix": "eslint src/**.ts --fix",
|
|
18
|
+
"prerelease": "yarn test && yarn build",
|
|
19
|
+
"release": "np --no-yarn"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"import": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./types": {
|
|
30
|
+
"types": "./dist/types.d.ts",
|
|
31
|
+
"import": "./dist/types.js"
|
|
32
|
+
},
|
|
33
|
+
"./factory": {
|
|
34
|
+
"types": "./dist/factory/index.d.ts",
|
|
35
|
+
"import": "./dist/factory/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./server": {
|
|
38
|
+
"types": "./dist/server/index.d.ts",
|
|
39
|
+
"import": "./dist/server/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./client": {
|
|
42
|
+
"types": "./dist/client/index.d.ts",
|
|
43
|
+
"import": "./dist/client/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./utils/*": {
|
|
46
|
+
"types": "./dist/utils/*.d.ts",
|
|
47
|
+
"import": "./dist/utils/*.js"
|
|
48
|
+
},
|
|
49
|
+
"./vite": {
|
|
50
|
+
"types": "./dist/vite/index.d.ts",
|
|
51
|
+
"import": "./dist/vite/index.js"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"typesVersions": {
|
|
55
|
+
"*": {
|
|
56
|
+
"types": [
|
|
57
|
+
"./dist/types"
|
|
58
|
+
],
|
|
59
|
+
"factory": [
|
|
60
|
+
"./dist/factory"
|
|
61
|
+
],
|
|
62
|
+
"server": [
|
|
63
|
+
"./dist/server"
|
|
64
|
+
],
|
|
65
|
+
"client": [
|
|
66
|
+
"./dist/client"
|
|
67
|
+
],
|
|
68
|
+
"utils/*": [
|
|
69
|
+
"./dist/utils/*"
|
|
70
|
+
],
|
|
71
|
+
"vite": [
|
|
72
|
+
"./dist/vite"
|
|
73
|
+
]
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
"author": "Yusuke Wada <yusuke@kamawada.com> (https://github.com/yusukebe)",
|
|
77
|
+
"license": "MIT",
|
|
78
|
+
"repository": {
|
|
79
|
+
"type": "git",
|
|
80
|
+
"url": "https://github.com/honojs/honox.git"
|
|
81
|
+
},
|
|
82
|
+
"publishConfig": {
|
|
83
|
+
"registry": "https://registry.npmjs.org",
|
|
84
|
+
"access": "public"
|
|
85
|
+
},
|
|
86
|
+
"homepage": "https://hono.dev",
|
|
87
|
+
"dependencies": {
|
|
88
|
+
"@babel/generator": "^7.23.6",
|
|
89
|
+
"@babel/parser": "^7.23.6",
|
|
90
|
+
"@babel/traverse": "^7.23.6",
|
|
91
|
+
"@babel/types": "^7.23.6",
|
|
92
|
+
"@hono/vite-dev-server": "^0.4.1"
|
|
93
|
+
},
|
|
94
|
+
"devDependencies": {
|
|
95
|
+
"@hono/eslint-config": "^0.0.3",
|
|
96
|
+
"@mdx-js/rollup": "^3.0.0",
|
|
97
|
+
"@playwright/test": "^1.41.0",
|
|
98
|
+
"@types/babel__generator": "^7",
|
|
99
|
+
"@types/babel__traverse": "^7",
|
|
100
|
+
"@types/node": "^20.10.5",
|
|
101
|
+
"eslint": "^8.56.0",
|
|
102
|
+
"glob": "^10.3.10",
|
|
103
|
+
"hono": "4.0.0-rc.2",
|
|
104
|
+
"np": "^9.2.0",
|
|
105
|
+
"prettier": "^3.1.1",
|
|
106
|
+
"publint": "^0.2.7",
|
|
107
|
+
"tsup": "^8.0.1",
|
|
108
|
+
"typescript": "^5.3.3",
|
|
109
|
+
"vite": "^5.0.12",
|
|
110
|
+
"vitest": "^1.2.1"
|
|
111
|
+
},
|
|
112
|
+
"packageManager": "yarn@4.0.2",
|
|
113
|
+
"engines": {
|
|
114
|
+
"node": ">=18.14.1"
|
|
115
|
+
}
|
|
116
|
+
}
|