@anaemia/cli 0.1.8 ā 0.3.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.
- package/dist/commands/build.js +23 -0
- package/dist/commands/create.js +203 -0
- package/dist/commands/dev.js +102 -0
- package/dist/commands/routes.js +30 -0
- package/dist/commands/start.js +15 -0
- package/dist/commands/typecheck.js +10 -0
- package/dist/index.js +12 -354
- package/dist/utils/config.js +18 -0
- package/dist/utils/logger.js +22 -0
- package/package.json +4 -5
- package/src/commands/build.ts +28 -0
- package/src/commands/create.ts +229 -0
- package/src/commands/dev.ts +125 -0
- package/src/commands/routes.ts +34 -0
- package/src/commands/start.ts +17 -0
- package/src/commands/typecheck.ts +10 -0
- package/src/index.ts +12 -412
- package/src/utils/config.ts +24 -0
- /package/src/{logger.ts ā utils/logger.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,420 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { cac } from "cac";
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import { fileURLToPath } from "node:url";
|
|
10
|
-
import { createJiti } from "jiti";
|
|
11
|
-
import fs from "node:fs";
|
|
12
|
-
import { ChildProcess, execSync } from "node:child_process";
|
|
13
|
-
import prompts from "prompts";
|
|
14
|
-
import { scaffoldFeature, generateSharedComponent, scaffoldPage, scaffoldHook } from "./scaffold.js";
|
|
15
|
-
import { transform } from "sucrase";
|
|
16
|
-
import { WebSocketServer } from "ws";
|
|
17
|
-
import { WebSocket as NodeWS } from "ws";
|
|
18
|
-
import logger from "./logger.js";
|
|
19
|
-
import http from "node:http";
|
|
20
|
-
import { AnaemiaConfig } from "@anaemia/core/config";
|
|
21
|
-
|
|
22
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
23
|
-
const __dirname = path.dirname(__filename);
|
|
3
|
+
import { register as registerDev } from "./commands/dev.js";
|
|
4
|
+
import { register as registerBuild } from "./commands/build.js";
|
|
5
|
+
import { register as registerStart } from "./commands/start.js";
|
|
6
|
+
import { register as registerRoutes } from "./commands/routes.js";
|
|
7
|
+
import { register as registerTypecheck } from "./commands/typecheck.js";
|
|
8
|
+
import { register as registerCreate } from "./commands/create.js";
|
|
24
9
|
|
|
25
10
|
const cli = cac("anaemia");
|
|
26
11
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const configPath = path.resolve(appRoot, "anaemia.config.ts");
|
|
34
|
-
if (!fs.existsSync(configPath)) return {};
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const jiti = createJiti(import.meta.url);
|
|
38
|
-
const module = (await jiti.import(configPath)) as UserConfigModule;
|
|
39
|
-
return (module.default ?? module) as AnaemiaConfig;
|
|
40
|
-
} catch (err) {
|
|
41
|
-
logger.error("failed parsing your anaemia.config.ts file:", err);
|
|
42
|
-
return {};
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
cli.command("dev", "launch local development environment").action(async () => {
|
|
47
|
-
process.env.NODE_ENV = "development";
|
|
48
|
-
const appRoot = process.cwd();
|
|
49
|
-
|
|
50
|
-
const userConfig = await loadUserConfig(appRoot);
|
|
51
|
-
const targetPort = userConfig.port || 3000;
|
|
52
|
-
|
|
53
|
-
const [clientConfig, serverConfig] = await getRspackConfig(appRoot, userConfig);
|
|
54
|
-
|
|
55
|
-
const clientCompiler = rspack(clientConfig);
|
|
56
|
-
const devServer = new RspackDevServer(clientConfig.devServer || {}, clientCompiler);
|
|
57
|
-
|
|
58
|
-
const bridgeServer = http.createServer();
|
|
59
|
-
const wss = new WebSocketServer({ server: bridgeServer });
|
|
60
|
-
|
|
61
|
-
wss.on("connection", (clientWs) => {
|
|
62
|
-
const rspackSocket = new NodeWS(`ws://localhost:${targetPort + 1}/ws`);
|
|
63
|
-
|
|
64
|
-
rspackSocket.on("message", (data) => {
|
|
65
|
-
const flattened = Array.isArray(data) ? Buffer.concat(data) : data;
|
|
66
|
-
if (Buffer.isBuffer(flattened)) clientWs.send(flattened.toString("utf-8"));
|
|
67
|
-
else clientWs.send(String(flattened));
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
rspackSocket.on("error", (err) => {
|
|
71
|
-
console.warn("[anaemia hmr] rspack socket error:", err.message);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
clientWs.on("message", (data) => {
|
|
75
|
-
if (rspackSocket.readyState === NodeWS.OPEN) rspackSocket.send(data);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
clientWs.on("close", () => {
|
|
79
|
-
if (rspackSocket.readyState === NodeWS.OPEN) rspackSocket.close();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
let serverProcess: ChildProcess | null = null;
|
|
84
|
-
|
|
85
|
-
const startServer = () => {
|
|
86
|
-
if (serverProcess) {
|
|
87
|
-
serverProcess.kill("SIGTERM");
|
|
88
|
-
serverProcess = null;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
setTimeout(() => {
|
|
92
|
-
serverProcess = spawn("node", [path.resolve(appRoot, "./dist/server/index.js")], {
|
|
93
|
-
stdio: "inherit",
|
|
94
|
-
env: { ...process.env, NODE_ENV: "development", PORT: String(targetPort), RSPACK_DEV_PORT: String(targetPort + 1) },
|
|
95
|
-
});
|
|
96
|
-
}, 200);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
const cleanup = async () => {
|
|
100
|
-
if (serverProcess) {
|
|
101
|
-
serverProcess.kill("SIGTERM");
|
|
102
|
-
serverProcess = null;
|
|
103
|
-
}
|
|
104
|
-
bridgeServer.close();
|
|
105
|
-
serverCompiler?.close(() => {});
|
|
106
|
-
if (devServer) {
|
|
107
|
-
await devServer.stop();
|
|
108
|
-
}
|
|
109
|
-
process.exit(0);
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
process.on("SIGINT", cleanup);
|
|
113
|
-
process.on("SIGTERM", cleanup);
|
|
114
|
-
|
|
115
|
-
logger.compiler("warming up and analyzing assets...");
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
await devServer.start();
|
|
119
|
-
logger.success(`hot reload asset infrastructure running on port ${targetPort + 1}`);
|
|
120
|
-
} catch (err) {
|
|
121
|
-
logger.error("failed to start client asset dev server:", err);
|
|
122
|
-
process.exit(1);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
bridgeServer.listen(targetPort + 2, () => {
|
|
126
|
-
logger.info(`HMR bridge running on port ${targetPort + 2}`);
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
const serverCompiler = rspack(serverConfig);
|
|
130
|
-
|
|
131
|
-
serverCompiler.watch({}, (err, stats) => {
|
|
132
|
-
if (err) {
|
|
133
|
-
logger.error("server compilation critical failure:", err);
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (stats?.hasErrors()) {
|
|
138
|
-
console.error(stats.toString({ colors: true, all: false, errors: true, warnings: true }));
|
|
139
|
-
logger.error("server compilation encountered build script errors.");
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
logger.info(`server bundles updated. booting runtime on http://localhost:${targetPort}`);
|
|
144
|
-
startServer();
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
cli.command("start", "serve the production build").action(async () => {
|
|
149
|
-
const appRoot = process.cwd();
|
|
150
|
-
const userConfig = await loadUserConfig(appRoot);
|
|
151
|
-
const targetPort = userConfig.port || 3000;
|
|
152
|
-
|
|
153
|
-
spawn("node", [path.resolve(appRoot, "./dist/server/index.js")], {
|
|
154
|
-
stdio: "inherit",
|
|
155
|
-
env: { ...process.env, NODE_ENV: "production", PORT: String(targetPort) },
|
|
156
|
-
});
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
cli.command("typecheck", "run TypeScript type checking without emitting").action(async () => {
|
|
160
|
-
const appRoot = process.cwd();
|
|
161
|
-
const result = spawn.sync("tsc", ["--noEmit"], { stdio: "inherit", cwd: appRoot });
|
|
162
|
-
if (result.status !== 0) process.exit(result.status ?? 1);
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
cli.command("build", "compile production-ready optimization bundles").action(async () => {
|
|
166
|
-
process.env.NODE_ENV = "production";
|
|
167
|
-
const appRoot = process.cwd();
|
|
168
|
-
|
|
169
|
-
const userConfig = await loadUserConfig(appRoot);
|
|
170
|
-
const configs = await getRspackConfig(appRoot, userConfig);
|
|
171
|
-
const compiler = rspack(configs);
|
|
172
|
-
|
|
173
|
-
logger.compiler("packaging production optimization bundles...");
|
|
174
|
-
|
|
175
|
-
await new Promise<void>((resolve, reject) => {
|
|
176
|
-
compiler.run((err, stats) => {
|
|
177
|
-
if (err || stats?.hasErrors()) {
|
|
178
|
-
reject(err || new Error(stats?.toString("normal")));
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
compiler.close(() => resolve());
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
cli.command("routes", "print the scanned route manifest").action(async () => {
|
|
187
|
-
const appRoot = process.cwd();
|
|
188
|
-
const routes = scanRoutes(appRoot);
|
|
189
|
-
|
|
190
|
-
logger.info("scanned route architecture:");
|
|
191
|
-
console.table(
|
|
192
|
-
(await routes).map((r) => ({
|
|
193
|
-
pattern: r.urlPattern,
|
|
194
|
-
chunk: r.chunkName,
|
|
195
|
-
layouts: r.layouts.length,
|
|
196
|
-
params: r.params.join(", ") || "ā",
|
|
197
|
-
type: r.type,
|
|
198
|
-
}))
|
|
199
|
-
);
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
cli
|
|
203
|
-
.command("create [target]", "initialize an application or generate domain features (e.g., feature:name)")
|
|
204
|
-
.alias("init")
|
|
205
|
-
.action(async (target) => {
|
|
206
|
-
const appRoot = process.cwd();
|
|
207
|
-
|
|
208
|
-
if (target && target.includes(":")) {
|
|
209
|
-
const [type, name] = target.split(":");
|
|
210
|
-
|
|
211
|
-
if (!name) {
|
|
212
|
-
logger.error(`missing name modifier. Use layout template like: ${pc.cyan(`create ${type}:your-name`)}`);
|
|
213
|
-
process.exit(1);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (!fs.existsSync(path.join(appRoot, "package.json"))) {
|
|
217
|
-
logger.error("no package.json detected. code generation commands must run inside an Anaemia project root.");
|
|
218
|
-
process.exit(1);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
const normalizedName = name.trim();
|
|
222
|
-
|
|
223
|
-
if (type === "feature") {
|
|
224
|
-
scaffoldFeature(normalizedName, appRoot);
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
if (type === "component") {
|
|
229
|
-
generateSharedComponent(appRoot, normalizedName, { logger, pc });
|
|
230
|
-
return;
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (type === "page") {
|
|
234
|
-
scaffoldPage(normalizedName, appRoot);
|
|
235
|
-
return;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (type === "hook") {
|
|
239
|
-
scaffoldHook(normalizedName, appRoot);
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
logger.error(`unknown layout generator type "${type}". Supported variants: "feature:", "component:", "page:", "hook:"`);
|
|
244
|
-
process.exit(1);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
logger.compiler("launching Anaemia project initialization wizard...");
|
|
248
|
-
|
|
249
|
-
const response = await prompts([
|
|
250
|
-
{
|
|
251
|
-
type: target ? null : "text",
|
|
252
|
-
name: "projectName",
|
|
253
|
-
message: "Project name:",
|
|
254
|
-
initial: "anaemia-app",
|
|
255
|
-
},
|
|
256
|
-
{
|
|
257
|
-
type: "select",
|
|
258
|
-
name: "variant",
|
|
259
|
-
message: "Select a variant:",
|
|
260
|
-
choices: [
|
|
261
|
-
{ title: pc.blue("TypeScript (Recommended)"), value: "ts" },
|
|
262
|
-
{ title: pc.yellow("JavaScript"), value: "js" },
|
|
263
|
-
],
|
|
264
|
-
initial: 0,
|
|
265
|
-
},
|
|
266
|
-
]);
|
|
267
|
-
|
|
268
|
-
if (!response.variant && response.variant !== 0) {
|
|
269
|
-
logger.warn("project creation aborted.");
|
|
270
|
-
process.exit(0);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
const targetDir = target || response.projectName;
|
|
274
|
-
const targetPath = path.resolve(appRoot, targetDir);
|
|
275
|
-
|
|
276
|
-
if (fs.existsSync(targetPath)) {
|
|
277
|
-
const files = fs.readdirSync(targetPath);
|
|
278
|
-
if (files.length > 0) {
|
|
279
|
-
const { overwrite } = await prompts({
|
|
280
|
-
type: "confirm",
|
|
281
|
-
name: "overwrite",
|
|
282
|
-
message: `target directory "${targetDir}" is not empty. remove existing files and continue?`,
|
|
283
|
-
initial: false,
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
if (!overwrite) {
|
|
287
|
-
logger.error("aborted to protect existing project directory.");
|
|
288
|
-
process.exit(1);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
logger.warn(`purging existing files inside ${targetDir}...`);
|
|
292
|
-
fs.rmSync(targetPath, { recursive: true, force: true });
|
|
293
|
-
fs.mkdirSync(targetPath, { recursive: true });
|
|
294
|
-
}
|
|
295
|
-
} else {
|
|
296
|
-
fs.mkdirSync(targetPath, { recursive: true });
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
let templatePath = path.resolve(__dirname, "../templates/template-base");
|
|
300
|
-
if (!fs.existsSync(templatePath)) {
|
|
301
|
-
templatePath = path.resolve(__dirname, "../templates/base-app");
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
if (fs.existsSync(templatePath)) {
|
|
305
|
-
logger.info("unpacking localized scaffolding architecture layout structures...");
|
|
306
|
-
fs.cpSync(templatePath, targetPath, {
|
|
307
|
-
recursive: true,
|
|
308
|
-
filter: (src) => !["node_modules", "dist", ".anaemia", ".rspack"].includes(path.basename(src)),
|
|
309
|
-
});
|
|
310
|
-
} else {
|
|
311
|
-
logger.warn("local templates missing. fetching remote registry packages over the network...");
|
|
312
|
-
const userAgent = process.env.npm_config_user_agent || "";
|
|
313
|
-
let packageManager = "npm";
|
|
314
|
-
if (userAgent.includes("pnpm")) packageManager = "pnpm";
|
|
315
|
-
else if (userAgent.includes("yarn")) packageManager = "yarn";
|
|
316
|
-
|
|
317
|
-
try {
|
|
318
|
-
if (packageManager === "pnpm") {
|
|
319
|
-
execSync(`pnpm dlx degit colourlabs/anaemia/templates/base-app "${targetPath}"`, { stdio: "ignore" });
|
|
320
|
-
} else {
|
|
321
|
-
execSync(`npx degit colourlabs/anaemia/templates/base-app "${targetPath}"`, { stdio: "ignore" });
|
|
322
|
-
}
|
|
323
|
-
} catch (err) {
|
|
324
|
-
logger.error("could not source template workspace assets locally or from network registry nodes. " + err);
|
|
325
|
-
process.exit(1);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const removeGitKeepFiles = (dir: string) => {
|
|
330
|
-
const files = fs.readdirSync(dir);
|
|
331
|
-
for (const file of files) {
|
|
332
|
-
const fullPath = path.join(dir, file);
|
|
333
|
-
if (fs.statSync(fullPath).isDirectory()) {
|
|
334
|
-
removeGitKeepFiles(fullPath);
|
|
335
|
-
} else if (file === ".gitkeep") {
|
|
336
|
-
fs.unlinkSync(fullPath);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
removeGitKeepFiles(targetPath);
|
|
341
|
-
|
|
342
|
-
if (response.variant === "js") {
|
|
343
|
-
logger.info("converting workspace assets to vanilla JavaScript...");
|
|
344
|
-
|
|
345
|
-
const convertTypeScriptToJs = (dir: string) => {
|
|
346
|
-
const files = fs.readdirSync(dir);
|
|
347
|
-
|
|
348
|
-
for (const file of files) {
|
|
349
|
-
const fullPath = path.join(dir, file);
|
|
350
|
-
const stat = fs.statSync(fullPath);
|
|
351
|
-
|
|
352
|
-
if (stat.isDirectory()) {
|
|
353
|
-
convertTypeScriptToJs(fullPath);
|
|
354
|
-
} else if (file.endsWith(".ts") || file.endsWith(".tsx")) {
|
|
355
|
-
const isTsx = file.endsWith(".tsx");
|
|
356
|
-
const code = fs.readFileSync(fullPath, "utf8");
|
|
357
|
-
|
|
358
|
-
try {
|
|
359
|
-
const compiled = transform(code, {
|
|
360
|
-
transforms: isTsx ? ["typescript", "jsx"] : ["typescript"],
|
|
361
|
-
jsxRuntime: "preserve",
|
|
362
|
-
production: true,
|
|
363
|
-
});
|
|
364
|
-
|
|
365
|
-
const newExt = isTsx ? ".jsx" : ".js";
|
|
366
|
-
const newPath = fullPath.replace(/\.tsx?$/, newExt);
|
|
367
|
-
|
|
368
|
-
fs.writeFileSync(newPath, compiled.code, "utf8");
|
|
369
|
-
fs.unlinkSync(fullPath);
|
|
370
|
-
} catch {
|
|
371
|
-
logger.warn(`failed to strip types from ${file}, skipping...`);
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
convertTypeScriptToJs(targetPath);
|
|
378
|
-
|
|
379
|
-
const tsconfigPath = path.join(targetPath, "tsconfig.json");
|
|
380
|
-
if (fs.existsSync(tsconfigPath)) {
|
|
381
|
-
fs.unlinkSync(tsconfigPath);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const pkgJsonPath = path.join(targetPath, "package.json");
|
|
386
|
-
if (fs.existsSync(pkgJsonPath)) {
|
|
387
|
-
try {
|
|
388
|
-
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8"));
|
|
389
|
-
pkg.name = path.basename(targetPath);
|
|
390
|
-
|
|
391
|
-
if (response.variant === "js") {
|
|
392
|
-
if (pkg.devDependencies) {
|
|
393
|
-
delete pkg.devDependencies["typescript"];
|
|
394
|
-
delete pkg.devDependencies["@types/node"];
|
|
395
|
-
delete pkg.devDependencies["@typescript-eslint/eslint-plugin"];
|
|
396
|
-
delete pkg.devDependencies["@typescript-eslint/parser"];
|
|
397
|
-
}
|
|
398
|
-
if (pkg.scripts && pkg.scripts.typecheck) {
|
|
399
|
-
delete pkg.scripts.typecheck;
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2), "utf8");
|
|
404
|
-
} catch (err) {
|
|
405
|
-
logger.error("failed rewriting package.json manifest structures:", err);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
logger.success(`\nš project successfully scaffolded into ${pc.magenta(targetDir)}!`);
|
|
410
|
-
console.log(pc.dim("\nfollow these steps to begin execution:\n"));
|
|
411
|
-
|
|
412
|
-
if (targetDir !== ".") {
|
|
413
|
-
console.log(` cd ${pc.cyan(targetDir)}`);
|
|
414
|
-
}
|
|
415
|
-
console.log(` ${pc.cyan("pnpm install")} ${pc.dim("# or npm i / yarn install")}`);
|
|
416
|
-
console.log(` ${pc.cyan("pnpm dev")} ${pc.dim("# launches hot reload server")}\n`);
|
|
417
|
-
});
|
|
12
|
+
registerDev(cli);
|
|
13
|
+
registerBuild(cli);
|
|
14
|
+
registerStart(cli);
|
|
15
|
+
registerRoutes(cli);
|
|
16
|
+
registerTypecheck(cli);
|
|
17
|
+
registerCreate(cli);
|
|
418
18
|
|
|
419
19
|
cli.help();
|
|
420
20
|
cli.parse();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AnaemiaConfig } from "@anaemia/core/config";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs";
|
|
4
|
+
import { createJiti } from "jiti";
|
|
5
|
+
import logger from "./logger.js";
|
|
6
|
+
|
|
7
|
+
interface UserConfigModule {
|
|
8
|
+
default?: AnaemiaConfig;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function loadUserConfig(appRoot: string): Promise<AnaemiaConfig> {
|
|
13
|
+
const configPath = path.resolve(appRoot, "anaemia.config.ts");
|
|
14
|
+
if (!fs.existsSync(configPath)) return {};
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const jiti = createJiti(import.meta.url);
|
|
18
|
+
const module = (await jiti.import(configPath)) as UserConfigModule;
|
|
19
|
+
return (module.default ?? module) as AnaemiaConfig;
|
|
20
|
+
} catch (err) {
|
|
21
|
+
logger.error("failed parsing your anaemia.config.ts file:", err);
|
|
22
|
+
return {};
|
|
23
|
+
}
|
|
24
|
+
}
|
|
File without changes
|