@warlock.js/core 4.0.2 → 4.0.4
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/bin/warlock.js +2 -2
- package/package.json +5 -4
- package/bin/warlock-loader.mjs +0 -256
package/bin/warlock.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warlock.js/core",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.4",
|
|
4
4
|
"description": "A robust nodejs framework for building blazing fast applications",
|
|
5
5
|
"main": "./cjs/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"@mongez/fs": "^3.0.5",
|
|
31
31
|
"@mongez/http": "^2.2.10",
|
|
32
32
|
"@mongez/localization": "^3.0.0",
|
|
33
|
-
"@warlock.js/logger": "4.0.
|
|
34
|
-
"@warlock.js/cascade": "4.0.
|
|
33
|
+
"@warlock.js/logger": "4.0.4",
|
|
34
|
+
"@warlock.js/cascade": "4.0.4",
|
|
35
35
|
"@mongez/reinforcements": "^2.3.12",
|
|
36
36
|
"commander": "^12.0.0",
|
|
37
37
|
"@mongez/slug": "^1.0.7",
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
"send": "^0.18.0",
|
|
49
49
|
"prettier": "^3.1.0",
|
|
50
50
|
"sharp": "^0.32.6",
|
|
51
|
-
"@mongez/copper": "^1.0.1"
|
|
51
|
+
"@mongez/copper": "^1.0.1",
|
|
52
|
+
"fast-glob": "^3.3.3"
|
|
52
53
|
},
|
|
53
54
|
"devDependencies": {
|
|
54
55
|
"fast-glob": "^3.3.3",
|
package/bin/warlock-loader.mjs
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
import { fileExistsAsync, isDirectoryAsync } from "@mongez/fs";
|
|
2
|
-
import { transform } from "esbuild";
|
|
3
|
-
import fs from "fs/promises";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import ts from "typescript";
|
|
6
|
-
import { fileURLToPath, pathToFileURL } from "url";
|
|
7
|
-
const configText = await fs.readFile(process.cwd() + "/tsconfig.json", "utf8");
|
|
8
|
-
|
|
9
|
-
const { config: tsconfigRaw } = ts.parseConfigFileTextToJson(
|
|
10
|
-
process.cwd() + "/tsconfig.json",
|
|
11
|
-
configText,
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
let manifest = {
|
|
15
|
-
aliases: {},
|
|
16
|
-
importLookup: {},
|
|
17
|
-
directoryIndexLookup: {},
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const manifestPath = path.resolve(process.cwd(), ".warlock/manifest.json");
|
|
21
|
-
|
|
22
|
-
const supportedExtensions = [".ts", ".tsx"];
|
|
23
|
-
|
|
24
|
-
const cacheFilesDirectory = path.resolve(process.cwd(), ".warlock/.cache");
|
|
25
|
-
const srcDirectory = path.resolve(process.cwd(), "src");
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Normalize Windows paths into forward slashes (for URL consistency)
|
|
29
|
-
*/
|
|
30
|
-
function normalizePath(p) {
|
|
31
|
-
return p.replace(/\\/g, "/");
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Load manifest file for efficient path resolution.
|
|
36
|
-
*/
|
|
37
|
-
async function loadManifest(force = false) {
|
|
38
|
-
if (!force && Object.keys(manifest.importLookup).length) {
|
|
39
|
-
return manifest;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const manifestRaw = JSON.parse(await fs.readFile(manifestPath, "utf8"));
|
|
44
|
-
manifest = {
|
|
45
|
-
aliases: manifestRaw.aliases ?? {},
|
|
46
|
-
importLookup: manifestRaw.importLookup ?? {},
|
|
47
|
-
directoryIndexLookup: manifestRaw.directoryIndexLookup ?? {},
|
|
48
|
-
};
|
|
49
|
-
} catch (err) {
|
|
50
|
-
console.warn(
|
|
51
|
-
"⚠️ Warlock loader: could not load manifest.json — using empty lookups.",
|
|
52
|
-
);
|
|
53
|
-
manifest = {
|
|
54
|
-
aliases: {},
|
|
55
|
-
importLookup: {},
|
|
56
|
-
directoryIndexLookup: {},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return manifest;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Load manifest initially
|
|
64
|
-
await loadManifest(true);
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Resolve hook — maps aliases and missing extensions using manifest.
|
|
68
|
-
*/
|
|
69
|
-
export async function resolve(specifier, context, nextResolve) {
|
|
70
|
-
const { parentURL = import.meta.url } = context;
|
|
71
|
-
|
|
72
|
-
// Skip custom resolution for node_modules - use default Node.js behavior
|
|
73
|
-
if (
|
|
74
|
-
specifier.includes("node_modules") ||
|
|
75
|
-
parentURL.includes("node_modules")
|
|
76
|
-
) {
|
|
77
|
-
return nextResolve(specifier, context, nextResolve);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const loadedManifest = await loadManifest();
|
|
81
|
-
|
|
82
|
-
// 1. Handle tsconfig aliases using manifest
|
|
83
|
-
for (const [alias, aliasInfo] of Object.entries(loadedManifest.aliases)) {
|
|
84
|
-
if (specifier.startsWith(alias)) {
|
|
85
|
-
const relativePart = specifier.slice(alias.length);
|
|
86
|
-
const importPath = normalizePath(path.join(aliasInfo.path, relativePart));
|
|
87
|
-
|
|
88
|
-
// Try direct import lookup first (e.g., "app/main" -> "app/main.ts")
|
|
89
|
-
if (loadedManifest.importLookup[importPath]) {
|
|
90
|
-
const fileInfo = loadedManifest.importLookup[importPath];
|
|
91
|
-
const fullPath = path.resolve(srcDirectory, fileInfo.path);
|
|
92
|
-
return {
|
|
93
|
-
url: pathToFileURL(fullPath).href,
|
|
94
|
-
shortCircuit: true,
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Try directory index lookup (e.g., "app" -> "app/index.ts")
|
|
99
|
-
if (loadedManifest.directoryIndexLookup[importPath]) {
|
|
100
|
-
const fileInfo = loadedManifest.directoryIndexLookup[importPath];
|
|
101
|
-
const fullPath = path.resolve(srcDirectory, fileInfo.path);
|
|
102
|
-
return {
|
|
103
|
-
url: pathToFileURL(fullPath).href,
|
|
104
|
-
shortCircuit: true,
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Fallback to file system checks if not in manifest (for new files)
|
|
109
|
-
const resolvedPath = path.resolve(
|
|
110
|
-
srcDirectory,
|
|
111
|
-
aliasInfo.path,
|
|
112
|
-
relativePart,
|
|
113
|
-
);
|
|
114
|
-
for (const extension of supportedExtensions) {
|
|
115
|
-
if (await fileExistsAsync(resolvedPath + extension)) {
|
|
116
|
-
return {
|
|
117
|
-
url: pathToFileURL(resolvedPath + extension).href,
|
|
118
|
-
shortCircuit: true,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (await fileExistsAsync(path.resolve(resolvedPath, "index.ts"))) {
|
|
124
|
-
return {
|
|
125
|
-
url: pathToFileURL(path.resolve(resolvedPath, "index.ts")).href,
|
|
126
|
-
shortCircuit: true,
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (await fileExistsAsync(path.resolve(resolvedPath, "index.tsx"))) {
|
|
131
|
-
return {
|
|
132
|
-
url: pathToFileURL(path.resolve(resolvedPath, "index.tsx")).href,
|
|
133
|
-
shortCircuit: true,
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
throw new Error(`Failed to resolve file: ${specifier}`);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 2. Handle relative imports using manifest
|
|
142
|
-
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
143
|
-
const parentPath = fileURLToPath(parentURL);
|
|
144
|
-
const filePath = path.resolve(path.dirname(parentPath), specifier);
|
|
145
|
-
const extension = path.extname(filePath);
|
|
146
|
-
|
|
147
|
-
// If already has extension, use it directly
|
|
148
|
-
if (supportedExtensions.includes(extension)) {
|
|
149
|
-
return { url: pathToFileURL(filePath).href, shortCircuit: true };
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Calculate the import path relative to src directory
|
|
153
|
-
const relativeToSrc = normalizePath(path.relative(srcDirectory, filePath));
|
|
154
|
-
|
|
155
|
-
// Try direct import lookup
|
|
156
|
-
if (loadedManifest.importLookup[relativeToSrc]) {
|
|
157
|
-
const fileInfo = loadedManifest.importLookup[relativeToSrc];
|
|
158
|
-
const fullPath = path.resolve(srcDirectory, fileInfo.path);
|
|
159
|
-
return {
|
|
160
|
-
url: pathToFileURL(fullPath).href,
|
|
161
|
-
shortCircuit: true,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// Try directory index lookup
|
|
166
|
-
if (loadedManifest.directoryIndexLookup[relativeToSrc]) {
|
|
167
|
-
const fileInfo = loadedManifest.directoryIndexLookup[relativeToSrc];
|
|
168
|
-
const fullPath = path.resolve(srcDirectory, fileInfo.path);
|
|
169
|
-
return {
|
|
170
|
-
url: pathToFileURL(fullPath).href,
|
|
171
|
-
shortCircuit: true,
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Fallback to file system checks for new files
|
|
176
|
-
for (const ext of supportedExtensions) {
|
|
177
|
-
const fullPath = filePath + ext;
|
|
178
|
-
if (await fileExistsAsync(fullPath)) {
|
|
179
|
-
return { url: pathToFileURL(fullPath).href, shortCircuit: true };
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (await isDirectoryAsync(filePath)) {
|
|
184
|
-
return {
|
|
185
|
-
url: pathToFileURL(path.resolve(filePath, "index.ts")).href,
|
|
186
|
-
shortCircuit: true,
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
throw new Error(`Failed to resolve file: ${filePath}`);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// 3. Fallback to Node default resolver
|
|
194
|
-
return nextResolve(specifier, context, nextResolve);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Load hook — transpiles TS/TSX into ESM on the fly.
|
|
199
|
-
*/
|
|
200
|
-
export async function load(url, context, nextLoad) {
|
|
201
|
-
if (url.includes("node_modules")) {
|
|
202
|
-
return nextLoad(url, context, nextLoad);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (url.endsWith(".ts") || url.endsWith(".tsx")) {
|
|
206
|
-
const filePath = fileURLToPath(url);
|
|
207
|
-
const relativePath = path
|
|
208
|
-
.relative(process.cwd(), filePath)
|
|
209
|
-
.replace(/\\/g, "/");
|
|
210
|
-
|
|
211
|
-
// we will create a cache file name by replacing / to - so we can store it in a single file
|
|
212
|
-
// make sure to trim any . dots at beginning of the path
|
|
213
|
-
const cacheFileName = relativePath.replace(/^\./, "").replace(/\//g, "-");
|
|
214
|
-
|
|
215
|
-
// Fallback to individual file read (for new files not in bundle)
|
|
216
|
-
try {
|
|
217
|
-
const cachedFile = await fs.readFile(
|
|
218
|
-
cacheFilesDirectory + "/" + cacheFileName,
|
|
219
|
-
"utf8",
|
|
220
|
-
);
|
|
221
|
-
|
|
222
|
-
return {
|
|
223
|
-
format: "module",
|
|
224
|
-
source: cachedFile,
|
|
225
|
-
shortCircuit: true,
|
|
226
|
-
};
|
|
227
|
-
} catch (error) {
|
|
228
|
-
// File not in cache at all, transpile it
|
|
229
|
-
const source = await fs.readFile(filePath, "utf8");
|
|
230
|
-
|
|
231
|
-
const { code } = await transform(source, {
|
|
232
|
-
loader: url.endsWith(".tsx") ? "tsx" : "ts",
|
|
233
|
-
format: "esm",
|
|
234
|
-
sourcemap: "inline",
|
|
235
|
-
sourcefile: filePath,
|
|
236
|
-
tsconfigRaw,
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
// if code length is zero, it means this was just an empty file or a types only file
|
|
240
|
-
let finalCode = code;
|
|
241
|
-
if (code.length === 0) {
|
|
242
|
-
finalCode = "/*_EMPTY_FILE_*/";
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
fs.writeFile(path.resolve(cacheFilesDirectory, cacheFileName), finalCode);
|
|
246
|
-
|
|
247
|
-
return {
|
|
248
|
-
format: "module",
|
|
249
|
-
source: code,
|
|
250
|
-
shortCircuit: true,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
return nextLoad(url, context, nextLoad);
|
|
256
|
-
}
|