@torpor/build 0.0.5 → 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/CHANGELOG.md +14 -0
- package/README.md +1 -1
- package/dist/Server-CB99REgs.d.cts +74 -0
- package/dist/Server-CB99REgs.d.ts +74 -0
- package/dist/Site-CgoeDt8k.d.cts +29 -0
- package/dist/Site-D95nwrAg.d.ts +29 -0
- package/dist/adapters/cloudflare/index.cjs +125 -0
- package/dist/adapters/cloudflare/index.cjs.map +1 -0
- package/dist/adapters/cloudflare/index.d.cts +13 -0
- package/dist/adapters/cloudflare/index.d.ts +13 -0
- package/dist/adapters/cloudflare/index.js +80 -0
- package/dist/adapters/cloudflare/index.js.map +1 -0
- package/dist/adapters/node/index.cjs +152 -0
- package/dist/adapters/node/index.cjs.map +1 -0
- package/dist/adapters/node/index.d.cts +8 -0
- package/dist/adapters/node/index.d.ts +8 -0
- package/dist/adapters/node/index.js +8 -0
- package/dist/adapters/node/index.js.map +1 -0
- package/dist/bin/index.cjs +541 -93
- package/dist/bin/index.cjs.map +1 -1
- package/dist/bin/index.js +511 -22
- package/dist/bin/index.js.map +1 -1
- package/dist/chunk-5X4T3PZN.js +23 -0
- package/dist/chunk-5X4T3PZN.js.map +1 -0
- package/dist/chunk-ALHFYD7U.js +113 -0
- package/dist/chunk-ALHFYD7U.js.map +1 -0
- package/dist/chunk-V4XTDQEV.js +19 -0
- package/dist/chunk-V4XTDQEV.js.map +1 -0
- package/dist/chunk-VAGHGWM5.js +110 -0
- package/dist/chunk-VAGHGWM5.js.map +1 -0
- package/dist/index.cjs +200 -97
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +33 -36
- package/dist/index.d.ts +33 -36
- package/dist/index.js +85 -17
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/response.js +17 -91
- package/dist/response.js.map +1 -1
- package/package.json +26 -9
- package/src/adapters/cloudflare/_worker.ts +38 -0
- package/src/adapters/cloudflare/index.ts +98 -0
- package/src/adapters/node/constants.ts +1 -0
- package/src/adapters/node/createFetchHandler.ts +29 -0
- package/src/adapters/node/createMiddlewareHandler.ts +79 -0
- package/src/adapters/node/createNodeServer.ts +8 -0
- package/src/adapters/node/flattenHeaders.ts +44 -0
- package/src/adapters/node/index.ts +18 -0
- package/src/adapters/node/nodeMessageToNodeResponse.ts +89 -0
- package/src/adapters/node/nodeMessageToRequest.ts +43 -0
- package/src/adapters/node/readableToBuffer.ts +16 -0
- package/src/adapters/node/requestToNodeMessage.ts +26 -0
- package/src/adapters/node/responseToNodeResponse.ts +44 -0
- package/src/bin/index.ts +43 -36
- package/src/index.ts +6 -14
- package/src/server/CookieHelper.ts +36 -0
- package/src/server/HeaderHelper.ts +25 -0
- package/src/server/Server.ts +119 -0
- package/src/server/ServerEvent.ts +33 -0
- package/src/server/ServerFunction.ts +5 -0
- package/src/server/contentType.ts +85 -0
- package/src/site/Router.ts +136 -0
- package/src/site/Routerx.ts +67 -0
- package/src/site/Site.ts +114 -0
- package/src/site/clientEntry.ts +22 -20
- package/src/site/manifest.ts +49 -0
- package/src/site/pathToRegex.ts +10 -0
- package/src/site/prepareTemplate.ts +20 -0
- package/src/site/runBuild.ts +92 -0
- package/src/site/runDev.ts +84 -0
- package/src/site/runPreview.ts +83 -0
- package/src/site/serverEntry.ts +113 -200
- package/src/types/Adapter.ts +10 -0
- package/src/types/HttpMethod.ts +12 -0
- package/src/types/LayoutHandler.ts +7 -0
- package/src/types/ManifestRoute.ts +8 -0
- package/src/types/MiddlewareFunction.ts +8 -0
- package/src/types/PageEndPoint.ts +4 -3
- package/src/types/{PageEvent.ts → PageLoadEvent.ts} +3 -2
- package/src/types/PageServerAction.ts +5 -2
- package/src/types/PageServerEndPoint.ts +1 -0
- package/src/types/PageServerLoad.ts +5 -2
- package/src/types/RouteHandler.ts +6 -5
- package/src/types/RouteHandlerCollection.ts +1 -0
- package/src/types/RouteLayoutHandler.ts +3 -2
- package/src/types/RouteMatchResult.ts +3 -2
- package/src/types/RouteType.ts +7 -0
- package/src/types/ServerEndPoint.ts +1 -0
- package/src/types/ServerHook.ts +3 -2
- package/src/types/{ServerEvent.ts → ServerLoadEvent.ts} +13 -6
- package/src/types/ServerRequest.ts +5 -2
- package/src/types/manifest.d.ts +7 -0
- package/test/app.test.ts +47 -0
- package/tsconfig.json +1 -1
- package/tsup.config.ts +11 -1
- package/vitest.config.ts +3 -0
- package/dist/chunk-L7GOYKUG.js +0 -93
- package/dist/chunk-L7GOYKUG.js.map +0 -1
- package/src/site/FileSystemRouter.ts +0 -25
- package/src/site/buildRoutePath.ts +0 -25
- package/src/site/defineConfig.ts +0 -75
- package/src/site/lazyRoute.ts +0 -72
- package/src/site/routeHandlers.ts +0 -126
- package/src/types/CookieHelper.ts +0 -8
- package/src/types/UserConfig.ts +0 -4
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import CookieHelper from "../server/CookieHelper";
|
|
2
|
+
import HeaderHelper from "../server/HeaderHelper";
|
|
3
3
|
|
|
4
|
-
type
|
|
4
|
+
type ServerLoadEvent = {
|
|
5
5
|
/**
|
|
6
6
|
* The URL for the server function.
|
|
7
7
|
*/
|
|
@@ -17,12 +17,19 @@ type ServerEvent = {
|
|
|
17
17
|
* and pages. It flows down in that order.
|
|
18
18
|
*/
|
|
19
19
|
appData: Record<string, any>;
|
|
20
|
-
|
|
20
|
+
/**
|
|
21
|
+
* The server request.
|
|
22
|
+
*/
|
|
21
23
|
request: Request;
|
|
22
|
-
response: ServerResponse;
|
|
24
|
+
//response: ServerResponse;
|
|
23
25
|
/**
|
|
24
26
|
* A helper for getting and setting cookie data.
|
|
25
27
|
*/
|
|
26
28
|
cookies: CookieHelper;
|
|
29
|
+
/**
|
|
30
|
+
* A helper for getting and setting headers.
|
|
31
|
+
*/
|
|
32
|
+
headers: HeaderHelper;
|
|
27
33
|
};
|
|
28
|
-
|
|
34
|
+
|
|
35
|
+
export default ServerLoadEvent;
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import type ServerLoadEvent from "./ServerLoadEvent";
|
|
2
|
+
|
|
3
|
+
type ServerRequest = (
|
|
4
|
+
event: ServerLoadEvent,
|
|
5
|
+
) => Response | Promise<Response | undefined> | Promise<void> | void;
|
|
2
6
|
|
|
3
|
-
type ServerRequest = (event: ServerEvent) => Response | Promise<Response | undefined> | void;
|
|
4
7
|
export default ServerRequest;
|
package/test/app.test.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import Server from "../src/server/Server";
|
|
3
|
+
|
|
4
|
+
test("app router methods", () => {
|
|
5
|
+
let app = new Server();
|
|
6
|
+
expect(app).not.toBeUndefined();
|
|
7
|
+
/*
|
|
8
|
+
app.add("GET", "/blah", () => "hi there");
|
|
9
|
+
expect(app.match("GET", "/blah")).not.toBeUndefined();
|
|
10
|
+
expect(app.match("POST", "/blah")).toBeUndefined();
|
|
11
|
+
|
|
12
|
+
app.get("/", () => "hi there");
|
|
13
|
+
app.head("/", () => "hi there");
|
|
14
|
+
app.patch("/", () => "hi there");
|
|
15
|
+
app.post("/", () => "hi there");
|
|
16
|
+
app.put("/", () => "hi there");
|
|
17
|
+
app.delete("/", () => "hi there");
|
|
18
|
+
app.options("/", () => "hi there");
|
|
19
|
+
app.connect("/", () => "hi there");
|
|
20
|
+
app.trace("/", () => "hi there");
|
|
21
|
+
|
|
22
|
+
expect(app.match("GET", "/")).not.toBeUndefined();
|
|
23
|
+
expect(app.match("HEAD", "/")).not.toBeUndefined();
|
|
24
|
+
expect(app.match("PATCH", "/")).not.toBeUndefined();
|
|
25
|
+
expect(app.match("POST", "/")).not.toBeUndefined();
|
|
26
|
+
expect(app.match("PUT", "/")).not.toBeUndefined();
|
|
27
|
+
expect(app.match("DELETE", "/")).not.toBeUndefined();
|
|
28
|
+
expect(app.match("OPTIONS", "/")).not.toBeUndefined();
|
|
29
|
+
expect(app.match("CONNECT", "/")).not.toBeUndefined();
|
|
30
|
+
expect(app.match("TRACE", "/")).not.toBeUndefined();
|
|
31
|
+
*/
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("app router params", () => {
|
|
35
|
+
let app = new Server();
|
|
36
|
+
expect(app).not.toBeUndefined();
|
|
37
|
+
/*
|
|
38
|
+
app.add("GET", "/posts/[id]", () => "hi there");
|
|
39
|
+
|
|
40
|
+
let route = app.match("GET", "/posts/5");
|
|
41
|
+
|
|
42
|
+
expect(route).not.toBeUndefined();
|
|
43
|
+
expect(route!.handler).not.toBeUndefined();
|
|
44
|
+
expect(route!.params).not.toBeUndefined();
|
|
45
|
+
expect(route!.params!.id).toBe("5");
|
|
46
|
+
*/
|
|
47
|
+
});
|
package/tsconfig.json
CHANGED
package/tsup.config.ts
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { defineConfig } from "tsup";
|
|
2
2
|
|
|
3
3
|
export default defineConfig({
|
|
4
|
-
entry: [
|
|
4
|
+
entry: [
|
|
5
|
+
"src/index.ts",
|
|
6
|
+
"src/state.ts",
|
|
7
|
+
"src/response.ts",
|
|
8
|
+
"src/bin/index.ts",
|
|
9
|
+
"src/adapters/node/index.ts",
|
|
10
|
+
"src/adapters/cloudflare/index.ts",
|
|
11
|
+
],
|
|
5
12
|
format: ["esm", "cjs"],
|
|
6
13
|
dts: true,
|
|
7
14
|
clean: true,
|
|
8
15
|
metafile: true,
|
|
9
16
|
sourcemap: true,
|
|
17
|
+
// Put this in here to stop issues with bundling Vite from bin/index.ts
|
|
18
|
+
// I'm not sure if this will cause further issues down the line?
|
|
19
|
+
external: ["vite"],
|
|
10
20
|
});
|
package/vitest.config.ts
ADDED
package/dist/chunk-L7GOYKUG.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
// src/site/defineConfig.ts
|
|
2
|
-
import torpor from "@torpor/unplugin/vite";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { createApp } from "vinxi";
|
|
5
|
-
import { config } from "vinxi/plugins/config";
|
|
6
|
-
|
|
7
|
-
// src/site/FileSystemRouter.ts
|
|
8
|
-
import { BaseFileSystemRouter, cleanPath } from "vinxi/fs-router";
|
|
9
|
-
var FileSystemRouter = class extends BaseFileSystemRouter {
|
|
10
|
-
toPath(src) {
|
|
11
|
-
let routePath = cleanPath(src, this.config).replace(/^\//, "").replace(/_hook.server$/, "_hook/~server").replace(/_layout.server$/, "_layout/~server").replace(/\+page.server$/, "~server").replace(/\+page$/, "").replace(/\+server$/, "").replace(/\/$/, "");
|
|
12
|
-
return routePath?.length > 0 ? `/${routePath}` : "/";
|
|
13
|
-
}
|
|
14
|
-
toRoute(filePath) {
|
|
15
|
-
return {
|
|
16
|
-
path: this.toPath(filePath),
|
|
17
|
-
$handler: {
|
|
18
|
-
src: filePath,
|
|
19
|
-
pick: ["default"]
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
// src/site/defineConfig.ts
|
|
26
|
-
function defineConfig(options) {
|
|
27
|
-
process.env.PORT = (options?.port || 7059).toString();
|
|
28
|
-
return createApp({
|
|
29
|
-
name: "torpor",
|
|
30
|
-
routers: [
|
|
31
|
-
{
|
|
32
|
-
name: "assets",
|
|
33
|
-
type: "static",
|
|
34
|
-
dir: "./src/assets"
|
|
35
|
-
},
|
|
36
|
-
// Doesn't look like we can have two server routes?
|
|
37
|
-
// Have to put api in /routes
|
|
38
|
-
// Maybe we can support having /routes/api and routes/site and stripping /site from the start?
|
|
39
|
-
//{
|
|
40
|
-
// name: "api",
|
|
41
|
-
// type: "http",
|
|
42
|
-
// target: "server",
|
|
43
|
-
// // TODO: change this when published
|
|
44
|
-
// handler: "node_modules/@torpor/build/src/site/serverEntry.ts",
|
|
45
|
-
// routes: apiRoutes,
|
|
46
|
-
// plugins: () => [config("custom", viteOptions())],
|
|
47
|
-
//},
|
|
48
|
-
{
|
|
49
|
-
name: "server",
|
|
50
|
-
type: "http",
|
|
51
|
-
target: "server",
|
|
52
|
-
// TODO: change this when published
|
|
53
|
-
handler: "./node_modules/@torpor/build/src/site/serverEntry.ts",
|
|
54
|
-
routes,
|
|
55
|
-
plugins: () => [config("custom", viteOptions()), torpor({ server: true })]
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
name: "client",
|
|
59
|
-
type: "client",
|
|
60
|
-
target: "browser",
|
|
61
|
-
// TODO: change this when published
|
|
62
|
-
handler: "./node_modules/@torpor/build/src/site/clientEntry.ts",
|
|
63
|
-
base: "/_build",
|
|
64
|
-
routes,
|
|
65
|
-
plugins: () => [config("custom", viteOptions()), torpor()]
|
|
66
|
-
}
|
|
67
|
-
]
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
function routes(router, app) {
|
|
71
|
-
return new FileSystemRouter(
|
|
72
|
-
{
|
|
73
|
-
dir: path.resolve("src/routes"),
|
|
74
|
-
extensions: ["js", "ts"]
|
|
75
|
-
},
|
|
76
|
-
router,
|
|
77
|
-
app
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
function viteOptions() {
|
|
81
|
-
return {
|
|
82
|
-
resolve: {
|
|
83
|
-
alias: {
|
|
84
|
-
"@": path.resolve("src")
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export {
|
|
91
|
-
defineConfig
|
|
92
|
-
};
|
|
93
|
-
//# sourceMappingURL=chunk-L7GOYKUG.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/site/defineConfig.ts","../src/site/FileSystemRouter.ts"],"sourcesContent":["import torpor from \"@torpor/unplugin/vite\";\nimport path from \"node:path\";\nimport { type AppOptions, type RouterSchemaInput, createApp } from \"vinxi\";\nimport { config } from \"vinxi/plugins/config\";\nimport { type UserConfig } from \"../types/UserConfig\";\nimport FileSystemRouter from \"./FileSystemRouter\";\n\nexport default function defineConfig(options?: UserConfig) {\n\t// Set the port\n\tprocess.env.PORT = (options?.port || 7059).toString();\n\n\t// Get Vinxi to create and serve the app\n\treturn createApp({\n\t\tname: \"torpor\",\n\t\trouters: [\n\t\t\t{\n\t\t\t\tname: \"assets\",\n\t\t\t\ttype: \"static\",\n\t\t\t\tdir: \"./src/assets\",\n\t\t\t},\n\t\t\t// Doesn't look like we can have two server routes?\n\t\t\t// Have to put api in /routes\n\t\t\t// Maybe we can support having /routes/api and routes/site and stripping /site from the start?\n\t\t\t//{\n\t\t\t//\tname: \"api\",\n\t\t\t//\ttype: \"http\",\n\t\t\t//\ttarget: \"server\",\n\t\t\t//\t// TODO: change this when published\n\t\t\t//\thandler: \"node_modules/@torpor/build/src/site/serverEntry.ts\",\n\t\t\t//\troutes: apiRoutes,\n\t\t\t//\tplugins: () => [config(\"custom\", viteOptions())],\n\t\t\t//},\n\t\t\t{\n\t\t\t\tname: \"server\",\n\t\t\t\ttype: \"http\",\n\t\t\t\ttarget: \"server\",\n\t\t\t\t// TODO: change this when published\n\t\t\t\thandler: \"./node_modules/@torpor/build/src/site/serverEntry.ts\",\n\t\t\t\troutes,\n\t\t\t\tplugins: () => [config(\"custom\", viteOptions()), torpor({ server: true })],\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"client\",\n\t\t\t\ttype: \"client\",\n\t\t\t\ttarget: \"browser\",\n\t\t\t\t// TODO: change this when published\n\t\t\t\thandler: \"./node_modules/@torpor/build/src/site/clientEntry.ts\",\n\t\t\t\tbase: \"/_build\",\n\t\t\t\troutes,\n\t\t\t\tplugins: () => [config(\"custom\", viteOptions()), torpor()],\n\t\t\t},\n\t\t],\n\t});\n}\n\nfunction routes(router: RouterSchemaInput, app: AppOptions) {\n\treturn new FileSystemRouter(\n\t\t{\n\t\t\tdir: path.resolve(\"src/routes\"),\n\t\t\textensions: [\"js\", \"ts\"],\n\t\t},\n\t\trouter,\n\t\tapp,\n\t);\n}\n\nfunction viteOptions() {\n\treturn {\n\t\tresolve: {\n\t\t\talias: {\n\t\t\t\t\"@\": path.resolve(\"src\"),\n\t\t\t},\n\t\t},\n\t};\n}\n","import { BaseFileSystemRouter, cleanPath } from \"vinxi/fs-router\";\n\nexport default class FileSystemRouter extends BaseFileSystemRouter {\n\ttoPath(src: string) {\n\t\tlet routePath = cleanPath(src, this.config)\n\t\t\t.replace(/^\\//, \"\")\n\t\t\t.replace(/_hook.server$/, \"_hook/~server\")\n\t\t\t.replace(/_layout.server$/, \"_layout/~server\")\n\t\t\t.replace(/\\+page.server$/, \"~server\")\n\t\t\t.replace(/\\+page$/, \"\")\n\t\t\t.replace(/\\+server$/, \"\")\n\t\t\t.replace(/\\/$/, \"\");\n\t\treturn routePath?.length > 0 ? `/${routePath}` : \"/\";\n\t}\n\n\ttoRoute(filePath: string) {\n\t\treturn {\n\t\t\tpath: this.toPath(filePath),\n\t\t\t$handler: {\n\t\t\t\tsrc: filePath,\n\t\t\t\tpick: [\"default\"],\n\t\t\t},\n\t\t};\n\t}\n}\n"],"mappings":";AAAA,OAAO,YAAY;AACnB,OAAO,UAAU;AACjB,SAAkD,iBAAiB;AACnE,SAAS,cAAc;;;ACHvB,SAAS,sBAAsB,iBAAiB;AAEhD,IAAqB,mBAArB,cAA8C,qBAAqB;AAAA,EAClE,OAAO,KAAa;AACnB,QAAI,YAAY,UAAU,KAAK,KAAK,MAAM,EACxC,QAAQ,OAAO,EAAE,EACjB,QAAQ,iBAAiB,eAAe,EACxC,QAAQ,mBAAmB,iBAAiB,EAC5C,QAAQ,kBAAkB,SAAS,EACnC,QAAQ,WAAW,EAAE,EACrB,QAAQ,aAAa,EAAE,EACvB,QAAQ,OAAO,EAAE;AACnB,WAAO,WAAW,SAAS,IAAI,IAAI,SAAS,KAAK;AAAA,EAClD;AAAA,EAEA,QAAQ,UAAkB;AACzB,WAAO;AAAA,MACN,MAAM,KAAK,OAAO,QAAQ;AAAA,MAC1B,UAAU;AAAA,QACT,KAAK;AAAA,QACL,MAAM,CAAC,SAAS;AAAA,MACjB;AAAA,IACD;AAAA,EACD;AACD;;;ADjBe,SAAR,aAA8B,SAAsB;AAE1D,UAAQ,IAAI,QAAQ,SAAS,QAAQ,MAAM,SAAS;AAGpD,SAAO,UAAU;AAAA,IAChB,MAAM;AAAA,IACN,SAAS;AAAA,MACR;AAAA,QACC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,KAAK;AAAA,MACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAaA;AAAA,QACC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA;AAAA,QAER,SAAS;AAAA,QACT;AAAA,QACA,SAAS,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,GAAG,OAAO,EAAE,QAAQ,KAAK,CAAC,CAAC;AAAA,MAC1E;AAAA,MACA;AAAA,QACC,MAAM;AAAA,QACN,MAAM;AAAA,QACN,QAAQ;AAAA;AAAA,QAER,SAAS;AAAA,QACT,MAAM;AAAA,QACN;AAAA,QACA,SAAS,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,GAAG,OAAO,CAAC;AAAA,MAC1D;AAAA,IACD;AAAA,EACD,CAAC;AACF;AAEA,SAAS,OAAO,QAA2B,KAAiB;AAC3D,SAAO,IAAI;AAAA,IACV;AAAA,MACC,KAAK,KAAK,QAAQ,YAAY;AAAA,MAC9B,YAAY,CAAC,MAAM,IAAI;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;AAEA,SAAS,cAAc;AACtB,SAAO;AAAA,IACN,SAAS;AAAA,MACR,OAAO;AAAA,QACN,KAAK,KAAK,QAAQ,KAAK;AAAA,MACxB;AAAA,IACD;AAAA,EACD;AACD;","names":[]}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { BaseFileSystemRouter, cleanPath } from "vinxi/fs-router";
|
|
2
|
-
|
|
3
|
-
export default class FileSystemRouter extends BaseFileSystemRouter {
|
|
4
|
-
toPath(src: string) {
|
|
5
|
-
let routePath = cleanPath(src, this.config)
|
|
6
|
-
.replace(/^\//, "")
|
|
7
|
-
.replace(/_hook.server$/, "_hook/~server")
|
|
8
|
-
.replace(/_layout.server$/, "_layout/~server")
|
|
9
|
-
.replace(/\+page.server$/, "~server")
|
|
10
|
-
.replace(/\+page$/, "")
|
|
11
|
-
.replace(/\+server$/, "")
|
|
12
|
-
.replace(/\/$/, "");
|
|
13
|
-
return routePath?.length > 0 ? `/${routePath}` : "/";
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
toRoute(filePath: string) {
|
|
17
|
-
return {
|
|
18
|
-
path: this.toPath(filePath),
|
|
19
|
-
$handler: {
|
|
20
|
-
src: filePath,
|
|
21
|
-
pick: ["default"],
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
type ParamsType = Record<PropertyKey, any>;
|
|
2
|
-
|
|
3
|
-
export default function buildRoutePath<RP extends ParamsType, UP extends ParamsType>(
|
|
4
|
-
path: string,
|
|
5
|
-
routeParams: RP,
|
|
6
|
-
urlParams?: UP,
|
|
7
|
-
) {
|
|
8
|
-
for (let [key, value] of Object.entries(routeParams)) {
|
|
9
|
-
path = path.replace(`[${key}]`, value);
|
|
10
|
-
}
|
|
11
|
-
if (urlParams) {
|
|
12
|
-
// TODO: More sophisticated url params serialization
|
|
13
|
-
let params = Object.entries(urlParams)
|
|
14
|
-
.map(([key, value]) => {
|
|
15
|
-
if (value != null) {
|
|
16
|
-
return `${key}=${value}`;
|
|
17
|
-
}
|
|
18
|
-
})
|
|
19
|
-
.filter(Boolean);
|
|
20
|
-
if (params.length) {
|
|
21
|
-
path += `?${params.join("&")}`;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return path;
|
|
25
|
-
}
|
package/src/site/defineConfig.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import torpor from "@torpor/unplugin/vite";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import { type AppOptions, type RouterSchemaInput, createApp } from "vinxi";
|
|
4
|
-
import { config } from "vinxi/plugins/config";
|
|
5
|
-
import type UserConfig from "../types/UserConfig";
|
|
6
|
-
import FileSystemRouter from "./FileSystemRouter";
|
|
7
|
-
|
|
8
|
-
export default function defineConfig(options?: UserConfig) {
|
|
9
|
-
// Set the port
|
|
10
|
-
process.env.PORT = (options?.port || 7059).toString();
|
|
11
|
-
|
|
12
|
-
// Get Vinxi to create and serve the app
|
|
13
|
-
return createApp({
|
|
14
|
-
name: "torpor",
|
|
15
|
-
routers: [
|
|
16
|
-
{
|
|
17
|
-
name: "assets",
|
|
18
|
-
type: "static",
|
|
19
|
-
dir: "./src/assets",
|
|
20
|
-
},
|
|
21
|
-
// Doesn't look like we can have two server routes?
|
|
22
|
-
// Have to put api in /routes
|
|
23
|
-
// Maybe we can support having /routes/api and routes/site and stripping /site from the start?
|
|
24
|
-
//{
|
|
25
|
-
// name: "api",
|
|
26
|
-
// type: "http",
|
|
27
|
-
// target: "server",
|
|
28
|
-
// // TODO: change this when published
|
|
29
|
-
// handler: "node_modules/@torpor/build/src/site/serverEntry.ts",
|
|
30
|
-
// routes: apiRoutes,
|
|
31
|
-
// plugins: () => [config("custom", viteOptions())],
|
|
32
|
-
//},
|
|
33
|
-
{
|
|
34
|
-
name: "server",
|
|
35
|
-
type: "http",
|
|
36
|
-
target: "server",
|
|
37
|
-
// TODO: change this when published
|
|
38
|
-
handler: "./node_modules/@torpor/build/src/site/serverEntry.ts",
|
|
39
|
-
routes,
|
|
40
|
-
plugins: () => [config("custom", viteOptions()), torpor({ server: true })],
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
name: "client",
|
|
44
|
-
type: "client",
|
|
45
|
-
target: "browser",
|
|
46
|
-
// TODO: change this when published
|
|
47
|
-
handler: "./node_modules/@torpor/build/src/site/clientEntry.ts",
|
|
48
|
-
base: "/_build",
|
|
49
|
-
routes,
|
|
50
|
-
plugins: () => [config("custom", viteOptions()), torpor()],
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function routes(router: RouterSchemaInput, app: AppOptions) {
|
|
57
|
-
return new FileSystemRouter(
|
|
58
|
-
{
|
|
59
|
-
dir: path.resolve("src/routes"),
|
|
60
|
-
extensions: ["js", "ts"],
|
|
61
|
-
},
|
|
62
|
-
router,
|
|
63
|
-
app,
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function viteOptions() {
|
|
68
|
-
return {
|
|
69
|
-
resolve: {
|
|
70
|
-
alias: {
|
|
71
|
-
"@": path.resolve("src"),
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
};
|
|
75
|
-
}
|
package/src/site/lazyRoute.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
export default async function lazyRoute(
|
|
2
|
-
component: { src: string; import(): Promise<any> },
|
|
3
|
-
clientManifest: any,
|
|
4
|
-
serverManifest: any,
|
|
5
|
-
//exported = "default",
|
|
6
|
-
) {
|
|
7
|
-
if (import.meta.env.DEV) {
|
|
8
|
-
const manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
9
|
-
const mod = await manifest.inputs[component.src].import();
|
|
10
|
-
return mod;
|
|
11
|
-
} else {
|
|
12
|
-
const mod = await component.import();
|
|
13
|
-
return mod;
|
|
14
|
-
}
|
|
15
|
-
/*
|
|
16
|
-
return lazy(async () => {
|
|
17
|
-
if (import.meta.env.DEV) {
|
|
18
|
-
let manifest = import.meta.env.SSR ? serverManifest : clientManifest;
|
|
19
|
-
|
|
20
|
-
const mod = await manifest.inputs[component.src].import();
|
|
21
|
-
invariant(mod[exported], `Module ${component.src} does not export ${exported}`);
|
|
22
|
-
const Component = mod[exported];
|
|
23
|
-
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
24
|
-
const styles = assets.filter((asset) => asset.tag === "style");
|
|
25
|
-
|
|
26
|
-
if (typeof window !== "undefined" && import.meta.hot) {
|
|
27
|
-
import.meta.hot.on("css-update", (data) => {
|
|
28
|
-
updateStyles(styles, data);
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const Comp = forwardRef((props, ref) => {
|
|
33
|
-
if (typeof window !== "undefined") {
|
|
34
|
-
useLayoutEffect(() => {
|
|
35
|
-
return () => {
|
|
36
|
-
// remove style tags added by vite when a CSS file is imported
|
|
37
|
-
cleanupStyles(styles);
|
|
38
|
-
};
|
|
39
|
-
}, []);
|
|
40
|
-
}
|
|
41
|
-
return createElement(
|
|
42
|
-
Fragment,
|
|
43
|
-
null,
|
|
44
|
-
...assets.map((asset) => renderAsset(asset)),
|
|
45
|
-
createElement(Component, { ...props, ref: ref }),
|
|
46
|
-
);
|
|
47
|
-
});
|
|
48
|
-
return { default: Comp };
|
|
49
|
-
} else {
|
|
50
|
-
const mod = await component.import();
|
|
51
|
-
|
|
52
|
-
const Component = mod[exported];
|
|
53
|
-
let assets = await clientManifest.inputs?.[component.src].assets();
|
|
54
|
-
|
|
55
|
-
if (typeof window !== "undefined") {
|
|
56
|
-
const styles = assets.filter((asset) => asset.attrs.rel === "stylesheet");
|
|
57
|
-
preloadStyles(styles);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const Comp = forwardRef((props, ref) => {
|
|
61
|
-
return createElement(
|
|
62
|
-
Fragment,
|
|
63
|
-
null,
|
|
64
|
-
...assets.map((asset) => renderAsset(asset)),
|
|
65
|
-
createElement(Component, { ...props, ref: ref }),
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
return { default: Comp };
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
*/
|
|
72
|
-
}
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { getManifest } from "vinxi/manifest";
|
|
2
|
-
import fileRoutes, { type RouteModule } from "vinxi/routes";
|
|
3
|
-
import type RouteHandler from "../types/RouteHandler";
|
|
4
|
-
import type RouteHandlerCollection from "../types/RouteHandlerCollection";
|
|
5
|
-
import type RouteLayoutHandler from "../types/RouteLayoutHandler";
|
|
6
|
-
import lazyRoute from "./lazyRoute";
|
|
7
|
-
|
|
8
|
-
const clientManifest = getManifest("client");
|
|
9
|
-
const serverManifest = getManifest("server");
|
|
10
|
-
|
|
11
|
-
const routeHandlers: RouteHandlerCollection = {
|
|
12
|
-
handlers: fileRoutes
|
|
13
|
-
// HACK: Is there a better way to filter? glob in the config?
|
|
14
|
-
.filter((route) => !route.path.startsWith("_"))
|
|
15
|
-
.map((route) => {
|
|
16
|
-
return {
|
|
17
|
-
...route,
|
|
18
|
-
regex: pathToRegExp(route.path),
|
|
19
|
-
// TODO: Implement the rest of the lazyRoute stuff from vinxi/react or vinxi/solid
|
|
20
|
-
endPoint: lazyRoute(route.$handler, clientManifest, serverManifest),
|
|
21
|
-
loaded: false,
|
|
22
|
-
};
|
|
23
|
-
})
|
|
24
|
-
.sort((a, b) => {
|
|
25
|
-
// Sort [param]s after paths
|
|
26
|
-
// There might be a quicker/easier way to do this
|
|
27
|
-
for (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {
|
|
28
|
-
if (a.path[i] === "[" && b.path[i] !== "[") {
|
|
29
|
-
return 1;
|
|
30
|
-
} else if (b.path[i] === "[" && a.path[i] !== "[") {
|
|
31
|
-
return -1;
|
|
32
|
-
} else if (a.path[i] === b.path[i]) {
|
|
33
|
-
// Keep going...
|
|
34
|
-
} else {
|
|
35
|
-
return a.path[i].localeCompare(b.path[i]);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return a.path.length - b.path.length;
|
|
39
|
-
}),
|
|
40
|
-
match(path, urlParams) {
|
|
41
|
-
// TODO: Lots of testing etc
|
|
42
|
-
for (let handler of (this as RouteHandlerCollection).handlers) {
|
|
43
|
-
let match = path.match(handler.regex);
|
|
44
|
-
if (match) {
|
|
45
|
-
console.log(`matching ${path}, found ${handler.path}`);
|
|
46
|
-
|
|
47
|
-
// Lazy load server endpoints and layouts
|
|
48
|
-
// Partly because it makes sense to do it here, but also because
|
|
49
|
-
// it doesn't work if we try to do it upfront for some reason
|
|
50
|
-
if (!handler.loaded) {
|
|
51
|
-
loadHandler(handler);
|
|
52
|
-
handler.loaded = true;
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
handler,
|
|
56
|
-
routeParams: match.groups,
|
|
57
|
-
urlParams: urlParams ? Object.fromEntries(urlParams) : undefined,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
console.log(`matching ${path}, not found`);
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
function pathToRegExp(path: string): RegExp {
|
|
67
|
-
const pattern = path
|
|
68
|
-
.split("/")
|
|
69
|
-
.map((p) => {
|
|
70
|
-
return p.replace(/\[([^\/]+?)\]/, "(?<$1>[^\\/]+?)");
|
|
71
|
-
})
|
|
72
|
-
.join("\\/");
|
|
73
|
-
return new RegExp(`^${pattern}$`);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
function loadHandler(handler: RouteHandler) {
|
|
77
|
-
handler.layouts = findLayouts(handler.path, fileRoutes);
|
|
78
|
-
handler.serverEndPoint = findServer(handler.path, fileRoutes);
|
|
79
|
-
handler.serverHook = findServerHook(handler.path, fileRoutes);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
function findLayouts(path: string, fileRoutes: RouteModule[]): RouteLayoutHandler[] | undefined {
|
|
83
|
-
let layouts: RouteLayoutHandler[] = [];
|
|
84
|
-
let parts = path
|
|
85
|
-
// Strip the trailing`~/server` (so we don't look for `~/server/_layout`
|
|
86
|
-
// which will never exist)
|
|
87
|
-
.replace(/\/~server$/, "")
|
|
88
|
-
// The path will always start with / so splitting e.g. `/first/second`
|
|
89
|
-
// will result in ['', 'first', 'second'] and checks for `/_layout`,
|
|
90
|
-
// `/first/_layout` and `/second/_layout`
|
|
91
|
-
.split("/");
|
|
92
|
-
let basePath = "";
|
|
93
|
-
for (let i = 0; i < parts.length; i++) {
|
|
94
|
-
if (i > 0) {
|
|
95
|
-
basePath += "/" + parts[i];
|
|
96
|
-
}
|
|
97
|
-
const layoutPath = basePath + "/_layout";
|
|
98
|
-
const layoutRoute = fileRoutes.find((r) => r.path === layoutPath);
|
|
99
|
-
if (layoutRoute) {
|
|
100
|
-
layouts.push({
|
|
101
|
-
path: layoutPath,
|
|
102
|
-
endPoint: lazyRoute(layoutRoute.$handler, clientManifest, serverManifest),
|
|
103
|
-
serverEndPoint: findServer(layoutPath, fileRoutes),
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
return layouts.length ? layouts : undefined;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function findServer(path: string, fileRoutes: RouteModule[]): Promise<any> | undefined {
|
|
111
|
-
const serverPath = path.replace(/\/$/, "") + "/~server";
|
|
112
|
-
const serverRoute = fileRoutes.find((r) => r.path === serverPath);
|
|
113
|
-
return serverRoute && lazyRoute(serverRoute.$handler, clientManifest, serverManifest);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function findServerHook(path: string, fileRoutes: RouteModule[]): Promise<any> | undefined {
|
|
117
|
-
// TODO: Should this be a collection, like layouts?
|
|
118
|
-
let hookPath = "/_hook/~server";
|
|
119
|
-
if (path.startsWith("/api/")) {
|
|
120
|
-
hookPath = "/api" + hookPath;
|
|
121
|
-
}
|
|
122
|
-
const hookRoute = fileRoutes.find((r) => r.path === hookPath);
|
|
123
|
-
return hookRoute && lazyRoute(hookRoute.$handler, clientManifest, serverManifest);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export default routeHandlers;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type CookieSerializeOptions } from "vinxi/http";
|
|
2
|
-
|
|
3
|
-
type CookieHelper = {
|
|
4
|
-
get: (name: string) => string | undefined;
|
|
5
|
-
set: (name: string, value: string, options?: CookieSerializeOptions) => void;
|
|
6
|
-
delete: (name: string, options?: CookieSerializeOptions) => void;
|
|
7
|
-
};
|
|
8
|
-
export default CookieHelper;
|
package/src/types/UserConfig.ts
DELETED