@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.
Files changed (106) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +1 -1
  3. package/dist/Server-CB99REgs.d.cts +74 -0
  4. package/dist/Server-CB99REgs.d.ts +74 -0
  5. package/dist/Site-CgoeDt8k.d.cts +29 -0
  6. package/dist/Site-D95nwrAg.d.ts +29 -0
  7. package/dist/adapters/cloudflare/index.cjs +125 -0
  8. package/dist/adapters/cloudflare/index.cjs.map +1 -0
  9. package/dist/adapters/cloudflare/index.d.cts +13 -0
  10. package/dist/adapters/cloudflare/index.d.ts +13 -0
  11. package/dist/adapters/cloudflare/index.js +80 -0
  12. package/dist/adapters/cloudflare/index.js.map +1 -0
  13. package/dist/adapters/node/index.cjs +152 -0
  14. package/dist/adapters/node/index.cjs.map +1 -0
  15. package/dist/adapters/node/index.d.cts +8 -0
  16. package/dist/adapters/node/index.d.ts +8 -0
  17. package/dist/adapters/node/index.js +8 -0
  18. package/dist/adapters/node/index.js.map +1 -0
  19. package/dist/bin/index.cjs +541 -93
  20. package/dist/bin/index.cjs.map +1 -1
  21. package/dist/bin/index.js +511 -22
  22. package/dist/bin/index.js.map +1 -1
  23. package/dist/chunk-5X4T3PZN.js +23 -0
  24. package/dist/chunk-5X4T3PZN.js.map +1 -0
  25. package/dist/chunk-ALHFYD7U.js +113 -0
  26. package/dist/chunk-ALHFYD7U.js.map +1 -0
  27. package/dist/chunk-V4XTDQEV.js +19 -0
  28. package/dist/chunk-V4XTDQEV.js.map +1 -0
  29. package/dist/chunk-VAGHGWM5.js +110 -0
  30. package/dist/chunk-VAGHGWM5.js.map +1 -0
  31. package/dist/index.cjs +200 -97
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +33 -36
  34. package/dist/index.d.ts +33 -36
  35. package/dist/index.js +85 -17
  36. package/dist/index.js.map +1 -1
  37. package/dist/metafile-cjs.json +1 -1
  38. package/dist/metafile-esm.json +1 -1
  39. package/dist/response.js +17 -91
  40. package/dist/response.js.map +1 -1
  41. package/package.json +26 -9
  42. package/src/adapters/cloudflare/_worker.ts +38 -0
  43. package/src/adapters/cloudflare/index.ts +98 -0
  44. package/src/adapters/node/constants.ts +1 -0
  45. package/src/adapters/node/createFetchHandler.ts +29 -0
  46. package/src/adapters/node/createMiddlewareHandler.ts +79 -0
  47. package/src/adapters/node/createNodeServer.ts +8 -0
  48. package/src/adapters/node/flattenHeaders.ts +44 -0
  49. package/src/adapters/node/index.ts +18 -0
  50. package/src/adapters/node/nodeMessageToNodeResponse.ts +89 -0
  51. package/src/adapters/node/nodeMessageToRequest.ts +43 -0
  52. package/src/adapters/node/readableToBuffer.ts +16 -0
  53. package/src/adapters/node/requestToNodeMessage.ts +26 -0
  54. package/src/adapters/node/responseToNodeResponse.ts +44 -0
  55. package/src/bin/index.ts +43 -36
  56. package/src/index.ts +6 -14
  57. package/src/server/CookieHelper.ts +36 -0
  58. package/src/server/HeaderHelper.ts +25 -0
  59. package/src/server/Server.ts +119 -0
  60. package/src/server/ServerEvent.ts +33 -0
  61. package/src/server/ServerFunction.ts +5 -0
  62. package/src/server/contentType.ts +85 -0
  63. package/src/site/Router.ts +136 -0
  64. package/src/site/Routerx.ts +67 -0
  65. package/src/site/Site.ts +114 -0
  66. package/src/site/clientEntry.ts +22 -20
  67. package/src/site/manifest.ts +49 -0
  68. package/src/site/pathToRegex.ts +10 -0
  69. package/src/site/prepareTemplate.ts +20 -0
  70. package/src/site/runBuild.ts +92 -0
  71. package/src/site/runDev.ts +84 -0
  72. package/src/site/runPreview.ts +83 -0
  73. package/src/site/serverEntry.ts +113 -200
  74. package/src/types/Adapter.ts +10 -0
  75. package/src/types/HttpMethod.ts +12 -0
  76. package/src/types/LayoutHandler.ts +7 -0
  77. package/src/types/ManifestRoute.ts +8 -0
  78. package/src/types/MiddlewareFunction.ts +8 -0
  79. package/src/types/PageEndPoint.ts +4 -3
  80. package/src/types/{PageEvent.ts → PageLoadEvent.ts} +3 -2
  81. package/src/types/PageServerAction.ts +5 -2
  82. package/src/types/PageServerEndPoint.ts +1 -0
  83. package/src/types/PageServerLoad.ts +5 -2
  84. package/src/types/RouteHandler.ts +6 -5
  85. package/src/types/RouteHandlerCollection.ts +1 -0
  86. package/src/types/RouteLayoutHandler.ts +3 -2
  87. package/src/types/RouteMatchResult.ts +3 -2
  88. package/src/types/RouteType.ts +7 -0
  89. package/src/types/ServerEndPoint.ts +1 -0
  90. package/src/types/ServerHook.ts +3 -2
  91. package/src/types/{ServerEvent.ts → ServerLoadEvent.ts} +13 -6
  92. package/src/types/ServerRequest.ts +5 -2
  93. package/src/types/manifest.d.ts +7 -0
  94. package/test/app.test.ts +47 -0
  95. package/tsconfig.json +1 -1
  96. package/tsup.config.ts +11 -1
  97. package/vitest.config.ts +3 -0
  98. package/dist/chunk-L7GOYKUG.js +0 -93
  99. package/dist/chunk-L7GOYKUG.js.map +0 -1
  100. package/src/site/FileSystemRouter.ts +0 -25
  101. package/src/site/buildRoutePath.ts +0 -25
  102. package/src/site/defineConfig.ts +0 -75
  103. package/src/site/lazyRoute.ts +0 -72
  104. package/src/site/routeHandlers.ts +0 -126
  105. package/src/types/CookieHelper.ts +0 -8
  106. package/src/types/UserConfig.ts +0 -4
