@torpor/build 0.1.6 → 0.1.8
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 +16 -0
- package/dist/{Site-Df1k0TuQ.d.cts → Server-B45PD5Ys.d.cts} +2 -27
- package/dist/{Site-Df1k0TuQ.d.ts → Server-B45PD5Ys.d.ts} +2 -27
- package/dist/Site-PxPCXGZ-.d.cts +29 -0
- package/dist/Site-Qpcmx0Xq.d.ts +29 -0
- package/dist/bin/index.cjs +19 -3
- package/dist/bin/index.cjs.map +1 -1
- package/dist/bin/index.js +3 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/{chunk-GQ4JCTRP.js → chunk-3OF7JZ3M.js} +6 -168
- package/dist/chunk-3OF7JZ3M.js.map +1 -0
- package/dist/chunk-65Z6BF2N.js +355 -0
- package/dist/chunk-65Z6BF2N.js.map +1 -0
- package/dist/chunk-T5K52YVJ.js +12 -0
- package/dist/chunk-T5K52YVJ.js.map +1 -0
- package/dist/index.cjs +104 -142
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -3
- package/dist/index.d.ts +50 -3
- package/dist/index.js +129 -3
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/run.cjs +19 -3
- package/dist/run.cjs.map +1 -1
- package/dist/run.d.cts +2 -1
- package/dist/run.d.ts +2 -1
- package/dist/run.js +3 -2
- package/dist/server.cjs +387 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +17 -0
- package/dist/server.d.ts +17 -0
- package/dist/server.js +16 -0
- package/dist/server.js.map +1 -0
- package/package.json +8 -13
- package/src/index.ts +2 -2
- package/src/{site → server}/Routerx.ts +4 -4
- package/src/server/Server.ts +22 -2
- package/src/server/connect/{createMiddlewareHandler.ts → connectMiddleware.ts} +2 -2
- package/src/{types → server/types}/MiddlewareFunction.ts +1 -1
- package/src/server/{ServerFunction.ts → types/ServerFunction.ts} +1 -1
- package/src/server.ts +7 -0
- package/src/site/Router.ts +35 -12
- package/src/site/runDev.ts +2 -2
- package/tsup.config.ts +8 -1
- package/dist/chunk-GQ4JCTRP.js.map +0 -1
- package/dist/chunk-L3QBUPXY.js +0 -176
- package/dist/chunk-L3QBUPXY.js.map +0 -1
- package/src/types/RouteHandlerCollection.ts +0 -9
- /package/src/{types → server/types}/HttpMethod.ts +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/site/pathToRegex.ts"],"sourcesContent":["export default function pathToRegex(path: string): RegExp {\n\tconst pattern = path\n\t\t.split(\"/\")\n\t\t.map((p) => {\n\t\t\treturn p.replace(/\\[([^\\/]+?)\\]/, \"(?<$1>[^\\\\/]+?)\");\n\t\t})\n\t\t.join(\"\\\\/\")\n\t\t.replaceAll(\"*\", \".*\");\n\treturn new RegExp(`^${pattern}$`);\n}\n"],"mappings":";AAAe,SAAR,YAA6B,MAAsB;AACzD,QAAM,UAAU,KACd,MAAM,GAAG,EACT,IAAI,CAAC,MAAM;AACX,WAAO,EAAE,QAAQ,iBAAiB,iBAAiB;AAAA,EACpD,CAAC,EACA,KAAK,KAAK,EACV,WAAW,KAAK,IAAI;AACtB,SAAO,IAAI,OAAO,IAAI,OAAO,GAAG;AACjC;","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
|
|
33
|
+
Router: () => Router,
|
|
34
34
|
Site: () => Site
|
|
35
35
|
});
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -43,167 +43,129 @@ function pathToRegex(path2) {
|
|
|
43
43
|
return new RegExp(`^${pattern}$`);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
// src/
|
|
47
|
-
var
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
cookies = /* @__PURE__ */ new Map();
|
|
51
|
-
constructor(request) {
|
|
52
|
-
this.request = request;
|
|
46
|
+
// src/site/Router.ts
|
|
47
|
+
var Router = class {
|
|
48
|
+
routes = [];
|
|
49
|
+
constructor() {
|
|
53
50
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
//add(path: string, file: string) {
|
|
52
|
+
// // TODO: Call the specific addX method based on the file path
|
|
53
|
+
// this.addPage(route, file);
|
|
54
|
+
//}
|
|
55
|
+
addPages(routes) {
|
|
56
|
+
for (let r of routes) {
|
|
57
|
+
this.routes.push(
|
|
58
|
+
new Route(r.path, {
|
|
59
|
+
path: r.path,
|
|
60
|
+
type: r.type,
|
|
61
|
+
endPoint: r.endPoint
|
|
62
|
+
})
|
|
63
|
+
);
|
|
57
64
|
}
|
|
58
|
-
|
|
59
|
-
return
|
|
60
|
-
}
|
|
61
|
-
set(name, value, options) {
|
|
62
|
-
options ??= {};
|
|
63
|
-
options.httpOnly ??= true;
|
|
64
|
-
options.secure ??= true;
|
|
65
|
-
options.sameSite ??= "lax";
|
|
66
|
-
this.cookies.set(name, (0, import_cookie.serialize)(name, value, options));
|
|
65
|
+
this.#sortRoutes();
|
|
66
|
+
return this;
|
|
67
67
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold
|
|
69
|
+
addPage(path2, type, endPoint) {
|
|
70
|
+
this.routes.push(
|
|
71
|
+
new Route(path2, {
|
|
72
|
+
path: path2,
|
|
73
|
+
type,
|
|
74
|
+
endPoint
|
|
75
|
+
})
|
|
76
|
+
);
|
|
77
|
+
this.#sortRoutes();
|
|
78
|
+
return this;
|
|
72
79
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this.request = request;
|
|
80
|
+
/*
|
|
81
|
+
loadPage(ev: ServerEvent, file: string): Response {
|
|
82
|
+
let page = this.pages.get(file);
|
|
83
|
+
if (!page) {
|
|
84
|
+
page = {};
|
|
85
|
+
this.pages.set(file, page);
|
|
86
|
+
}
|
|
81
87
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
88
|
+
*/
|
|
89
|
+
match(path2, query) {
|
|
90
|
+
for (let route of this.routes) {
|
|
91
|
+
let match = path2.match(route.regex);
|
|
92
|
+
if (match) {
|
|
93
|
+
if (!route.handler.loaded) {
|
|
94
|
+
this.#loadHandler(route.handler, route.path);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
handler: route.handler,
|
|
98
|
+
params: match.groups,
|
|
99
|
+
query
|
|
100
|
+
};
|
|
101
|
+
}
|
|
85
102
|
}
|
|
86
|
-
|
|
103
|
+
console.log(`not found: '${path2}'`);
|
|
87
104
|
}
|
|
88
|
-
|
|
89
|
-
this
|
|
105
|
+
#loadHandler(handler, path2) {
|
|
106
|
+
handler.layouts = this.#findLayouts(path2);
|
|
107
|
+
handler.serverEndPoint = this.#findServer(path2);
|
|
108
|
+
handler.serverHook = this.#findServerHook(path2);
|
|
90
109
|
}
|
|
91
|
-
|
|
92
|
-
|
|
110
|
+
#findLayouts(path2) {
|
|
111
|
+
let layouts = [];
|
|
112
|
+
let parts = path2.replace(/\/~server$/, "").split("/");
|
|
113
|
+
let basePath = "";
|
|
114
|
+
for (let i = 0; i < parts.length; i++) {
|
|
115
|
+
if (i > 0) {
|
|
116
|
+
basePath += "/" + parts[i];
|
|
117
|
+
}
|
|
118
|
+
const layoutPath = basePath + "/_layout";
|
|
119
|
+
const layoutRoute = this.routes.find((r) => r.path === layoutPath);
|
|
120
|
+
if (layoutRoute) {
|
|
121
|
+
layouts.push({
|
|
122
|
+
path: layoutPath,
|
|
123
|
+
endPoint: layoutRoute.handler.endPoint,
|
|
124
|
+
serverEndPoint: this.#findServer(layoutPath)
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return layouts.length ? layouts : void 0;
|
|
93
129
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
request;
|
|
99
|
-
response;
|
|
100
|
-
// TODO: Should we cast types??
|
|
101
|
-
params;
|
|
102
|
-
cookies;
|
|
103
|
-
headers;
|
|
104
|
-
constructor(request, params) {
|
|
105
|
-
this.request = request;
|
|
106
|
-
this.params = params;
|
|
107
|
-
this.cookies = new CookieHelper(request);
|
|
108
|
-
this.headers = new HeaderHelper(request);
|
|
130
|
+
#findServer(path2) {
|
|
131
|
+
const serverPath = path2.replace(/\/$/, "") + "/~server";
|
|
132
|
+
const serverRoute = this.routes.find((r) => r.path === serverPath);
|
|
133
|
+
return serverRoute && serverRoute.handler.endPoint;
|
|
109
134
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
for (let cookie of this.cookies.cookies.values()) {
|
|
115
|
-
this.response.headers.append("set-cookie", cookie);
|
|
116
|
-
}
|
|
117
|
-
for (let header of this.headers.headers.entries()) {
|
|
118
|
-
this.response.headers.append(header[0], header[1]);
|
|
135
|
+
#findServerHook(path2) {
|
|
136
|
+
let serverHookPath = "/_hook/~server";
|
|
137
|
+
if (path2.startsWith("/api/")) {
|
|
138
|
+
serverHookPath = "/api" + serverHookPath;
|
|
119
139
|
}
|
|
140
|
+
const serverHookRoute = this.routes.find((r) => r.path === serverHookPath);
|
|
141
|
+
return serverHookRoute && serverHookRoute.handler.endPoint;
|
|
120
142
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
constructor() {
|
|
132
|
-
this.routes = [];
|
|
133
|
-
this.middleware = [];
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* The standard Fetch API method that should work in any runtime (including
|
|
137
|
-
* Node with polyfills).
|
|
138
|
-
* @returns
|
|
139
|
-
*/
|
|
140
|
-
fetch = async (input, init) => {
|
|
141
|
-
const request = new Request(input, init);
|
|
142
|
-
const url = new URL(request.url);
|
|
143
|
-
const match = this.match(url.pathname);
|
|
144
|
-
let ev = new ServerEvent(request, match?.params);
|
|
145
|
-
if (this.middleware.length) {
|
|
146
|
-
let buildNext2 = function(middleware, i) {
|
|
147
|
-
if (ev.response) {
|
|
148
|
-
return noop;
|
|
149
|
-
}
|
|
150
|
-
if (i < middleware.length - 1) {
|
|
151
|
-
let next = middleware[i + 1];
|
|
152
|
-
return async () => next(ev, buildNext2(middleware, i + 1));
|
|
143
|
+
// HACK: We're doing this here as well as in Site, so that you can use the
|
|
144
|
+
// Router externally without Site
|
|
145
|
+
#sortRoutes() {
|
|
146
|
+
this.routes = this.routes.sort((a, b) => {
|
|
147
|
+
for (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {
|
|
148
|
+
if (a.path[i] === "[" && b.path[i] !== "[") {
|
|
149
|
+
return 1;
|
|
150
|
+
} else if (b.path[i] === "[" && a.path[i] !== "[") {
|
|
151
|
+
return -1;
|
|
152
|
+
} else if (a.path[i] === b.path[i]) {
|
|
153
153
|
} else {
|
|
154
|
-
return
|
|
155
|
-
ev.response = await match.fn(ev);
|
|
156
|
-
} : noop;
|
|
154
|
+
return a.path[i].localeCompare(b.path[i]);
|
|
157
155
|
}
|
|
158
|
-
};
|
|
159
|
-
var buildNext = buildNext2;
|
|
160
|
-
await this.middleware[0](ev, buildNext2(this.middleware, 0));
|
|
161
|
-
} else if (match) {
|
|
162
|
-
ev.response = await match.fn(ev);
|
|
163
|
-
} else {
|
|
164
|
-
return new Response(null, { status: 404 });
|
|
165
|
-
}
|
|
166
|
-
ev.response ??= new Response(null, { status: 200 });
|
|
167
|
-
ev.addHeaders();
|
|
168
|
-
return ev.response;
|
|
169
|
-
};
|
|
170
|
-
/**
|
|
171
|
-
* Adds a server function at a route path.
|
|
172
|
-
* @param path The route path pattern.
|
|
173
|
-
* @param fn The function to call when the pattern is matched.
|
|
174
|
-
* @returns
|
|
175
|
-
*/
|
|
176
|
-
add(path2, fn) {
|
|
177
|
-
this.routes.push(new RouteHandler(path2, fn));
|
|
178
|
-
return this;
|
|
179
|
-
}
|
|
180
|
-
match(path2) {
|
|
181
|
-
for (let handler of this.routes) {
|
|
182
|
-
let match = path2.match(handler.regex);
|
|
183
|
-
if (match) {
|
|
184
|
-
return {
|
|
185
|
-
fn: handler.fn,
|
|
186
|
-
params: match.groups
|
|
187
|
-
};
|
|
188
156
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
}
|
|
192
|
-
// TODO:
|
|
193
|
-
//use(path: string, ...fn: MiddlewareFunction[])
|
|
194
|
-
use(...fn) {
|
|
195
|
-
this.middleware = this.middleware.concat(fn);
|
|
196
|
-
return this;
|
|
157
|
+
return a.path.length - b.path.length;
|
|
158
|
+
});
|
|
197
159
|
}
|
|
198
160
|
};
|
|
199
|
-
var
|
|
161
|
+
var Route = class {
|
|
200
162
|
path;
|
|
201
163
|
regex;
|
|
202
|
-
|
|
203
|
-
constructor(path2,
|
|
164
|
+
handler;
|
|
165
|
+
constructor(path2, handler) {
|
|
204
166
|
this.path = path2;
|
|
205
167
|
this.regex = pathToRegex(path2);
|
|
206
|
-
this.
|
|
168
|
+
this.handler = handler;
|
|
207
169
|
}
|
|
208
170
|
};
|
|
209
171
|
|
|
@@ -302,7 +264,7 @@ var Site = class {
|
|
|
302
264
|
};
|
|
303
265
|
// Annotate the CommonJS export names for ESM import in node:
|
|
304
266
|
0 && (module.exports = {
|
|
305
|
-
|
|
267
|
+
Router,
|
|
306
268
|
Site
|
|
307
269
|
});
|
|
308
270
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/site/pathToRegex.ts","../src/server/CookieHelper.ts","../src/server/HeaderHelper.ts","../src/server/ServerEvent.ts","../src/server/Server.ts","../src/site/Site.ts","../src/types/RouteType.ts","../src/site/defaultAdapter.ts"],"sourcesContent":["import Server from \"./server/Server\";\nimport Site from \"./site/Site\";\nimport type Adapter from \"./types/Adapter\";\nimport type PageEndPoint from \"./types/PageEndPoint\";\nimport type PageLoadEvent from \"./types/PageLoadEvent\";\nimport type PageServerAction from \"./types/PageServerAction\";\nimport type PageServerEndPoint from \"./types/PageServerEndPoint\";\nimport type PageServerLoad from \"./types/PageServerLoad\";\nimport type ServerEndPoint from \"./types/ServerEndPoint\";\nimport type ServerHook from \"./types/ServerHook\";\nimport type ServerLoadEvent from \"./types/ServerLoadEvent\";\nimport type ServerRequest from \"./types/ServerRequest\";\n\nexport { Server, Site };\n\nexport type {\n\tAdapter,\n\tPageEndPoint,\n\tPageServerEndPoint,\n\tPageServerLoad,\n\tPageServerAction,\n\tServerEndPoint,\n\tServerRequest,\n\tServerHook,\n\tPageLoadEvent,\n\tServerLoadEvent,\n};\n","export default function pathToRegex(path: string): RegExp {\n\tconst pattern = path\n\t\t.split(\"/\")\n\t\t.map((p) => {\n\t\t\treturn p.replace(/\\[([^\\/]+?)\\]/, \"(?<$1>[^\\\\/]+?)\");\n\t\t})\n\t\t.join(\"\\\\/\")\n\t\t.replaceAll(\"*\", \".*\");\n\treturn new RegExp(`^${pattern}$`);\n}\n","import { SerializeOptions, parse, serialize } from \"cookie\";\n\nexport default class CookieHelper {\n\trequest: Request;\n\tcookies: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the updated value\n\t\tif (this.cookies.has(name)) {\n\t\t\treturn this.cookies.get(name);\n\t\t}\n\t\t// Otherwise, return the cookie value from the `Cookie` header\n\t\tconst header = this.request.headers.get(\"cookie\");\n\t\treturn parse(header ?? \"\")[name];\n\t}\n\n\tset(name: string, value: string, options?: SerializeOptions) {\n\t\t// Set a cookie header with some default values for security\n\t\toptions ??= {};\n\t\toptions.httpOnly ??= true;\n\t\toptions.secure ??= true;\n\t\toptions.sameSite ??= \"lax\";\n\t\tthis.cookies.set(name, serialize(name, value, options));\n\t}\n\n\tdelete(name: string, options?: SerializeOptions) {\n\t\t// Set a cookie header with an immediate expiry date\n\t\toptions ??= {};\n\t\toptions.expires = new Date(0);\n\t\tthis.cookies.set(name, serialize(name, \"\", options));\n\t}\n}\n","export default class HeaderHelper {\n\trequest: Request;\n\theaders: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the updated value\n\t\tif (this.headers.has(name)) {\n\t\t\treturn this.headers.get(name);\n\t\t}\n\t\t// Otherwise, return the value from the header\n\t\treturn this.request.headers.get(name) ?? undefined;\n\t}\n\n\tset(name: string, value: string) {\n\t\tthis.headers.set(name, value);\n\t}\n\n\tdelete(name: string) {\n\t\tthis.headers.delete(name);\n\t}\n}\n","import CookieHelper from \"./CookieHelper\";\nimport HeaderHelper from \"./HeaderHelper\";\n\nexport default class ServerEvent {\n\trequest: Request;\n\tresponse?: Response;\n\t// TODO: Should we cast types??\n\tparams?: { [key: string]: string };\n\n\tcookies: CookieHelper;\n\theaders: HeaderHelper;\n\n\tconstructor(request: Request, params?: { [key: string]: string }) {\n\t\tthis.request = request;\n\t\tthis.params = params;\n\t\tthis.cookies = new CookieHelper(request);\n\t\tthis.headers = new HeaderHelper(request);\n\t}\n\n\taddHeaders() {\n\t\tif (!this.response) {\n\t\t\tthrow new Error(\"Response not created yet\");\n\t\t}\n\n\t\tfor (let cookie of this.cookies.cookies.values()) {\n\t\t\tthis.response.headers.append(\"set-cookie\", cookie);\n\t\t}\n\n\t\tfor (let header of this.headers.headers.entries()) {\n\t\t\tthis.response.headers.append(header[0], header[1]);\n\t\t}\n\t}\n}\n","import pathToRegex from \"../site/pathToRegex\";\nimport type MiddlewareFunction from \"../types/MiddlewareFunction\";\nimport ServerEvent from \"./ServerEvent\";\nimport type ServerFunction from \"./ServerFunction\";\n\nconst noop = () => {};\n\n/**\n * A Fetch API Request/Response server.\n */\nexport default class Server {\n\t// TODO: We don't use any of the routes, just add(\"*\") in runDev/runBuild...\n\troutes: RouteHandler[] = [];\n\t// TODO: We only use the Vite middleware here\n\tmiddleware: MiddlewareFunction[] = [];\n\n\tconstructor() {\n\t\tthis.routes = [];\n\t\tthis.middleware = [];\n\t}\n\n\t/**\n\t * The standard Fetch API method that should work in any runtime (including\n\t * Node with polyfills).\n\t * @returns\n\t */\n\tfetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\tconst request = new Request(input, init);\n\t\tconst url = new URL(request.url);\n\t\tconst match = this.match(url.pathname);\n\t\tlet ev = new ServerEvent(request, match?.params);\n\n\t\tif (this.middleware.length) {\n\t\t\t// TODO: Get middleware that applies to this route only?\n\t\t\tawait this.middleware[0](ev, buildNext(this.middleware, 0));\n\t\t\tfunction buildNext(middleware: MiddlewareFunction[], i: number): () => void | Promise<void> {\n\t\t\t\tif (ev.response) {\n\t\t\t\t\treturn noop;\n\t\t\t\t}\n\n\t\t\t\tif (i < middleware.length - 1) {\n\t\t\t\t\tlet next = middleware[i + 1];\n\t\t\t\t\treturn async () => next(ev, buildNext(middleware, i + 1));\n\t\t\t\t} else {\n\t\t\t\t\treturn match\n\t\t\t\t\t\t? async () => {\n\t\t\t\t\t\t\t\tev.response = await match.fn(ev);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: noop;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (match) {\n\t\t\tev.response = await match.fn(ev);\n\t\t} else {\n\t\t\treturn new Response(null, { status: 404 });\n\t\t}\n\n\t\t// TODO: Should I be returning 200 if there's no response? Because it's not an error??\n\t\tev.response ??= new Response(null, { status: 200 });\n\t\tev.addHeaders();\n\n\t\treturn ev.response;\n\t};\n\n\t/**\n\t * Adds a server function at a route path.\n\t * @param path The route path pattern.\n\t * @param fn The function to call when the pattern is matched.\n\t * @returns\n\t */\n\tadd(path: string, fn: ServerFunction): Server {\n\t\tthis.routes.push(new RouteHandler(path, fn));\n\t\treturn this;\n\t}\n\n\tmatch(path: string) {\n\t\tfor (let handler of this.routes) {\n\t\t\tlet match = path.match(handler.regex);\n\t\t\tif (match) {\n\t\t\t\treturn {\n\t\t\t\t\tfn: handler.fn,\n\t\t\t\t\tparams: match.groups,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tconsole.log(`Server path not found: ${path}`);\n\t}\n\n\t// TODO:\n\t//use(path: string, ...fn: MiddlewareFunction[])\n\tuse(...fn: MiddlewareFunction[]): Server {\n\t\tthis.middleware = this.middleware.concat(fn);\n\t\treturn this;\n\t}\n}\n\nclass RouteHandler {\n\tpath: string;\n\tregex: RegExp;\n\tfn: ServerFunction;\n\n\tconstructor(path: string, fn: ServerFunction) {\n\t\tthis.path = path;\n\t\tthis.regex = pathToRegex(path);\n\t\tthis.fn = fn;\n\t}\n}\n\n//class MiddlewareHandler {\n//\tpath: string;\n//\tregex: RegExp;\n//\tfn: MiddlewareFunction;\n//\n//\tconstructor(path: string, fn: MiddlewareFunction) {\n//\t\tthis.path = path;\n//\t\tthis.regex = pathToRegex(path);\n//\t\tthis.fn = fn;\n//\t}\n//}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { Plugin } from \"vite\";\nimport tsconfigPaths from \"vite-tsconfig-paths\";\nimport Adapter from \"../types/Adapter\";\nimport {\n\tHOOK_ROUTE,\n\tHOOK_SERVER_ROUTE,\n\tLAYOUT_ROUTE,\n\tLAYOUT_SERVER_ROUTE,\n\tPAGE_ROUTE,\n\tPAGE_SERVER_ROUTE,\n\tSERVER_ROUTE,\n} from \"../types/RouteType\";\nimport defaultAdapter from \"./defaultAdapter\";\n\n// 1. The user sets this up\n// 2. It is passed into serverEntry and clientEntry through a Vite plugin\n// (defined in manifest.ts)\n// 3. In those files, it is used to build a Router\n\n/**\n * The Site class contains the information necessary to setup a @torpor/build\n * site, including routes, plugins, and options.\n */\nexport default class Site {\n\troot: string;\n\troutes: { path: string; file: string; type: number }[] = [];\n\t// Is default plugins a bad idea?\n\t// HACK: Set loose because otherwise it uses a list of allowed extensions\n\t// TODO: Should probably just do this ourselves and let the user pass in\n\t// tsconfigPaths themselves if they want to do something funky\n\tplugins: Plugin[] = [tsconfigPaths({ loose: true })];\n\t// Is default adapter a bad idea?\n\tadapter: Adapter = defaultAdapter;\n\n\tconstructor() {\n\t\tthis.root = process.cwd();\n\t}\n\n\tasync addRouteFolder(folder: string) {\n\t\tconst routeFolder = path.join(this.root, folder);\n\t\tconst routeFiles = await fs.readdir(routeFolder, { recursive: true });\n\n\t\tfor (let file of routeFiles) {\n\t\t\t// The file must start with `+` or `_` and end with `.js` or `.ts`\n\t\t\tif (/^(\\+|_).+(\\.js|\\.ts)$/.test(path.basename(file))) {\n\t\t\t\tlet routePath = file\n\t\t\t\t\t.replace(/^\\//, \"\")\n\t\t\t\t\t.replace(/(\\.ts|\\.js)$/, \"\")\n\t\t\t\t\t.replace(/_hook.server$/, \"_hook/~server\")\n\t\t\t\t\t.replace(/_layout.server$/, \"_layout/~server\")\n\t\t\t\t\t.replace(/\\+page.server$/, \"~server\")\n\t\t\t\t\t.replace(/\\+server$/, \"\")\n\t\t\t\t\t.replace(/\\+page$/, \"\")\n\t\t\t\t\t.replace(/\\/$/, \"\");\n\t\t\t\troutePath = routePath.length > 0 ? `/${routePath}` : \"/\";\n\t\t\t\tlet type = this.#routeType(file);\n\t\t\t\tfile = path.relative(this.root, path.resolve(routeFolder, file));\n\t\t\t\tthis.routes.push({ path: routePath, file, type });\n\t\t\t}\n\t\t}\n\t\tthis.#sortRoutes();\n\t}\n\n\taddRouteFile(path: string, file: string) {\n\t\tlet type = this.#routeType(file);\n\t\tthis.routes.push({ path, file, type });\n\t\tthis.#sortRoutes();\n\t}\n\n\t#routeType(file: string): number {\n\t\tlet routePath = file.replace(/^\\//, \"\").replace(/(\\.ts|\\.js)$/, \"\");\n\t\tif (routePath.endsWith(\"+page\")) {\n\t\t\treturn PAGE_ROUTE;\n\t\t} else if (routePath.endsWith(\"+page.server\")) {\n\t\t\treturn PAGE_SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"+server\")) {\n\t\t\treturn SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"_layout\")) {\n\t\t\treturn LAYOUT_ROUTE;\n\t\t} else if (routePath.endsWith(\"_layout.server\")) {\n\t\t\treturn LAYOUT_SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"_hook\")) {\n\t\t\treturn HOOK_ROUTE;\n\t\t} else if (routePath.endsWith(\"_hook.server\")) {\n\t\t\treturn HOOK_SERVER_ROUTE;\n\t\t}\n\t\treturn -1;\n\t}\n\n\t// TODO: You could make your site in a single file, like e.g. Hono...\n\t//addPage(path: string, endPoint: PageEndPoint, serverEndPoint?: PageServerEndPoint) {}\n\t//addEndPoint(path: string, endPoint: ServerEndPoint) {}\n\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n","export const PAGE_ROUTE = 0;\nexport const PAGE_SERVER_ROUTE = 1;\nexport const SERVER_ROUTE = 3;\nexport const LAYOUT_ROUTE = 4;\nexport const LAYOUT_SERVER_ROUTE = 5;\nexport const HOOK_ROUTE = 6;\nexport const HOOK_SERVER_ROUTE = 7;\n","import Adapter from \"../types/Adapter\";\n\n// TODO: This should be an adapter-auto package that conditionally loads other packages...\n\nconst defaultAdapter: Adapter = {\n\tserve: () => {\n\t\tconsole.log(\"An adapter needs to be set in site.config\");\n\t},\n};\n\nexport default defaultAdapter;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAe,SAAR,YAA6BA,OAAsB;AACzD,QAAM,UAAUA,MACd,MAAM,GAAG,EACT,IAAI,CAAC,MAAM;AACX,WAAO,EAAE,QAAQ,iBAAiB,iBAAiB;AAAA,EACpD,CAAC,EACA,KAAK,KAAK,EACV,WAAW,KAAK,IAAI;AACtB,SAAO,IAAI,OAAO,IAAI,OAAO,GAAG;AACjC;;;ACTA,oBAAmD;AAEnD,IAAqB,eAArB,MAAkC;AAAA,EACjC;AAAA,EACA,UAA+B,oBAAI,IAAI;AAAA,EAEvC,YAAY,SAAkB;AAC7B,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,IAAI,MAAkC;AAErC,QAAI,KAAK,QAAQ,IAAI,IAAI,GAAG;AAC3B,aAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC7B;AAEA,UAAM,SAAS,KAAK,QAAQ,QAAQ,IAAI,QAAQ;AAChD,eAAO,qBAAM,UAAU,EAAE,EAAE,IAAI;AAAA,EAChC;AAAA,EAEA,IAAI,MAAc,OAAe,SAA4B;AAE5D,gBAAY,CAAC;AACb,YAAQ,aAAa;AACrB,YAAQ,WAAW;AACnB,YAAQ,aAAa;AACrB,SAAK,QAAQ,IAAI,UAAM,yBAAU,MAAM,OAAO,OAAO,CAAC;AAAA,EACvD;AAAA,EAEA,OAAO,MAAc,SAA4B;AAEhD,gBAAY,CAAC;AACb,YAAQ,UAAU,oBAAI,KAAK,CAAC;AAC5B,SAAK,QAAQ,IAAI,UAAM,yBAAU,MAAM,IAAI,OAAO,CAAC;AAAA,EACpD;AACD;;;ACnCA,IAAqB,eAArB,MAAkC;AAAA,EACjC;AAAA,EACA,UAA+B,oBAAI,IAAI;AAAA,EAEvC,YAAY,SAAkB;AAC7B,SAAK,UAAU;AAAA,EAChB;AAAA,EAEA,IAAI,MAAkC;AAErC,QAAI,KAAK,QAAQ,IAAI,IAAI,GAAG;AAC3B,aAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,IAC7B;AAEA,WAAO,KAAK,QAAQ,QAAQ,IAAI,IAAI,KAAK;AAAA,EAC1C;AAAA,EAEA,IAAI,MAAc,OAAe;AAChC,SAAK,QAAQ,IAAI,MAAM,KAAK;AAAA,EAC7B;AAAA,EAEA,OAAO,MAAc;AACpB,SAAK,QAAQ,OAAO,IAAI;AAAA,EACzB;AACD;;;ACrBA,IAAqB,cAArB,MAAiC;AAAA,EAChC;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EAEA,YAAY,SAAkB,QAAoC;AACjE,SAAK,UAAU;AACf,SAAK,SAAS;AACd,SAAK,UAAU,IAAI,aAAa,OAAO;AACvC,SAAK,UAAU,IAAI,aAAa,OAAO;AAAA,EACxC;AAAA,EAEA,aAAa;AACZ,QAAI,CAAC,KAAK,UAAU;AACnB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC3C;AAEA,aAAS,UAAU,KAAK,QAAQ,QAAQ,OAAO,GAAG;AACjD,WAAK,SAAS,QAAQ,OAAO,cAAc,MAAM;AAAA,IAClD;AAEA,aAAS,UAAU,KAAK,QAAQ,QAAQ,QAAQ,GAAG;AAClD,WAAK,SAAS,QAAQ,OAAO,OAAO,CAAC,GAAG,OAAO,CAAC,CAAC;AAAA,IAClD;AAAA,EACD;AACD;;;AC3BA,IAAM,OAAO,MAAM;AAAC;AAKpB,IAAqB,SAArB,MAA4B;AAAA;AAAA,EAE3B,SAAyB,CAAC;AAAA;AAAA,EAE1B,aAAmC,CAAC;AAAA,EAEpC,cAAc;AACb,SAAK,SAAS,CAAC;AACf,SAAK,aAAa,CAAC;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,OAAO,OAA0B,SAA0C;AAClF,UAAM,UAAU,IAAI,QAAQ,OAAO,IAAI;AACvC,UAAM,MAAM,IAAI,IAAI,QAAQ,GAAG;AAC/B,UAAM,QAAQ,KAAK,MAAM,IAAI,QAAQ;AACrC,QAAI,KAAK,IAAI,YAAY,SAAS,OAAO,MAAM;AAE/C,QAAI,KAAK,WAAW,QAAQ;AAG3B,UAASC,aAAT,SAAmB,YAAkC,GAAuC;AAC3F,YAAI,GAAG,UAAU;AAChB,iBAAO;AAAA,QACR;AAEA,YAAI,IAAI,WAAW,SAAS,GAAG;AAC9B,cAAI,OAAO,WAAW,IAAI,CAAC;AAC3B,iBAAO,YAAY,KAAK,IAAIA,WAAU,YAAY,IAAI,CAAC,CAAC;AAAA,QACzD,OAAO;AACN,iBAAO,QACJ,YAAY;AACZ,eAAG,WAAW,MAAM,MAAM,GAAG,EAAE;AAAA,UAChC,IACC;AAAA,QACJ;AAAA,MACD;AAfS,sBAAAA;AADT,YAAM,KAAK,WAAW,CAAC,EAAE,IAAIA,WAAU,KAAK,YAAY,CAAC,CAAC;AAAA,IAiB3D,WAAW,OAAO;AACjB,SAAG,WAAW,MAAM,MAAM,GAAG,EAAE;AAAA,IAChC,OAAO;AACN,aAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC1C;AAGA,OAAG,aAAa,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;AAClD,OAAG,WAAW;AAEd,WAAO,GAAG;AAAA,EACX;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAIC,OAAc,IAA4B;AAC7C,SAAK,OAAO,KAAK,IAAI,aAAaA,OAAM,EAAE,CAAC;AAC3C,WAAO;AAAA,EACR;AAAA,EAEA,MAAMA,OAAc;AACnB,aAAS,WAAW,KAAK,QAAQ;AAChC,UAAI,QAAQA,MAAK,MAAM,QAAQ,KAAK;AACpC,UAAI,OAAO;AACV,eAAO;AAAA,UACN,IAAI,QAAQ;AAAA,UACZ,QAAQ,MAAM;AAAA,QACf;AAAA,MACD;AAAA,IACD;AACA,YAAQ,IAAI,0BAA0BA,KAAI,EAAE;AAAA,EAC7C;AAAA;AAAA;AAAA,EAIA,OAAO,IAAkC;AACxC,SAAK,aAAa,KAAK,WAAW,OAAO,EAAE;AAC3C,WAAO;AAAA,EACR;AACD;AAEA,IAAM,eAAN,MAAmB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAYA,OAAc,IAAoB;AAC7C,SAAK,OAAOA;AACZ,SAAK,QAAQ,YAAYA,KAAI;AAC7B,SAAK,KAAK;AAAA,EACX;AACD;;;AC1GA,qBAA+B;AAC/B,uBAAiB;AAEjB,iCAA0B;;;ACHnB,IAAM,aAAa;AACnB,IAAM,oBAAoB;AAC1B,IAAM,eAAe;AACrB,IAAM,eAAe;AACrB,IAAM,sBAAsB;AAC5B,IAAM,aAAa;AACnB,IAAM,oBAAoB;;;ACFjC,IAAM,iBAA0B;AAAA,EAC/B,OAAO,MAAM;AACZ,YAAQ,IAAI,2CAA2C;AAAA,EACxD;AACD;AAEA,IAAO,yBAAQ;;;AFef,IAAqB,OAArB,MAA0B;AAAA,EACzB;AAAA,EACA,SAAyD,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAK1D,UAAoB,KAAC,2BAAAC,SAAc,EAAE,OAAO,KAAK,CAAC,CAAC;AAAA;AAAA,EAEnD,UAAmB;AAAA,EAEnB,cAAc;AACb,SAAK,OAAO,QAAQ,IAAI;AAAA,EACzB;AAAA,EAEA,MAAM,eAAe,QAAgB;AACpC,UAAM,cAAc,iBAAAC,QAAK,KAAK,KAAK,MAAM,MAAM;AAC/C,UAAM,aAAa,MAAM,eAAAC,SAAG,QAAQ,aAAa,EAAE,WAAW,KAAK,CAAC;AAEpE,aAAS,QAAQ,YAAY;AAE5B,UAAI,wBAAwB,KAAK,iBAAAD,QAAK,SAAS,IAAI,CAAC,GAAG;AACtD,YAAI,YAAY,KACd,QAAQ,OAAO,EAAE,EACjB,QAAQ,gBAAgB,EAAE,EAC1B,QAAQ,iBAAiB,eAAe,EACxC,QAAQ,mBAAmB,iBAAiB,EAC5C,QAAQ,kBAAkB,SAAS,EACnC,QAAQ,aAAa,EAAE,EACvB,QAAQ,WAAW,EAAE,EACrB,QAAQ,OAAO,EAAE;AACnB,oBAAY,UAAU,SAAS,IAAI,IAAI,SAAS,KAAK;AACrD,YAAI,OAAO,KAAK,WAAW,IAAI;AAC/B,eAAO,iBAAAA,QAAK,SAAS,KAAK,MAAM,iBAAAA,QAAK,QAAQ,aAAa,IAAI,CAAC;AAC/D,aAAK,OAAO,KAAK,EAAE,MAAM,WAAW,MAAM,KAAK,CAAC;AAAA,MACjD;AAAA,IACD;AACA,SAAK,YAAY;AAAA,EAClB;AAAA,EAEA,aAAaA,OAAc,MAAc;AACxC,QAAI,OAAO,KAAK,WAAW,IAAI;AAC/B,SAAK,OAAO,KAAK,EAAE,MAAAA,OAAM,MAAM,KAAK,CAAC;AACrC,SAAK,YAAY;AAAA,EAClB;AAAA,EAEA,WAAW,MAAsB;AAChC,QAAI,YAAY,KAAK,QAAQ,OAAO,EAAE,EAAE,QAAQ,gBAAgB,EAAE;AAClE,QAAI,UAAU,SAAS,OAAO,GAAG;AAChC,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,cAAc,GAAG;AAC9C,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,SAAS,GAAG;AACzC,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,SAAS,GAAG;AACzC,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,gBAAgB,GAAG;AAChD,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,OAAO,GAAG;AACvC,aAAO;AAAA,IACR,WAAW,UAAU,SAAS,cAAc,GAAG;AAC9C,aAAO;AAAA,IACR;AACA,WAAO;AAAA,EACR;AAAA;AAAA;AAAA;AAAA,EAMA,cAAc;AACb,SAAK,SAAS,KAAK,OAAO,KAAK,CAAC,GAAG,MAAM;AAGxC,eAAS,IAAI,GAAG,IAAI,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,KAAK,MAAM,GAAG,KAAK;AAChE,YAAI,EAAE,KAAK,CAAC,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK;AAC3C,iBAAO;AAAA,QACR,WAAW,EAAE,KAAK,CAAC,MAAM,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK;AAClD,iBAAO;AAAA,QACR,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG;AAAA,QAEpC,OAAO;AACN,iBAAO,EAAE,KAAK,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;AAAA,QACzC;AAAA,MACD;AACA,aAAO,EAAE,KAAK,SAAS,EAAE,KAAK;AAAA,IAC/B,CAAC;AAAA,EACF;AACD;","names":["path","buildNext","path","tsconfigPaths","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/site/pathToRegex.ts","../src/site/Router.ts","../src/site/Site.ts","../src/types/RouteType.ts","../src/site/defaultAdapter.ts"],"sourcesContent":["import Router from \"./site/Router\";\nimport Site from \"./site/Site\";\nimport type Adapter from \"./types/Adapter\";\nimport type PageEndPoint from \"./types/PageEndPoint\";\nimport type PageLoadEvent from \"./types/PageLoadEvent\";\nimport type PageServerAction from \"./types/PageServerAction\";\nimport type PageServerEndPoint from \"./types/PageServerEndPoint\";\nimport type PageServerLoad from \"./types/PageServerLoad\";\nimport type ServerEndPoint from \"./types/ServerEndPoint\";\nimport type ServerHook from \"./types/ServerHook\";\nimport type ServerLoadEvent from \"./types/ServerLoadEvent\";\nimport type ServerRequest from \"./types/ServerRequest\";\n\nexport { Site, Router };\n\nexport type {\n\tAdapter,\n\tPageEndPoint,\n\tPageServerEndPoint,\n\tPageServerLoad,\n\tPageServerAction,\n\tServerEndPoint,\n\tServerRequest,\n\tServerHook,\n\tPageLoadEvent,\n\tServerLoadEvent,\n};\n","export default function pathToRegex(path: string): RegExp {\n\tconst pattern = path\n\t\t.split(\"/\")\n\t\t.map((p) => {\n\t\t\treturn p.replace(/\\[([^\\/]+?)\\]/, \"(?<$1>[^\\\\/]+?)\");\n\t\t})\n\t\t.join(\"\\\\/\")\n\t\t.replaceAll(\"*\", \".*\");\n\treturn new RegExp(`^${pattern}$`);\n}\n","import type LayoutHandler from \"../types/LayoutHandler\";\nimport type ManifestRoute from \"../types/ManifestRoute\";\nimport type RouteHandler from \"../types/RouteHandler\";\nimport pathToRegex from \"./pathToRegex\";\n\n/**\n * A router that handles file routes with layouts, hooks, etc.\n */\nexport default class Router {\n\troutes: Route[] = [];\n\n\tconstructor() {}\n\n\t//add(path: string, file: string) {\n\t//\t// TODO: Call the specific addX method based on the file path\n\t//\tthis.addPage(route, file);\n\t//}\n\n\taddPages(routes: ManifestRoute[]) {\n\t\tfor (let r of routes) {\n\t\t\tthis.routes.push(\n\t\t\t\tnew Route(r.path, {\n\t\t\t\t\tpath: r.path,\n\t\t\t\t\ttype: r.type,\n\t\t\t\t\tendPoint: r.endPoint,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\t// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold\n\taddPage(path: string, type: number, endPoint: () => Promise<any>) {\n\t\tthis.routes.push(\n\t\t\tnew Route(path, {\n\t\t\t\tpath,\n\t\t\t\ttype,\n\t\t\t\tendPoint,\n\t\t\t}),\n\t\t);\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\t/*\n\tloadPage(ev: ServerEvent, file: string): Response {\n\t\tlet page = this.pages.get(file);\n\t\tif (!page) {\n\t\t\tpage = {};\n\t\t\tthis.pages.set(file, page);\n\t\t}\n\t}\n\t*/\n\n\tmatch(path: string, query: URLSearchParams) {\n\t\tfor (let route of this.routes) {\n\t\t\tlet match = path.match(route.regex);\n\t\t\tif (match) {\n\t\t\t\t// Lazy load server endpoints and layouts\n\t\t\t\tif (!route.handler.loaded) {\n\t\t\t\t\tthis.#loadHandler(route.handler, route.path);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\thandler: route.handler,\n\t\t\t\t\tparams: match.groups,\n\t\t\t\t\tquery,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tconsole.log(`not found: '${path}'`);\n\t}\n\n\t#loadHandler(handler: RouteHandler, path: string) {\n\t\thandler.layouts = this.#findLayouts(path);\n\t\thandler.serverEndPoint = this.#findServer(path);\n\t\thandler.serverHook = this.#findServerHook(path);\n\t}\n\n\t#findLayouts(path: string): LayoutHandler[] | undefined {\n\t\tlet layouts: LayoutHandler[] = [];\n\t\tlet parts = path\n\t\t\t// Strip the trailing`~/server` (so we don't look for `~/server/_layout`\n\t\t\t// which will never exist)\n\t\t\t.replace(/\\/~server$/, \"\")\n\t\t\t// The path will always start with / so splitting e.g. `/first/second`\n\t\t\t// will result in ['', 'first', 'second'] and checks for `/_layout`,\n\t\t\t// `/first/_layout` and `/second/_layout`\n\t\t\t.split(\"/\");\n\t\tlet basePath = \"\";\n\t\tfor (let i = 0; i < parts.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbasePath += \"/\" + parts[i];\n\t\t\t}\n\t\t\tconst layoutPath = basePath + \"/_layout\";\n\t\t\tconst layoutRoute = this.routes.find((r) => r.path === layoutPath);\n\t\t\tif (layoutRoute) {\n\t\t\t\tlayouts.push({\n\t\t\t\t\tpath: layoutPath,\n\t\t\t\t\tendPoint: layoutRoute.handler.endPoint,\n\t\t\t\t\tserverEndPoint: this.#findServer(layoutPath),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn layouts.length ? layouts : undefined;\n\t}\n\n\t#findServer(path: string): (() => Promise<any>) | undefined {\n\t\tconst serverPath = path.replace(/\\/$/, \"\") + \"/~server\";\n\t\tconst serverRoute = this.routes.find((r) => r.path === serverPath);\n\t\treturn serverRoute && serverRoute.handler.endPoint;\n\t}\n\n\t#findServerHook(path: string): (() => Promise<any>) | undefined {\n\t\t// TODO: Should this be a collection, like layouts?\n\t\tlet serverHookPath = \"/_hook/~server\";\n\t\t// HACK: Generalise this\n\t\tif (path.startsWith(\"/api/\")) {\n\t\t\tserverHookPath = \"/api\" + serverHookPath;\n\t\t}\n\t\tconst serverHookRoute = this.routes.find((r) => r.path === serverHookPath);\n\t\treturn serverHookRoute && serverHookRoute.handler.endPoint;\n\t}\n\n\t// HACK: We're doing this here as well as in Site, so that you can use the\n\t// Router externally without Site\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n\nclass Route {\n\tpath: string;\n\tregex: RegExp;\n\thandler: RouteHandler;\n\n\tconstructor(path: string, handler: RouteHandler) {\n\t\tthis.path = path;\n\t\tthis.regex = pathToRegex(path);\n\t\tthis.handler = handler;\n\t}\n}\n","import { promises as fs } from \"node:fs\";\nimport path from \"node:path\";\nimport { Plugin } from \"vite\";\nimport tsconfigPaths from \"vite-tsconfig-paths\";\nimport Adapter from \"../types/Adapter\";\nimport {\n\tHOOK_ROUTE,\n\tHOOK_SERVER_ROUTE,\n\tLAYOUT_ROUTE,\n\tLAYOUT_SERVER_ROUTE,\n\tPAGE_ROUTE,\n\tPAGE_SERVER_ROUTE,\n\tSERVER_ROUTE,\n} from \"../types/RouteType\";\nimport defaultAdapter from \"./defaultAdapter\";\n\n// 1. The user sets this up\n// 2. It is passed into serverEntry and clientEntry through a Vite plugin\n// (defined in manifest.ts)\n// 3. In those files, it is used to build a Router\n\n/**\n * The Site class contains the information necessary to setup a @torpor/build\n * site, including routes, plugins, and options.\n */\nexport default class Site {\n\troot: string;\n\troutes: { path: string; file: string; type: number }[] = [];\n\t// Is default plugins a bad idea?\n\t// HACK: Set loose because otherwise it uses a list of allowed extensions\n\t// TODO: Should probably just do this ourselves and let the user pass in\n\t// tsconfigPaths themselves if they want to do something funky\n\tplugins: Plugin[] = [tsconfigPaths({ loose: true })];\n\t// Is default adapter a bad idea?\n\tadapter: Adapter = defaultAdapter;\n\n\tconstructor() {\n\t\tthis.root = process.cwd();\n\t}\n\n\tasync addRouteFolder(folder: string) {\n\t\tconst routeFolder = path.join(this.root, folder);\n\t\tconst routeFiles = await fs.readdir(routeFolder, { recursive: true });\n\n\t\tfor (let file of routeFiles) {\n\t\t\t// The file must start with `+` or `_` and end with `.js` or `.ts`\n\t\t\tif (/^(\\+|_).+(\\.js|\\.ts)$/.test(path.basename(file))) {\n\t\t\t\tlet routePath = file\n\t\t\t\t\t.replace(/^\\//, \"\")\n\t\t\t\t\t.replace(/(\\.ts|\\.js)$/, \"\")\n\t\t\t\t\t.replace(/_hook.server$/, \"_hook/~server\")\n\t\t\t\t\t.replace(/_layout.server$/, \"_layout/~server\")\n\t\t\t\t\t.replace(/\\+page.server$/, \"~server\")\n\t\t\t\t\t.replace(/\\+server$/, \"\")\n\t\t\t\t\t.replace(/\\+page$/, \"\")\n\t\t\t\t\t.replace(/\\/$/, \"\");\n\t\t\t\troutePath = routePath.length > 0 ? `/${routePath}` : \"/\";\n\t\t\t\tlet type = this.#routeType(file);\n\t\t\t\tfile = path.relative(this.root, path.resolve(routeFolder, file));\n\t\t\t\tthis.routes.push({ path: routePath, file, type });\n\t\t\t}\n\t\t}\n\t\tthis.#sortRoutes();\n\t}\n\n\taddRouteFile(path: string, file: string) {\n\t\tlet type = this.#routeType(file);\n\t\tthis.routes.push({ path, file, type });\n\t\tthis.#sortRoutes();\n\t}\n\n\t#routeType(file: string): number {\n\t\tlet routePath = file.replace(/^\\//, \"\").replace(/(\\.ts|\\.js)$/, \"\");\n\t\tif (routePath.endsWith(\"+page\")) {\n\t\t\treturn PAGE_ROUTE;\n\t\t} else if (routePath.endsWith(\"+page.server\")) {\n\t\t\treturn PAGE_SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"+server\")) {\n\t\t\treturn SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"_layout\")) {\n\t\t\treturn LAYOUT_ROUTE;\n\t\t} else if (routePath.endsWith(\"_layout.server\")) {\n\t\t\treturn LAYOUT_SERVER_ROUTE;\n\t\t} else if (routePath.endsWith(\"_hook\")) {\n\t\t\treturn HOOK_ROUTE;\n\t\t} else if (routePath.endsWith(\"_hook.server\")) {\n\t\t\treturn HOOK_SERVER_ROUTE;\n\t\t}\n\t\treturn -1;\n\t}\n\n\t// TODO: You could make your site in a single file, like e.g. Hono...\n\t//addPage(path: string, endPoint: PageEndPoint, serverEndPoint?: PageServerEndPoint) {}\n\t//addEndPoint(path: string, endPoint: ServerEndPoint) {}\n\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n","export const PAGE_ROUTE = 0;\nexport const PAGE_SERVER_ROUTE = 1;\nexport const SERVER_ROUTE = 3;\nexport const LAYOUT_ROUTE = 4;\nexport const LAYOUT_SERVER_ROUTE = 5;\nexport const HOOK_ROUTE = 6;\nexport const HOOK_SERVER_ROUTE = 7;\n","import Adapter from \"../types/Adapter\";\n\n// TODO: This should be an adapter-auto package that conditionally loads other packages...\n\nconst defaultAdapter: Adapter = {\n\tserve: () => {\n\t\tconsole.log(\"An adapter needs to be set in site.config\");\n\t},\n};\n\nexport default defaultAdapter;\n"],"mappings":"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","names":["path","path","tsconfigPaths","path","fs"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
export { A as Adapter, a as Server, S as Site } from './Site-Df1k0TuQ.cjs';
|
|
1
|
+
export { A as Adapter, S as Site } from './Site-PxPCXGZ-.cjs';
|
|
3
2
|
import { Component } from '@torpor/view';
|
|
3
|
+
import { C as CookieHelper, H as HeaderHelper } from './Server-B45PD5Ys.cjs';
|
|
4
4
|
import 'vite';
|
|
5
5
|
import 'cookie';
|
|
6
6
|
|
|
7
|
+
type ManifestRoute = {
|
|
8
|
+
path: string;
|
|
9
|
+
type: number;
|
|
10
|
+
file: string;
|
|
11
|
+
endPoint: () => Promise<any>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type RouteLayoutHandler = {
|
|
15
|
+
path: string;
|
|
16
|
+
endPoint: () => Promise<any>;
|
|
17
|
+
serverEndPoint?: () => Promise<any>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type RouteHandler = {
|
|
21
|
+
path: string;
|
|
22
|
+
type: number;
|
|
23
|
+
endPoint: () => Promise<any>;
|
|
24
|
+
loaded?: boolean;
|
|
25
|
+
layouts?: RouteLayoutHandler[];
|
|
26
|
+
serverEndPoint?: () => Promise<any>;
|
|
27
|
+
serverHook?: () => Promise<any>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A router that handles file routes with layouts, hooks, etc.
|
|
32
|
+
*/
|
|
33
|
+
declare class Router {
|
|
34
|
+
#private;
|
|
35
|
+
routes: Route[];
|
|
36
|
+
constructor();
|
|
37
|
+
addPages(routes: ManifestRoute[]): this;
|
|
38
|
+
addPage(path: string, type: number, endPoint: () => Promise<any>): this;
|
|
39
|
+
match(path: string, query: URLSearchParams): {
|
|
40
|
+
handler: RouteHandler;
|
|
41
|
+
params: {
|
|
42
|
+
[key: string]: string;
|
|
43
|
+
} | undefined;
|
|
44
|
+
query: URLSearchParams;
|
|
45
|
+
} | undefined;
|
|
46
|
+
}
|
|
47
|
+
declare class Route {
|
|
48
|
+
path: string;
|
|
49
|
+
regex: RegExp;
|
|
50
|
+
handler: RouteHandler;
|
|
51
|
+
constructor(path: string, handler: RouteHandler);
|
|
52
|
+
}
|
|
53
|
+
|
|
7
54
|
type PageLoadEvent = {
|
|
8
55
|
/**
|
|
9
56
|
* The URL for the server function.
|
|
@@ -147,4 +194,4 @@ type ServerHook = {
|
|
|
147
194
|
|
|
148
195
|
type ServerLoad = (event: ServerLoadEvent) => Promise<void> | void;
|
|
149
196
|
|
|
150
|
-
export type
|
|
197
|
+
export { type PageEndPoint, type PageLoadEvent, type PageServerAction, type PageServerEndPoint, type PageServerLoad, Router, type ServerEndPoint, type ServerHook, type ServerLoadEvent, type ServerRequest };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
export { A as Adapter, a as Server, S as Site } from './Site-Df1k0TuQ.js';
|
|
1
|
+
export { A as Adapter, S as Site } from './Site-Qpcmx0Xq.js';
|
|
3
2
|
import { Component } from '@torpor/view';
|
|
3
|
+
import { C as CookieHelper, H as HeaderHelper } from './Server-B45PD5Ys.js';
|
|
4
4
|
import 'vite';
|
|
5
5
|
import 'cookie';
|
|
6
6
|
|
|
7
|
+
type ManifestRoute = {
|
|
8
|
+
path: string;
|
|
9
|
+
type: number;
|
|
10
|
+
file: string;
|
|
11
|
+
endPoint: () => Promise<any>;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type RouteLayoutHandler = {
|
|
15
|
+
path: string;
|
|
16
|
+
endPoint: () => Promise<any>;
|
|
17
|
+
serverEndPoint?: () => Promise<any>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
type RouteHandler = {
|
|
21
|
+
path: string;
|
|
22
|
+
type: number;
|
|
23
|
+
endPoint: () => Promise<any>;
|
|
24
|
+
loaded?: boolean;
|
|
25
|
+
layouts?: RouteLayoutHandler[];
|
|
26
|
+
serverEndPoint?: () => Promise<any>;
|
|
27
|
+
serverHook?: () => Promise<any>;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A router that handles file routes with layouts, hooks, etc.
|
|
32
|
+
*/
|
|
33
|
+
declare class Router {
|
|
34
|
+
#private;
|
|
35
|
+
routes: Route[];
|
|
36
|
+
constructor();
|
|
37
|
+
addPages(routes: ManifestRoute[]): this;
|
|
38
|
+
addPage(path: string, type: number, endPoint: () => Promise<any>): this;
|
|
39
|
+
match(path: string, query: URLSearchParams): {
|
|
40
|
+
handler: RouteHandler;
|
|
41
|
+
params: {
|
|
42
|
+
[key: string]: string;
|
|
43
|
+
} | undefined;
|
|
44
|
+
query: URLSearchParams;
|
|
45
|
+
} | undefined;
|
|
46
|
+
}
|
|
47
|
+
declare class Route {
|
|
48
|
+
path: string;
|
|
49
|
+
regex: RegExp;
|
|
50
|
+
handler: RouteHandler;
|
|
51
|
+
constructor(path: string, handler: RouteHandler);
|
|
52
|
+
}
|
|
53
|
+
|
|
7
54
|
type PageLoadEvent = {
|
|
8
55
|
/**
|
|
9
56
|
* The URL for the server function.
|
|
@@ -147,4 +194,4 @@ type ServerHook = {
|
|
|
147
194
|
|
|
148
195
|
type ServerLoad = (event: ServerLoadEvent) => Promise<void> | void;
|
|
149
196
|
|
|
150
|
-
export type
|
|
197
|
+
export { type PageEndPoint, type PageLoadEvent, type PageServerAction, type PageServerEndPoint, type PageServerLoad, Router, type ServerEndPoint, type ServerHook, type ServerLoadEvent, type ServerRequest };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,132 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
pathToRegex
|
|
3
|
+
} from "./chunk-T5K52YVJ.js";
|
|
4
|
+
|
|
5
|
+
// src/site/Router.ts
|
|
6
|
+
var Router = class {
|
|
7
|
+
routes = [];
|
|
8
|
+
constructor() {
|
|
9
|
+
}
|
|
10
|
+
//add(path: string, file: string) {
|
|
11
|
+
// // TODO: Call the specific addX method based on the file path
|
|
12
|
+
// this.addPage(route, file);
|
|
13
|
+
//}
|
|
14
|
+
addPages(routes) {
|
|
15
|
+
for (let r of routes) {
|
|
16
|
+
this.routes.push(
|
|
17
|
+
new Route(r.path, {
|
|
18
|
+
path: r.path,
|
|
19
|
+
type: r.type,
|
|
20
|
+
endPoint: r.endPoint
|
|
21
|
+
})
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
this.#sortRoutes();
|
|
25
|
+
return this;
|
|
26
|
+
}
|
|
27
|
+
// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold
|
|
28
|
+
addPage(path2, type, endPoint) {
|
|
29
|
+
this.routes.push(
|
|
30
|
+
new Route(path2, {
|
|
31
|
+
path: path2,
|
|
32
|
+
type,
|
|
33
|
+
endPoint
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
this.#sortRoutes();
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
/*
|
|
40
|
+
loadPage(ev: ServerEvent, file: string): Response {
|
|
41
|
+
let page = this.pages.get(file);
|
|
42
|
+
if (!page) {
|
|
43
|
+
page = {};
|
|
44
|
+
this.pages.set(file, page);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
*/
|
|
48
|
+
match(path2, query) {
|
|
49
|
+
for (let route of this.routes) {
|
|
50
|
+
let match = path2.match(route.regex);
|
|
51
|
+
if (match) {
|
|
52
|
+
if (!route.handler.loaded) {
|
|
53
|
+
this.#loadHandler(route.handler, route.path);
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
handler: route.handler,
|
|
57
|
+
params: match.groups,
|
|
58
|
+
query
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
console.log(`not found: '${path2}'`);
|
|
63
|
+
}
|
|
64
|
+
#loadHandler(handler, path2) {
|
|
65
|
+
handler.layouts = this.#findLayouts(path2);
|
|
66
|
+
handler.serverEndPoint = this.#findServer(path2);
|
|
67
|
+
handler.serverHook = this.#findServerHook(path2);
|
|
68
|
+
}
|
|
69
|
+
#findLayouts(path2) {
|
|
70
|
+
let layouts = [];
|
|
71
|
+
let parts = path2.replace(/\/~server$/, "").split("/");
|
|
72
|
+
let basePath = "";
|
|
73
|
+
for (let i = 0; i < parts.length; i++) {
|
|
74
|
+
if (i > 0) {
|
|
75
|
+
basePath += "/" + parts[i];
|
|
76
|
+
}
|
|
77
|
+
const layoutPath = basePath + "/_layout";
|
|
78
|
+
const layoutRoute = this.routes.find((r) => r.path === layoutPath);
|
|
79
|
+
if (layoutRoute) {
|
|
80
|
+
layouts.push({
|
|
81
|
+
path: layoutPath,
|
|
82
|
+
endPoint: layoutRoute.handler.endPoint,
|
|
83
|
+
serverEndPoint: this.#findServer(layoutPath)
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return layouts.length ? layouts : void 0;
|
|
88
|
+
}
|
|
89
|
+
#findServer(path2) {
|
|
90
|
+
const serverPath = path2.replace(/\/$/, "") + "/~server";
|
|
91
|
+
const serverRoute = this.routes.find((r) => r.path === serverPath);
|
|
92
|
+
return serverRoute && serverRoute.handler.endPoint;
|
|
93
|
+
}
|
|
94
|
+
#findServerHook(path2) {
|
|
95
|
+
let serverHookPath = "/_hook/~server";
|
|
96
|
+
if (path2.startsWith("/api/")) {
|
|
97
|
+
serverHookPath = "/api" + serverHookPath;
|
|
98
|
+
}
|
|
99
|
+
const serverHookRoute = this.routes.find((r) => r.path === serverHookPath);
|
|
100
|
+
return serverHookRoute && serverHookRoute.handler.endPoint;
|
|
101
|
+
}
|
|
102
|
+
// HACK: We're doing this here as well as in Site, so that you can use the
|
|
103
|
+
// Router externally without Site
|
|
104
|
+
#sortRoutes() {
|
|
105
|
+
this.routes = this.routes.sort((a, b) => {
|
|
106
|
+
for (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {
|
|
107
|
+
if (a.path[i] === "[" && b.path[i] !== "[") {
|
|
108
|
+
return 1;
|
|
109
|
+
} else if (b.path[i] === "[" && a.path[i] !== "[") {
|
|
110
|
+
return -1;
|
|
111
|
+
} else if (a.path[i] === b.path[i]) {
|
|
112
|
+
} else {
|
|
113
|
+
return a.path[i].localeCompare(b.path[i]);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return a.path.length - b.path.length;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
var Route = class {
|
|
121
|
+
path;
|
|
122
|
+
regex;
|
|
123
|
+
handler;
|
|
124
|
+
constructor(path2, handler) {
|
|
125
|
+
this.path = path2;
|
|
126
|
+
this.regex = pathToRegex(path2);
|
|
127
|
+
this.handler = handler;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
4
130
|
|
|
5
131
|
// src/site/Site.ts
|
|
6
132
|
import { promises as fs } from "node:fs";
|
|
@@ -96,7 +222,7 @@ var Site = class {
|
|
|
96
222
|
}
|
|
97
223
|
};
|
|
98
224
|
export {
|
|
99
|
-
|
|
225
|
+
Router,
|
|
100
226
|
Site
|
|
101
227
|
};
|
|
102
228
|
//# sourceMappingURL=index.js.map
|