vinojs 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -0
- package/dist/client.d.mts +41 -0
- package/dist/client.d.mts.map +1 -0
- package/dist/client.mjs +287 -0
- package/dist/client.mjs.map +1 -0
- package/dist/compile-Lxl_tdxL.mjs +155 -0
- package/dist/compile-Lxl_tdxL.mjs.map +1 -0
- package/dist/component-wrap.d.mts +10 -0
- package/dist/component-wrap.d.mts.map +1 -0
- package/dist/component-wrap.mjs +33 -0
- package/dist/component-wrap.mjs.map +1 -0
- package/dist/constants-BVT2bJEd.mjs +27 -0
- package/dist/constants-BVT2bJEd.mjs.map +1 -0
- package/dist/definePage-Ba4r-TFh.mjs +51 -0
- package/dist/definePage-Ba4r-TFh.mjs.map +1 -0
- package/dist/types-CQITdkpF.d.mts +77 -0
- package/dist/types-CQITdkpF.d.mts.map +1 -0
- package/dist/vino.d.mts +144 -0
- package/dist/vino.d.mts.map +1 -0
- package/dist/vino.mjs +197 -0
- package/dist/vino.mjs.map +1 -0
- package/dist/vite.d.mts +10 -0
- package/dist/vite.d.mts.map +1 -0
- package/dist/vite.mjs +729 -0
- package/dist/vite.mjs.map +1 -0
- package/examples/basic/dist/client/.assetsignore +2 -0
- package/examples/basic/dist/client/about.html +1 -0
- package/examples/basic/dist/client/admin.html +1 -0
- package/examples/basic/dist/client/assets/Counter-BvqMZKON.js +1 -0
- package/examples/basic/dist/client/assets/_slug_-CYpOSbrn.js +1 -0
- package/examples/basic/dist/client/assets/about-BZXRzUyv.js +1 -0
- package/examples/basic/dist/client/assets/admin-DRE7uh2s.js +1 -0
- package/examples/basic/dist/client/assets/client-B6nFkut5.js +1 -0
- package/examples/basic/dist/client/assets/client-pages-Bc6cNZAm.js +2 -0
- package/examples/basic/dist/client/assets/components-DX9r6vHn.js +1 -0
- package/examples/basic/dist/client/assets/components-DsWJ6F73.js +2 -0
- package/examples/basic/dist/client/assets/counter-DBpvln_F.js +1 -0
- package/examples/basic/dist/client/assets/dom-B5sHIJ1E.js +1 -0
- package/examples/basic/dist/client/assets/honoto-9UtdLp4J.js +33 -0
- package/examples/basic/dist/client/assets/honoto-client-DEh86_WZ.css +1 -0
- package/examples/basic/dist/client/assets/honoto-client.js +2 -0
- package/examples/basic/dist/client/assets/hooks-Cz6AT21d.js +1 -0
- package/examples/basic/dist/client/assets/jsx-dev-runtime-92VDsVyo.js +1 -0
- package/examples/basic/dist/client/counter.html +1 -0
- package/examples/basic/dist/client/index.html +1 -0
- package/examples/basic/dist/client/jobs.html +1 -0
- package/examples/basic/dist/ssr/.vite/manifest.json +140 -0
- package/examples/basic/dist/ssr/assets/_slug_-CY3-kffX.js +46 -0
- package/examples/basic/dist/ssr/assets/about-CTDjNhkO.js +15 -0
- package/examples/basic/dist/ssr/assets/admin-DvS-UGJx.js +26 -0
- package/examples/basic/dist/ssr/assets/constants-UoriGYcX-CUecBFMT.js +6 -0
- package/examples/basic/dist/ssr/assets/counter-DfIbc9Sp.js +30 -0
- package/examples/basic/dist/ssr/assets/honoto-CA313cVy.js +2129 -0
- package/examples/basic/dist/ssr/assets/jobs-D9hh-UO9.js +42 -0
- package/examples/basic/dist/ssr/assets/jsx-CgYLQazd.js +1080 -0
- package/examples/basic/dist/ssr/assets/jsx-dev-runtime-BlUda7H8.js +742 -0
- package/examples/basic/dist/ssr/assets/jsx-renderer-CzZcZPnS.js +65 -0
- package/examples/basic/dist/ssr/assets/layout-DYvLwr2u.js +53 -0
- package/examples/basic/dist/ssr/assets/pages-DB6jeyrt.js +53 -0
- package/examples/basic/dist/ssr/assets/rolldown-runtime-D7D4PA-g.js +13 -0
- package/examples/basic/dist/ssr/assets/ssr-hooks-CBQr0cdH.js +7 -0
- package/examples/basic/dist/ssr/index.js +22 -0
- package/examples/basic/dist/ssr/wrangler.json +1 -0
- package/examples/full/dist/client/.assetsignore +2 -0
- package/examples/full/dist/client/assets/BookmarkButton-py0xGxgl.js +1 -0
- package/examples/full/dist/client/assets/_slug_-DZUFsE9O.js +1 -0
- package/examples/full/dist/client/assets/auth-client-D2Wtuobe.js +1 -0
- package/examples/full/dist/client/assets/bun-sqlite-dialect-C7ftEUSI-CsHdUKBY.js +1 -0
- package/examples/full/dist/client/assets/client-B6nFkut5.js +1 -0
- package/examples/full/dist/client/assets/client-pages-fshKs747.js +2 -0
- package/examples/full/dist/client/assets/components-DX9r6vHn.js +1 -0
- package/examples/full/dist/client/assets/components-S_-rWrKi.js +2 -0
- package/examples/full/dist/client/assets/d1-sqlite-dialect-BZmaVTp8-FPCaMZqX.js +1 -0
- package/examples/full/dist/client/assets/default-query-compiler-CUdqIu1h.js +1 -0
- package/examples/full/dist/client/assets/dist-BoGTNvkC.js +1 -0
- package/examples/full/dist/client/assets/dom-DCd3wYW7.js +1 -0
- package/examples/full/dist/client/assets/factory-Bgf4EtLx.js +8 -0
- package/examples/full/dist/client/assets/honoto-client-BSvNAnxN.css +1 -0
- package/examples/full/dist/client/assets/honoto-client.js +2 -0
- package/examples/full/dist/client/assets/hooks-Cz6AT21d.js +1 -0
- package/examples/full/dist/client/assets/jsx-dev-runtime-92VDsVyo.js +1 -0
- package/examples/full/dist/client/assets/kysely-adapter-BHhasAnc.js +1 -0
- package/examples/full/dist/client/assets/kysely-migration-tables-DFfmKhq--U5ujlMwE.js +1 -0
- package/examples/full/dist/client/assets/node-sqlite-dialect-DJDXH5Ot.js +1 -0
- package/examples/full/dist/client/assets/pages-CUQx6Eus.js +1 -0
- package/examples/full/dist/client/assets/saved-jIi74ncJ.js +1 -0
- package/examples/full/dist/client/assets/session-B-accyM3.js +611 -0
- package/examples/full/dist/client/assets/sign-in-BelI3gSs.js +1 -0
- package/examples/full/dist/client/assets/sign-up-pR94lfdu.js +1 -0
- package/examples/full/dist/client/index.html +1 -0
- package/examples/full/dist/client/saved.html +1 -0
- package/examples/full/dist/client/sign-in.html +1 -0
- package/examples/full/dist/client/sign-up.html +1 -0
- package/examples/full/dist/ssr/.dev.vars +1 -0
- package/examples/full/dist/ssr/.vite/manifest.json +219 -0
- package/examples/full/dist/ssr/assets/BookmarkButton-KS7z5_vi.js +298 -0
- package/examples/full/dist/ssr/assets/_slug_-rRStRaAN.js +89 -0
- package/examples/full/dist/ssr/assets/auth-DSFZ4iak.js +31434 -0
- package/examples/full/dist/ssr/assets/auth-client-BFSBVoML.js +894 -0
- package/examples/full/dist/ssr/assets/bun-sqlite-dialect-C7ftEUSI-BeXpIqKl.js +162 -0
- package/examples/full/dist/ssr/assets/compiled-query-DmoyCh28.js +8410 -0
- package/examples/full/dist/ssr/assets/d1-sqlite-dialect-BZmaVTp8-CjJdvL94.js +114 -0
- package/examples/full/dist/ssr/assets/default-query-compiler-D7xOzCCJ.js +1727 -0
- package/examples/full/dist/ssr/assets/dist-LmmDoNdk.js +6832 -0
- package/examples/full/dist/ssr/assets/dist-kFDN1l4Z.js +342 -0
- package/examples/full/dist/ssr/assets/factory-AD6s9SIW.js +2079 -0
- package/examples/full/dist/ssr/assets/jsx-renderer-mMLf5XLN.js +1926 -0
- package/examples/full/dist/ssr/assets/kysely-adapter-BCLenpM8.js +2 -0
- package/examples/full/dist/ssr/assets/kysely-migration-tables-DFfmKhq--BtVr6hRe.js +17 -0
- package/examples/full/dist/ssr/assets/layout-mVA7qP4j.js +44 -0
- package/examples/full/dist/ssr/assets/node-sqlite-dialect-D-wtYAD7.js +162 -0
- package/examples/full/dist/ssr/assets/pages-Do5kR_Ia.js +147 -0
- package/examples/full/dist/ssr/assets/saved-Dr4pP6B5.js +111 -0
- package/examples/full/dist/ssr/assets/session-BvIpX7tr.js +13 -0
- package/examples/full/dist/ssr/assets/sign-in-22pzTnJE.js +115 -0
- package/examples/full/dist/ssr/assets/sign-up-CN4j8Qg1.js +117 -0
- package/examples/full/dist/ssr/assets/sqlite-adapter-DVlms5wO.js +79 -0
- package/examples/full/dist/ssr/index.js +97 -0
- package/examples/full/dist/ssr/wrangler.json +1 -0
- package/package.json +62 -6
- package/index.js +0 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { o as readPageDefinition } from "./definePage-Ba4r-TFh.mjs";
|
|
2
|
+
//#region src/vino/config.ts
|
|
3
|
+
function loadMergedConfig(page, pageMod) {
|
|
4
|
+
const merged = { ...page.config };
|
|
5
|
+
const inline = readPageDefinition(pageMod?.default)?.config;
|
|
6
|
+
if (inline) Object.assign(merged, inline);
|
|
7
|
+
return merged;
|
|
8
|
+
}
|
|
9
|
+
async function loadMergedData(_page, c, pageMod) {
|
|
10
|
+
const fn = readPageDefinition(pageMod?.default)?.data;
|
|
11
|
+
if (!fn) return void 0;
|
|
12
|
+
return await fn(c);
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/vino/defineServerFn.ts
|
|
16
|
+
const SERVER_FN_KIND = "vino:server-fn";
|
|
17
|
+
function isServerFn(value) {
|
|
18
|
+
return typeof value === "function" && value.kind === "vino:server-fn";
|
|
19
|
+
}
|
|
20
|
+
function readServerFn(value) {
|
|
21
|
+
return isServerFn(value) ? value : void 0;
|
|
22
|
+
}
|
|
23
|
+
/** Call-site of `defineServerFn(...)`, not `function defineServerFn(`. */
|
|
24
|
+
const DEFINE_SERVER_FN_CALL = /(?<!function\s)(?<![$\w])defineServerFn\s*(?:<[^>]*>\s*)?\(/g;
|
|
25
|
+
/** True when source *calls* `defineServerFn(...)`. */
|
|
26
|
+
function usesDefineServerFn(code) {
|
|
27
|
+
DEFINE_SERVER_FN_CALL.lastIndex = 0;
|
|
28
|
+
return DEFINE_SERVER_FN_CALL.test(code);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Mark a function as server-only.
|
|
32
|
+
*
|
|
33
|
+
* Pass the result to `definePage({ data })` (or `defineServerPage`) as a
|
|
34
|
+
* loader. The same function can later be imported and invoked
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* // [slug].server.ts
|
|
38
|
+
* export default defineServerFn(c => {
|
|
39
|
+
* const slug = c.req.param("slug") ?? ""
|
|
40
|
+
* return { slug }
|
|
41
|
+
* })
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* // [slug].tsx
|
|
45
|
+
* import data from "./[slug].server"
|
|
46
|
+
* export default definePage({ data, render: ({ data }) => <h1>{data.slug}</h1> })
|
|
47
|
+
*/
|
|
48
|
+
function defineServerFn(fn) {
|
|
49
|
+
function serverFn(c) {
|
|
50
|
+
return fn(c);
|
|
51
|
+
}
|
|
52
|
+
Object.defineProperty(serverFn, "kind", {
|
|
53
|
+
value: SERVER_FN_KIND,
|
|
54
|
+
enumerable: true
|
|
55
|
+
});
|
|
56
|
+
return serverFn;
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/vino/compile.ts
|
|
60
|
+
const GROUP_RE = /^\([^)]+\)$/;
|
|
61
|
+
const CATCH_ALL_RE = /^\[\.\.\.(.+)\]$/;
|
|
62
|
+
const PARAM_RE = /^\[([^\]]+)\]$/;
|
|
63
|
+
function toPosix(relativePath) {
|
|
64
|
+
return relativePath.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
65
|
+
}
|
|
66
|
+
function stripExt(posixPath) {
|
|
67
|
+
return posixPath.replace(/\.(tsx|ts|jsx|js|mjs)$/, "");
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Compile a pages-dir-relative file path to a Hono route.
|
|
71
|
+
* `(group)` dirs are omitted, `[param]` becomes `:param`, `[...slug]` becomes `:slug{.+}`,
|
|
72
|
+
* trailing `index` is dropped.
|
|
73
|
+
*/
|
|
74
|
+
function compileFilePath(relativePath) {
|
|
75
|
+
const segs = stripExt(toPosix(relativePath)).split("/").filter(Boolean).filter((seg) => !GROUP_RE.test(seg));
|
|
76
|
+
if (segs.at(-1) === "index") segs.pop();
|
|
77
|
+
const out = [];
|
|
78
|
+
const paramNames = [];
|
|
79
|
+
let isCatchAll = false;
|
|
80
|
+
for (const seg of segs) {
|
|
81
|
+
const catchAll = CATCH_ALL_RE.exec(seg);
|
|
82
|
+
if (catchAll) {
|
|
83
|
+
paramNames.push(catchAll[1]);
|
|
84
|
+
out.push(`:${catchAll[1]}{.+}`);
|
|
85
|
+
isCatchAll = true;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const param = PARAM_RE.exec(seg);
|
|
89
|
+
if (param && !param[1].startsWith("...")) {
|
|
90
|
+
paramNames.push(param[1]);
|
|
91
|
+
out.push(`:${param[1]}`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
out.push(seg);
|
|
95
|
+
}
|
|
96
|
+
const pattern = out.length === 0 ? "/" : `/${out.join("/")}`;
|
|
97
|
+
const path = pattern.replaceAll("{.+}", "");
|
|
98
|
+
const isStatic = paramNames.length === 0 && !isCatchAll;
|
|
99
|
+
return {
|
|
100
|
+
path,
|
|
101
|
+
pattern,
|
|
102
|
+
isCatchAll,
|
|
103
|
+
isStatic,
|
|
104
|
+
paramNames
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function pathSegments(path) {
|
|
108
|
+
return path.split("/").filter(Boolean);
|
|
109
|
+
}
|
|
110
|
+
function pathDepth(path) {
|
|
111
|
+
return pathSegments(path).length;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* True if `parent` is `/` or a prefix of `child`.
|
|
115
|
+
* A `:param` segment in `parent` matches any child segment; a static parent
|
|
116
|
+
* segment does not match a param child segment.
|
|
117
|
+
*/
|
|
118
|
+
function pathCovers(parent, child) {
|
|
119
|
+
if (parent === "/" || parent === "") return true;
|
|
120
|
+
const a = pathSegments(parent);
|
|
121
|
+
const b = pathSegments(child);
|
|
122
|
+
if (a.length > b.length) return false;
|
|
123
|
+
return a.every((seg, i) => {
|
|
124
|
+
if (seg === b[i]) return true;
|
|
125
|
+
if (seg.startsWith(":")) return true;
|
|
126
|
+
return false;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
function applyParams(path, params) {
|
|
130
|
+
let url = path;
|
|
131
|
+
for (const [key, value] of Object.entries(params)) url = url.replace(`:${key}`, value);
|
|
132
|
+
if (!url.startsWith("/")) url = `/${url}`;
|
|
133
|
+
return url;
|
|
134
|
+
}
|
|
135
|
+
function urlToHtmlFile(url) {
|
|
136
|
+
const clean = url.split("?")[0].split("#")[0];
|
|
137
|
+
if (clean === "/") return "index.html";
|
|
138
|
+
const trimmed = clean.replace(/^\//, "").replace(/\/$/, "");
|
|
139
|
+
if (clean.endsWith("/")) return `${trimmed}/index.html`;
|
|
140
|
+
return `${trimmed}.html`;
|
|
141
|
+
}
|
|
142
|
+
function routeRank(pattern) {
|
|
143
|
+
if (pattern.includes("{.+}")) return 2;
|
|
144
|
+
if (pattern.includes(":")) return 1;
|
|
145
|
+
return 0;
|
|
146
|
+
}
|
|
147
|
+
function compareRoutes(a, b) {
|
|
148
|
+
const d = routeRank(a.pattern) - routeRank(b.pattern);
|
|
149
|
+
if (d !== 0) return d;
|
|
150
|
+
return b.pattern.length - a.pattern.length;
|
|
151
|
+
}
|
|
152
|
+
//#endregion
|
|
153
|
+
export { pathDepth as a, SERVER_FN_KIND as c, readServerFn as d, usesDefineServerFn as f, pathCovers as i, defineServerFn as l, loadMergedData as m, compareRoutes as n, urlToHtmlFile as o, loadMergedConfig as p, compileFilePath as r, DEFINE_SERVER_FN_CALL as s, applyParams as t, isServerFn as u };
|
|
154
|
+
|
|
155
|
+
//# sourceMappingURL=compile-Lxl_tdxL.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compile-Lxl_tdxL.mjs","names":[],"sources":["../src/vino/config.ts","../src/vino/defineServerFn.ts","../src/vino/compile.ts"],"sourcesContent":["import { readPageDefinition } from \"./definePage.ts\";\nimport type { DataLoader, ManifestPage, PageConfig, PageModule } from \"./types.ts\";\n\nexport function loadMergedConfig(page: ManifestPage, pageMod?: PageModule): PageConfig {\n const merged: PageConfig = { ...page.config };\n const inline = readPageDefinition(pageMod?.default)?.config;\n if (inline) Object.assign(merged, inline);\n return merged;\n}\n\nexport async function loadMergedData(\n _page: ManifestPage,\n c: Parameters<DataLoader>[0],\n pageMod?: PageModule,\n): Promise<unknown> {\n const fn = readPageDefinition(pageMod?.default)?.data;\n if (!fn) return undefined;\n return await fn(c);\n}\n","import type { Context, Env } from \"hono\";\n\nexport const SERVER_FN_KIND = \"vino:server-fn\" as const;\n\nexport type ServerFnHandler<T = unknown, E extends Env = Env> = (\n c: Context<E, string>,\n) => T | Promise<T>;\n\n/**\n * A server-only function. Callable as a `definePage({ data })` loader\n */\nexport type ServerFn<T = unknown, E extends Env = Env> = ServerFnHandler<T, E> & {\n readonly kind: typeof SERVER_FN_KIND;\n};\n\nexport function isServerFn(value: unknown): value is ServerFn {\n return typeof value === \"function\" && (value as ServerFn).kind === SERVER_FN_KIND;\n}\n\nexport function readServerFn(value: unknown): ServerFn | undefined {\n return isServerFn(value) ? value : undefined;\n}\n\n/** Call-site of `defineServerFn(...)`, not `function defineServerFn(`. */\nexport const DEFINE_SERVER_FN_CALL =\n /(?<!function\\s)(?<![$\\w])defineServerFn\\s*(?:<[^>]*>\\s*)?\\(/g;\n\n/** True when source *calls* `defineServerFn(...)`. */\nexport function usesDefineServerFn(code: string): boolean {\n DEFINE_SERVER_FN_CALL.lastIndex = 0;\n return DEFINE_SERVER_FN_CALL.test(code);\n}\n\n/**\n * Mark a function as server-only.\n *\n * Pass the result to `definePage({ data })` (or `defineServerPage`) as a\n * loader. The same function can later be imported and invoked\n *\n * @example\n * // [slug].server.ts\n * export default defineServerFn(c => {\n * const slug = c.req.param(\"slug\") ?? \"\"\n * return { slug }\n * })\n *\n * @example\n * // [slug].tsx\n * import data from \"./[slug].server\"\n * export default definePage({ data, render: ({ data }) => <h1>{data.slug}</h1> })\n */\nexport function defineServerFn<T, E extends Env = Env>(fn: ServerFnHandler<T, E>): ServerFn<T, E> {\n function serverFn(c: Context<E, string>) {\n return fn(c);\n }\n Object.defineProperty(serverFn, \"kind\", {\n value: SERVER_FN_KIND,\n enumerable: true,\n });\n return serverFn as ServerFn<T, E>;\n}\n","export interface CompiledRoute {\n /** Filesystem-derived path using `:param` (no Hono regex). `/`, `/about`, `/blog/:slug`. */\n path: string;\n /** Hono route pattern (`:slug{.+}` for catch-all). */\n pattern: string;\n isCatchAll: boolean;\n isStatic: boolean;\n paramNames: string[];\n}\n\nconst GROUP_RE = /^\\([^)]+\\)$/;\nconst CATCH_ALL_RE = /^\\[\\.\\.\\.(.+)\\]$/;\nconst PARAM_RE = /^\\[([^\\]]+)\\]$/;\n\nfunction toPosix(relativePath: string): string {\n return relativePath.replaceAll(\"\\\\\", \"/\").replace(/^\\.\\//, \"\");\n}\n\nfunction stripExt(posixPath: string): string {\n return posixPath.replace(/\\.(tsx|ts|jsx|js|mjs)$/, \"\");\n}\n\n/**\n * Compile a pages-dir-relative file path to a Hono route.\n * `(group)` dirs are omitted, `[param]` becomes `:param`, `[...slug]` becomes `:slug{.+}`,\n * trailing `index` is dropped.\n */\nexport function compileFilePath(relativePath: string): CompiledRoute {\n const posix = toPosix(relativePath);\n const withoutExt = stripExt(posix);\n\n const rawSegs = withoutExt.split(\"/\").filter(Boolean);\n const segs = rawSegs.filter((seg) => !GROUP_RE.test(seg));\n if (segs.at(-1) === \"index\") segs.pop();\n\n const out: string[] = [];\n const paramNames: string[] = [];\n let isCatchAll = false;\n\n for (const seg of segs) {\n const catchAll = CATCH_ALL_RE.exec(seg);\n if (catchAll) {\n paramNames.push(catchAll[1]);\n out.push(`:${catchAll[1]}{.+}`);\n isCatchAll = true;\n continue;\n }\n const param = PARAM_RE.exec(seg);\n if (param && !param[1].startsWith(\"...\")) {\n paramNames.push(param[1]);\n out.push(`:${param[1]}`);\n continue;\n }\n out.push(seg);\n }\n\n const pattern = out.length === 0 ? \"/\" : `/${out.join(\"/\")}`;\n const path = pattern.replaceAll(\"{.+}\", \"\");\n const isStatic = paramNames.length === 0 && !isCatchAll;\n\n return { path, pattern, isCatchAll, isStatic, paramNames };\n}\n\nexport function pathSegments(path: string): string[] {\n return path.split(\"/\").filter(Boolean);\n}\n\nexport function pathDepth(path: string): number {\n return pathSegments(path).length;\n}\n\n/**\n * True if `parent` is `/` or a prefix of `child`.\n * A `:param` segment in `parent` matches any child segment; a static parent\n * segment does not match a param child segment.\n */\nexport function pathCovers(parent: string, child: string): boolean {\n if (parent === \"/\" || parent === \"\") return true;\n const a = pathSegments(parent);\n const b = pathSegments(child);\n if (a.length > b.length) return false;\n return a.every((seg, i) => {\n const other = b[i];\n if (seg === other) return true;\n if (seg.startsWith(\":\")) return true;\n return false;\n });\n}\n\nexport function applyParams(path: string, params: Record<string, string>): string {\n let url = path;\n for (const [key, value] of Object.entries(params)) {\n url = url.replace(`:${key}`, value);\n }\n if (!url.startsWith(\"/\")) url = `/${url}`;\n return url;\n}\n\nexport function urlToHtmlFile(url: string): string {\n const clean = url.split(\"?\")[0].split(\"#\")[0];\n if (clean === \"/\") return \"index.html\";\n const trimmed = clean.replace(/^\\//, \"\").replace(/\\/$/, \"\");\n if (clean.endsWith(\"/\")) return `${trimmed}/index.html`;\n return `${trimmed}.html`;\n}\n\nexport function routeRank(pattern: string): number {\n if (pattern.includes(\"{.+}\")) return 2;\n if (pattern.includes(\":\")) return 1;\n return 0;\n}\n\nexport function compareRoutes(a: { pattern: string }, b: { pattern: string }): number {\n const d = routeRank(a.pattern) - routeRank(b.pattern);\n if (d !== 0) return d;\n return b.pattern.length - a.pattern.length;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Child } from "hono/jsx";
|
|
2
|
+
//#region src/vino/component-wrap.d.ts
|
|
3
|
+
declare function wrapComponent(Component: (...args: never[]) => unknown, componentId: string, exportName: string): {
|
|
4
|
+
(props?: Record<string, unknown>): import("hono/jsx").JSXNode;
|
|
5
|
+
displayName: string;
|
|
6
|
+
};
|
|
7
|
+
declare function wrapModule(mod: Record<string, unknown>, componentId: string): Record<string, unknown>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { type Child, wrapComponent, wrapModule };
|
|
10
|
+
//# sourceMappingURL=component-wrap.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-wrap.d.mts","names":[],"sources":["../src/vino/component-wrap.ts"],"mappings":";;iBAcgB,cACd,eAAe,2BACf,qBACA;GAEwB,QAAA,6CAAuB;;;iBAYjC,WAAW,KAAK,yBAAyB,sBAAmB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { t as COMPONENT_TAG } from "./constants-BVT2bJEd.mjs";
|
|
2
|
+
import { jsxDEV } from "hono/jsx/jsx-dev-runtime";
|
|
3
|
+
//#region src/vino/component-wrap.ts
|
|
4
|
+
function serializeProps(props) {
|
|
5
|
+
const rest = {};
|
|
6
|
+
for (const [key, value] of Object.entries(props)) {
|
|
7
|
+
if (key === "children") continue;
|
|
8
|
+
if (typeof value === "function" || typeof value === "symbol") continue;
|
|
9
|
+
rest[key] = value;
|
|
10
|
+
}
|
|
11
|
+
return JSON.stringify(rest);
|
|
12
|
+
}
|
|
13
|
+
function wrapComponent(Component, componentId, exportName) {
|
|
14
|
+
function Wrapped(props = {}) {
|
|
15
|
+
return jsxDEV(COMPONENT_TAG, {
|
|
16
|
+
"data-component": componentId,
|
|
17
|
+
"data-export": exportName,
|
|
18
|
+
"data-props": serializeProps(props),
|
|
19
|
+
children: jsxDEV(Component, props)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
Wrapped.displayName = `Vino(${exportName})`;
|
|
23
|
+
return Wrapped;
|
|
24
|
+
}
|
|
25
|
+
function wrapModule(mod, componentId) {
|
|
26
|
+
const out = { ...mod };
|
|
27
|
+
for (const [key, value] of Object.entries(mod)) if (typeof value === "function" && key !== "__esModule") out[key] = wrapComponent(value, componentId, key);
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { wrapComponent, wrapModule };
|
|
32
|
+
|
|
33
|
+
//# sourceMappingURL=component-wrap.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-wrap.mjs","names":["jsx"],"sources":["../src/vino/component-wrap.ts"],"sourcesContent":["import { jsxDEV as jsx } from \"hono/jsx/jsx-dev-runtime\";\nimport type { Child } from \"hono/jsx\";\nimport { COMPONENT_TAG } from \"./constants.ts\";\n\nfunction serializeProps(props: Record<string, unknown>): string {\n const rest: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (key === \"children\") continue;\n if (typeof value === \"function\" || typeof value === \"symbol\") continue;\n rest[key] = value;\n }\n return JSON.stringify(rest);\n}\n\nexport function wrapComponent(\n Component: (...args: never[]) => unknown,\n componentId: string,\n exportName: string,\n) {\n function Wrapped(props: Record<string, unknown> = {}) {\n return jsx(COMPONENT_TAG, {\n \"data-component\": componentId,\n \"data-export\": exportName,\n \"data-props\": serializeProps(props),\n children: jsx(Component, props),\n });\n }\n Wrapped.displayName = `Vino(${exportName})`;\n return Wrapped;\n}\n\nexport function wrapModule(mod: Record<string, unknown>, componentId: string) {\n const out: Record<string, unknown> = { ...mod };\n for (const [key, value] of Object.entries(mod)) {\n if (typeof value === \"function\" && key !== \"__esModule\") {\n out[key] = wrapComponent(value as (...args: never[]) => unknown, componentId, key);\n }\n }\n return out;\n}\n\nexport type { Child };\n"],"mappings":";;;AAIA,SAAS,eAAe,OAAwC;CAC9D,MAAM,OAAgC,CAAC;CACvC,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,KAAK,GAAG;EAChD,IAAI,QAAQ,YAAY;EACxB,IAAI,OAAO,UAAU,cAAc,OAAO,UAAU,UAAU;EAC9D,KAAK,OAAO;CACd;CACA,OAAO,KAAK,UAAU,IAAI;AAC5B;AAEA,SAAgB,cACd,WACA,aACA,YACA;CACA,SAAS,QAAQ,QAAiC,CAAC,GAAG;EACpD,OAAOA,OAAI,eAAe;GACxB,kBAAkB;GAClB,eAAe;GACf,cAAc,eAAe,KAAK;GAClC,UAAUA,OAAI,WAAW,KAAK;EAChC,CAAC;CACH;CACA,QAAQ,cAAc,QAAQ,WAAW;CACzC,OAAO;AACT;AAEA,SAAgB,WAAW,KAA8B,aAAqB;CAC5E,MAAM,MAA+B,EAAE,GAAG,IAAI;CAC9C,KAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,GAAG,GAC3C,IAAI,OAAO,UAAU,cAAc,QAAQ,cACzC,IAAI,OAAO,cAAc,OAAwC,aAAa,GAAG;CAGrF,OAAO;AACT"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/vino/constants.ts
|
|
2
|
+
const PAGE_SLOT_ID = "vino-page";
|
|
3
|
+
const PAYLOAD_SCRIPT_ID = "__VINO__";
|
|
4
|
+
const COMPONENT_TAG = "vino-component";
|
|
5
|
+
const DEFAULT_PAGES_DIR = "src/pages";
|
|
6
|
+
const DEFAULT_LAYOUTS_DIR = "src/layout";
|
|
7
|
+
const DEFAULT_COMPONENTS_DIR = "src/components";
|
|
8
|
+
const DEFAULT_ENTRY = "src/server.ts";
|
|
9
|
+
const NAV_HEADER = "X-Vino-Nav";
|
|
10
|
+
const SHELL_HEADER = "X-Vino-Shell";
|
|
11
|
+
const VIRTUAL_MANIFEST = "virtual:vino/manifest";
|
|
12
|
+
const VIRTUAL_COMPONENTS = "virtual:vino/components";
|
|
13
|
+
const VIRTUAL_ASSETS = "virtual:vino/assets";
|
|
14
|
+
const VIRTUAL_CLIENT = "virtual:vino/client";
|
|
15
|
+
const VIRTUAL_CLIENT_PAGES = "virtual:vino/client-pages";
|
|
16
|
+
const VIRTUAL_SSR_HOOKS = "virtual:vino/ssr-hooks";
|
|
17
|
+
const PAGE_EXTS = [
|
|
18
|
+
".tsx",
|
|
19
|
+
".ts",
|
|
20
|
+
".jsx",
|
|
21
|
+
".js",
|
|
22
|
+
".mjs"
|
|
23
|
+
];
|
|
24
|
+
//#endregion
|
|
25
|
+
export { DEFAULT_PAGES_DIR as a, PAGE_SLOT_ID as c, VIRTUAL_ASSETS as d, VIRTUAL_CLIENT as f, VIRTUAL_SSR_HOOKS as g, VIRTUAL_MANIFEST as h, DEFAULT_LAYOUTS_DIR as i, PAYLOAD_SCRIPT_ID as l, VIRTUAL_COMPONENTS as m, DEFAULT_COMPONENTS_DIR as n, NAV_HEADER as o, VIRTUAL_CLIENT_PAGES as p, DEFAULT_ENTRY as r, PAGE_EXTS as s, COMPONENT_TAG as t, SHELL_HEADER as u };
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=constants-BVT2bJEd.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants-BVT2bJEd.mjs","names":[],"sources":["../src/vino/constants.ts"],"sourcesContent":["export const PAGE_SLOT_ID = \"vino-page\";\nexport const PAYLOAD_SCRIPT_ID = \"__VINO__\";\nexport const COMPONENT_TAG = \"vino-component\";\nexport const DEFAULT_PAGES_DIR = \"src/pages\";\nexport const DEFAULT_LAYOUTS_DIR = \"src/layout\";\nexport const DEFAULT_COMPONENTS_DIR = \"src/components\";\nexport const DEFAULT_ENTRY = \"src/server.ts\";\nexport const NAV_HEADER = \"X-Vino-Nav\";\nexport const SHELL_HEADER = \"X-Vino-Shell\";\n\nexport const VIRTUAL_MANIFEST = \"virtual:vino/manifest\";\nexport const VIRTUAL_COMPONENTS = \"virtual:vino/components\";\nexport const VIRTUAL_ASSETS = \"virtual:vino/assets\";\nexport const VIRTUAL_CLIENT = \"virtual:vino/client\";\nexport const VIRTUAL_CLIENT_PAGES = \"virtual:vino/client-pages\";\nexport const VIRTUAL_SSR_HOOKS = \"virtual:vino/ssr-hooks\";\n\nexport const PAGE_EXTS = [\".tsx\", \".ts\", \".jsx\", \".js\", \".mjs\"] as const;\n"],"mappings":";AAAA,MAAa,eAAe;AAC5B,MAAa,oBAAoB;AACjC,MAAa,gBAAgB;AAC7B,MAAa,oBAAoB;AACjC,MAAa,sBAAsB;AACnC,MAAa,yBAAyB;AACtC,MAAa,gBAAgB;AAC7B,MAAa,aAAa;AAC1B,MAAa,eAAe;AAE5B,MAAa,mBAAmB;AAChC,MAAa,qBAAqB;AAClC,MAAa,iBAAiB;AAC9B,MAAa,iBAAiB;AAC9B,MAAa,uBAAuB;AACpC,MAAa,oBAAoB;AAEjC,MAAa,YAAY;CAAC;CAAQ;CAAO;CAAQ;CAAO;AAAM"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/vino/definePage.ts
|
|
2
|
+
const PAGE_KIND = "vino:page";
|
|
3
|
+
const SERVER_PAGE_KIND = "vino:server-page";
|
|
4
|
+
function isPageDefinition(value) {
|
|
5
|
+
if (value === null || typeof value !== "object" && typeof value !== "function") return false;
|
|
6
|
+
const candidate = value;
|
|
7
|
+
return (candidate.kind === "vino:page" || candidate.kind === "vino:server-page") && typeof candidate.render === "function";
|
|
8
|
+
}
|
|
9
|
+
function isClientPageDefinition(value) {
|
|
10
|
+
return isPageDefinition(value) && value.kind === "vino:page";
|
|
11
|
+
}
|
|
12
|
+
function isServerPageDefinition(value) {
|
|
13
|
+
return isPageDefinition(value) && value.kind === "vino:server-page";
|
|
14
|
+
}
|
|
15
|
+
function readPageDefinition(value) {
|
|
16
|
+
return isPageDefinition(value) ? value : void 0;
|
|
17
|
+
}
|
|
18
|
+
function resolvePageRender(value) {
|
|
19
|
+
if (isPageDefinition(value)) return value.render;
|
|
20
|
+
if (typeof value === "function") return value;
|
|
21
|
+
}
|
|
22
|
+
/** True when source calls `definePage(...)` (hydratable pages). */
|
|
23
|
+
function usesDefinePage(code) {
|
|
24
|
+
return /(?:^|[^\w$])definePage\s*(?:<[^>]*>\s*)?\(/.test(code);
|
|
25
|
+
}
|
|
26
|
+
function pageDefinition(page, kind, fnName) {
|
|
27
|
+
if (typeof page === "function") return {
|
|
28
|
+
kind,
|
|
29
|
+
client: kind === PAGE_KIND,
|
|
30
|
+
render: page
|
|
31
|
+
};
|
|
32
|
+
const render = page.render ?? page.page;
|
|
33
|
+
if (typeof render !== "function") throw new TypeError(`[vino] ${fnName}() requires a JSX function or { render }`);
|
|
34
|
+
return {
|
|
35
|
+
kind,
|
|
36
|
+
client: kind === PAGE_KIND,
|
|
37
|
+
render,
|
|
38
|
+
data: page.data,
|
|
39
|
+
config: page.config
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function definePage(page) {
|
|
43
|
+
return pageDefinition(page, PAGE_KIND, "definePage");
|
|
44
|
+
}
|
|
45
|
+
function defineServerPage(page) {
|
|
46
|
+
return pageDefinition(page, SERVER_PAGE_KIND, "defineServerPage");
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
49
|
+
export { isServerPageDefinition as a, usesDefinePage as c, isPageDefinition as i, defineServerPage as n, readPageDefinition as o, isClientPageDefinition as r, resolvePageRender as s, definePage as t };
|
|
50
|
+
|
|
51
|
+
//# sourceMappingURL=definePage-Ba4r-TFh.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definePage-Ba4r-TFh.mjs","names":[],"sources":["../src/vino/definePage.ts"],"sourcesContent":["import type { ServerFn } from \"./defineServerFn.ts\";\nimport type { DataLoader, PageConfig, PageProps, VinoHtml } from \"./types.ts\";\n\nexport const PAGE_KIND = \"vino:page\" as const;\nexport const SERVER_PAGE_KIND = \"vino:server-page\" as const;\n\nexport type PageRender<Data = unknown> = (props: PageProps<Data>) => VinoHtml;\n\nexport interface DefinePageOptions<Data = unknown> {\n /** JSX page component. Alias: `page`. */\n render?: PageRender<Data>;\n page?: PageRender<Data>;\n /** Loader or `defineServerFn(...)` (including a default import from `*.server.ts`). */\n data?: DataLoader | ServerFn<Data>;\n config?: PageConfig;\n}\n\nexport interface PageDefinition<Data = unknown> {\n readonly kind: typeof PAGE_KIND | typeof SERVER_PAGE_KIND;\n readonly client: boolean;\n readonly render: PageRender<Data>;\n readonly data?: DataLoader | ServerFn<Data>;\n readonly config?: PageConfig;\n}\n\nexport function isPageDefinition(value: unknown): value is PageDefinition {\n if (value === null || (typeof value !== \"object\" && typeof value !== \"function\")) return false;\n const candidate = value as PageDefinition;\n return (\n (candidate.kind === PAGE_KIND || candidate.kind === SERVER_PAGE_KIND) &&\n typeof candidate.render === \"function\"\n );\n}\n\nexport function isClientPageDefinition(value: unknown): value is PageDefinition {\n return isPageDefinition(value) && value.kind === PAGE_KIND;\n}\n\nexport function isServerPageDefinition(value: unknown): value is PageDefinition {\n return isPageDefinition(value) && value.kind === SERVER_PAGE_KIND;\n}\n\nexport function readPageDefinition(value: unknown): PageDefinition | undefined {\n return isPageDefinition(value) ? value : undefined;\n}\n\nexport function resolvePageRender(value: unknown): PageRender | undefined {\n if (isPageDefinition(value)) return value.render;\n if (typeof value === \"function\") return value as PageRender;\n return undefined;\n}\n\n/** True when source calls `definePage(...)` (hydratable pages). */\nexport function usesDefinePage(code: string): boolean {\n return /(?:^|[^\\w$])definePage\\s*(?:<[^>]*>\\s*)?\\(/.test(code);\n}\n\nfunction pageDefinition<Data>(\n page: PageRender<Data> | DefinePageOptions<Data>,\n kind: typeof PAGE_KIND | typeof SERVER_PAGE_KIND,\n fnName: string,\n): PageDefinition<Data> {\n if (typeof page === \"function\") {\n return { kind, client: kind === PAGE_KIND, render: page };\n }\n const render = page.render ?? page.page;\n if (typeof render !== \"function\") {\n throw new TypeError(`[vino] ${fnName}() requires a JSX function or { render }`);\n }\n return {\n kind,\n client: kind === PAGE_KIND,\n render,\n data: page.data,\n config: page.config,\n };\n}\n\n/**\n * Declare a page that SSRs with `hono/jsx`, then hydrates `#vino-page` with `hono/jsx/dom`.\n *\n * @example\n * export default definePage(() => {\n * const [n, setN] = useState(0)\n * return <button onClick={() => setN(n + 1)}>{n}</button>\n * })\n */\nexport function definePage<Data = unknown>(page: PageRender<Data>): PageDefinition<Data>;\n\n/**\n * Declare a hydratable page as `{ render, data?, config? }`.\n *\n * @example\n * export default definePage({\n * config: { prerender: 'full', clientRouting: true },\n * data: async (c) => ({ title: 'Hello' }),\n * render: ({ data }) => <h1>{data.title}</h1>,\n * })\n *\n * @example\n * import data from './[slug].server'\n * export default definePage({ data, render: ({ data }) => <h1>{data.title}</h1> })\n */\nexport function definePage<D extends DataLoader | ServerFn>(options: {\n render: PageRender<Awaited<ReturnType<D>>>;\n page?: PageRender<Awaited<ReturnType<D>>>;\n data?: D;\n config?: PageConfig;\n}): PageDefinition<Awaited<ReturnType<D>>>;\nexport function definePage<Data = unknown>(options: DefinePageOptions<Data>): PageDefinition<Data>;\nexport function definePage<Data = unknown>(\n page: PageRender<Data> | DefinePageOptions<Data>,\n): PageDefinition<Data> {\n return pageDefinition(page, PAGE_KIND, \"definePage\");\n}\n\n/**\n * Declare a page that SSRs only. The output is never hydrated.\n *\n * @example\n * export default defineServerPage(() => <h1>About</h1>)\n */\nexport function defineServerPage<Data = unknown>(page: PageRender<Data>): PageDefinition<Data>;\nexport function defineServerPage<D extends DataLoader | ServerFn>(options: {\n render: PageRender<Awaited<ReturnType<D>>>;\n page?: PageRender<Awaited<ReturnType<D>>>;\n data?: D;\n config?: PageConfig;\n}): PageDefinition<Awaited<ReturnType<D>>>;\nexport function defineServerPage<Data = unknown>(\n options: DefinePageOptions<Data>,\n): PageDefinition<Data>;\nexport function defineServerPage<Data = unknown>(\n page: PageRender<Data> | DefinePageOptions<Data>,\n): PageDefinition<Data> {\n return pageDefinition(page, SERVER_PAGE_KIND, \"defineServerPage\");\n}\n"],"mappings":";AAGA,MAAa,YAAY;AACzB,MAAa,mBAAmB;AAqBhC,SAAgB,iBAAiB,OAAyC;CACxE,IAAI,UAAU,QAAS,OAAO,UAAU,YAAY,OAAO,UAAU,YAAa,OAAO;CACzF,MAAM,YAAY;CAClB,QACG,UAAU,SAAA,eAAsB,UAAU,SAAA,uBAC3C,OAAO,UAAU,WAAW;AAEhC;AAEA,SAAgB,uBAAuB,OAAyC;CAC9E,OAAO,iBAAiB,KAAK,KAAK,MAAM,SAAA;AAC1C;AAEA,SAAgB,uBAAuB,OAAyC;CAC9E,OAAO,iBAAiB,KAAK,KAAK,MAAM,SAAA;AAC1C;AAEA,SAAgB,mBAAmB,OAA4C;CAC7E,OAAO,iBAAiB,KAAK,IAAI,QAAQ,KAAA;AAC3C;AAEA,SAAgB,kBAAkB,OAAwC;CACxE,IAAI,iBAAiB,KAAK,GAAG,OAAO,MAAM;CAC1C,IAAI,OAAO,UAAU,YAAY,OAAO;AAE1C;;AAGA,SAAgB,eAAe,MAAuB;CACpD,OAAO,6CAA6C,KAAK,IAAI;AAC/D;AAEA,SAAS,eACP,MACA,MACA,QACsB;CACtB,IAAI,OAAO,SAAS,YAClB,OAAO;EAAE;EAAM,QAAQ,SAAS;EAAW,QAAQ;CAAK;CAE1D,MAAM,SAAS,KAAK,UAAU,KAAK;CACnC,IAAI,OAAO,WAAW,YACpB,MAAM,IAAI,UAAU,UAAU,OAAO,yCAAyC;CAEhF,OAAO;EACL;EACA,QAAQ,SAAS;EACjB;EACA,MAAM,KAAK;EACX,QAAQ,KAAK;CACf;AACF;AAkCA,SAAgB,WACd,MACsB;CACtB,OAAO,eAAe,MAAM,WAAW,YAAY;AACrD;AAkBA,SAAgB,iBACd,MACsB;CACtB,OAAO,eAAe,MAAM,kBAAkB,kBAAkB;AAClE"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { Context, Env } from "hono";
|
|
2
|
+
import { Child } from "hono/jsx";
|
|
3
|
+
//#region src/vino/types.d.ts
|
|
4
|
+
type VinoHtml = Child;
|
|
5
|
+
interface PageProps<Data = unknown> {
|
|
6
|
+
data: Data;
|
|
7
|
+
params: Record<string, string>;
|
|
8
|
+
}
|
|
9
|
+
interface LayoutProps<Data = unknown> {
|
|
10
|
+
children?: Child;
|
|
11
|
+
data: Data;
|
|
12
|
+
params: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
type DataLoader<E extends Env = Env> = (c: Context<E, string>) => unknown;
|
|
15
|
+
type SsgParams = Record<string, string>;
|
|
16
|
+
type SsgParamsFn = () => SsgParams[] | Promise<SsgParams[]>;
|
|
17
|
+
type RenderMode = "full" | "shell" | "content";
|
|
18
|
+
interface PageConfig {
|
|
19
|
+
prerender?: "full" | "partial" | false;
|
|
20
|
+
clientRouting?: boolean;
|
|
21
|
+
ssgParams?: SsgParamsFn;
|
|
22
|
+
}
|
|
23
|
+
interface PageModule {
|
|
24
|
+
default?: unknown;
|
|
25
|
+
GET?: (c: Context) => unknown;
|
|
26
|
+
POST?: (c: Context) => unknown;
|
|
27
|
+
PUT?: (c: Context) => unknown;
|
|
28
|
+
PATCH?: (c: Context) => unknown;
|
|
29
|
+
DELETE?: (c: Context) => unknown;
|
|
30
|
+
[method: string]: unknown;
|
|
31
|
+
}
|
|
32
|
+
interface LayoutModule {
|
|
33
|
+
default: (props: LayoutProps) => VinoHtml;
|
|
34
|
+
}
|
|
35
|
+
type ManifestLoader<T> = () => Promise<T>;
|
|
36
|
+
interface ManifestPage {
|
|
37
|
+
id: string;
|
|
38
|
+
path: string;
|
|
39
|
+
pattern: string;
|
|
40
|
+
isClientPage: boolean;
|
|
41
|
+
isStatic: boolean;
|
|
42
|
+
isCatchAll: boolean;
|
|
43
|
+
paramNames: string[];
|
|
44
|
+
config?: PageConfig;
|
|
45
|
+
loadPage: ManifestLoader<PageModule>;
|
|
46
|
+
loadClientPage?: ManifestLoader<PageModule>;
|
|
47
|
+
loadLayouts: ManifestLoader<LayoutModule>[];
|
|
48
|
+
}
|
|
49
|
+
interface VinoManifest {
|
|
50
|
+
pages: ManifestPage[];
|
|
51
|
+
defaults?: PageConfig;
|
|
52
|
+
}
|
|
53
|
+
interface VinoPayload {
|
|
54
|
+
path: string;
|
|
55
|
+
params: Record<string, string>;
|
|
56
|
+
data: unknown;
|
|
57
|
+
clientRouting: boolean;
|
|
58
|
+
clientPage: string | null;
|
|
59
|
+
/** True when the document is a layout shell; client should fetch page content. */
|
|
60
|
+
partial?: boolean;
|
|
61
|
+
title?: string;
|
|
62
|
+
}
|
|
63
|
+
interface CreateVinoOptions {
|
|
64
|
+
manifest?: VinoManifest;
|
|
65
|
+
}
|
|
66
|
+
interface VinoViteOptions {
|
|
67
|
+
pagesDir?: string;
|
|
68
|
+
layoutsDir?: string;
|
|
69
|
+
componentsDir?: string;
|
|
70
|
+
entry?: string;
|
|
71
|
+
prerender?: "full" | "partial" | false;
|
|
72
|
+
clientRouting?: boolean;
|
|
73
|
+
client?: string;
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
export { PageConfig as a, VinoHtml as c, VinoViteOptions as d, ManifestPage as i, VinoManifest as l, DataLoader as n, PageProps as o, LayoutProps as r, RenderMode as s, CreateVinoOptions as t, VinoPayload as u };
|
|
77
|
+
//# sourceMappingURL=types-CQITdkpF.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-CQITdkpF.d.mts","names":[],"sources":["../src/vino/types.ts"],"mappings":";;;KAGY,WAAW;UAEN,UAAU;EACzB,MAAM;EACN,QAAQ;;UAGO,YAAY;EAC3B,WAAW;EACX,MAAM;EACN,QAAQ;;KAGE,WAAW,UAAU,MAAM,QAAQ,GAAG,QAAQ;KAE9C,YAAY;KACZ,oBAAoB,cAAc,QAAQ;KAE1C;UAEK;EACf;EACA;EACA,YAAY;;UAGG;EACf;EACA,OAAO,GAAG;EACV,QAAQ,GAAG;EACX,OAAO,GAAG;EACV,SAAS,GAAG;EACZ,UAAU,GAAG;GACZ;;UAGc;EACf,UAAU,OAAO,gBAAgB;;KAGvB,eAAe,WAAW,QAAQ;UAE7B;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU,eAAe;EACzB,iBAAiB,eAAe;EAChC,aAAa,eAAe;;UAGb;EACf,OAAO;EACP,WAAW;;UAGI;EACf;EACA,QAAQ;EACR;EACA;EACA;;EAEA;EACA;;UAGe;EACf,WAAW;;UAGI;EACf;EACA;EACA;EACA;EACA;EACA;EACA"}
|
package/dist/vino.d.mts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { a as PageConfig, c as VinoHtml, d as VinoViteOptions, i as ManifestPage, l as VinoManifest, n as DataLoader, o as PageProps, r as LayoutProps, s as RenderMode, t as CreateVinoOptions, u as VinoPayload } from "./types-CQITdkpF.mjs";
|
|
2
|
+
import { wrapComponent, wrapModule } from "./component-wrap.mjs";
|
|
3
|
+
import { Context, Env, Hono, Schema } from "hono";
|
|
4
|
+
import { BlankSchema } from "hono/types";
|
|
5
|
+
//#region src/vino/createVino.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Mount filesystem pages from the Vite-generated manifest onto a user-owned Hono app.
|
|
8
|
+
* Extra API routes should be registered on `app` before calling this.
|
|
9
|
+
*/
|
|
10
|
+
declare function mountVino<E extends Env, S extends Schema, BasePath extends string>(app: Hono<E, S, BasePath>, options?: CreateVinoOptions): Hono<E, S, BasePath>;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new Vino app. Returns a Hono app with the Vino pages mounted.
|
|
13
|
+
* @param options - The options for the Vino app.
|
|
14
|
+
* @returns A Hono app with the Vino pages mounted.
|
|
15
|
+
*/
|
|
16
|
+
declare function createVino<E extends Env = Env, S extends Schema = BlankSchema, BasePath extends string = "/">(options?: CreateVinoOptions): Hono<E, S, BasePath>;
|
|
17
|
+
//#endregion
|
|
18
|
+
//#region src/vino/defineServerFn.d.ts
|
|
19
|
+
declare const SERVER_FN_KIND: "vino:server-fn";
|
|
20
|
+
type ServerFnHandler<T = unknown, E extends Env = Env> = (c: Context<E, string>) => T | Promise<T>;
|
|
21
|
+
/**
|
|
22
|
+
* A server-only function. Callable as a `definePage({ data })` loader
|
|
23
|
+
*/
|
|
24
|
+
type ServerFn<T = unknown, E extends Env = Env> = ServerFnHandler<T, E> & {
|
|
25
|
+
readonly kind: typeof SERVER_FN_KIND;
|
|
26
|
+
};
|
|
27
|
+
declare function isServerFn(value: unknown): value is ServerFn;
|
|
28
|
+
declare function readServerFn(value: unknown): ServerFn | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Mark a function as server-only.
|
|
31
|
+
*
|
|
32
|
+
* Pass the result to `definePage({ data })` (or `defineServerPage`) as a
|
|
33
|
+
* loader. The same function can later be imported and invoked
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // [slug].server.ts
|
|
37
|
+
* export default defineServerFn(c => {
|
|
38
|
+
* const slug = c.req.param("slug") ?? ""
|
|
39
|
+
* return { slug }
|
|
40
|
+
* })
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // [slug].tsx
|
|
44
|
+
* import data from "./[slug].server"
|
|
45
|
+
* export default definePage({ data, render: ({ data }) => <h1>{data.slug}</h1> })
|
|
46
|
+
*/
|
|
47
|
+
declare function defineServerFn<T, E extends Env = Env>(fn: ServerFnHandler<T, E>): ServerFn<T, E>;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/vino/definePage.d.ts
|
|
50
|
+
declare const PAGE_KIND: "vino:page";
|
|
51
|
+
declare const SERVER_PAGE_KIND: "vino:server-page";
|
|
52
|
+
type PageRender<Data = unknown> = (props: PageProps<Data>) => VinoHtml;
|
|
53
|
+
interface DefinePageOptions<Data = unknown> {
|
|
54
|
+
/** JSX page component. Alias: `page`. */
|
|
55
|
+
render?: PageRender<Data>;
|
|
56
|
+
page?: PageRender<Data>;
|
|
57
|
+
/** Loader or `defineServerFn(...)` (including a default import from `*.server.ts`). */
|
|
58
|
+
data?: DataLoader | ServerFn<Data>;
|
|
59
|
+
config?: PageConfig;
|
|
60
|
+
}
|
|
61
|
+
interface PageDefinition<Data = unknown> {
|
|
62
|
+
readonly kind: typeof PAGE_KIND | typeof SERVER_PAGE_KIND;
|
|
63
|
+
readonly client: boolean;
|
|
64
|
+
readonly render: PageRender<Data>;
|
|
65
|
+
readonly data?: DataLoader | ServerFn<Data>;
|
|
66
|
+
readonly config?: PageConfig;
|
|
67
|
+
}
|
|
68
|
+
declare function isPageDefinition(value: unknown): value is PageDefinition;
|
|
69
|
+
declare function isClientPageDefinition(value: unknown): value is PageDefinition;
|
|
70
|
+
declare function isServerPageDefinition(value: unknown): value is PageDefinition;
|
|
71
|
+
declare function resolvePageRender(value: unknown): PageRender | undefined;
|
|
72
|
+
/**
|
|
73
|
+
* Declare a page that SSRs with `hono/jsx`, then hydrates `#vino-page` with `hono/jsx/dom`.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
* export default definePage(() => {
|
|
77
|
+
* const [n, setN] = useState(0)
|
|
78
|
+
* return <button onClick={() => setN(n + 1)}>{n}</button>
|
|
79
|
+
* })
|
|
80
|
+
*/
|
|
81
|
+
declare function definePage<Data = unknown>(page: PageRender<Data>): PageDefinition<Data>;
|
|
82
|
+
/**
|
|
83
|
+
* Declare a hydratable page as `{ render, data?, config? }`.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* export default definePage({
|
|
87
|
+
* config: { prerender: 'full', clientRouting: true },
|
|
88
|
+
* data: async (c) => ({ title: 'Hello' }),
|
|
89
|
+
* render: ({ data }) => <h1>{data.title}</h1>,
|
|
90
|
+
* })
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* import data from './[slug].server'
|
|
94
|
+
* export default definePage({ data, render: ({ data }) => <h1>{data.title}</h1> })
|
|
95
|
+
*/
|
|
96
|
+
declare function definePage<D extends DataLoader | ServerFn>(options: {
|
|
97
|
+
render: PageRender<Awaited<ReturnType<D>>>;
|
|
98
|
+
page?: PageRender<Awaited<ReturnType<D>>>;
|
|
99
|
+
data?: D;
|
|
100
|
+
config?: PageConfig;
|
|
101
|
+
}): PageDefinition<Awaited<ReturnType<D>>>;
|
|
102
|
+
declare function definePage<Data = unknown>(options: DefinePageOptions<Data>): PageDefinition<Data>;
|
|
103
|
+
/**
|
|
104
|
+
* Declare a page that SSRs only. The output is never hydrated.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* export default defineServerPage(() => <h1>About</h1>)
|
|
108
|
+
*/
|
|
109
|
+
declare function defineServerPage<Data = unknown>(page: PageRender<Data>): PageDefinition<Data>;
|
|
110
|
+
declare function defineServerPage<D extends DataLoader | ServerFn>(options: {
|
|
111
|
+
render: PageRender<Awaited<ReturnType<D>>>;
|
|
112
|
+
page?: PageRender<Awaited<ReturnType<D>>>;
|
|
113
|
+
data?: D;
|
|
114
|
+
config?: PageConfig;
|
|
115
|
+
}): PageDefinition<Awaited<ReturnType<D>>>;
|
|
116
|
+
declare function defineServerPage<Data = unknown>(options: DefinePageOptions<Data>): PageDefinition<Data>;
|
|
117
|
+
//#endregion
|
|
118
|
+
//#region src/vino/compile.d.ts
|
|
119
|
+
interface CompiledRoute {
|
|
120
|
+
/** Filesystem-derived path using `:param` (no Hono regex). `/`, `/about`, `/blog/:slug`. */
|
|
121
|
+
path: string;
|
|
122
|
+
/** Hono route pattern (`:slug{.+}` for catch-all). */
|
|
123
|
+
pattern: string;
|
|
124
|
+
isCatchAll: boolean;
|
|
125
|
+
isStatic: boolean;
|
|
126
|
+
paramNames: string[];
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Compile a pages-dir-relative file path to a Hono route.
|
|
130
|
+
* `(group)` dirs are omitted, `[param]` becomes `:param`, `[...slug]` becomes `:slug{.+}`,
|
|
131
|
+
* trailing `index` is dropped.
|
|
132
|
+
*/
|
|
133
|
+
declare function compileFilePath(relativePath: string): CompiledRoute;
|
|
134
|
+
declare function applyParams(path: string, params: Record<string, string>): string;
|
|
135
|
+
//#endregion
|
|
136
|
+
//#region src/vino/constants.d.ts
|
|
137
|
+
declare const PAGE_SLOT_ID = "vino-page";
|
|
138
|
+
declare const PAYLOAD_SCRIPT_ID = "__VINO__";
|
|
139
|
+
declare const COMPONENT_TAG = "vino-component";
|
|
140
|
+
declare const NAV_HEADER = "X-Vino-Nav";
|
|
141
|
+
declare const SHELL_HEADER = "X-Vino-Shell";
|
|
142
|
+
//#endregion
|
|
143
|
+
export { COMPONENT_TAG, type CreateVinoOptions, type DefinePageOptions, type LayoutProps, type ManifestPage, NAV_HEADER, PAGE_SLOT_ID, PAYLOAD_SCRIPT_ID, type PageConfig, type PageDefinition, type PageProps, type PageRender, type RenderMode, SHELL_HEADER, type ServerFn, type ServerFnHandler, type VinoManifest, type VinoPayload, type VinoViteOptions, applyParams, compileFilePath, createVino, definePage, defineServerFn, defineServerPage, isClientPageDefinition, isPageDefinition, isServerFn, isServerPageDefinition, mountVino, readServerFn, resolvePageRender, wrapComponent, wrapModule };
|
|
144
|
+
//# sourceMappingURL=vino.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vino.d.mts","names":[],"sources":["../src/vino/createVino.ts","../src/vino/defineServerFn.ts","../src/vino/definePage.ts","../src/vino/compile.ts","../src/vino/constants.ts"],"mappings":";;;;;;;;;iBAgGgB,UAAU,UAAU,KAAK,UAAU,QAAQ,yBAAyB,KAAK,KAAK,GAAG,GAAG,WAAW,UAAS,oBAAyB,KAAK,GAAG,GAAG;;;;;;iBAc5I,WAAW,UAAU,MAAM,KAAK,UAAU,SAAS,aAAa,+BAA+B,UAAS,oBAAyB,KAAK,GAAG,GAAG;;;cC5G/I;KAED,gBAAgB,aAAa,UAAU,MAAM,QACvD,GAAG,QAAQ,eACR,IAAI,QAAQ;;;;KAKL,SAAS,aAAa,UAAU,MAAM,OAAO,gBAAgB,GAAG;WACjE,aAAa;;iBAGR,WAAW,iBAAiB,SAAS;iBAIrC,aAAa,iBAAiB;;;;;;;;;;;;;;;;;;;iBAgC9B,eAAe,GAAG,UAAU,MAAM,KAAK,IAAI,gBAAgB,GAAG,KAAK,SAAS,GAAG;;;cChDlF;cACA;KAED,WAAW,mBAAmB,OAAO,UAAU,UAAU;UAEpD,kBAAkB;;EAEjC,SAAS,WAAW;EACpB,OAAO,WAAW;;EAElB,OAAO,aAAa,SAAS;EAC7B,SAAS;;UAGM,eAAe;WACrB,aAAa,mBAAmB;WAChC;WACA,QAAQ,WAAW;WACnB,OAAO,aAAa,SAAS;WAC7B,SAAS;;iBAGJ,iBAAiB,iBAAiB,SAAS;iBAS3C,uBAAuB,iBAAiB,SAAS;iBAIjD,uBAAuB,iBAAiB,SAAS;iBAQjD,kBAAkB,iBAAiB;;;;;;;;;;iBAyCnC,WAAW,gBAAgB,MAAM,WAAW,QAAQ,eAAe;;;;;;;;;;;;;;;iBAgBnE,WAAW,UAAU,aAAa,UAAU;EAC1D,QAAQ,WAAW,QAAQ,WAAW;EACtC,OAAO,WAAW,QAAQ,WAAW;EACrC,OAAO;EACP,SAAS;IACP,eAAe,QAAQ,WAAW;iBACtB,WAAW,gBAAgB,SAAS,kBAAkB,QAAQ,eAAe;;;;;;;iBAa7E,iBAAiB,gBAAgB,MAAM,WAAW,QAAQ,eAAe;iBACzE,iBAAiB,UAAU,aAAa,UAAU;EAChE,QAAQ,WAAW,QAAQ,WAAW;EACtC,OAAO,WAAW,QAAQ,WAAW;EACrC,OAAO;EACP,SAAS;IACP,eAAe,QAAQ,WAAW;iBACtB,iBAAiB,gBAC/B,SAAS,kBAAkB,QAC1B,eAAe;;;UCnID;;EAEf;;EAEA;EACA;EACA;EACA;;;;;;;iBAoBc,gBAAgB,uBAAuB;iBA8DvC,YAAY,cAAc,QAAQ;;;cCzFrC;cACA;cACA;cAKA;cACA"}
|