owebjs 1.3.7 → 1.3.9

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.
@@ -12,7 +12,14 @@ import generateFunctionFromTypescript from './generateFunctionFromTypescript.js'
12
12
  import { readdirSync } from "node:fs";
13
13
  const __dirname = dirname(fileURLToPath(import.meta.url));
14
14
  let matcherOverrides = {};
15
- let routeFunctions = {};
15
+ let routeFunctions = {
16
+ get: {},
17
+ post: {},
18
+ put: {},
19
+ delete: {},
20
+ patch: {},
21
+ options: {}
22
+ };
16
23
  const temporaryRequests = {
17
24
  get: {},
18
25
  post: {},
@@ -71,7 +78,7 @@ const applyRouteHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fallba
71
78
  if (op === "new-file") {
72
79
  const start = Date.now();
73
80
  const files = await walk(workingDir, [], fallbackDir);
74
- const routes = await generateRoutes(files);
81
+ const routes = await generateRoutes(files, path2);
75
82
  routesCache = routes;
76
83
  const f = routes.find((x) => x.fileInfo.filePath == path2);
77
84
  temporaryRequests[f.method.toLowerCase()][f.url] = inner(oweb, f);
@@ -80,29 +87,34 @@ const applyRouteHMR = /* @__PURE__ */ __name(async (oweb, op, workingDir, fallba
80
87
  } else if (op === "modify-file") {
81
88
  const start = Date.now();
82
89
  const files = await walk(workingDir, [], fallbackDir);
83
- const routes = await generateRoutes(files);
90
+ const routes = await generateRoutes(files, path2);
84
91
  routesCache = routes;
85
92
  const f = routes.find((x) => x.fileInfo.filePath == path2);
86
93
  if (f.url in temporaryRequests[f.method.toLowerCase()]) {
87
94
  temporaryRequests[f.method.toLowerCase()][f.url] = inner(oweb, f);
88
95
  } else {
89
- routeFunctions[f.fileInfo.filePath] = inner(oweb, f);
96
+ routeFunctions[f.method.toLowerCase()][f.url] = inner(oweb, f);
90
97
  }
91
98
  const end = Date.now() - start;
92
99
  success(`Route ${f.method.toUpperCase()}:${f.url} reloaded in ${end}ms`, "HMR");
93
100
  } else if (op === "delete-file") {
94
101
  const start = Date.now();
95
- const f = routesCache.find((x) => x.fileInfo.filePath == path2);
102
+ const newFilePath = path2.slice(workingDir.length).replaceAll("\\", "/").slice(0, -3);
103
+ let builded = buildRouteURL(newFilePath);
104
+ if (builded.url.endsWith("/index")) {
105
+ builded.url = builded.url.slice(0, -"/index".length);
106
+ }
107
+ const f = routesCache.find((x) => x.method == builded.method && x.url == builded.url);
96
108
  if (f.url in temporaryRequests[f.method.toLowerCase()]) {
97
109
  delete temporaryRequests[f.method.toLowerCase()][f.url];
98
110
  } else {
99
- delete routeFunctions[f.fileInfo.filePath];
111
+ delete routeFunctions[f.method.toLowerCase()][f.url];
100
112
  }
101
113
  const end = Date.now() - start;
102
114
  success(`Route ${f.method.toUpperCase()}:${f.url} removed in ${end}ms`, "HMR");
103
115
  }
104
116
  }, "applyRouteHMR");
105
- const generateRoutes = /* @__PURE__ */ __name(async (files) => {
117
+ const generateRoutes = /* @__PURE__ */ __name(async (files, onlyGenerateFn) => {
106
118
  const routes = [];
107
119
  for (const file of files) {
108
120
  const parsedFile = path.parse(file.rel);
@@ -120,9 +132,12 @@ const generateRoutes = /* @__PURE__ */ __name(async (files) => {
120
132
  });
121
133
  continue;
122
134
  }
123
- const cacheBuster = `?t=${Date.now()}`;
124
- const def = await import(packageURL + cacheBuster);
125
- const routeFuncs = def.default;
135
+ let routeFuncs;
136
+ if (!(onlyGenerateFn && file.filePath !== onlyGenerateFn)) {
137
+ const cacheBuster = `?t=${Date.now()}`;
138
+ const def = await import(packageURL + cacheBuster);
139
+ routeFuncs = def.default;
140
+ }
126
141
  routes.push({
127
142
  url: route.url,
128
143
  method: route.method,
@@ -205,12 +220,12 @@ __name(send404, "send404");
205
220
  function assignSpecificRoute(oweb, route) {
206
221
  if (!route.fn) return;
207
222
  const routeFunc = new route.fn();
208
- routeFunctions[route.fileInfo.filePath] = inner(oweb, route);
223
+ routeFunctions[route.method][route.url] = inner(oweb, route);
209
224
  oweb[route.method](route.url, routeFunc._options || {}, function(req, res) {
210
- if (routeFunctions[route.fileInfo.filePath]) {
211
- return routeFunctions[route.fileInfo.filePath](req, res);
225
+ if (routeFunctions[route.method][route.url]) {
226
+ return routeFunctions[route.method][route.url](req, res);
212
227
  } else {
213
- const vals = temporaryRequests[req.method.toLowerCase()];
228
+ const vals = temporaryRequests[route.method];
214
229
  const keys = Object.keys(vals);
215
230
  if (!vals || !keys.length) {
216
231
  return send404(req, res);
@@ -4,44 +4,49 @@ import {
4
4
  import { parse } from "@babel/parser";
5
5
  import traverse from "@babel/traverse";
6
6
  import generate from "@babel/generator";
7
+ import * as babel from "@babel/core";
7
8
  import path from "node:path";
8
- import babel from "@babel/core";
9
9
  import { pathToFileURL } from "node:url";
10
10
  import { writeFile, unlink, readFile } from "node:fs/promises";
11
11
  import { existsSync } from "node:fs";
12
- import { tmpdir } from "node:os";
13
12
  import { randomBytes } from "node:crypto";
14
- import { createRequire } from "node:module";
15
13
  import { error } from './logger.js';
16
- const require2 = createRequire(import.meta.url);
17
- async function getAliasesFromTsConfig(tsConfigPath) {
14
+ async function getTsConfig(projectRoot) {
15
+ const tsConfigPath = path.join(projectRoot, "tsconfig.json");
18
16
  if (!existsSync(tsConfigPath)) {
17
+ error("tsconfig.json not found in the project root.", "HMR");
19
18
  return null;
20
19
  }
21
20
  try {
22
21
  const tsConfigFile = await readFile(tsConfigPath, "utf-8");
23
22
  const json = JSON.parse(tsConfigFile.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, ""));
24
23
  const compilerOptions = json.compilerOptions || {};
24
+ if (!compilerOptions.outDir) {
25
+ error("`compilerOptions.outDir` is not defined in tsconfig.json.", "HMR");
26
+ return null;
27
+ }
25
28
  const baseUrl = path.resolve(path.dirname(tsConfigPath), compilerOptions.baseUrl || ".");
29
+ const outDir = path.resolve(path.dirname(tsConfigPath), compilerOptions.outDir);
26
30
  const paths = compilerOptions.paths || {};
27
31
  return {
28
32
  paths,
29
- baseUrl
33
+ baseUrl,
34
+ outDir
30
35
  };
31
- } catch (error2) {
32
- console.error("Error reading or parsing tsconfig.json:", error2);
36
+ } catch (e) {
37
+ error(`Error reading or parsing tsconfig.json: ${e.message}`, "HMR");
33
38
  return null;
34
39
  }
35
40
  }
36
- __name(getAliasesFromTsConfig, "getAliasesFromTsConfig");
37
- function resolveAlias(importPath, tsConfigPaths, baseUrl) {
38
- for (const alias in tsConfigPaths) {
41
+ __name(getTsConfig, "getTsConfig");
42
+ function resolveAliasToSourcePath(importPath, tsConfig) {
43
+ const { paths, baseUrl } = tsConfig;
44
+ for (const alias in paths) {
39
45
  const aliasPattern = new RegExp(`^${alias.replace("*", "(.*)")}$`);
40
46
  const match = importPath.match(aliasPattern);
41
47
  if (match) {
42
48
  const [_fullMatch, restOfPath] = match;
43
- const targetPaths = tsConfigPaths[alias];
44
- const targetPath = targetPaths[0];
49
+ const targetPath = paths[alias][0];
45
50
  if (!alias.endsWith("*")) {
46
51
  return path.resolve(baseUrl, targetPath);
47
52
  }
@@ -51,10 +56,13 @@ function resolveAlias(importPath, tsConfigPaths, baseUrl) {
51
56
  }
52
57
  return null;
53
58
  }
54
- __name(resolveAlias, "resolveAlias");
59
+ __name(resolveAliasToSourcePath, "resolveAliasToSourcePath");
55
60
  async function generateFunctionFromTypescript(tsCode, filePath) {
56
- const tsConfigPath = path.join(process.cwd(), "tsconfig.json");
57
- const tsConfig = await getAliasesFromTsConfig(tsConfigPath);
61
+ const projectRoot = process.cwd();
62
+ const tsConfig = await getTsConfig(projectRoot);
63
+ if (!tsConfig) {
64
+ throw new Error("Failed to load or validate tsconfig.json configuration.");
65
+ }
58
66
  const result = babel.transformSync(tsCode, {
59
67
  presets: [
60
68
  "@babel/preset-typescript"
@@ -65,44 +73,35 @@ async function generateFunctionFromTypescript(tsCode, filePath) {
65
73
  const ast = parse(jsCode, {
66
74
  sourceType: "module"
67
75
  });
68
- const fileDir = path.dirname(filePath);
76
+ const originalFileDir = path.dirname(filePath);
69
77
  traverse.default(ast, {
70
78
  ImportDeclaration(astPath) {
71
- const importSourceNode = astPath.node.source;
72
- const importPath = importSourceNode.value;
73
- let resolvedUrl = null;
74
- if (tsConfig && tsConfig.paths) {
75
- const resolvedAliasPath = resolveAlias(importPath, tsConfig.paths, tsConfig.baseUrl);
76
- if (resolvedAliasPath) {
77
- const finalPath = path.extname(resolvedAliasPath) === "" ? resolvedAliasPath + ".ts" : resolvedAliasPath;
78
- resolvedUrl = pathToFileURL(finalPath).href;
79
- }
80
- }
81
- if (!resolvedUrl && importPath.startsWith(".")) {
82
- const resolvedPathWithExt = path.extname(importPath) === "" ? importPath + ".ts" : importPath;
83
- const absoluteDepPath = path.resolve(fileDir, resolvedPathWithExt);
84
- resolvedUrl = pathToFileURL(absoluteDepPath).href;
79
+ const importNode = astPath.node.source;
80
+ const importPath = importNode.value;
81
+ let resolvedPathForDist = null;
82
+ const aliasedSourcePath = resolveAliasToSourcePath(importPath, tsConfig);
83
+ if (aliasedSourcePath) {
84
+ resolvedPathForDist = path.relative(tsConfig.baseUrl, aliasedSourcePath);
85
+ } else if (importPath.startsWith(".")) {
86
+ const absoluteSourcePath = path.resolve(originalFileDir, importPath);
87
+ resolvedPathForDist = path.relative(tsConfig.baseUrl, absoluteSourcePath);
85
88
  }
86
- if (!resolvedUrl) {
87
- try {
88
- const resolvedNodeModulePath = require2.resolve(importPath, {
89
- paths: [
90
- fileDir
91
- ]
92
- });
93
- resolvedUrl = pathToFileURL(resolvedNodeModulePath).href;
94
- } catch (_) {
95
- error(`Could not resolve import path for: ${importPath} in ${filePath}.`, "HMR");
89
+ if (resolvedPathForDist) {
90
+ if (resolvedPathForDist.startsWith("src" + path.sep)) {
91
+ resolvedPathForDist = resolvedPathForDist.substring("src".length + 1);
96
92
  }
97
- }
98
- if (resolvedUrl) {
99
- importSourceNode.value = resolvedUrl;
93
+ let jsPath = resolvedPathForDist.replace(/\.(ts|js|mts|cts)$/, ".js");
94
+ if (jsPath.startsWith("dist")) {
95
+ jsPath = jsPath.slice("dist".length + 1);
96
+ }
97
+ const targetDistPath = path.join(tsConfig.outDir, jsPath);
98
+ importNode.value = pathToFileURL(targetDistPath).href;
100
99
  }
101
100
  }
102
101
  });
103
102
  const { code: modifiedCode } = generate.default(ast);
104
103
  const tempFileName = `oweb-temp-${randomBytes(16).toString("hex")}.mjs`;
105
- const tempFilePath = path.join(tmpdir(), tempFileName);
104
+ const tempFilePath = path.join(process.cwd(), tempFileName);
106
105
  let module;
107
106
  try {
108
107
  await writeFile(tempFilePath, modifiedCode, "utf-8");
@@ -112,6 +111,9 @@ async function generateFunctionFromTypescript(tsCode, filePath) {
112
111
  await unlink(tempFilePath).catch(() => {
113
112
  });
114
113
  }
114
+ if (!module || typeof module.default === "undefined") {
115
+ throw new Error(`The file ${filePath} was processed, but it did not have a default export.`);
116
+ }
115
117
  return module.default;
116
118
  }
117
119
  __name(generateFunctionFromTypescript, "generateFunctionFromTypescript");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "owebjs",
3
- "version": "1.3.7",
3
+ "version": "1.3.9",
4
4
  "description": "A flexible and modern web framework built on top of Fastify",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",