@kasperrt/smolter 0.0.1 → 0.3.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/{src/internal → .generated}/client/index.ts +1 -0
- package/.generated/core/environment.ts +43 -0
- package/{src/internal → .generated}/core/errors.ts +1 -1
- package/{src/internal → .generated}/core/index.ts +2 -0
- package/.generated/core/navigation-router.ts +107 -0
- package/.generated/core/navigation.ts +147 -0
- package/.generated/core/presentation.ts +108 -0
- package/.generated/core/resource-types.ts +44 -0
- package/.generated/core/resources.ts +444 -0
- package/.generated/core/responses.ts +86 -0
- package/{src/internal → .generated}/core/router.ts +136 -63
- package/.generated/core/serialize.ts +20 -0
- package/.generated/core/store.ts +25 -0
- package/.generated/core/submission.ts +116 -0
- package/{src/internal → .generated}/core/types.ts +18 -1
- package/.generated/core/url.ts +29 -0
- package/.generated/core/utils.ts +5 -0
- package/.generated/preact/await.tsx +41 -0
- package/.generated/preact/client.tsx +93 -0
- package/.generated/preact/context.ts +59 -0
- package/.generated/preact/document.tsx +198 -0
- package/{src/internal → .generated}/preact/fetcher.ts +43 -23
- package/.generated/preact/form.ts +58 -0
- package/{src/internal → .generated}/preact/hooks.ts +25 -28
- package/.generated/preact/index.ts +34 -0
- package/.generated/preact/lazy-route.ts +100 -0
- package/.generated/preact/navigation-state.ts +9 -0
- package/.generated/preact/navigation.tsx +147 -0
- package/.generated/preact/root-context.ts +21 -0
- package/.generated/preact/root-data.ts +45 -0
- package/.generated/preact/route-hooks.tsx +170 -0
- package/.generated/preact/route-types.ts +76 -0
- package/.generated/preact/router.tsx +107 -0
- package/{src/internal → .generated}/preact/routes.ts +17 -9
- package/.generated/react/context.ts +59 -0
- package/.generated/react/data.ts +25 -0
- package/{src/internal → .generated}/react/fetcher.ts +13 -11
- package/.generated/react/form.ts +58 -0
- package/{src/internal → .generated}/react/hooks.ts +9 -14
- package/{src/internal/preact → .generated/react}/index.ts +5 -1
- package/{src/internal → .generated}/react/link.ts +13 -21
- package/.generated/react/resources/components.tsx +404 -0
- package/{src/internal → .generated}/react/routes.ts +17 -9
- package/.generated/server/application.tsx +185 -0
- package/.generated/server/assets.ts +19 -0
- package/.generated/server/handler.ts +69 -0
- package/.generated/server/http.ts +55 -0
- package/{src/internal → .generated}/server/index.ts +4 -17
- package/.generated/server/node.ts +4 -0
- package/.generated/server/preact.ts +7 -0
- package/.generated/vite/application/browser-boundary.ts +42 -0
- package/.generated/vite/application/lazy-files.ts +136 -0
- package/.generated/vite/application/vite.ts +144 -0
- package/{src/internal → .generated}/vite/index.ts +4 -2
- package/.generated/vite/preact.ts +24 -0
- package/.generated/vite/react.ts +18 -0
- package/{src/internal → .generated}/vite/transport.ts +2 -1
- package/CHANGELOG.md +54 -0
- package/README.md +269 -55
- package/dist/client/deserialize.js +10 -0
- package/dist/{internal/client → client}/index.d.ts +1 -0
- package/dist/client/index.js +46 -0
- package/dist/core/environment.d.ts +12 -0
- package/dist/core/environment.js +23 -0
- package/dist/core/errors.js +7 -0
- package/dist/{internal/core → core}/index.d.ts +2 -0
- package/dist/core/match.js +33 -0
- package/dist/core/navigation-router.d.ts +15 -0
- package/dist/core/navigation-router.js +64 -0
- package/dist/core/navigation.d.ts +15 -0
- package/dist/core/navigation.js +92 -0
- package/dist/core/presentation.d.ts +5 -0
- package/dist/core/presentation.js +69 -0
- package/dist/core/resource-types.d.ts +37 -0
- package/dist/core/resources.d.ts +19 -0
- package/dist/core/resources.js +345 -0
- package/dist/core/responses.d.ts +15 -0
- package/dist/core/responses.js +48 -0
- package/dist/{internal/core → core}/router.d.ts +1 -1
- package/dist/core/router.js +204 -0
- package/dist/core/serialize.d.ts +5 -0
- package/dist/core/serialize.js +17 -0
- package/dist/core/store.d.ts +6 -0
- package/dist/core/store.js +21 -0
- package/dist/core/submission.d.ts +30 -0
- package/dist/core/submission.js +41 -0
- package/dist/{internal/core → core}/types.d.ts +16 -1
- package/dist/core/url.d.ts +7 -0
- package/dist/core/url.js +12 -0
- package/dist/core/utils.d.ts +5 -0
- package/dist/core/utils.js +5 -0
- package/dist/files/index.js +64 -0
- package/dist/preact/await.d.ts +7 -0
- package/dist/preact/await.js +19 -0
- package/dist/preact/client.d.ts +7 -0
- package/dist/preact/client.js +67 -0
- package/dist/preact/context.d.ts +18 -0
- package/dist/preact/context.js +23 -0
- package/dist/preact/document.d.ts +15 -0
- package/dist/preact/document.js +155 -0
- package/dist/{internal/preact → preact}/fetcher.d.ts +9 -5
- package/dist/preact/fetcher.js +45 -0
- package/dist/{internal/preact → preact}/form.d.ts +5 -6
- package/dist/preact/form.js +21 -0
- package/dist/{internal/preact → preact}/hooks.d.ts +7 -6
- package/dist/preact/hooks.js +25 -0
- package/dist/preact/index.d.ts +18 -0
- package/dist/preact/index.js +15 -0
- package/dist/preact/lazy-route.d.ts +19 -0
- package/dist/preact/lazy-route.js +51 -0
- package/dist/preact/navigation-state.d.ts +2 -0
- package/dist/preact/navigation-state.js +9 -0
- package/dist/preact/navigation.d.ts +28 -0
- package/dist/preact/navigation.js +60 -0
- package/dist/preact/root-context.d.ts +13 -0
- package/dist/preact/root-context.js +9 -0
- package/dist/preact/root-data.d.ts +8 -0
- package/dist/preact/root-data.js +28 -0
- package/dist/preact/route-hooks.d.ts +32 -0
- package/dist/preact/route-hooks.js +94 -0
- package/dist/preact/route-types.d.ts +54 -0
- package/dist/preact/router.d.ts +16 -0
- package/dist/preact/router.js +63 -0
- package/dist/{internal/preact → preact}/routes.d.ts +1 -1
- package/dist/preact/routes.js +12 -0
- package/dist/{internal/preact → preact}/runtime.js +1 -1
- package/dist/react/context.d.ts +18 -0
- package/dist/react/context.js +23 -0
- package/dist/react/data.d.ts +5 -0
- package/dist/react/data.js +3 -0
- package/dist/{internal/react → react}/fetcher.d.ts +2 -2
- package/dist/react/fetcher.js +34 -0
- package/dist/{internal/react → react}/form.d.ts +5 -6
- package/dist/react/form.js +21 -0
- package/dist/react/hooks.js +25 -0
- package/dist/{internal/react → react}/index.d.ts +1 -1
- package/dist/react/index.js +10 -0
- package/dist/{internal/react → react}/link.d.ts +2 -2
- package/dist/react/link.js +27 -0
- package/dist/react/resources/components.d.ts +64 -0
- package/dist/react/resources/components.js +239 -0
- package/dist/{internal/react → react}/routes.d.ts +1 -1
- package/dist/react/routes.js +12 -0
- package/dist/react/runtime.js +1 -0
- package/dist/server/application.d.ts +4 -0
- package/dist/server/application.js +119 -0
- package/dist/server/assets.d.ts +5 -0
- package/dist/server/assets.js +7 -0
- package/dist/server/handler.d.ts +19 -0
- package/dist/server/handler.js +22 -0
- package/dist/server/http.d.ts +4 -0
- package/dist/server/http.js +27 -0
- package/dist/{internal/server → server}/index.d.ts +2 -3
- package/dist/server/index.js +76 -0
- package/dist/server/node.d.ts +3 -0
- package/dist/server/node.js +3 -0
- package/dist/server/preact.d.ts +3 -0
- package/dist/server/preact.js +4 -0
- package/dist/vite/application/browser-boundary.d.ts +3 -0
- package/dist/vite/application/browser-boundary.js +35 -0
- package/dist/vite/application/lazy-files.d.ts +2 -0
- package/dist/vite/application/lazy-files.js +87 -0
- package/dist/vite/application/vite.d.ts +9 -0
- package/dist/vite/application/vite.js +101 -0
- package/dist/{internal/vite → vite}/index.d.ts +2 -1
- package/dist/vite/index.js +104 -0
- package/dist/vite/preact.d.ts +11 -0
- package/dist/vite/preact.js +15 -0
- package/dist/vite/react.d.ts +9 -0
- package/dist/vite/react.js +14 -0
- package/dist/{internal/vite → vite}/transport.d.ts +1 -1
- package/dist/vite/transport.js +35 -0
- package/jsr.json +28 -11
- package/package.json +119 -38
- package/dist/client.d.ts +0 -2
- package/dist/client.js +0 -2
- package/dist/core.d.ts +0 -2
- package/dist/core.js +0 -2
- package/dist/files.d.ts +0 -2
- package/dist/files.js +0 -2
- package/dist/internal/client/deserialize.js +0 -11
- package/dist/internal/client/index.js +0 -44
- package/dist/internal/core/errors.js +0 -6
- package/dist/internal/core/index.js +0 -6
- package/dist/internal/core/match.js +0 -27
- package/dist/internal/core/router.js +0 -189
- package/dist/internal/core/types.js +0 -5
- package/dist/internal/core/url.d.ts +0 -2
- package/dist/internal/core/url.js +0 -6
- package/dist/internal/files/index.js +0 -77
- package/dist/internal/preact/context.d.ts +0 -18
- package/dist/internal/preact/context.js +0 -20
- package/dist/internal/preact/fetcher.js +0 -28
- package/dist/internal/preact/form.js +0 -41
- package/dist/internal/preact/hooks.js +0 -35
- package/dist/internal/preact/index.d.ts +0 -9
- package/dist/internal/preact/index.js +0 -7
- package/dist/internal/preact/link.d.ts +0 -12
- package/dist/internal/preact/link.js +0 -28
- package/dist/internal/preact/routes.js +0 -22
- package/dist/internal/react/context.d.ts +0 -18
- package/dist/internal/react/context.js +0 -20
- package/dist/internal/react/fetcher.js +0 -28
- package/dist/internal/react/form.js +0 -41
- package/dist/internal/react/hooks.js +0 -35
- package/dist/internal/react/index.js +0 -7
- package/dist/internal/react/link.js +0 -28
- package/dist/internal/react/routes.js +0 -22
- package/dist/internal/react/runtime.js +0 -2
- package/dist/internal/server/index.js +0 -81
- package/dist/internal/vite/index.js +0 -132
- package/dist/internal/vite/transport.js +0 -42
- package/dist/preact.d.ts +0 -2
- package/dist/preact.js +0 -2
- package/dist/react.d.ts +0 -2
- package/dist/react.js +0 -2
- package/dist/server.d.ts +0 -2
- package/dist/server.js +0 -2
- package/dist/vite.d.ts +0 -2
- package/dist/vite.js +0 -2
- package/src/client.ts +0 -2
- package/src/core.ts +0 -2
- package/src/files.ts +0 -2
- package/src/internal/core/url.ts +0 -6
- package/src/internal/preact/context.ts +0 -46
- package/src/internal/preact/form.ts +0 -79
- package/src/internal/preact/link.ts +0 -46
- package/src/internal/react/context.ts +0 -46
- package/src/internal/react/form.ts +0 -79
- package/src/internal/react/index.ts +0 -13
- package/src/preact.ts +0 -2
- package/src/react.ts +0 -2
- package/src/server.ts +0 -2
- package/src/vite.ts +0 -2
- /package/{src/internal → .generated}/client/deserialize.ts +0 -0
- /package/{src/internal → .generated}/core/match.ts +0 -0
- /package/{src/internal → .generated}/files/index.ts +0 -0
- /package/{src/internal → .generated}/preact/runtime.ts +0 -0
- /package/{src/internal → .generated}/react/runtime.ts +0 -0
- /package/dist/{internal/client → client}/deserialize.d.ts +0 -0
- /package/dist/{internal/core → core}/errors.d.ts +0 -0
- /package/dist/{internal/core → core}/match.d.ts +0 -0
- /package/dist/{internal/files → files}/index.d.ts +0 -0
- /package/dist/{internal/preact → preact}/runtime.d.ts +0 -0
- /package/dist/{internal/react → react}/hooks.d.ts +0 -0
- /package/dist/{internal/react → react}/runtime.d.ts +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { flatRoutes } from "../files/index.js";
|
|
2
|
+
import { configureTransport } from "./transport.js";
|
|
3
|
+
import { readFile } from "node:fs/promises";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { transformWithOxc } from "vite";
|
|
6
|
+
//#region .generated/vite/index.ts
|
|
7
|
+
/** Build-time flat route discovery and the optional server data transport. */
|
|
8
|
+
function routerPlugin({ directory = "src/routes", clientRoutes, serverRoutes, framework = "react" } = {}) {
|
|
9
|
+
let root;
|
|
10
|
+
let projectRoot;
|
|
11
|
+
const publicId = "virtual:smolter/routes";
|
|
12
|
+
const virtualId = `\0${publicId}`;
|
|
13
|
+
const suffix = "?smolter-client";
|
|
14
|
+
return {
|
|
15
|
+
name: "smolter-flat-routes",
|
|
16
|
+
enforce: "pre",
|
|
17
|
+
configResolved(config) {
|
|
18
|
+
projectRoot = config.root;
|
|
19
|
+
root = resolve(config.root, directory);
|
|
20
|
+
},
|
|
21
|
+
resolveId(id) {
|
|
22
|
+
if (id === publicId) return virtualId;
|
|
23
|
+
},
|
|
24
|
+
async load(id, options) {
|
|
25
|
+
if (id.endsWith(suffix)) {
|
|
26
|
+
const file = id.slice(0, -15);
|
|
27
|
+
const transformed = await transformWithOxc(await readFile(file, "utf8"), file);
|
|
28
|
+
const ast = this.parse(transformed.code);
|
|
29
|
+
const edits = [];
|
|
30
|
+
for (const statement of ast.body) {
|
|
31
|
+
if (statement.type === "ExportAllDeclaration") return this.error(`Use explicit named exports in ${file}; export * cannot be safely split between server and browser.`);
|
|
32
|
+
if (statement.type !== "ExportNamedDeclaration") continue;
|
|
33
|
+
const server = statement.specifiers.filter((specifier) => {
|
|
34
|
+
const name = specifier.exported.type === "Identifier" ? specifier.exported.name : specifier.exported.value;
|
|
35
|
+
return name === "loader" || name === "action";
|
|
36
|
+
});
|
|
37
|
+
if (!server.length) {
|
|
38
|
+
const declaration = statement.declaration;
|
|
39
|
+
const name = declaration?.type === "FunctionDeclaration" ? declaration.id?.name : void 0;
|
|
40
|
+
const variables = declaration?.type === "VariableDeclaration" ? declaration.declarations : [];
|
|
41
|
+
if (name === "loader" || name === "action" || variables.some((item) => item.id.type === "Identifier" && ["loader", "action"].includes(item.id.name))) return this.error(`Re-export loader/action from separate files in ${file}; inline server handlers cannot enter a browser module.`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!statement.source || server.length !== statement.specifiers.length) return this.error(`Use separate export { loader } / export { action } statements in ${file}.`);
|
|
45
|
+
edits.push([statement.start, statement.end]);
|
|
46
|
+
}
|
|
47
|
+
let code = transformed.code;
|
|
48
|
+
for (const [start, end] of edits.reverse()) code = code.slice(0, start) + code.slice(end);
|
|
49
|
+
return {
|
|
50
|
+
code,
|
|
51
|
+
map: null
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (id !== virtualId) return;
|
|
55
|
+
if (clientRoutes || serverRoutes) {
|
|
56
|
+
if (!clientRoutes || !serverRoutes) return this.error("Specify both clientRoutes and serverRoutes for manual routing.");
|
|
57
|
+
const entry = resolve(projectRoot, options?.ssr ? serverRoutes : clientRoutes).replaceAll("\\", "/");
|
|
58
|
+
return `export { routes as default } from ${JSON.stringify(entry)};`;
|
|
59
|
+
}
|
|
60
|
+
const routes = await flatRoutes(root);
|
|
61
|
+
if (routes instanceof Error) return this.error(routes.message);
|
|
62
|
+
const imports = [];
|
|
63
|
+
const definitions = [];
|
|
64
|
+
for (const [index, route] of routes.entries()) {
|
|
65
|
+
this.addWatchFile(route.file);
|
|
66
|
+
const file = route.file.replaceAll("\\", "/");
|
|
67
|
+
const transformed = await transformWithOxc(await readFile(file, "utf8"), file);
|
|
68
|
+
const ast = this.parse(transformed.code);
|
|
69
|
+
const handlers = {};
|
|
70
|
+
for (const statement of ast.body) {
|
|
71
|
+
if (statement.type !== "ExportNamedDeclaration") continue;
|
|
72
|
+
for (const specifier of statement.specifiers) {
|
|
73
|
+
const name = specifier.exported.type === "Identifier" ? specifier.exported.name : specifier.exported.value;
|
|
74
|
+
if (name === "loader" || name === "action") handlers[name] = true;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
imports.push(`import * as route${index} from ${JSON.stringify(file + (options?.ssr ? "" : suffix))};`);
|
|
78
|
+
definitions.push(options?.ssr || !Object.keys(handlers).length ? `{ ...route${index}, path: ${JSON.stringify(route.path)} }` : `serverRoute(${JSON.stringify(route.path)}, route${index}, ${JSON.stringify(handlers)})`);
|
|
79
|
+
}
|
|
80
|
+
if (!options?.ssr && definitions.some((definition) => definition.startsWith("serverRoute("))) imports.unshift(`import { serverRoute } from "@kasperrt/smolter/${framework}/client";`);
|
|
81
|
+
return `${imports.join("\n")}\nexport default [${definitions.join(",\n")}];\n`;
|
|
82
|
+
},
|
|
83
|
+
configureServer(server) {
|
|
84
|
+
server.watcher.add(root);
|
|
85
|
+
const refresh = (file) => {
|
|
86
|
+
if (!file.startsWith(`${root}/`)) return;
|
|
87
|
+
const module = server.moduleGraph.getModuleById(virtualId);
|
|
88
|
+
if (module) server.moduleGraph.invalidateModule(module);
|
|
89
|
+
server.ws.send({ type: "full-reload" });
|
|
90
|
+
};
|
|
91
|
+
server.watcher.on("add", refresh);
|
|
92
|
+
server.watcher.on("change", refresh);
|
|
93
|
+
server.watcher.on("unlink", refresh);
|
|
94
|
+
server.httpServer?.once("close", () => {
|
|
95
|
+
server.watcher.off("add", refresh);
|
|
96
|
+
server.watcher.off("change", refresh);
|
|
97
|
+
server.watcher.off("unlink", refresh);
|
|
98
|
+
});
|
|
99
|
+
configureTransport(server, publicId, framework);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
//#endregion
|
|
104
|
+
export { routerPlugin };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Optional flat-file routing for Preact builds. @module */
|
|
2
|
+
import type { Plugin } from "vite";
|
|
3
|
+
import { type FileRouterOptions } from "./index.ts";
|
|
4
|
+
export * from "../files/index.ts";
|
|
5
|
+
export type { FileRouterOptions } from "./index.ts";
|
|
6
|
+
/** Configure flat routes and server transport for Preact. */
|
|
7
|
+
export declare function routerPlugin(options?: FileRouterOptions): Plugin;
|
|
8
|
+
/** File routing is the default; this alias keeps configuration explicit. */
|
|
9
|
+
export declare const fileRouter: typeof routerPlugin;
|
|
10
|
+
export type { ApplicationOptions } from "./application/vite.ts";
|
|
11
|
+
export { applicationPlugins, preactConfig, } from "./application/vite.ts";
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { flatRoutes } from "../files/index.js";
|
|
2
|
+
import { routerPlugin as routerPlugin$1 } from "./index.js";
|
|
3
|
+
import { applicationPlugins, preactConfig } from "./application/vite.js";
|
|
4
|
+
//#region .generated/vite/preact.ts
|
|
5
|
+
/** Configure flat routes and server transport for Preact. */
|
|
6
|
+
function routerPlugin(options = {}) {
|
|
7
|
+
return routerPlugin$1({
|
|
8
|
+
...options,
|
|
9
|
+
framework: "preact"
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
/** File routing is the default; this alias keeps configuration explicit. */
|
|
13
|
+
var fileRouter = routerPlugin;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { applicationPlugins, fileRouter, flatRoutes, preactConfig, routerPlugin };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Optional flat-file routing for React builds. @module */
|
|
2
|
+
import type { Plugin } from "vite";
|
|
3
|
+
import { type FileRouterOptions } from "./index.ts";
|
|
4
|
+
export * from "../files/index.ts";
|
|
5
|
+
export type { FileRouterOptions } from "./index.ts";
|
|
6
|
+
/** Configure flat routes and server transport for React. */
|
|
7
|
+
export declare function routerPlugin(options?: FileRouterOptions): Plugin;
|
|
8
|
+
/** File routing is the default; this alias keeps configuration explicit. */
|
|
9
|
+
export declare const fileRouter: typeof routerPlugin;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { flatRoutes } from "../files/index.js";
|
|
2
|
+
import { routerPlugin as routerPlugin$1 } from "./index.js";
|
|
3
|
+
//#region .generated/vite/react.ts
|
|
4
|
+
/** Configure flat routes and server transport for React. */
|
|
5
|
+
function routerPlugin(options = {}) {
|
|
6
|
+
return routerPlugin$1({
|
|
7
|
+
...options,
|
|
8
|
+
framework: "react"
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
/** File routing is the default; this alias keeps configuration explicit. */
|
|
12
|
+
var fileRouter = routerPlugin;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { fileRouter, flatRoutes, routerPlugin };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ViteDevServer } from "vite";
|
|
2
|
-
export declare function configureTransport(server: ViteDevServer, publicId: string): void;
|
|
2
|
+
export declare function configureTransport(server: ViteDevServer, publicId: string, framework?: "react" | "preact"): void;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//#region .generated/vite/transport.ts
|
|
2
|
+
function configureTransport(server, publicId, framework = "react") {
|
|
3
|
+
server.middlewares.use((incoming, outgoing, next) => {
|
|
4
|
+
if (!incoming.url?.startsWith("/_smolter?")) return next();
|
|
5
|
+
const dispatch = async () => {
|
|
6
|
+
const origin = `http://${incoming.headers.host}`;
|
|
7
|
+
const target = new URL(incoming.url, origin).searchParams.get("url");
|
|
8
|
+
if (!target?.startsWith("/") || target.startsWith("//")) {
|
|
9
|
+
outgoing.statusCode = 400;
|
|
10
|
+
outgoing.end("Invalid route URL");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
const headers = new Headers();
|
|
14
|
+
for (const [name, value] of Object.entries(incoming.headers)) if (value) headers.set(name, Array.isArray(value) ? value.join(", ") : value);
|
|
15
|
+
const chunks = [];
|
|
16
|
+
for await (const chunk of incoming) chunks.push(chunk);
|
|
17
|
+
const controller = new AbortController();
|
|
18
|
+
outgoing.once("close", () => controller.abort());
|
|
19
|
+
const request = new Request(new URL(target, origin), {
|
|
20
|
+
signal: controller.signal,
|
|
21
|
+
method: incoming.method,
|
|
22
|
+
headers,
|
|
23
|
+
...incoming.method !== "GET" && { body: new Uint8Array(Buffer.concat(chunks)) }
|
|
24
|
+
});
|
|
25
|
+
const [{ default: routes }, { handleRequest }] = await Promise.all([server.ssrLoadModule(publicId), server.ssrLoadModule(`@kasperrt/smolter/${framework}/server`)]);
|
|
26
|
+
const response = await handleRequest(routes, request);
|
|
27
|
+
outgoing.statusCode = response.status;
|
|
28
|
+
response.headers.forEach((value, name) => outgoing.setHeader(name, value));
|
|
29
|
+
outgoing.end(new Uint8Array(await response.arrayBuffer()));
|
|
30
|
+
};
|
|
31
|
+
dispatch().catch(next);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { configureTransport };
|
package/jsr.json
CHANGED
|
@@ -1,22 +1,39 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kasperrt/smolter",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"exports": {
|
|
5
|
-
"
|
|
6
|
-
"./preact": "
|
|
7
|
-
"./
|
|
8
|
-
"./server": "
|
|
9
|
-
"./client": "
|
|
10
|
-
"./
|
|
11
|
-
"./
|
|
5
|
+
"./react": "./.generated/react/index.ts",
|
|
6
|
+
"./preact": "./.generated/preact/index.ts",
|
|
7
|
+
"./react/server": "./.generated/server/index.ts",
|
|
8
|
+
"./preact/server": "./.generated/server/preact.ts",
|
|
9
|
+
"./react/client": "./.generated/client/index.ts",
|
|
10
|
+
"./preact/client": "./.generated/preact/client.tsx",
|
|
11
|
+
"./utils": "./.generated/core/utils.ts",
|
|
12
|
+
"./utils/http": "./.generated/server/node.ts",
|
|
13
|
+
"./utils/assets": "./.generated/server/assets.ts",
|
|
14
|
+
"./utils/responses": "./.generated/core/responses.ts",
|
|
15
|
+
"./react/data": "./.generated/react/data.ts",
|
|
16
|
+
"./preact/lazy-route": "./.generated/preact/lazy-route.ts",
|
|
17
|
+
"./preact/document": "./.generated/preact/document.tsx"
|
|
12
18
|
},
|
|
13
19
|
"imports": {
|
|
14
20
|
"react": "npm:react@19.3.1",
|
|
15
|
-
"preact/compat": "npm:preact@11.0.1/compat"
|
|
21
|
+
"preact/compat": "npm:preact@11.0.1/compat",
|
|
22
|
+
"preact": "npm:preact@11.0.1",
|
|
23
|
+
"preact/hooks": "npm:preact@11.0.1/hooks",
|
|
24
|
+
"preact/jsx-runtime": "npm:preact@11.0.1/jsx-runtime",
|
|
25
|
+
"preact-render-to-string": "npm:preact-render-to-string@6.8.1",
|
|
26
|
+
"react/jsx-runtime": "npm:react@19.3.1/jsx-runtime"
|
|
16
27
|
},
|
|
17
28
|
"publish": {
|
|
18
|
-
"include": [
|
|
19
|
-
|
|
29
|
+
"include": [
|
|
30
|
+
".generated",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"jsr.json",
|
|
34
|
+
"CHANGELOG.md"
|
|
35
|
+
],
|
|
36
|
+
"exclude": [".generated/vite"]
|
|
20
37
|
},
|
|
21
38
|
"license": "MIT",
|
|
22
39
|
"compatibility": {
|
package/package.json
CHANGED
|
@@ -1,64 +1,144 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kasperrt/smolter",
|
|
3
|
-
"
|
|
4
|
-
"description": "A tiny typed data router for React and Preact.",
|
|
3
|
+
"packageManager": "pnpm@11.8.0",
|
|
5
4
|
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
7
|
+
"dev": "pnpm build && pnpm --parallel --filter \"@smolter/example-*\" dev",
|
|
8
|
+
"fix": "biome check --write .",
|
|
9
|
+
"lint": "biome check .",
|
|
10
|
+
"typecheck": "pnpm build && tsc --noEmit",
|
|
11
|
+
"test": "pnpm build && vitest run --project unit",
|
|
12
|
+
"coverage": "pnpm build && vitest run --coverage",
|
|
13
|
+
"smoke": "playwright test",
|
|
14
|
+
"size": "pnpm build && node scripts/size.mjs",
|
|
15
|
+
"check": "pnpm lint && pnpm typecheck && pnpm test && pnpm size",
|
|
16
|
+
"version:patch": "node scripts/version.mjs patch",
|
|
17
|
+
"version:minor": "node scripts/version.mjs minor",
|
|
18
|
+
"version:release": "node scripts/version.mjs release",
|
|
19
|
+
"pack:smoke": "node scripts/pack-smoke.mjs",
|
|
20
|
+
"build:examples": "pnpm --filter \"@smolter/example-*\" build",
|
|
21
|
+
"smoke:production": "node scripts/production-smoke.mjs",
|
|
22
|
+
"jsr:check": "node scripts/jsr.mjs",
|
|
23
|
+
"build:site": "vite build --config apps/site/vite.config.ts && pnpm --filter @smolter/example-react build --mode hosted && pnpm --filter @smolter/example-preact build --mode hosted",
|
|
24
|
+
"smoke:site": "node scripts/site-smoke.mjs",
|
|
25
|
+
"docs:badges": "node scripts/readme-badges.mjs",
|
|
26
|
+
"docs:reference": "pnpm build && node scripts/docs-reference.mjs",
|
|
27
|
+
"docs:check": "pnpm build && node scripts/docs-reference.mjs --check"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@biomejs/biome": "2.5.15",
|
|
31
|
+
"@playwright/test": "1.64.1",
|
|
32
|
+
"@smolter/client": "workspace:*",
|
|
33
|
+
"@smolter/core": "workspace:*",
|
|
34
|
+
"@smolter/files": "workspace:*",
|
|
35
|
+
"@smolter/preact": "workspace:*",
|
|
36
|
+
"@smolter/react": "workspace:*",
|
|
37
|
+
"@smolter/server": "workspace:*",
|
|
38
|
+
"@smolter/vite": "workspace:*",
|
|
39
|
+
"@types/node": "24.10.1",
|
|
40
|
+
"@types/react": "19.3.0",
|
|
41
|
+
"@types/react-dom": "19.3.0",
|
|
42
|
+
"@vitejs/plugin-react": "6.1.2",
|
|
43
|
+
"@vitest/browser-playwright": "5.0.5",
|
|
44
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
45
|
+
"esbuild": "0.28.2",
|
|
46
|
+
"oxc-transform-react": "0.152.0",
|
|
47
|
+
"preact": "11.0.1",
|
|
48
|
+
"preact-render-to-string": "6.8.1",
|
|
49
|
+
"react": "19.3.1",
|
|
50
|
+
"react-dom": "19.3.1",
|
|
51
|
+
"react-router": "8.4.0",
|
|
52
|
+
"terser": "5.44.1",
|
|
53
|
+
"typescript": "6.0.3",
|
|
54
|
+
"vite": "8.3.4",
|
|
55
|
+
"vitest": "5.0.5",
|
|
56
|
+
"wouter": "3.13.0",
|
|
57
|
+
"wouter-preact": "3.13.0"
|
|
58
|
+
},
|
|
59
|
+
"version": "0.3.0",
|
|
60
|
+
"description": "A tiny typed data router for React and Preact.",
|
|
6
61
|
"sideEffects": false,
|
|
7
62
|
"license": "MIT",
|
|
8
63
|
"repository": {
|
|
9
64
|
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/kasperrt/smolter.git"
|
|
11
|
-
"directory": "packages/smolter"
|
|
65
|
+
"url": "git+https://github.com/kasperrt/smolter.git"
|
|
12
66
|
},
|
|
13
67
|
"exports": {
|
|
14
|
-
"
|
|
15
|
-
"types": "./dist/
|
|
16
|
-
"import": "./dist/
|
|
68
|
+
"./react": {
|
|
69
|
+
"types": "./dist/react/index.d.ts",
|
|
70
|
+
"import": "./dist/react/index.js"
|
|
17
71
|
},
|
|
18
72
|
"./preact": {
|
|
19
|
-
"types": "./dist/preact.d.ts",
|
|
20
|
-
"import": "./dist/preact.js"
|
|
73
|
+
"types": "./dist/preact/index.d.ts",
|
|
74
|
+
"import": "./dist/preact/index.js"
|
|
21
75
|
},
|
|
22
|
-
"./
|
|
23
|
-
"types": "./dist/
|
|
24
|
-
"import": "./dist/
|
|
76
|
+
"./react/server": {
|
|
77
|
+
"types": "./dist/server/index.d.ts",
|
|
78
|
+
"import": "./dist/server/index.js"
|
|
25
79
|
},
|
|
26
|
-
"./server": {
|
|
27
|
-
"types": "./dist/server.d.ts",
|
|
28
|
-
"import": "./dist/server.js"
|
|
80
|
+
"./preact/server": {
|
|
81
|
+
"types": "./dist/server/preact.d.ts",
|
|
82
|
+
"import": "./dist/server/preact.js"
|
|
29
83
|
},
|
|
30
|
-
"./
|
|
31
|
-
"types": "./dist/
|
|
32
|
-
"import": "./dist/
|
|
84
|
+
"./react/client": {
|
|
85
|
+
"types": "./dist/client/index.d.ts",
|
|
86
|
+
"import": "./dist/client/index.js"
|
|
33
87
|
},
|
|
34
|
-
"./
|
|
35
|
-
"types": "./dist/
|
|
36
|
-
"import": "./dist/
|
|
88
|
+
"./preact/client": {
|
|
89
|
+
"types": "./dist/preact/client.d.ts",
|
|
90
|
+
"import": "./dist/preact/client.js"
|
|
37
91
|
},
|
|
38
|
-
"./
|
|
39
|
-
"types": "./dist/
|
|
40
|
-
"import": "./dist/
|
|
92
|
+
"./react/vite": {
|
|
93
|
+
"types": "./dist/vite/react.d.ts",
|
|
94
|
+
"import": "./dist/vite/react.js"
|
|
41
95
|
},
|
|
42
|
-
"./
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
|
|
96
|
+
"./preact/vite": {
|
|
97
|
+
"types": "./dist/vite/preact.d.ts",
|
|
98
|
+
"import": "./dist/vite/preact.js"
|
|
99
|
+
},
|
|
100
|
+
"./utils": {
|
|
101
|
+
"types": "./dist/core/utils.d.ts",
|
|
102
|
+
"import": "./dist/core/utils.js"
|
|
103
|
+
},
|
|
104
|
+
"./utils/http": {
|
|
105
|
+
"types": "./dist/server/node.d.ts",
|
|
106
|
+
"import": "./dist/server/node.js"
|
|
107
|
+
},
|
|
108
|
+
"./utils/assets": {
|
|
109
|
+
"types": "./dist/server/assets.d.ts",
|
|
110
|
+
"import": "./dist/server/assets.js"
|
|
111
|
+
},
|
|
112
|
+
"./utils/responses": {
|
|
113
|
+
"types": "./dist/core/responses.d.ts",
|
|
114
|
+
"import": "./dist/core/responses.js"
|
|
115
|
+
},
|
|
116
|
+
"./react/data": {
|
|
117
|
+
"types": "./dist/react/data.d.ts",
|
|
118
|
+
"import": "./dist/react/data.js"
|
|
119
|
+
},
|
|
120
|
+
"./preact/lazy-route": {
|
|
121
|
+
"types": "./dist/preact/lazy-route.d.ts",
|
|
122
|
+
"import": "./dist/preact/lazy-route.js"
|
|
123
|
+
},
|
|
124
|
+
"./preact/document": {
|
|
125
|
+
"types": "./dist/preact/document.d.ts",
|
|
126
|
+
"import": "./dist/preact/document.js"
|
|
46
127
|
}
|
|
47
128
|
},
|
|
48
129
|
"files": [
|
|
49
130
|
"dist",
|
|
50
|
-
"
|
|
131
|
+
".generated",
|
|
51
132
|
"README.md",
|
|
52
133
|
"LICENSE",
|
|
53
|
-
"jsr.json"
|
|
134
|
+
"jsr.json",
|
|
135
|
+
"CHANGELOG.md"
|
|
54
136
|
],
|
|
55
|
-
"scripts": {
|
|
56
|
-
"build": "node ../../scripts/build.mjs"
|
|
57
|
-
},
|
|
58
137
|
"peerDependencies": {
|
|
59
138
|
"react": ">=18",
|
|
60
|
-
"preact": ">=
|
|
61
|
-
"vite": ">=8"
|
|
139
|
+
"preact": ">=11.0.1",
|
|
140
|
+
"vite": ">=8",
|
|
141
|
+
"preact-render-to-string": ">=6"
|
|
62
142
|
},
|
|
63
143
|
"peerDependenciesMeta": {
|
|
64
144
|
"react": {
|
|
@@ -69,9 +149,12 @@
|
|
|
69
149
|
},
|
|
70
150
|
"vite": {
|
|
71
151
|
"optional": true
|
|
152
|
+
},
|
|
153
|
+
"preact-render-to-string": {
|
|
154
|
+
"optional": true
|
|
72
155
|
}
|
|
73
156
|
},
|
|
74
|
-
"author": "Kasper Rynning-
|
|
157
|
+
"author": "Kasper Rynning-T\u00f8nnesen <kasperrt@users.noreply.github.com> (https://github.com/kasperrt)",
|
|
75
158
|
"homepage": "https://kasperrt.github.io/smolter/",
|
|
76
159
|
"bugs": {
|
|
77
160
|
"url": "https://github.com/kasperrt/smolter/issues"
|
|
@@ -87,8 +170,6 @@
|
|
|
87
170
|
"ssr",
|
|
88
171
|
"file-routing"
|
|
89
172
|
],
|
|
90
|
-
"main": "./dist/core.js",
|
|
91
|
-
"types": "./dist/core.d.ts",
|
|
92
173
|
"publishConfig": {
|
|
93
174
|
"access": "public",
|
|
94
175
|
"provenance": true
|
package/dist/client.d.ts
DELETED
package/dist/client.js
DELETED
package/dist/core.d.ts
DELETED
package/dist/core.js
DELETED
package/dist/files.d.ts
DELETED
package/dist/files.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/** Restore a trusted snapshot produced by @kasperrt/smolter/server serialize, including its route error. */
|
|
2
|
-
export function deserialize(json) {
|
|
3
|
-
const snapshot = JSON.parse(json);
|
|
4
|
-
const error = snapshot.error;
|
|
5
|
-
if (error) {
|
|
6
|
-
snapshot.error = Object.assign(new Error(error.message), {
|
|
7
|
-
name: error.name,
|
|
8
|
-
});
|
|
9
|
-
}
|
|
10
|
-
return snapshot;
|
|
11
|
-
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Optional browser transport for server loaders and actions.
|
|
3
|
-
* @module
|
|
4
|
-
*/
|
|
5
|
-
export { deserialize } from "./deserialize.js";
|
|
6
|
-
/** Browser transport for server routes. File-router builds generate this call. */
|
|
7
|
-
export function serverRoute(path, module, handlers = { loader: true, action: true }) {
|
|
8
|
-
const remote = async ({ request, signal }) => {
|
|
9
|
-
const url = new URL(request.url);
|
|
10
|
-
const response = await fetch(`/_smolter?url=${encodeURIComponent(url.pathname + url.search)}`, {
|
|
11
|
-
method: request.method,
|
|
12
|
-
signal,
|
|
13
|
-
...(request.method !== "GET" && { body: await request.formData() }),
|
|
14
|
-
});
|
|
15
|
-
const location = response.headers.get("X-Smolter-Redirect");
|
|
16
|
-
if (location)
|
|
17
|
-
return new Response(null, {
|
|
18
|
-
status: 303,
|
|
19
|
-
headers: { Location: location },
|
|
20
|
-
});
|
|
21
|
-
const data = await response.json();
|
|
22
|
-
if (!response.ok)
|
|
23
|
-
return new Error(data.error ?? "Route request failed");
|
|
24
|
-
return data;
|
|
25
|
-
};
|
|
26
|
-
return {
|
|
27
|
-
...module,
|
|
28
|
-
path,
|
|
29
|
-
...(handlers.loader && { loader: remote }),
|
|
30
|
-
...(handlers.action && { action: remote }),
|
|
31
|
-
...(module.clientLoader && {
|
|
32
|
-
clientLoader: (args) => module.clientLoader({ ...args, serverLoader: () => remote(args) }),
|
|
33
|
-
}),
|
|
34
|
-
...(module.clientAction && {
|
|
35
|
-
clientAction: (args) => {
|
|
36
|
-
const request = args.request.clone();
|
|
37
|
-
return module.clientAction({
|
|
38
|
-
...args,
|
|
39
|
-
serverAction: () => remote({ ...args, request: request.clone() }),
|
|
40
|
-
});
|
|
41
|
-
},
|
|
42
|
-
}),
|
|
43
|
-
};
|
|
44
|
-
}
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/** Resolve returned or rejected errors into Error values without losing their cause. */
|
|
2
|
-
export function safeWrapAsync(work) {
|
|
3
|
-
return Promise.resolve()
|
|
4
|
-
.then(work)
|
|
5
|
-
.then((data) => (data instanceof Error ? { error: data } : { data }), (cause) => ({ error: new Error(String(cause), { cause }) }));
|
|
6
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/** Associate a URL pattern with a module while retaining its inferred handler types. */
|
|
2
|
-
export function defineRoute(path, module) {
|
|
3
|
-
return { ...module, path };
|
|
4
|
-
}
|
|
5
|
-
/** Static segments, :params and a terminal * wildcard; first match wins. */
|
|
6
|
-
export function matchRoutes(routes, pathname) {
|
|
7
|
-
const segments = pathname.replace(/\/$/, "").split("/");
|
|
8
|
-
for (const route of routes) {
|
|
9
|
-
const parts = route.path.replace(/\/$/, "").split("/");
|
|
10
|
-
const params = {};
|
|
11
|
-
const matched = (parts.length === segments.length || parts.at(-1) === "*") &&
|
|
12
|
-
parts.every((part, index) => {
|
|
13
|
-
const value = segments[index];
|
|
14
|
-
if (part === "*") {
|
|
15
|
-
params["*"] = segments.slice(index).join("/");
|
|
16
|
-
return true;
|
|
17
|
-
}
|
|
18
|
-
if (part[0] === ":" && value) {
|
|
19
|
-
params[part.slice(1)] = new URLSearchParams(`=${value.replace(/[+&]/g, encodeURIComponent)}`).get("");
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
return part === value;
|
|
23
|
-
});
|
|
24
|
-
if (matched)
|
|
25
|
-
return { route, params };
|
|
26
|
-
}
|
|
27
|
-
}
|