owebjs 1.5.4-dev → 1.5.7-dev

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.
@@ -2,7 +2,7 @@ import {
2
2
  __name
3
3
  } from "../chunk-SHUYVCID.js";
4
4
  import path from "node:path";
5
- import { fileURLToPath } from "node:url";
5
+ import { pathToFileURL } from "node:url";
6
6
  import { buildRoutePath, buildRouteURL } from './utils.js';
7
7
  import { walk } from './walk.js';
8
8
  import { error, success, warn } from './logger.js';
@@ -13,27 +13,51 @@ import { WebSocketRoute } from '../structures/WebSocketRoute.js';
13
13
  import { FastifyWebSocketAdapter } from '../structures/FastifyWebSocketAdapter.js';
14
14
  import { formatSSE } from './utils.js';
15
15
  const websocketRoutes = {};
16
- const registeredWebSockets = /* @__PURE__ */ new Set();
17
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
18
- let matcherOverrides = {};
19
- let routeFunctions = {
16
+ const WS_REGISTRY_KEY = "ws:registered-routes";
17
+ const createMethodMap = /* @__PURE__ */ __name(() => ({
20
18
  get: {},
21
19
  post: {},
22
20
  put: {},
23
21
  delete: {},
24
22
  patch: {},
25
23
  options: {}
26
- };
27
- const temporaryRequests = {
28
- get: {},
29
- post: {},
30
- put: {},
31
- delete: {},
32
- patch: {},
33
- options: {}
34
- };
24
+ }), "createMethodMap");
25
+ let matcherOverrides = {};
26
+ let routeFunctions = createMethodMap();
27
+ let temporaryRequests = createMethodMap();
35
28
  let routesCache = [];
36
- const compiledRoutes = {};
29
+ let compiledRoutes = {};
30
+ function normalizeFsPath(filePath) {
31
+ return path.resolve(filePath).replaceAll("\\", "/").toLowerCase();
32
+ }
33
+ __name(normalizeFsPath, "normalizeFsPath");
34
+ async function importFreshModule(filePath, source) {
35
+ const resolvedHref = pathToFileURL(path.resolve(filePath)).href;
36
+ const cacheBuster = `?t=${Date.now()}-${Math.random().toString(36).slice(2)}`;
37
+ if (source?.length && !/['"]\.\.?\//.test(source)) {
38
+ const stampedSource = `${source}
39
+ //# sourceURL=${resolvedHref}${cacheBuster}`;
40
+ const dataUrl = `data:text/javascript;base64,${Buffer.from(stampedSource, "utf-8").toString("base64")}`;
41
+ try {
42
+ return await import(dataUrl);
43
+ } catch {
44
+ }
45
+ }
46
+ return import(resolvedHref + cacheBuster);
47
+ }
48
+ __name(importFreshModule, "importFreshModule");
49
+ function resetRuntimeCaches(oweb) {
50
+ matcherOverrides = {};
51
+ routeFunctions = createMethodMap();
52
+ temporaryRequests = createMethodMap();
53
+ routesCache = [];
54
+ compiledRoutes = {};
55
+ for (const key of Object.keys(websocketRoutes)) {
56
+ delete websocketRoutes[key];
57
+ }
58
+ oweb._internalKV.delete(WS_REGISTRY_KEY);
59
+ }
60
+ __name(resetRuntimeCaches, "resetRuntimeCaches");
37
61
  function removeExtension(filePath) {
38
62
  const lastDotIndex = filePath.lastIndexOf(".");
39
63
  if (lastDotIndex !== -1) {
@@ -91,8 +115,7 @@ const applyMatcherHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fall
91
115
  success(`Matcher ${filePath} compiled and reloaded in ${end}ms`, "HMR");
92
116
  } else {
93
117
  const start = Date.now();
94
- const newFilePath = filePath.replaceAll("\\", "/");
95
- const packageURL = new URL(path.resolve(newFilePath), `file://${__dirname}`).pathname.replaceAll("\\", "/");
118
+ const packageURL = pathToFileURL(path.resolve(filePath)).href;
96
119
  const cacheBuster = `?t=${Date.now()}`;
97
120
  def = (await import(packageURL + cacheBuster)).default;
98
121
  const end = Date.now() - start;
@@ -103,6 +126,7 @@ const applyMatcherHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fall
103
126
  }
104
127
  }, "applyMatcherHMR");
