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.
|
|
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
|
|
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.
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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.
|
|
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.
|
|
211
|
-
return routeFunctions[route.
|
|
225
|
+
if (routeFunctions[route.method][route.url]) {
|
|
226
|
+
return routeFunctions[route.method][route.url](req, res);
|
|
212
227
|
} else {
|
|
213
|
-
const vals = temporaryRequests[
|
|
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
|
-
|
|
17
|
-
|
|
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 (
|
|
32
|
-
|
|
36
|
+
} catch (e) {
|
|
37
|
+
error(`Error reading or parsing tsconfig.json: ${e.message}`, "HMR");
|
|
33
38
|
return null;
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
|
-
__name(
|
|
37
|
-
function
|
|
38
|
-
|
|
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
|
|
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(
|
|
59
|
+
__name(resolveAliasToSourcePath, "resolveAliasToSourcePath");
|
|
55
60
|
async function generateFunctionFromTypescript(tsCode, filePath) {
|
|
56
|
-
const
|
|
57
|
-
const tsConfig = await
|
|
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
|
|
76
|
+
const originalFileDir = path.dirname(filePath);
|
|
69
77
|
traverse.default(ast, {
|
|
70
78
|
ImportDeclaration(astPath) {
|
|
71
|
-
const
|
|
72
|
-
const importPath =
|
|
73
|
-
let
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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 (
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
99
|
-
|
|
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(
|
|
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");
|