@@ -24,115 +24,563 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  ));
25
25
 
26
26
  // src/bin/index.ts
27
- var import_node_fs = __toESM(require("fs"), 1);
28
- var import_path = __toESM(require("path"), 1);
27
+ var import_node_fs4 = __toESM(require("fs"), 1);
28
+ var import_node_path4 = __toESM(require("path"), 1);
29
+ var import_vite5 = require("vite");
29
30
 
30
- // src/site/defineConfig.ts
31
+ // src/site/runBuild.ts
31
32
  var import_vite = __toESM(require("@torpor/unplugin/vite"), 1);
33
+ var import_node_fs2 = require("fs");
34
+ var import_node_path2 = __toESM(require("path"), 1);
35
+ var import_node_url = require("url");
36
+ var import_vite2 = require("vite");
37
+
38
+ // src/site/manifest.ts
39
+ var import_node_fs = require("fs");
32
40
  var import_node_path = __toESM(require("path"), 1);
33
- var import_vinxi = require("vinxi");
34
- var import_config = require("vinxi/plugins/config");
35
-
36
- // src/site/FileSystemRouter.ts
37
- var import_fs_router = require("vinxi/fs-router");
38
- var FileSystemRouter = class extends import_fs_router.BaseFileSystemRouter {
39
- toPath(src) {
40
- let routePath = (0, import_fs_router.cleanPath)(src, this.config).replace(/^\//, "").replace(/_hook.server$/, "_hook/~server").replace(/_layout.server$/, "_layout/~server").replace(/\+page.server$/, "~server").replace(/\+page$/, "").replace(/\+server$/, "").replace(/\/$/, "");
41
- return routePath?.length > 0 ? `/${routePath}` : "/";
42
- }
43
- toRoute(filePath) {
44
- return {
45
- path: this.toPath(filePath),
46
- $handler: {
47
- src: filePath,
48
- pick: ["default"]
41
+ var moduleId = "@torpor/build/manifest";
42
+ function manifest(site, server = false) {
43
+ return {
44
+ name: "torpor-manifest",
45
+ resolveId: {
46
+ order: "pre",
47
+ handler(id) {
48
+ if (id === moduleId) {
49
+ return id;
50
+ }
49
51
  }
50
- };
51
- }
52
+ },
53
+ load(id) {
54
+ if (id === moduleId) {
55
+ return `
56
+ ${!server ? "const load = { default: { load: true } };" : ""}
57
+ export default {
58
+ routes: [
59
+ ${site.routes.map((r) => {
60
+ if (server || !/server\.(ts|js)$/.test(r.file)) {
61
+ return `{ path: "${r.path}", file: "${r.file}", type: ${r.type}, endPoint: ${server || !/server\.(ts|js)$/.test(r.file) ? `() => import(/* @vite-ignore */ "${import_node_path.default.join(site.root, r.file)}")` : "undefined"} }`;
62
+ } else {
63
+ const haveLoad = (0, import_node_fs.readFileSync)(import_node_path.default.join(site.root, r.file)).includes("load:");
64
+ return `{ path: "${r.path}", file: "${r.file}", type: ${r.type}, endPoint: ${haveLoad ? "() => load" : "undefined"} }`;
65
+ }
66
+ }).join(",\n ")}
67
+ ],
52
68
  };
69
+ `;
70
+ }
71
+ }
72
+ };
73
+ }
53
74
 
54
- // src/site/defineConfig.ts
55
- function defineConfig(options2) {
56
- process.env.PORT = (options2?.port || 7059).toString();
57
- return (0, import_vinxi.createApp)({
58
- name: "torpor",
59
- routers: [
60
- {
61
- name: "assets",
62
- type: "static",
63
- dir: "./src/assets"
64
- },
65
- // Doesn't look like we can have two server routes?
66
- // Have to put api in /routes
67
- // Maybe we can support having /routes/api and routes/site and stripping /site from the start?
68
- //{
69
- // name: "api",
70
- // type: "http",
71
- // target: "server",
72
- // // TODO: change this when published
73
- // handler: "node_modules/@torpor/build/src/site/serverEntry.ts",
74
- // routes: apiRoutes,
75
- // plugins: () => [config("custom", viteOptions())],
76
- //},
77
- {
78
- name: "server",
79
- type: "http",
80
- target: "server",
81
- // TODO: change this when published
82
- handler: "./node_modules/@torpor/build/src/site/serverEntry.ts",
83
- routes,
84
- plugins: () => [(0, import_config.config)("custom", viteOptions()), (0, import_vite.default)({ server: true })]
85
- },
86
- {
87
- name: "client",
88
- type: "client",
89
- target: "browser",
90
- // TODO: change this when published
91
- handler: "./node_modules/@torpor/build/src/site/clientEntry.ts",
92
- base: "/_build",
93
- routes,
94
- plugins: () => [(0, import_config.config)("custom", viteOptions()), (0, import_vite.default)()]
75
+ // src/site/runBuild.ts
76
+ var import_meta = {};
77
+ var __dirname = import_node_path2.default.dirname((0, import_node_url.fileURLToPath)(import_meta.url));
78
+ async function runBuild(site) {
79
+ const distFolder = import_node_path2.default.resolve(site.root, "dist");
80
+ if ((0, import_node_fs2.existsSync)(distFolder)) {
81
+ await import_node_fs2.promises.rm(distFolder, { recursive: true });
82
+ }
83
+ const clientFolder = import_node_path2.default.join(distFolder, "client");
84
+ const serverFolder = import_node_path2.default.join(distFolder, "server");
85
+ if (site.adapter.prebuild) {
86
+ await site.adapter.prebuild(site);
87
+ }
88
+ let siteHtml = import_node_path2.default.resolve(site.root, "src/site.html");
89
+ let clientScript = import_node_path2.default.resolve(__dirname, "../../src/site/clientEntry.ts");
90
+ let serverScript = import_node_path2.default.resolve(__dirname, "../../src/site/serverEntry.ts");
91
+ await (0, import_vite2.build)(
92
+ (0, import_vite2.defineConfig)({
93
+ plugins: [
94
+ manifest(site),
95
+ // @ts-ignore
96
+ (0, import_vite.default)(),
97
+ ...site.plugins
98
+ ],
99
+ build: {
100
+ outDir: clientFolder,
101
+ rollupOptions: {
102
+ input: [
103
+ siteHtml,
104
+ clientScript,
105
+ ...site.routes.filter((r) => !/server\.(ts|js)$/.test(r.file)).map((r) => import_node_path2.default.resolve(site.root, r.file))
106
+ ]
107
+ },
108
+ ssrManifest: true
95
109
  }
96
- ]
110
+ })
111
+ );
112
+ await (0, import_vite2.build)(
113
+ (0, import_vite2.defineConfig)({
114
+ plugins: [
115
+ manifest(site, true),
116
+ // @ts-ignore
117
+ (0, import_vite.default)(),
118
+ ...site.plugins
119
+ ],
120
+ build: {
121
+ outDir: serverFolder,
122
+ rollupOptions: {
123
+ input: [serverScript, ...site.routes.map((r) => import_node_path2.default.resolve(site.root, r.file))]
124
+ },
125
+ ssr: serverScript
126
+ }
127
+ })
128
+ );
129
+ siteHtml = import_node_path2.default.join(clientFolder, "site.html");
130
+ await import_node_fs2.promises.rename(import_node_path2.default.join(clientFolder, "src", "site.html"), siteHtml);
131
+ await import_node_fs2.promises.rm(import_node_path2.default.join(clientFolder, "src"), { recursive: true });
132
+ if (site.adapter.postbuild) {
133
+ await site.adapter.postbuild(site);
134
+ }
135
+ }
136
+
137
+ // src/site/runDev.ts
138
+ var import_vite3 = __toESM(require("@torpor/unplugin/vite"), 1);
139
+ var import_dotenv = require("dotenv");
140
+ var import_node_fs3 = require("fs");
141
+ var import_node_path3 = __toESM(require("path"), 1);
142
+ var import_node_url2 = require("url");
143
+ var import_vite4 = require("vite");
144
+
145
+ // src/adapters/node/flattenHeaders.ts
146
+ function flattenHeaders(headers) {
147
+ const flatHeaders = new Headers();
148
+ for (const [key, value] of Object.entries(headers)) {
149
+ if (value === void 0 || value === null) {
150
+ continue;
151
+ } else if (Array.isArray(value)) {
152
+ for (const v of value) {
153
+ if (v !== void 0 && v !== null) {
154
+ value.forEach((v2) => flatHeaders.append(key, v2));
155
+ }
156
+ }
157
+ } else {
158
+ flatHeaders.set(key, String(value));
159
+ }
160
+ }
161
+ return flatHeaders;
162
+ }
163
+
164
+ // src/adapters/node/nodeMessageToNodeResponse.ts
165
+ var import_node_http = require("http");
166
+ var import_node_stream = require("stream");
167
+ function nodeMessageToNodeResponse(incomingMessage) {
168
+ const res = new import_node_http.ServerResponse(incomingMessage);
169
+ const passThrough = new import_node_stream.PassThrough();
170
+ let handled = false;
171
+ const onReadable = (cb) => {
172
+ const handleReadable = () => {
173
+ if (handled) return;
174
+ handled = true;
175
+ cb({
176
+ readable: import_node_stream.Readable.from(passThrough),
177
+ headers: res.getHeaders(),
178
+ status: res.statusCode
179
+ });
180
+ };
181
+ passThrough.once("readable", handleReadable);
182
+ passThrough.once("end", handleReadable);
183
+ };
184
+ passThrough.once("finish", () => {
185
+ res.emit("finish");
186
+ });
187
+ passThrough.once("close", () => {
188
+ res.destroy();
189
+ res.emit("close");
97
190
  });
191
+ passThrough.on("drain", () => {
192
+ res.emit("drain");
193
+ });
194
+ res.write = passThrough.write.bind(passThrough);
195
+ res.end = passThrough.end.bind(passThrough);
196
+ res.writeHead = function writeHead(statusCode, statusMessage, headers) {
197
+ res.statusCode = statusCode;
198
+ if (typeof statusMessage === "object") {
199
+ headers = statusMessage;
200
+ statusMessage = void 0;
201
+ }
202
+ if (headers) {
203
+ for (const [key, value] of Object.entries(headers)) {
204
+ if (value !== void 0) {
205
+ res.setHeader(key, value);
206
+ }
207
+ }
208
+ }
209
+ return res;
210
+ };
211
+ return {
212
+ res,
213
+ onReadable
214
+ };
98
215
  }
99
- function routes(router, app) {
100
- return new FileSystemRouter(
101
- {
102
- dir: import_node_path.default.resolve("src/routes"),
103
- extensions: ["js", "ts"]
104
- },
105
- router,
106
- app
216
+
217
+ // src/adapters/node/readableToBuffer.ts
218
+ function readableToBuffer(req) {
219
+ return new Promise((resolve, reject) => {
220
+ const chunks = [];
221
+ req.on("data", (chunk) => {
222
+ chunks.push(chunk);
223
+ });
224
+ req.on("end", () => {
225
+ resolve(Buffer.concat(chunks));
226
+ });
227
+ req.on("error", (err) => {
228
+ reject(err);
229
+ });
230
+ });
231
+ }
232
+
233
+ // src/adapters/node/requestToNodeMessage.ts
234
+ var import_node_stream2 = require("stream");
235
+ var DUMMY_BASE_URL = "http://localhost";
236
+ function requestToNodeMessage(request) {
237
+ const parsedUrl = new URL(request.url, DUMMY_BASE_URL);
238
+ const pathAndQuery = (parsedUrl.pathname || "") + (parsedUrl.search || "");
239
+ const body = (
240
+ /*request.body ? Readable.fromWeb(request.body as any) :*/
241
+ import_node_stream2.Readable.from([])
107
242
  );
243
+ return Object.assign(body, {
244
+ url: pathAndQuery,
245
+ method: request.method,
246
+ headers: Object.fromEntries(request.headers)
247
+ });
108
248
  }
109
- function viteOptions() {
110
- return {
111
- resolve: {
112
- alias: {
113
- "@": import_node_path.default.resolve("src")
249
+
250
+ // src/adapters/node/createMiddlewareHandler.ts
251
+ function createMiddlewareHandler(handler) {
252
+ return async (ev, next) => {
253
+ const req = requestToNodeMessage(ev.request);
254
+ const { res, onReadable } = nodeMessageToNodeResponse(req);
255
+ return new Promise(async (resolve, reject) => {
256
+ onReadable(async ({ readable, headers, status }) => {
257
+ const responseBody = statusCodesWithoutBody.includes(status) ? null : (
258
+ //(Readable.toWeb(readable) as ReadableStream);
259
+ // HACK: Chunked bodies are not being
260
+ // read correctly somewhere...
261
+ await readableToBuffer(readable)
262
+ );
263
+ ev.response = new Response(responseBody, {
264
+ status,
265
+ headers: flattenHeaders(headers)
266
+ });
267
+ resolve();
268
+ });
269
+ const cnext = async (error) => {
270
+ if (error) {
271
+ reject(error instanceof Error ? error : new Error(String(error)));
272
+ } else {
273
+ await next();
274
+ resolve();
275
+ }
276
+ };
277
+ try {
278
+ const handled = await handler(req, res, cnext);
279
+ if (handled === false) {
280
+ res.destroy();
281
+ resolve();
282
+ }
283
+ } catch (e) {
284
+ cnext(e);
114
285
  }
286
+ });
287
+ };
288
+ }
289
+ var statusCodesWithoutBody = [
290
+ 100,
291
+ // Continue
292
+ 101,
293
+ // Switching Protocols
294
+ 102,
295
+ // Processing (WebDAV)
296
+ 103,
297
+ // Early Hints
298
+ 204,
299
+ // No Content
300
+ 205,
301
+ // Reset Content
302
+ 304
303
+ // Not Modified
304
+ ];
305
+
306
+ // src/response/response.ts
307
+ function response(status, body) {
308
+ let headers = void 0;
309
+ if (body) {
310
+ if (typeof body === "object") {
311
+ headers = { "content-type": "application/json" };
312
+ body = JSON.stringify(body);
313
+ } else {
314
+ headers = { "content-type": "text/plain" };
115
315
  }
316
+ }
317
+ return new Response(body, {
318
+ status,
319
+ headers
320
+ });
321
+ }
322
+
323
+ // src/response/serverError.ts
324
+ function serverError(body) {
325
+ return response(500, body);
326
+ }
327
+
328
+ // src/site/pathToRegex.ts
329
+ function pathToRegex(path5) {
330
+ const pattern = path5.split("/").map((p) => {
331
+ return p.replace(/\[([^\/]+?)\]/, "(?<$1>[^\\/]+?)");
332
+ }).join("\\/").replaceAll("*", ".*");
333
+ return new RegExp(`^${pattern}$`);
334
+ }
335
+
336
+ // src/server/CookieHelper.ts
337
+ var import_cookie = require("cookie");
338
+ var CookieHelper = class {
339
+ request;
340
+ cookies = /* @__PURE__ */ new Map();
341
+ constructor(request) {
342
+ this.request = request;
343
+ }
344
+ get(name) {
345
+ if (this.cookies.has(name)) {
346
+ return this.cookies.get(name);
347
+ }
348
+ const header = this.request.headers.get("cookie");
349
+ return (0, import_cookie.parse)(header ?? "")[name];
350
+ }
351
+ set(name, value, options) {
352
+ options ??= {};
353
+ options.httpOnly ??= true;
354
+ options.secure ??= true;
355
+ options.sameSite ??= "lax";
356
+ this.cookies.set(name, (0, import_cookie.serialize)(name, value, options));
357
+ }
358
+ delete(name, options) {
359
+ options ??= {};
360
+ options.expires = /* @__PURE__ */ new Date(0);
361
+ this.cookies.set(name, (0, import_cookie.serialize)(name, "", options));
362
+ }
363
+ };
364
+
365
+ // src/server/HeaderHelper.ts
366
+ var HeaderHelper = class {
367
+ request;
368
+ headers = /* @__PURE__ */ new Map();
369
+ constructor(request) {
370
+ this.request = request;
371
+ }
372
+ get(name) {
373
+ if (this.headers.has(name)) {
374
+ return this.headers.get(name);
375
+ }
376
+ return this.request.headers.get(name) ?? void 0;
377
+ }
378
+ set(name, value) {
379
+ this.headers.set(name, value);
380
+ }
381
+ delete(name) {
382
+ this.headers.delete(name);
383
+ }
384
+ };
385
+
386
+ // src/server/ServerEvent.ts
387
+ var ServerEvent = class {
388
+ request;
389
+ response;
390
+ // TODO: Should we cast types??
391
+ params;
392
+ cookies;
393
+ headers;
394
+ constructor(request, params) {
395
+ this.request = request;
396
+ this.params = params;
397
+ this.cookies = new CookieHelper(request);
398
+ this.headers = new HeaderHelper(request);
399
+ }
400
+ addHeaders() {
401
+ if (!this.response) {
402
+ throw new Error("Response not created yet");
403
+ }
404
+ for (let cookie of this.cookies.cookies.values()) {
405
+ this.response.headers.append("set-cookie", cookie);
406
+ }
407
+ for (let header of this.headers.headers.entries()) {
408
+ this.response.headers.append(header[0], header[1]);
409
+ }
410
+ }
411
+ };
412
+
413
+ // src/server/Server.ts
414
+ var noop = () => {
415
+ };
416
+ var Server = class {
417
+ // TODO: We don't use any of the routes, just add("*") in runDev/runBuild...
418
+ routes = [];
419
+ // TODO: We only use the Vite middleware here
420
+ middleware = [];
421
+ constructor() {
422
+ this.routes = [];
423
+ this.middleware = [];
424
+ }
425
+ /**
426
+ * The standard Fetch API method that should work in any runtime (including
427
+ * Node with polyfills).
428
+ * @returns
429
+ */
430
+ fetch = async (input, init) => {
431
+ const request = new Request(input, init);
432
+ const url = new URL(request.url);
433
+ const match = this.match(url.pathname);
434
+ let ev = new ServerEvent(request, match?.params);
435
+ if (this.middleware.length) {
436
+ let buildNext2 = function(middleware, i) {
437
+ if (ev.response) {
438
+ return noop;
439
+ }
440
+ if (i < middleware.length - 1) {
441
+ let next = middleware[i + 1];
442
+ return async () => next(ev, buildNext2(middleware, i + 1));
443
+ } else {
444
+ return match ? async () => {
445
+ ev.response = await match.fn(ev);
446
+ } : noop;
447
+ }
448
+ };
449
+ var buildNext = buildNext2;
450
+ await this.middleware[0](ev, buildNext2(this.middleware, 0));
451
+ } else if (match) {
452
+ ev.response = await match.fn(ev);
453
+ } else {
454
+ return new Response(null, { status: 404 });
455
+ }
456
+ ev.response ??= new Response(null, { status: 200 });
457
+ ev.addHeaders();
458
+ return ev.response;
116
459
  };
460
+ /**
461
+ * Adds a server function at a route path.
462
+ * @param path The route path pattern.
463
+ * @param fn The function to call when the pattern is matched.
464
+ * @returns
465
+ */
466
+ add(path5, fn) {
467
+ this.routes.push(new RouteHandler(path5, fn));
468
+ return this;
469
+ }
470
+ match(path5) {
471
+ for (let handler of this.routes) {
472
+ let match = path5.match(handler.regex);
473
+ if (match) {
474
+ return {
475
+ fn: handler.fn,
476
+ params: match.groups
477
+ };
478
+ }
479
+ }
480
+ console.log(`Server path not found: ${path5}`);
481
+ }
482
+ // TODO:
483
+ //use(path: string, ...fn: MiddlewareFunction[])
484
+ use(...fn) {
485
+ this.middleware = this.middleware.concat(fn);
486
+ return this;
487
+ }
488
+ };
489
+ var RouteHandler = class {
490
+ path;
491
+ regex;
492
+ fn;
493
+ constructor(path5, fn) {
494
+ this.path = path5;
495
+ this.regex = pathToRegex(path5);
496
+ this.fn = fn;
497
+ }
498
+ };
499
+
500
+ // src/site/prepareTemplate.ts
501
+ function prepareTemplate(template, clientScript) {
502
+ let contentStart = regexIndexOf(template, /\<div\s+id=("app"|'app'|app)\s+/);
503
+ contentStart = template.indexOf(">", contentStart) + 1;
504
+ let contentEnd = template.indexOf("</div>", contentStart);
505
+ if (contentStart === -1 || contentEnd === -1) {
506
+ throw new Error(`Couldn't find <div id="app"></div>`);
507
+ }
508
+ return template.substring(0, contentStart) + "%COMPONENT_HTML%" + template.substring(contentEnd) + `<script type="module" src="${clientScript}"></script>`;
509
+ }
510
+ function regexIndexOf(string, regex, position) {
511
+ var indexOf = string.substring(position || 0).search(regex);
512
+ return indexOf >= 0 ? indexOf + (position || 0) : indexOf;
117
513
  }
118
514
 
119
- // src/bin/index.ts
120
- var options;
121
- var workingDir = process.cwd();
122
- var jsConfigFile = import_path.default.join(workingDir, "torpor.config.js");
123
- var tsConfigFile = import_path.default.join(workingDir, "torpor.config.ts");
124
- var source;
125
- if (import_node_fs.default.existsSync(jsConfigFile)) {
126
- source = import_node_fs.default.readFileSync(jsConfigFile, "utf8");
127
- source = source.replace(
128
- /import\s+\{\s+defineConfig\s+\}\s+from\s+["']@torpor\/build["']/,
129
- "const defineConfig = (x) => x"
130
- ).replace("export default", "");
131
- } else if (import_node_fs.default.existsSync(tsConfigFile)) {
132
- console.log("TS config file is not supported");
515
+ // src/site/runDev.ts
516
+ var import_meta2 = {};
517
+ var __dirname2 = import_node_path3.default.dirname((0, import_node_url2.fileURLToPath)(import_meta2.url));
518
+ async function runDev(site) {
519
+ const server = new Server();
520
+ const vite = await (0, import_vite4.createServer)({
521
+ server: { middlewareMode: true },
522
+ appType: "custom",
523
+ plugins: [
524
+ manifest(site, true),
525
+ // @ts-ignore not sure...
526
+ (0, import_vite3.default)(),
527
+ ...site.plugins
528
+ ]
529
+ });
530
+ const templateFile = import_node_path3.default.resolve(site.root, "src/site.html");
531
+ let template = await import_node_fs3.promises.readFile(templateFile, "utf-8");
532
+ template = await vite.transformIndexHtml("", template);
533
+ const clientScript = import_node_path3.default.resolve(__dirname2, "../../src/site/clientEntry.ts");
534
+ const serverScript = import_node_path3.default.resolve(__dirname2, "../../src/site/serverEntry.ts");
535
+ template = prepareTemplate(template, clientScript);
536
+ server.use(createMiddlewareHandler(vite.middlewares));
537
+ server.add("*", async (ev) => {
538
+ try {
539
+ const { load } = await vite.ssrLoadModule(serverScript);
540
+ return await load(ev, template);
541
+ } catch (e) {
542
+ vite.ssrFixStacktrace(e);
543
+ return serverError(e);
544
+ }
545
+ });
546
+ (0, import_dotenv.configDotenv)();
547
+ process.env.PROTOCOL ??= "http:";
548
+ process.env.HOST ??= "localhost";
549
+ process.env.PORT ??= "7059";
550
+ site.adapter.serve(server, site);
133
551
  }
134
- if (source) {
135
- options = eval(source);
552
+
553
+ // src/bin/index.ts
554
+ run();
555
+ async function run() {
556
+ const workingDir = process.cwd();
557
+ let configFile = "";
558
+ let deleteConfigFile = false;
559
+ const jsConfigFile = import_node_path4.default.join(workingDir, "site.config.js");
560
+ const tsConfigFile = import_node_path4.default.join(workingDir, "site.config.ts");
561
+ if (import_node_fs4.default.existsSync(jsConfigFile)) {
562
+ configFile = jsConfigFile;
563
+ } else if (import_node_fs4.default.existsSync(tsConfigFile)) {
564
+ configFile = import_node_path4.default.join(workingDir, "site.config.temp.js");
565
+ let source = (await (0, import_vite5.transformWithEsbuild)(import_node_fs4.default.readFileSync(tsConfigFile, "utf-8"), tsConfigFile, {
566
+ loader: "ts"
567
+ })).code;
568
+ import_node_fs4.default.writeFileSync(configFile, source);
569
+ deleteConfigFile = true;
570
+ } else {
571
+ throw new Error("site.config file not found");
572
+ }
573
+ const site = (await import(configFile)).default;
574
+ if (!site || !site.root || !site.routes) {
575
+ throw new Error("Invalid site in config file");
576
+ }
577
+ if (deleteConfigFile) {
578
+ import_node_fs4.default.rmSync(configFile);
579
+ }
580
+ if (process.argv.includes("--dev")) {
581
+ await runDev(site);
582
+ } else if (process.argv.includes("--build")) {
583
+ await runBuild(site);
584
+ }
136
585
  }
137
- defineConfig(options);
138
586
  //# sourceMappingURL=index.cjs.map