105
128
  const applyRouteHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fallbackDir, path2, content) => {
129
+ const normalizedChangedPath = normalizeFsPath(path2);
106
130
  if (path2.endsWith("hooks.js") || path2.endsWith("hooks.ts")) {
107
131
  warn(`Hot Module Replacement is not supported for hooks. Restart the server for changes to take effect.`, "HMR");
108
132
  return;
@@ -118,14 +142,30 @@ const applyRouteHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fallba
118
142
  const files = await walk(workingDir, [], fallbackDir);
119
143
  const routes = await generateRoutes(files, path2);
120
144
  routesCache = routes;
121
- const f = routes.find((x) => x.fileInfo.filePath == path2);
122
- if (f?.fn?.prototype instanceof WebSocketRoute) {
145
+ const f = routes.find((x) => normalizeFsPath(x.fileInfo.filePath) === normalizedChangedPath);
146
+ if (!f) {
147
+ warn(`HMR could not resolve route metadata for file ${path2}`, "HMR");
148
+ return;
149
+ }
150
+ if (!path2.endsWith(".ts") && content.length) {
151
+ const fresh = await importFreshModule(path2, content);
152
+ if (fresh?.default) {
153
+ f.fn = fresh.default;
154
+ }
155
+ }
156
+ if (f.fn?.prototype instanceof WebSocketRoute) {
123
157
  assignSpecificRoute(oweb, f);
124
158
  const end2 = Date.now() - start;
125
159
  success(`WebSocket Route ${f.url} created in ${end2}ms`, "HMR");
126
160
  return;
127
161
  }
128
- temporaryRequests[f.method.toLowerCase()][f.url] = inner(oweb, f);
162
+ const method = f.method.toLowerCase();
163
+ const nextHandler = inner(oweb, f);
164
+ if (routeFunctions[method][f.url]) {
165
+ routeFunctions[method][f.url] = nextHandler;
166
+ } else {
167
+ temporaryRequests[method][f.url] = nextHandler;
168
+ }
129
169
  const end = Date.now() - start;
130
170
  success(`Route ${f.method.toUpperCase()}:${f.url} created in ${end}ms`, "HMR");
131
171
  } else if (op === "modify-file") {
@@ -133,17 +173,31 @@ const applyRouteHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fallba
133
173
  const files = await walk(workingDir, [], fallbackDir);
134
174
  const routes = await generateRoutes(files, path2);
135
175
  routesCache = routes;
136
- const f = routes.find((x) => x.fileInfo.filePath == path2);
137
- if (f?.fn?.prototype instanceof WebSocketRoute) {
176
+ const f = routes.find((x) => normalizeFsPath(x.fileInfo.filePath) === normalizedChangedPath);
177
+ if (!f) {
178
+ warn(`HMR could not resolve route metadata for file ${path2}`, "HMR");
179
+ return;
180
+ }
181
+ if (!path2.endsWith(".ts") && content.length) {
182
+ const fresh = await importFreshModule(path2, content);
183
+ if (fresh?.default) {
184
+ f.fn = fresh.default;
185
+ }
186
+ }
187
+ if (f.fn?.prototype instanceof WebSocketRoute) {
138
188
  websocketRoutes[f.url] = new f.fn();
139
189
  const end2 = Date.now() - start;
140
190
  success(`WebSocket Route ${f.url} reloaded in ${end2}ms`, "HMR");
141
191
  return;
142
192
  }
143
- if (f.url in temporaryRequests[f.method.toLowerCase()]) {
144
- temporaryRequests[f.method.toLowerCase()][f.url] = inner(oweb, f);
193
+ const method = f.method.toLowerCase();
194
+ const nextHandler = inner(oweb, f);
195
+ if (routeFunctions[method][f.url]) {
196
+ routeFunctions[method][f.url] = nextHandler;
197
+ } else if (f.url in temporaryRequests[method]) {
198
+ temporaryRequests[method][f.url] = nextHandler;
145
199
  } else {
146
- routeFunctions[f.method.toLowerCase()][f.url] = inner(oweb, f);
200
+ routeFunctions[method][f.url] = nextHandler;
147
201
  }
148
202
  const end = Date.now() - start;
149
203
  success(`Route ${f.method.toUpperCase()}:${f.url} reloaded in ${end}ms`, "HMR");
@@ -176,8 +230,7 @@ const generateRoutes = /* @__PURE__ */ __name(async (files, onlyGenerateFn) => {
176
230
  const routes = [];
177
231
  for (const file of files) {
178
232
  const parsedFile = path.parse(file.rel);
179
- const filePath = file.filePath.replaceAll("\\", "/");
180
- const packageURL = new URL(path.resolve(filePath), `file://${__dirname}`).pathname.replaceAll("\\", "/");
233
+ const packageURL = pathToFileURL(path.resolve(file.filePath)).href;
181
234
  const routePath = buildRoutePath(parsedFile);
182
235
  const route = buildRouteURL(routePath);
183
236
  if (compiledRoutes[file.filePath]) {
@@ -191,7 +244,7 @@ const generateRoutes = /* @__PURE__ */ __name(async (files, onlyGenerateFn) => {
191
244
  continue;
192
245
  }
193
246
  let routeFuncs;
194
- if (!(onlyGenerateFn && file.filePath !== onlyGenerateFn)) {
247
+ if (!(onlyGenerateFn && normalizeFsPath(file.filePath) !== normalizeFsPath(onlyGenerateFn))) {
195
248
  const cacheBuster = `?t=${Date.now()}`;
196
249
  const def = await import(packageURL + cacheBuster);
197
250
  routeFuncs = def.default;
@@ -212,134 +265,186 @@ function inner(oweb, route) {
212
265
  }
213
266
  const routeFunc = new route.fn();
214
267
  const matchers = route.matchers;
268
+ const hooks = route.fileInfo.hooks;
269
+ const hasHooks = hooks.length > 0;
270
+ const hasMatchers = matchers.length > 0;
215
271
  const isParametric = route.url.includes(":") || route.url.includes("*");
216
- return function(req, res) {
217
- if (oweb._internalKV.get("hmr") && isParametric) {
218
- const currentPath = req.raw.url.split("?")[0];
219
- const method = req.method.toLowerCase();
220
- const specificHandler = temporaryRequests[method]?.[currentPath];
221
- if (specificHandler && specificHandler !== temporaryRequests[route.method][route.url]) {
222
- return specificHandler(req, res);
272
+ const handleIsAsync = routeFunc.handle.constructor.name === "AsyncFunction";
273
+ const hasRouteErrorHandler = typeof routeFunc?.handleError === "function";
274
+ const hmrEnabled = !!oweb._internalKV.get("hmr");
275
+ const checkMatchers = /* @__PURE__ */ __name((req) => {
276
+ if (!hasMatchers) return true;
277
+ for (const matcher of matchers) {
278
+ const param = req.params[matcher.paramName];
279
+ const fun = matcherOverrides[matcher.matcherName];
280
+ if (fun) {
281
+ return fun(param);
223
282
  }
224
283
  }
225
- const checkMatchers = /* @__PURE__ */ __name(() => {
226
- for (const matcher of matchers) {
227
- const param = req.params[matcher.paramName];
228
- const fun = matcherOverrides[matcher.matcherName];
229
- if (fun) {
230
- return fun(param);
231
- }
284
+ return true;
285
+ }, "checkMatchers");
286
+ const handleError = /* @__PURE__ */ __name((req, res, err) => {
287
+ const normalizedError = err instanceof Error ? err : new Error(String(err));
288
+ if (hasRouteErrorHandler) {
289
+ routeFunc.handleError(req, res, normalizedError);
290
+ } else {
291
+ oweb._options.OWEB_INTERNAL_ERROR_HANDLER(req, res, normalizedError);
292
+ }
293
+ }, "handleError");
294
+ const streamResult = /* @__PURE__ */ __name(async (req, res, result, isAsyncIterable) => {
295
+ const iterator = isAsyncIterable ? result[Symbol.asyncIterator]() : result[Symbol.iterator]();
296
+ let firstChunk;
297
+ try {
298
+ firstChunk = await iterator.next();
299
+ } catch (err) {
300
+ handleError(req, res, err);
301
+ return;
302
+ }
303
+ if (res.sent) return;
304
+ if (firstChunk.done) {
305
+ if (firstChunk.value !== void 0) res.send(firstChunk.value);
306
+ return;
307
+ }
308
+ const rawObj = res.raw;
309
+ const uwsRes = rawObj.res && typeof rawObj.res.cork === "function" ? rawObj.res : null;
310
+ const corkedOp = /* @__PURE__ */ __name((op) => {
311
+ if (uwsRes) uwsRes.cork(op);
312
+ else op();
313
+ }, "corkedOp");
314
+ corkedOp(() => {
315
+ const headers = {
316
+ ...res.getHeaders(),
317
+ "Content-Type": "text/event-stream",
318
+ "Cache-Control": "no-cache",
319
+ Connection: "keep-alive"
320
+ };
321
+ res.raw.writeHead(200, headers);
322
+ if (res.raw.flushHeaders) res.raw.flushHeaders();
323
+ });
324
+ let aborted = false;
325
+ const onAborted = /* @__PURE__ */ __name(() => {
326
+ aborted = true;
327
+ }, "onAborted");
328
+ if (res.raw.on) {
329
+ res.raw.on("close", onAborted);
330
+ res.raw.on("aborted", onAborted);
331
+ } else if (rawObj["onAborted"]) {
332
+ rawObj["onAborted"](onAborted);
333
+ }
334
+ try {
335
+ corkedOp(() => {
336
+ res.raw.write(formatSSE(firstChunk.value));
337
+ });
338
+ while (true) {
339
+ if (aborted || res.raw.destroyed) break;
340
+ const chunk = await iterator.next();
341
+ if (chunk.done) break;
342
+ corkedOp(() => {
343
+ res.raw.write(formatSSE(chunk.value));
344
+ });
232
345
  }
233
- return true;
234
- }, "checkMatchers");
235
- const handle = /* @__PURE__ */ __name(async () => {
236
- let result;
237
- try {
238
- if (routeFunc.handle.constructor.name === "AsyncFunction") {
239
- result = await routeFunc.handle(req, res);
240
- } else {
241
- result = routeFunc.handle(req, res);
242
- if (result instanceof Promise) {
243
- result = await result;
244
- }
245
- }
246
- } catch (error2) {
247
- if (routeFunc?.handleError) {
248
- routeFunc.handleError(req, res, error2);
249
- } else {
250
- oweb._options.OWEB_INTERNAL_ERROR_HANDLER(req, res, error2);
251
- }
252
- return;
346
+ } catch (err) {
347
+ error("Error while streaming response for " + route.method.toUpperCase() + ":" + route.url + " - " + err.message, "SSE");
348
+ } finally {
349
+ if (res.raw.off) {
350
+ res.raw.off("close", onAborted);
351
+ res.raw.off("aborted", onAborted);
253
352
  }
254
- const isIterable = result && typeof result[Symbol.iterator] === "function";
255
- const isAsyncIterable = result && typeof result[Symbol.asyncIterator] === "function";
256
- if ((isIterable || isAsyncIterable) && !res.sent) {
257
- const rawObj = res.raw;
258
- const uwsRes = rawObj.res && typeof rawObj.res.cork === "function" ? rawObj.res : null;
259
- const corkedOp = /* @__PURE__ */ __name((op) => {
260
- if (uwsRes) {
261
- uwsRes.cork(op);
262
- } else {
263
- op();
264
- }
265
- }, "corkedOp");
353
+ if (!aborted && !res.raw.destroyed) {
266
354
  corkedOp(() => {
267
- res.raw.writeHead(200, {
268
- ...res.getHeaders(),
269
- "Content-Type": "text/event-stream",
270
- "Cache-Control": "no-cache",
271
- Connection: "keep-alive"
272
- });
273
- if (res.raw.flushHeaders) {
274
- res.raw.flushHeaders();
275
- }
355
+ res.raw.end();
276
356
  });
277
- let aborted = false;
278
- const onAborted = /* @__PURE__ */ __name(() => {
279
- aborted = true;
280
- }, "onAborted");
281
- if (res.raw.on) {
282
- res.raw.on("close", onAborted);
283
- res.raw.on("aborted", onAborted);
284
- } else if (rawObj["onAborted"]) {
285
- rawObj["onAborted"](onAborted);
286
- }
287
- try {
288
- if (isAsyncIterable) {
289
- for await (const chunk of result) {
290
- if (aborted || res.raw.destroyed) break;
291
- corkedOp(() => {
292
- res.raw.write(formatSSE(chunk));
293
- });
294
- }
295
- } else {
296
- for (const chunk of result) {
297
- if (aborted || res.raw.destroyed) break;
298
- corkedOp(() => {
299
- res.raw.write(formatSSE(chunk));
300
- });
301
- }
302
- }
303
- } catch (err) {
304
- error(`Error while streaming response for ${route.method.toUpperCase()}:${route.url} - ${err.message}`, "SSE");
305
- } finally {
306
- if (res.raw.off) {
307
- res.raw.off("close", onAborted);
308
- res.raw.off("aborted", onAborted);
309
- }
310
- if (!aborted && !res.raw.destroyed) {
311
- corkedOp(() => {
312
- res.raw.end();
313
- });
314
- }
315
- }
357
+ }
358
+ }
359
+ }, "streamResult");
360
+ const finalizeResult = /* @__PURE__ */ __name((req, res, result) => {
361
+ if (res.sent) return;
362
+ const isIterable = result && typeof result[Symbol.iterator] === "function";
363
+ const isAsyncIterable = result && typeof result[Symbol.asyncIterator] === "function";
364
+ if (isIterable || isAsyncIterable) {
365
+ streamResult(req, res, result, isAsyncIterable);
366
+ return;
367
+ }
368
+ if (!res.sent && result !== void 0) {
369
+ res.send(result);
370
+ }
371
+ }, "finalizeResult");
372
+ const executeRoute = handleIsAsync ? async (req, res) => {
373
+ try {
374
+ const result = await routeFunc.handle(req, res);
375
+ finalizeResult(req, res, result);
376
+ } catch (error2) {
377
+ handleError(req, res, error2);
378
+ }
379
+ } : (req, res) => {
380
+ let result;
381
+ try {
382
+ result = routeFunc.handle(req, res);
383
+ } catch (error2) {
384
+ handleError(req, res, error2);
385
+ return;
386
+ }
387
+ if (result instanceof Promise) {
388
+ result.then((resolved) => {
389
+ finalizeResult(req, res, resolved);
390
+ }).catch((error2) => {
391
+ handleError(req, res, error2);
392
+ });
393
+ return;
394
+ }
395
+ finalizeResult(req, res, result);
396
+ };
397
+ const isSimpleRoute = !hmrEnabled && !hasHooks && !hasMatchers && !isParametric;
398
+ if (isSimpleRoute) {
399
+ return function(req, res) {
400
+ executeRoute(req, res);
401
+ };
402
+ }
403
+ const runHooks = /* @__PURE__ */ __name((req, res) => {
404
+ let hookIndex = 0;
405
+ const runNextHook = /* @__PURE__ */ __name((hookErr) => {
406
+ if (hookErr) {
407
+ handleError(req, res, hookErr);
316
408
  return;
317
409
  }
318
- if (!res.sent && result !== void 0) {
319
- res.send(result);
410
+ if (res.sent) return;
411
+ if (hookIndex >= hooks.length) {
412
+ executeRoute(req, res);
413
+ return;
320
414
  }
321
- }, "handle");
322
- if (route.fileInfo.hooks.length) {
323
- for (let index = 0; index < route.fileInfo.hooks.length; index++) {
324
- const hookFun = route.fileInfo.hooks[index];
325
- const hookInstance = typeof hookFun === "function" ? new hookFun() : hookFun;
326
- hookInstance.handle(req, res, () => {
327
- if (index + 1 == route.fileInfo.hooks.length) {
328
- if (!checkMatchers()) {
329
- send404(req, res);
330
- } else {
331
- handle();
332
- }
333
- }
334
- });
415
+ const hookFun = hooks[hookIndex++];
416
+ const hookInstance = typeof hookFun === "function" ? new hookFun() : hookFun;
417
+ let doneCalled = false;
418
+ const done = /* @__PURE__ */ __name((doneErr) => {
419
+ if (doneCalled) return;
420
+ doneCalled = true;
421
+ runNextHook(doneErr);
422
+ }, "done");
423
+ try {
424
+ hookInstance.handle(req, res, done);
425
+ } catch (err) {
426
+ done(err);
335
427
  }
336
- } else {
337
- if (!checkMatchers()) {
338
- send404(req, res);
339
- } else {
340
- handle();
428
+ }, "runNextHook");
429
+ runNextHook();
430
+ }, "runHooks");
431
+ return function(req, res) {
432
+ if (hmrEnabled && isParametric) {
433
+ const currentPath = req.raw.url.split("?")[0];
434
+ const method = req.method.toLowerCase();
435
+ const specificHandler = temporaryRequests[method]?.[currentPath];
436
+ if (specificHandler) {
437
+ return specificHandler(req, res);
341
438
  }
342
439
  }
440
+ if (!checkMatchers(req)) {
441
+ return send404(req, res);
442
+ }
443
+ if (!hasHooks) {
444
+ executeRoute(req, res);
445
+ return;
446
+ }
447
+ runHooks(req, res);
343
448
  };
344
449
  }
345
450
  __name(inner, "inner");
@@ -351,11 +456,21 @@ function send404(req, res) {
351
456
  });
352
457
  }
353
458
  __name(send404, "send404");
459
+ function getRegisteredWebSocketsForApp(oweb) {
460
+ let wsRegistry = oweb._internalKV.get(WS_REGISTRY_KEY);
461
+ if (!wsRegistry) {
462
+ wsRegistry = /* @__PURE__ */ new Set();
463
+ oweb._internalKV.set(WS_REGISTRY_KEY, wsRegistry);
464
+ }
465
+ return wsRegistry;
466
+ }
467
+ __name(getRegisteredWebSocketsForApp, "getRegisteredWebSocketsForApp");
354
468
  function assignSpecificRoute(oweb, route) {
355
469
  if (!route?.fn) return;
356
470
  if (route?.fn?.prototype instanceof WebSocketRoute) {
357
471
  const wsInstance = new route.fn();
358
472
  websocketRoutes[route.url] = wsInstance;
473
+ const registeredWebSockets = getRegisteredWebSocketsForApp(oweb);
359
474
  if (!registeredWebSockets.has(route.url)) {
360
475
  registeredWebSockets.add(route.url);
361
476
  if (oweb._options.uWebSocketsEnabled && oweb.uServer) {
@@ -454,27 +569,34 @@ function assignSpecificRoute(oweb, route) {
454
569
  return;
455
570
  }
456
571
  const routeFunc = new route.fn();
457
- routeFunctions[route.method][route.url] = inner(oweb, route);
458
- oweb[route.method](route.url, routeFunc._options || {}, function(req, res) {
459
- if (routeFunctions[route.method][route.url]) {
460
- return routeFunctions[route.method][route.url](req, res);
461
- } else {
462
- const vals = temporaryRequests[route.method];
463
- const keys = Object.keys(vals);
464
- if (!vals || !keys.length) {
465
- return send404(req, res);
466
- }
467
- const f = keys.find((tempName) => {
468
- const matcher = match(tempName);
469
- return matcher(req.url);
470
- });
471
- if (f && vals[f]) {
472
- return vals[f](req, res);
572
+ const routeHandler = inner(oweb, route);
573
+ if (!routeHandler) return;
574
+ const hmrEnabled = !!oweb._internalKV.get("hmr");
575
+ if (hmrEnabled) {
576
+ routeFunctions[route.method][route.url] = routeHandler;
577
+ oweb[route.method](route.url, routeFunc._options || {}, function(req, res) {
578
+ if (routeFunctions[route.method][route.url]) {
579
+ return routeFunctions[route.method][route.url](req, res);
473
580
  } else {
474
- return send404(req, res);
581
+ const vals = temporaryRequests[route.method];
582
+ const keys = Object.keys(vals);
583
+ if (!vals || !keys.length) {
584
+ return send404(req, res);
585
+ }
586
+ const f = keys.find((tempName) => {
587
+ const matcher = match(tempName);
588
+ return matcher(req.url);
589
+ });
590
+ if (f && vals[f]) {
591
+ return vals[f](req, res);
592
+ } else {
593
+ return send404(req, res);
594
+ }
475
595
  }
476
- }
477
- });
596
+ });
597
+ return;
598
+ }
599
+ oweb[route.method](route.url, routeFunc._options || {}, routeHandler);
478
600
  }
479
601
  __name(assignSpecificRoute, "assignSpecificRoute");
480
602
  async function loadMatchers(directoryPath) {
@@ -483,17 +605,18 @@ async function loadMatchers(directoryPath) {
483
605
  ".ts"
484
606
  ].includes(path.extname(f)));
485
607
  for (const file of files) {
486
- const filePath = path.join(directoryPath, file).replaceAll("\\", "/");
608
+ const filePath = path.join(directoryPath, file);
487
609
  const fileName = path.basename(filePath);
488
- const packageURL = new URL(path.resolve(filePath), `file://${__dirname}`).pathname.replaceAll("\\", "/");
610
+ const packageURL = pathToFileURL(path.resolve(filePath)).href;
489
611
  const def = await import(packageURL);
490
612
  matcherOverrides[removeExtension(fileName)] = def.default;
491
613
  }
492
614
  }
493
615
  __name(loadMatchers, "loadMatchers");
494
616
  const assignRoutes = /* @__PURE__ */ __name(async (oweb, directory, matchersDirectory) => {
617
+ resetRuntimeCaches(oweb);
495
618
  if (matchersDirectory) {
496
- loadMatchers(matchersDirectory);
619
+ await loadMatchers(matchersDirectory);
497
620
  }
498
621
  const files = await walk(directory);
499
622
  const routes = await generateRoutes(files);
@@ -515,14 +638,16 @@ const assignRoutes = /* @__PURE__ */ __name(async (oweb, directory, matchersDire
515
638
  }
516
639
  }
517
640
  __name(fallbackHandle, "fallbackHandle");
518
- for (const element of [
519
- "get",
520
- "post",
521
- "put",
522
- "patch",
523
- "delete"
524
- ]) {
525
- oweb[element]("*", fallbackHandle);
641
+ if (oweb._internalKV.get("hmr")) {
642
+ for (const element of [
643
+ "get",
644
+ "post",
645
+ "put",
646
+ "patch",
647
+ "delete"
648
+ ]) {
649
+ oweb[element]("*", fallbackHandle);
650
+ }
526
651
  }
527
652
  for (const route of routes) {
528
653
  assignSpecificRoute(oweb, route);
@@ -2,11 +2,10 @@ import {
2
2
  __name
3
3
  } from "../chunk-SHUYVCID.js";
4
4
  import { readdirSync, statSync } from "node:fs";
5
- import { fileURLToPath, pathToFileURL } from "node:url";
5
+ import { pathToFileURL } from "node:url";
6
6
  import path from "node:path";
7
7
  import { mergePaths } from './utils.js';
8
8
  import { warn } from './logger.js';
9
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
10
9
  const isParentOrGrandparent = /* @__PURE__ */ __name((parentFolderPath, childFolderPath) => {
11
10
  if (childFolderPath.startsWith(parentFolderPath)) {
12
11
  const relativePath = path.relative(parentFolderPath, childFolderPath);
@@ -15,8 +14,7 @@ const isParentOrGrandparent = /* @__PURE__ */ __name((parentFolderPath, childFol
15
14
  }
16
15
  return false;
17
16
  }, "isParentOrGrandparent");
18
- const hookPaths = /* @__PURE__ */ new Set();
19
- const walk = /* @__PURE__ */ __name(async (directory, tree = [], fallbackDir) => {
17
+ const walk = /* @__PURE__ */ __name(async (directory, tree = [], fallbackDir, hookPaths = /* @__PURE__ */ new Set()) => {
20
18
  const results = [];
21
19
  const readDirPriority = readdirSync(directory);
22
20
  readDirPriority.sort((a, b) => {
@@ -40,7 +38,7 @@ const walk = /* @__PURE__ */ __name(async (directory, tree = [], fallbackDir) =>
40
38
  results.push(...await walk(filePath, [
41
39
  ...tree,
42
40
  fileName
43
- ], fallbackDir));
41
+ ], fallbackDir, hookPaths));
44
42
  } else {
45
43
  if (![
46
44
  ".js",
@@ -76,7 +74,8 @@ const walk = /* @__PURE__ */ __name(async (directory, tree = [], fallbackDir) =>
76
74
  rootWalkDir = path.dirname(rootWalkDir);
77
75
  }
78
76
  const relHook = path.relative(rootWalkDir, hookPath);
79
- const targetDir = path.join(process.cwd(), fallbackDir, relHook);
77
+ const fallbackRoot = path.isAbsolute(fallbackDir) ? fallbackDir : path.join(process.cwd(), fallbackDir);
78
+ const targetDir = path.join(fallbackRoot, relHook);
80
79
  targetFile = path.join(targetDir, "_hooks.js");
81
80
  } else {
82
81
  targetFile = path.join(hookPath, "_hooks.js");