express-file-cluster 0.1.8 → 0.2.1
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/README.md +367 -0
- package/dist/auth/index.cjs +2 -2
- package/dist/auth/index.d.cts +2 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +1 -1
- package/dist/{chunk-M7UOT4ZR.js → chunk-DQGWFWBV.js} +13 -10
- package/dist/chunk-DQGWFWBV.js.map +1 -0
- package/dist/chunk-QB3X6LKZ.cjs +63 -0
- package/dist/chunk-QB3X6LKZ.cjs.map +1 -0
- package/dist/cli/index.cjs +34 -34
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +38 -38
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +2 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/package.json +3 -5
- package/dist/chunk-M7UOT4ZR.js.map +0 -1
- package/dist/chunk-PFJWEU4E.cjs +0 -60
- package/dist/chunk-PFJWEU4E.cjs.map +0 -1
package/dist/cli/index.cjs
CHANGED
|
@@ -11,7 +11,7 @@ var _commander = require('commander');
|
|
|
11
11
|
var _child_process = require('child_process');
|
|
12
12
|
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
13
13
|
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
14
|
-
var
|
|
14
|
+
var _picocolors = require('picocolors'); var _picocolors2 = _interopRequireDefault(_picocolors);
|
|
15
15
|
function startCommand() {
|
|
16
16
|
const cmd = new (0, _commander.Command)("start");
|
|
17
17
|
cmd.argument("<mode>", "dev | prod").description("Start the EFC server").action((mode) => {
|
|
@@ -20,7 +20,7 @@ function startCommand() {
|
|
|
20
20
|
} else if (mode === "prod") {
|
|
21
21
|
startProd();
|
|
22
22
|
} else {
|
|
23
|
-
console.error(
|
|
23
|
+
console.error(_picocolors2.default.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
});
|
|
@@ -44,11 +44,11 @@ function parseDotenv(cwd) {
|
|
|
44
44
|
function startDev() {
|
|
45
45
|
const entry = resolveEntry();
|
|
46
46
|
if (!entry) {
|
|
47
|
-
console.error(
|
|
47
|
+
console.error(_picocolors2.default.red("[EFC] Could not find entry point. Expected src/index.ts or index.ts"));
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
|
-
console.log(
|
|
51
|
-
console.log(
|
|
50
|
+
console.log(_picocolors2.default.cyan("[EFC] Starting development server\u2026"));
|
|
51
|
+
console.log(_picocolors2.default.dim(` Entry: ${entry}`));
|
|
52
52
|
const cwd = process.cwd();
|
|
53
53
|
const localTsx = _path2.default.join(cwd, "node_modules", ".bin", "tsx");
|
|
54
54
|
const tsx = _fs2.default.existsSync(localTsx) ? localTsx : "tsx";
|
|
@@ -60,10 +60,10 @@ function startProd() {
|
|
|
60
60
|
const cwd = process.cwd();
|
|
61
61
|
const distEntry = _path2.default.join(cwd, "dist", "index.js");
|
|
62
62
|
if (!_fs2.default.existsSync(distEntry)) {
|
|
63
|
-
console.error(
|
|
63
|
+
console.error(_picocolors2.default.red("[EFC] dist/index.js not found. Run `efc build prod` first."));
|
|
64
64
|
process.exit(1);
|
|
65
65
|
}
|
|
66
|
-
console.log(
|
|
66
|
+
console.log(_picocolors2.default.cyan("[EFC] Starting production server\u2026"));
|
|
67
67
|
const child = _child_process.spawn.call(void 0, "node", [distEntry], {
|
|
68
68
|
stdio: "inherit",
|
|
69
69
|
env: { ...process.env, NODE_ENV: "production" }
|
|
@@ -89,7 +89,7 @@ function buildCommand() {
|
|
|
89
89
|
const cmd = new (0, _commander.Command)("build");
|
|
90
90
|
cmd.argument("<mode>", "prod").description("Build the application for production").action((mode) => {
|
|
91
91
|
if (mode !== "prod") {
|
|
92
|
-
console.error(
|
|
92
|
+
console.error(_picocolors2.default.red(`Unknown build mode: ${mode}. Use 'prod'.`));
|
|
93
93
|
process.exit(1);
|
|
94
94
|
}
|
|
95
95
|
buildProd();
|
|
@@ -97,17 +97,17 @@ function buildCommand() {
|
|
|
97
97
|
return cmd;
|
|
98
98
|
}
|
|
99
99
|
function buildProd() {
|
|
100
|
-
console.log(
|
|
100
|
+
console.log(_picocolors2.default.cyan("[EFC] Building for production\u2026"));
|
|
101
101
|
const tsc = _child_process.spawn.call(void 0, "npx", ["tsc", "--noEmit"], { stdio: "inherit" });
|
|
102
102
|
tsc.on("exit", (code) => {
|
|
103
103
|
if (code !== 0) {
|
|
104
|
-
console.error(
|
|
104
|
+
console.error(_picocolors2.default.red("[EFC] TypeScript errors found. Fix them before building."));
|
|
105
105
|
process.exit(1);
|
|
106
106
|
}
|
|
107
107
|
const tsup = _child_process.spawn.call(void 0, "npx", ["tsup"], { stdio: "inherit" });
|
|
108
108
|
tsup.on("exit", (tsupCode) => {
|
|
109
109
|
if (tsupCode === 0) {
|
|
110
|
-
console.log(
|
|
110
|
+
console.log(_picocolors2.default.green("[EFC] Build complete \u2192 dist/"));
|
|
111
111
|
} else {
|
|
112
112
|
process.exit(_nullishCoalesce(tsupCode, () => ( 1)));
|
|
113
113
|
}
|
|
@@ -125,14 +125,14 @@ function runCommand() {
|
|
|
125
125
|
if (runner === "tests") {
|
|
126
126
|
runTests(cmd.args.slice(1));
|
|
127
127
|
} else {
|
|
128
|
-
console.error(
|
|
128
|
+
console.error(_picocolors2.default.red(`Unknown runner: ${runner}. Use 'tests'.`));
|
|
129
129
|
process.exit(1);
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
132
|
return cmd;
|
|
133
133
|
}
|
|
134
134
|
function runTests(extraArgs) {
|
|
135
|
-
console.log(
|
|
135
|
+
console.log(_picocolors2.default.cyan("[EFC] Running tests via Vitest\u2026"));
|
|
136
136
|
const child = _child_process.spawn.call(void 0, "npx", ["vitest", "run", ...extraArgs], { stdio: "inherit" });
|
|
137
137
|
child.on("exit", (code) => process.exit(_nullishCoalesce(code, () => ( 0))));
|
|
138
138
|
}
|
|
@@ -153,11 +153,11 @@ function writeFile(filePath, content) {
|
|
|
153
153
|
const dir = _path2.default.dirname(filePath);
|
|
154
154
|
_fs2.default.mkdirSync(dir, { recursive: true });
|
|
155
155
|
if (_fs2.default.existsSync(filePath)) {
|
|
156
|
-
console.error(
|
|
156
|
+
console.error(_picocolors2.default.red(`File already exists: ${filePath}`));
|
|
157
157
|
process.exit(1);
|
|
158
158
|
}
|
|
159
159
|
_fs2.default.writeFileSync(filePath, content, "utf8");
|
|
160
|
-
console.log(
|
|
160
|
+
console.log(_picocolors2.default.green(` created ${_path2.default.relative(process.cwd(), filePath)}`));
|
|
161
161
|
}
|
|
162
162
|
function generateRoute(routePath) {
|
|
163
163
|
const cwd = process.cwd();
|
|
@@ -173,7 +173,7 @@ export const POST = async (req: Request, res: Response) => {
|
|
|
173
173
|
};
|
|
174
174
|
`;
|
|
175
175
|
writeFile(filePath, content);
|
|
176
|
-
console.log(
|
|
176
|
+
console.log(_picocolors2.default.cyan(`[EFC] Route scaffolded`));
|
|
177
177
|
}
|
|
178
178
|
function generateTask(name) {
|
|
179
179
|
const cwd = process.cwd();
|
|
@@ -190,7 +190,7 @@ export default defineTask<${name}Payload>(async (payload) => {
|
|
|
190
190
|
});
|
|
191
191
|
`;
|
|
192
192
|
writeFile(filePath, content);
|
|
193
|
-
console.log(
|
|
193
|
+
console.log(_picocolors2.default.cyan(`[EFC] Task scaffolded`));
|
|
194
194
|
}
|
|
195
195
|
function generateMiddleware(name) {
|
|
196
196
|
const cwd = process.cwd();
|
|
@@ -203,7 +203,7 @@ export function ${name}(req: Request, res: Response, next: NextFunction): void {
|
|
|
203
203
|
}
|
|
204
204
|
`;
|
|
205
205
|
writeFile(filePath, content);
|
|
206
|
-
console.log(
|
|
206
|
+
console.log(_picocolors2.default.cyan(`[EFC] Middleware scaffolded`));
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
// src/cli/commands/diagnostics.ts
|
|
@@ -218,22 +218,22 @@ function routesCommand() {
|
|
|
218
218
|
return new (0, _commander.Command)("routes").description("Print the resolved route table").action(() => {
|
|
219
219
|
const apiDir = resolveApiDir();
|
|
220
220
|
if (!apiDir) {
|
|
221
|
-
console.error(
|
|
221
|
+
console.error(_picocolors2.default.red("[EFC] Could not find apiDir (expected src/api)"));
|
|
222
222
|
process.exit(1);
|
|
223
223
|
}
|
|
224
224
|
const routes = _chunkMQNVNOH5cjs.scanDir.call(void 0, apiDir);
|
|
225
225
|
if (routes.length === 0) {
|
|
226
|
-
console.log(
|
|
226
|
+
console.log(_picocolors2.default.yellow("No routes found."));
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
229
|
-
console.log(
|
|
230
|
-
console.log(
|
|
229
|
+
console.log(_picocolors2.default.bold("\n Route Table\n"));
|
|
230
|
+
console.log(_picocolors2.default.dim(" " + "\u2500".repeat(60)));
|
|
231
231
|
for (const route of routes) {
|
|
232
232
|
const rel = _path2.default.relative(process.cwd(), route.filePath);
|
|
233
|
-
console.log(` ${
|
|
233
|
+
console.log(` ${_picocolors2.default.cyan(route.urlPath.padEnd(35))} ${_picocolors2.default.dim(rel)}`);
|
|
234
234
|
}
|
|
235
|
-
console.log(
|
|
236
|
-
console.log(
|
|
235
|
+
console.log(_picocolors2.default.dim(" " + "\u2500".repeat(60)));
|
|
236
|
+
console.log(_picocolors2.default.dim(`
|
|
237
237
|
${routes.length} route(s) found
|
|
238
238
|
`));
|
|
239
239
|
});
|
|
@@ -242,17 +242,17 @@ function tasksCommand() {
|
|
|
242
242
|
return new (0, _commander.Command)("tasks").description("List registered background tasks").action(() => {
|
|
243
243
|
const tasksDir = resolveTasksDir();
|
|
244
244
|
if (!tasksDir || !_fs2.default.existsSync(tasksDir)) {
|
|
245
|
-
console.log(
|
|
245
|
+
console.log(_picocolors2.default.yellow("No tasks directory found."));
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
248
|
const files = _fs2.default.readdirSync(tasksDir).filter((f) => /\.(ts|js)$/.test(f));
|
|
249
249
|
if (files.length === 0) {
|
|
250
|
-
console.log(
|
|
250
|
+
console.log(_picocolors2.default.yellow("No tasks found."));
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
-
console.log(
|
|
253
|
+
console.log(_picocolors2.default.bold("\n Background Tasks\n"));
|
|
254
254
|
for (const file of files) {
|
|
255
|
-
console.log(` ${
|
|
255
|
+
console.log(` ${_picocolors2.default.cyan(_path2.default.basename(file, _path2.default.extname(file)))}`);
|
|
256
256
|
}
|
|
257
257
|
console.log();
|
|
258
258
|
});
|
|
@@ -286,21 +286,21 @@ function doctorCommand() {
|
|
|
286
286
|
hint: "Add JWT_SECRET to .env (generate: openssl rand -hex 64)"
|
|
287
287
|
}
|
|
288
288
|
];
|
|
289
|
-
console.log(
|
|
289
|
+
console.log(_picocolors2.default.bold("\n EFC Doctor\n"));
|
|
290
290
|
let allOk = true;
|
|
291
291
|
for (const check of checks) {
|
|
292
|
-
const icon = check.ok ?
|
|
292
|
+
const icon = check.ok ? _picocolors2.default.green("\u2713") : _picocolors2.default.red("\u2717");
|
|
293
293
|
console.log(` ${icon} ${check.label}`);
|
|
294
294
|
if (!check.ok) {
|
|
295
295
|
allOk = false;
|
|
296
|
-
if (check.hint) console.log(
|
|
296
|
+
if (check.hint) console.log(_picocolors2.default.dim(` \u2192 ${check.hint}`));
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
console.log();
|
|
300
300
|
if (allOk) {
|
|
301
|
-
console.log(
|
|
301
|
+
console.log(_picocolors2.default.green(" All checks passed!\n"));
|
|
302
302
|
} else {
|
|
303
|
-
console.log(
|
|
303
|
+
console.log(_picocolors2.default.yellow(" Some checks failed. Fix the issues above.\n"));
|
|
304
304
|
process.exit(1);
|
|
305
305
|
}
|
|
306
306
|
});
|
package/dist/cli/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/efc.js/efc.js/packages/core/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/commands/start.ts","../../src/cli/commands/build.ts","../../src/cli/commands/run.ts","../../src/cli/commands/generate.ts","../../src/cli/commands/diagnostics.ts"],"names":["path","chalk"],"mappings":"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","file":"/home/runner/work/efc.js/efc.js/packages/core/dist/cli/index.cjs","sourcesContent":[null,"#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { startCommand } from './commands/start.js';\nimport { buildCommand } from './commands/build.js';\nimport { runCommand } from './commands/run.js';\nimport { generateCommand } from './commands/generate.js';\nimport { diagnosticsCommands } from './commands/diagnostics.js';\n\nconst program = new Command('efc')\n .description('Express File Cluster CLI')\n .version('0.1.0');\n\nprogram.addCommand(startCommand());\nprogram.addCommand(buildCommand());\nprogram.addCommand(runCommand());\nprogram.addCommand(generateCommand());\n\nfor (const cmd of diagnosticsCommands()) {\n program.addCommand(cmd);\n}\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport chalk from 'chalk';\n\nexport function startCommand(): Command {\n const cmd = new Command('start');\n\n cmd\n .argument('<mode>', 'dev | prod')\n .description('Start the EFC server')\n .action((mode: string) => {\n if (mode === 'dev') {\n startDev();\n } else if (mode === 'prod') {\n startProd();\n } else {\n console.error(chalk.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\nfunction parseDotenv(cwd: string): Record<string, string> {\n const envFile = path.join(cwd, '.env');\n if (!fs.existsSync(envFile)) return {};\n const vars: Record<string, string> = {};\n for (const line of fs.readFileSync(envFile, 'utf8').split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eq = trimmed.indexOf('=');\n if (eq === -1) continue;\n const key = trimmed.slice(0, eq).trim();\n const raw = trimmed.slice(eq + 1).trim();\n vars[key] = raw.replace(/^(['\"])(.*)\\1$/, '$2');\n }\n return vars;\n}\n\nfunction startDev(): void {\n const entry = resolveEntry();\n if (!entry) {\n console.error(chalk.red('[EFC] Could not find entry point. Expected src/index.ts or index.ts'));\n process.exit(1);\n }\n\n console.log(chalk.cyan('[EFC] Starting development server…'));\n console.log(chalk.dim(` Entry: ${entry}`));\n\n const cwd = process.cwd();\n const localTsx = path.join(cwd, 'node_modules', '.bin', 'tsx');\n const tsx = fs.existsSync(localTsx) ? localTsx : 'tsx';\n\n // .env values are base; existing process.env takes precedence (same as dotenv default)\n const env: NodeJS.ProcessEnv = { ...parseDotenv(cwd), ...process.env, NODE_ENV: 'development' };\n\n const child = spawn(tsx, ['watch', '--include', 'src', entry], { stdio: 'inherit', env });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n\nfunction startProd(): void {\n const cwd = process.cwd();\n const distEntry = path.join(cwd, 'dist', 'index.js');\n\n if (!fs.existsSync(distEntry)) {\n console.error(chalk.red('[EFC] dist/index.js not found. Run `efc build prod` first.'));\n process.exit(1);\n }\n\n console.log(chalk.cyan('[EFC] Starting production server…'));\n\n // Production env comes exclusively from process.env — no .env file loading.\n // Platforms (Docker, Kubernetes, Railway, Heroku, etc.) inject vars directly.\n const child = spawn('node', [distEntry], {\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'production' },\n });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n\nfunction resolveEntry(): string | null {\n const cwd = process.cwd();\n const candidates = [\n path.join(cwd, 'src', 'index.ts'),\n path.join(cwd, 'index.ts'),\n path.join(cwd, 'src', 'index.js'),\n path.join(cwd, 'index.js'),\n ];\n return candidates.find((f) => fs.existsSync(f)) ?? null;\n}\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport chalk from 'chalk';\n\nexport function buildCommand(): Command {\n const cmd = new Command('build');\n\n cmd\n .argument('<mode>', 'prod')\n .description('Build the application for production')\n .action((mode: string) => {\n if (mode !== 'prod') {\n console.error(chalk.red(`Unknown build mode: ${mode}. Use 'prod'.`));\n process.exit(1);\n }\n buildProd();\n });\n\n return cmd;\n}\n\nfunction buildProd(): void {\n console.log(chalk.cyan('[EFC] Building for production…'));\n\n // Type-check first\n const tsc = spawn('npx', ['tsc', '--noEmit'], { stdio: 'inherit' });\n\n tsc.on('exit', (code) => {\n if (code !== 0) {\n console.error(chalk.red('[EFC] TypeScript errors found. Fix them before building.'));\n process.exit(1);\n }\n\n const tsup = spawn('npx', ['tsup'], { stdio: 'inherit' });\n tsup.on('exit', (tsupCode) => {\n if (tsupCode === 0) {\n console.log(chalk.green('[EFC] Build complete → dist/'));\n } else {\n process.exit(tsupCode ?? 1);\n }\n });\n });\n}\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport chalk from 'chalk';\n\nexport function runCommand(): Command {\n const cmd = new Command('run');\n\n cmd\n .argument('<runner>', 'tests')\n .description('Run EFC sub-commands (tests)')\n .allowUnknownOption()\n .action((runner: string) => {\n if (runner === 'tests') {\n runTests(cmd.args.slice(1));\n } else {\n console.error(chalk.red(`Unknown runner: ${runner}. Use 'tests'.`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\nfunction runTests(extraArgs: string[]): void {\n console.log(chalk.cyan('[EFC] Running tests via Vitest…'));\n const child = spawn('npx', ['vitest', 'run', ...extraArgs], { stdio: 'inherit' });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n","import { Command } from 'commander';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport chalk from 'chalk';\n\nexport function generateCommand(): Command {\n const cmd = new Command('generate').alias('g').description('Scaffold EFC modules');\n\n cmd\n .command('route <routePath>')\n .description('Scaffold a route module, e.g. users/[id]')\n .action((routePath: string) => generateRoute(routePath));\n\n cmd\n .command('task <name>')\n .description('Scaffold a background task module')\n .action((name: string) => generateTask(name));\n\n cmd\n .command('middleware <name>')\n .description('Scaffold a middleware module')\n .action((name: string) => generateMiddleware(name));\n\n return cmd;\n}\n\nfunction writeFile(filePath: string, content: string): void {\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n if (fs.existsSync(filePath)) {\n console.error(chalk.red(`File already exists: ${filePath}`));\n process.exit(1);\n }\n fs.writeFileSync(filePath, content, 'utf8');\n console.log(chalk.green(` created ${path.relative(process.cwd(), filePath)}`));\n}\n\nfunction generateRoute(routePath: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'api', `${routePath}.ts`);\n\n const content = `import type { Request, Response } from 'express';\n\nexport const GET = async (req: Request, res: Response) => {\n res.json({ message: 'OK' });\n};\n\nexport const POST = async (req: Request, res: Response) => {\n res.status(201).json({ message: 'Created' });\n};\n`;\n\n writeFile(filePath, content);\n console.log(chalk.cyan(`[EFC] Route scaffolded`));\n}\n\nfunction generateTask(name: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'tasks', `${name}.ts`);\n\n const content = `import { defineTask } from 'express-file-cluster/tasks';\n\ninterface ${name}Payload {\n // TODO: define payload fields\n}\n\nexport default defineTask<${name}Payload>(async (payload) => {\n // TODO: implement task logic\n console.log('[Task:${name}]', payload);\n});\n`;\n\n writeFile(filePath, content);\n console.log(chalk.cyan(`[EFC] Task scaffolded`));\n}\n\nfunction generateMiddleware(name: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'middlewares', `${name}.ts`);\n\n const content = `import type { Request, Response, NextFunction } from 'express';\n\nexport function ${name}(req: Request, res: Response, next: NextFunction): void {\n // TODO: implement middleware logic\n next();\n}\n`;\n\n writeFile(filePath, content);\n console.log(chalk.cyan(`[EFC] Middleware scaffolded`));\n}\n","import { Command } from 'commander';\nimport { scanDir } from '../../router/scan.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport chalk from 'chalk';\n\nexport function diagnosticsCommands(): Command[] {\n return [routesCommand(), tasksCommand(), doctorCommand()];\n}\n\nfunction routesCommand(): Command {\n return new Command('routes')\n .description('Print the resolved route table')\n .action(() => {\n const apiDir = resolveApiDir();\n if (!apiDir) {\n console.error(chalk.red('[EFC] Could not find apiDir (expected src/api)'));\n process.exit(1);\n }\n\n const routes = scanDir(apiDir);\n if (routes.length === 0) {\n console.log(chalk.yellow('No routes found.'));\n return;\n }\n\n console.log(chalk.bold('\\n Route Table\\n'));\n console.log(chalk.dim(' ' + '─'.repeat(60)));\n for (const route of routes) {\n const rel = path.relative(process.cwd(), route.filePath);\n console.log(` ${chalk.cyan(route.urlPath.padEnd(35))} ${chalk.dim(rel)}`);\n }\n console.log(chalk.dim(' ' + '─'.repeat(60)));\n console.log(chalk.dim(`\\n ${routes.length} route(s) found\\n`));\n });\n}\n\nfunction tasksCommand(): Command {\n return new Command('tasks')\n .description('List registered background tasks')\n .action(() => {\n const tasksDir = resolveTasksDir();\n if (!tasksDir || !fs.existsSync(tasksDir)) {\n console.log(chalk.yellow('No tasks directory found.'));\n return;\n }\n\n const files = fs.readdirSync(tasksDir).filter((f) => /\\.(ts|js)$/.test(f));\n if (files.length === 0) {\n console.log(chalk.yellow('No tasks found.'));\n return;\n }\n\n console.log(chalk.bold('\\n Background Tasks\\n'));\n for (const file of files) {\n console.log(` ${chalk.cyan(path.basename(file, path.extname(file)))}`);\n }\n console.log();\n });\n}\n\nfunction doctorCommand(): Command {\n return new Command('doctor')\n .description('Validate config, env vars, and project setup')\n .action(() => {\n const cwd = process.cwd();\n const checks: { label: string; ok: boolean; hint?: string }[] = [\n {\n label: 'package.json exists',\n ok: fs.existsSync(path.join(cwd, 'package.json')),\n },\n {\n label: 'tsconfig.json exists',\n ok: fs.existsSync(path.join(cwd, 'tsconfig.json')),\n hint: 'Run `tsc --init` to create one',\n },\n {\n label: 'src/api directory exists',\n ok: fs.existsSync(path.join(cwd, 'src', 'api')),\n hint: 'Create src/api/ and add route files',\n },\n {\n label: 'DATABASE_URL set',\n ok: Boolean(process.env['DATABASE_URL']),\n hint: 'Add DATABASE_URL to .env',\n },\n {\n label: 'JWT_SECRET set',\n ok: Boolean(process.env['JWT_SECRET']),\n hint: 'Add JWT_SECRET to .env (generate: openssl rand -hex 64)',\n },\n ];\n\n console.log(chalk.bold('\\n EFC Doctor\\n'));\n let allOk = true;\n for (const check of checks) {\n const icon = check.ok ? chalk.green('✓') : chalk.red('✗');\n console.log(` ${icon} ${check.label}`);\n if (!check.ok) {\n allOk = false;\n if (check.hint) console.log(chalk.dim(` → ${check.hint}`));\n }\n }\n console.log();\n if (allOk) {\n console.log(chalk.green(' All checks passed!\\n'));\n } else {\n console.log(chalk.yellow(' Some checks failed. Fix the issues above.\\n'));\n process.exit(1);\n }\n });\n}\n\nfunction resolveApiDir(): string | null {\n const cwd = process.cwd();\n const candidates = [path.join(cwd, 'src', 'api'), path.join(cwd, 'api')];\n return candidates.find((d) => fs.existsSync(d)) ?? null;\n}\n\nfunction resolveTasksDir(): string | null {\n const cwd = process.cwd();\n const candidates = [path.join(cwd, 'src', 'tasks'), path.join(cwd, 'tasks')];\n return candidates.find((d) => fs.existsSync(d)) ?? null;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/efc.js/efc.js/packages/core/dist/cli/index.cjs","../../src/cli/index.ts","../../src/cli/commands/start.ts","../../src/cli/commands/build.ts","../../src/cli/commands/run.ts","../../src/cli/commands/generate.ts","../../src/cli/commands/diagnostics.ts"],"names":["path","pc"],"mappings":"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","file":"/home/runner/work/efc.js/efc.js/packages/core/dist/cli/index.cjs","sourcesContent":[null,"#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { startCommand } from './commands/start.js';\nimport { buildCommand } from './commands/build.js';\nimport { runCommand } from './commands/run.js';\nimport { generateCommand } from './commands/generate.js';\nimport { diagnosticsCommands } from './commands/diagnostics.js';\n\nconst program = new Command('efc')\n .description('Express File Cluster CLI')\n .version('0.1.0');\n\nprogram.addCommand(startCommand());\nprogram.addCommand(buildCommand());\nprogram.addCommand(runCommand());\nprogram.addCommand(generateCommand());\n\nfor (const cmd of diagnosticsCommands()) {\n program.addCommand(cmd);\n}\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport pc from 'picocolors';\n\nexport function startCommand(): Command {\n const cmd = new Command('start');\n\n cmd\n .argument('<mode>', 'dev | prod')\n .description('Start the EFC server')\n .action((mode: string) => {\n if (mode === 'dev') {\n startDev();\n } else if (mode === 'prod') {\n startProd();\n } else {\n console.error(pc.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\nfunction parseDotenv(cwd: string): Record<string, string> {\n const envFile = path.join(cwd, '.env');\n if (!fs.existsSync(envFile)) return {};\n const vars: Record<string, string> = {};\n for (const line of fs.readFileSync(envFile, 'utf8').split('\\n')) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('#')) continue;\n const eq = trimmed.indexOf('=');\n if (eq === -1) continue;\n const key = trimmed.slice(0, eq).trim();\n const raw = trimmed.slice(eq + 1).trim();\n vars[key] = raw.replace(/^(['\"])(.*)\\1$/, '$2');\n }\n return vars;\n}\n\nfunction startDev(): void {\n const entry = resolveEntry();\n if (!entry) {\n console.error(pc.red('[EFC] Could not find entry point. Expected src/index.ts or index.ts'));\n process.exit(1);\n }\n\n console.log(pc.cyan('[EFC] Starting development server…'));\n console.log(pc.dim(` Entry: ${entry}`));\n\n const cwd = process.cwd();\n const localTsx = path.join(cwd, 'node_modules', '.bin', 'tsx');\n const tsx = fs.existsSync(localTsx) ? localTsx : 'tsx';\n\n // .env values are base; existing process.env takes precedence (same as dotenv default)\n const env: NodeJS.ProcessEnv = { ...parseDotenv(cwd), ...process.env, NODE_ENV: 'development' };\n\n const child = spawn(tsx, ['watch', '--include', 'src', entry], { stdio: 'inherit', env });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n\nfunction startProd(): void {\n const cwd = process.cwd();\n const distEntry = path.join(cwd, 'dist', 'index.js');\n\n if (!fs.existsSync(distEntry)) {\n console.error(pc.red('[EFC] dist/index.js not found. Run `efc build prod` first.'));\n process.exit(1);\n }\n\n console.log(pc.cyan('[EFC] Starting production server…'));\n\n // Production env comes exclusively from process.env — no .env file loading.\n // Platforms (Docker, Kubernetes, Railway, Heroku, etc.) inject vars directly.\n const child = spawn('node', [distEntry], {\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'production' },\n });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n\nfunction resolveEntry(): string | null {\n const cwd = process.cwd();\n const candidates = [\n path.join(cwd, 'src', 'index.ts'),\n path.join(cwd, 'index.ts'),\n path.join(cwd, 'src', 'index.js'),\n path.join(cwd, 'index.js'),\n ];\n return candidates.find((f) => fs.existsSync(f)) ?? null;\n}\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport pc from 'picocolors';\n\nexport function buildCommand(): Command {\n const cmd = new Command('build');\n\n cmd\n .argument('<mode>', 'prod')\n .description('Build the application for production')\n .action((mode: string) => {\n if (mode !== 'prod') {\n console.error(pc.red(`Unknown build mode: ${mode}. Use 'prod'.`));\n process.exit(1);\n }\n buildProd();\n });\n\n return cmd;\n}\n\nfunction buildProd(): void {\n console.log(pc.cyan('[EFC] Building for production…'));\n\n // Type-check first\n const tsc = spawn('npx', ['tsc', '--noEmit'], { stdio: 'inherit' });\n\n tsc.on('exit', (code) => {\n if (code !== 0) {\n console.error(pc.red('[EFC] TypeScript errors found. Fix them before building.'));\n process.exit(1);\n }\n\n const tsup = spawn('npx', ['tsup'], { stdio: 'inherit' });\n tsup.on('exit', (tsupCode) => {\n if (tsupCode === 0) {\n console.log(pc.green('[EFC] Build complete → dist/'));\n } else {\n process.exit(tsupCode ?? 1);\n }\n });\n });\n}\n","import { Command } from 'commander';\nimport { spawn } from 'node:child_process';\nimport pc from 'picocolors';\n\nexport function runCommand(): Command {\n const cmd = new Command('run');\n\n cmd\n .argument('<runner>', 'tests')\n .description('Run EFC sub-commands (tests)')\n .allowUnknownOption()\n .action((runner: string) => {\n if (runner === 'tests') {\n runTests(cmd.args.slice(1));\n } else {\n console.error(pc.red(`Unknown runner: ${runner}. Use 'tests'.`));\n process.exit(1);\n }\n });\n\n return cmd;\n}\n\nfunction runTests(extraArgs: string[]): void {\n console.log(pc.cyan('[EFC] Running tests via Vitest…'));\n const child = spawn('npx', ['vitest', 'run', ...extraArgs], { stdio: 'inherit' });\n child.on('exit', (code) => process.exit(code ?? 0));\n}\n","import { Command } from 'commander';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport pc from 'picocolors';\n\nexport function generateCommand(): Command {\n const cmd = new Command('generate').alias('g').description('Scaffold EFC modules');\n\n cmd\n .command('route <routePath>')\n .description('Scaffold a route module, e.g. users/[id]')\n .action((routePath: string) => generateRoute(routePath));\n\n cmd\n .command('task <name>')\n .description('Scaffold a background task module')\n .action((name: string) => generateTask(name));\n\n cmd\n .command('middleware <name>')\n .description('Scaffold a middleware module')\n .action((name: string) => generateMiddleware(name));\n\n return cmd;\n}\n\nfunction writeFile(filePath: string, content: string): void {\n const dir = path.dirname(filePath);\n fs.mkdirSync(dir, { recursive: true });\n if (fs.existsSync(filePath)) {\n console.error(pc.red(`File already exists: ${filePath}`));\n process.exit(1);\n }\n fs.writeFileSync(filePath, content, 'utf8');\n console.log(pc.green(` created ${path.relative(process.cwd(), filePath)}`));\n}\n\nfunction generateRoute(routePath: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'api', `${routePath}.ts`);\n\n const content = `import type { Request, Response } from 'express';\n\nexport const GET = async (req: Request, res: Response) => {\n res.json({ message: 'OK' });\n};\n\nexport const POST = async (req: Request, res: Response) => {\n res.status(201).json({ message: 'Created' });\n};\n`;\n\n writeFile(filePath, content);\n console.log(pc.cyan(`[EFC] Route scaffolded`));\n}\n\nfunction generateTask(name: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'tasks', `${name}.ts`);\n\n const content = `import { defineTask } from 'express-file-cluster/tasks';\n\ninterface ${name}Payload {\n // TODO: define payload fields\n}\n\nexport default defineTask<${name}Payload>(async (payload) => {\n // TODO: implement task logic\n console.log('[Task:${name}]', payload);\n});\n`;\n\n writeFile(filePath, content);\n console.log(pc.cyan(`[EFC] Task scaffolded`));\n}\n\nfunction generateMiddleware(name: string): void {\n const cwd = process.cwd();\n const filePath = path.join(cwd, 'src', 'middlewares', `${name}.ts`);\n\n const content = `import type { Request, Response, NextFunction } from 'express';\n\nexport function ${name}(req: Request, res: Response, next: NextFunction): void {\n // TODO: implement middleware logic\n next();\n}\n`;\n\n writeFile(filePath, content);\n console.log(pc.cyan(`[EFC] Middleware scaffolded`));\n}\n","import { Command } from 'commander';\nimport { scanDir } from '../../router/scan.js';\nimport path from 'node:path';\nimport fs from 'node:fs';\nimport pc from 'picocolors';\n\nexport function diagnosticsCommands(): Command[] {\n return [routesCommand(), tasksCommand(), doctorCommand()];\n}\n\nfunction routesCommand(): Command {\n return new Command('routes')\n .description('Print the resolved route table')\n .action(() => {\n const apiDir = resolveApiDir();\n if (!apiDir) {\n console.error(pc.red('[EFC] Could not find apiDir (expected src/api)'));\n process.exit(1);\n }\n\n const routes = scanDir(apiDir);\n if (routes.length === 0) {\n console.log(pc.yellow('No routes found.'));\n return;\n }\n\n console.log(pc.bold('\\n Route Table\\n'));\n console.log(pc.dim(' ' + '─'.repeat(60)));\n for (const route of routes) {\n const rel = path.relative(process.cwd(), route.filePath);\n console.log(` ${pc.cyan(route.urlPath.padEnd(35))} ${pc.dim(rel)}`);\n }\n console.log(pc.dim(' ' + '─'.repeat(60)));\n console.log(pc.dim(`\\n ${routes.length} route(s) found\\n`));\n });\n}\n\nfunction tasksCommand(): Command {\n return new Command('tasks')\n .description('List registered background tasks')\n .action(() => {\n const tasksDir = resolveTasksDir();\n if (!tasksDir || !fs.existsSync(tasksDir)) {\n console.log(pc.yellow('No tasks directory found.'));\n return;\n }\n\n const files = fs.readdirSync(tasksDir).filter((f) => /\\.(ts|js)$/.test(f));\n if (files.length === 0) {\n console.log(pc.yellow('No tasks found.'));\n return;\n }\n\n console.log(pc.bold('\\n Background Tasks\\n'));\n for (const file of files) {\n console.log(` ${pc.cyan(path.basename(file, path.extname(file)))}`);\n }\n console.log();\n });\n}\n\nfunction doctorCommand(): Command {\n return new Command('doctor')\n .description('Validate config, env vars, and project setup')\n .action(() => {\n const cwd = process.cwd();\n const checks: { label: string; ok: boolean; hint?: string }[] = [\n {\n label: 'package.json exists',\n ok: fs.existsSync(path.join(cwd, 'package.json')),\n },\n {\n label: 'tsconfig.json exists',\n ok: fs.existsSync(path.join(cwd, 'tsconfig.json')),\n hint: 'Run `tsc --init` to create one',\n },\n {\n label: 'src/api directory exists',\n ok: fs.existsSync(path.join(cwd, 'src', 'api')),\n hint: 'Create src/api/ and add route files',\n },\n {\n label: 'DATABASE_URL set',\n ok: Boolean(process.env['DATABASE_URL']),\n hint: 'Add DATABASE_URL to .env',\n },\n {\n label: 'JWT_SECRET set',\n ok: Boolean(process.env['JWT_SECRET']),\n hint: 'Add JWT_SECRET to .env (generate: openssl rand -hex 64)',\n },\n ];\n\n console.log(pc.bold('\\n EFC Doctor\\n'));\n let allOk = true;\n for (const check of checks) {\n const icon = check.ok ? pc.green('✓') : pc.red('✗');\n console.log(` ${icon} ${check.label}`);\n if (!check.ok) {\n allOk = false;\n if (check.hint) console.log(pc.dim(` → ${check.hint}`));\n }\n }\n console.log();\n if (allOk) {\n console.log(pc.green(' All checks passed!\\n'));\n } else {\n console.log(pc.yellow(' Some checks failed. Fix the issues above.\\n'));\n process.exit(1);\n }\n });\n}\n\nfunction resolveApiDir(): string | null {\n const cwd = process.cwd();\n const candidates = [path.join(cwd, 'src', 'api'), path.join(cwd, 'api')];\n return candidates.find((d) => fs.existsSync(d)) ?? null;\n}\n\nfunction resolveTasksDir(): string | null {\n const cwd = process.cwd();\n const candidates = [path.join(cwd, 'src', 'tasks'), path.join(cwd, 'tasks')];\n return candidates.find((d) => fs.existsSync(d)) ?? null;\n}\n"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import { Command } from "commander";
|
|
|
11
11
|
import { spawn } from "child_process";
|
|
12
12
|
import path from "path";
|
|
13
13
|
import fs from "fs";
|
|
14
|
-
import
|
|
14
|
+
import pc from "picocolors";
|
|
15
15
|
function startCommand() {
|
|
16
16
|
const cmd = new Command("start");
|
|
17
17
|
cmd.argument("<mode>", "dev | prod").description("Start the EFC server").action((mode) => {
|
|
@@ -20,7 +20,7 @@ function startCommand() {
|
|
|
20
20
|
} else if (mode === "prod") {
|
|
21
21
|
startProd();
|
|
22
22
|
} else {
|
|
23
|
-
console.error(
|
|
23
|
+
console.error(pc.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));
|
|
24
24
|
process.exit(1);
|
|
25
25
|
}
|
|
26
26
|
});
|
|
@@ -44,11 +44,11 @@ function parseDotenv(cwd) {
|
|
|
44
44
|
function startDev() {
|
|
45
45
|
const entry = resolveEntry();
|
|
46
46
|
if (!entry) {
|
|
47
|
-
console.error(
|
|
47
|
+
console.error(pc.red("[EFC] Could not find entry point. Expected src/index.ts or index.ts"));
|
|
48
48
|
process.exit(1);
|
|
49
49
|
}
|
|
50
|
-
console.log(
|
|
51
|
-
console.log(
|
|
50
|
+
console.log(pc.cyan("[EFC] Starting development server\u2026"));
|
|
51
|
+
console.log(pc.dim(` Entry: ${entry}`));
|
|
52
52
|
const cwd = process.cwd();
|
|
53
53
|
const localTsx = path.join(cwd, "node_modules", ".bin", "tsx");
|
|
54
54
|
const tsx = fs.existsSync(localTsx) ? localTsx : "tsx";
|
|
@@ -60,10 +60,10 @@ function startProd() {
|
|
|
60
60
|
const cwd = process.cwd();
|
|
61
61
|
const distEntry = path.join(cwd, "dist", "index.js");
|
|
62
62
|
if (!fs.existsSync(distEntry)) {
|
|
63
|
-
console.error(
|
|
63
|
+
console.error(pc.red("[EFC] dist/index.js not found. Run `efc build prod` first."));
|
|
64
64
|
process.exit(1);
|
|
65
65
|
}
|
|
66
|
-
console.log(
|
|
66
|
+
console.log(pc.cyan("[EFC] Starting production server\u2026"));
|
|
67
67
|
const child = spawn("node", [distEntry], {
|
|
68
68
|
stdio: "inherit",
|
|
69
69
|
env: { ...process.env, NODE_ENV: "production" }
|
|
@@ -84,12 +84,12 @@ function resolveEntry() {
|
|
|
84
84
|
// src/cli/commands/build.ts
|
|
85
85
|
import { Command as Command2 } from "commander";
|
|
86
86
|
import { spawn as spawn2 } from "child_process";
|
|
87
|
-
import
|
|
87
|
+
import pc2 from "picocolors";
|
|
88
88
|
function buildCommand() {
|
|
89
89
|
const cmd = new Command2("build");
|
|
90
90
|
cmd.argument("<mode>", "prod").description("Build the application for production").action((mode) => {
|
|
91
91
|
if (mode !== "prod") {
|
|
92
|
-
console.error(
|
|
92
|
+
console.error(pc2.red(`Unknown build mode: ${mode}. Use 'prod'.`));
|
|
93
93
|
process.exit(1);
|
|
94
94
|
}
|
|
95
95
|
buildProd();
|
|
@@ -97,17 +97,17 @@ function buildCommand() {
|
|
|
97
97
|
return cmd;
|
|
98
98
|
}
|
|
99
99
|
function buildProd() {
|
|
100
|
-
console.log(
|
|
100
|
+
console.log(pc2.cyan("[EFC] Building for production\u2026"));
|
|
101
101
|
const tsc = spawn2("npx", ["tsc", "--noEmit"], { stdio: "inherit" });
|
|
102
102
|
tsc.on("exit", (code) => {
|
|
103
103
|
if (code !== 0) {
|
|
104
|
-
console.error(
|
|
104
|
+
console.error(pc2.red("[EFC] TypeScript errors found. Fix them before building."));
|
|
105
105
|
process.exit(1);
|
|
106
106
|
}
|
|
107
107
|
const tsup = spawn2("npx", ["tsup"], { stdio: "inherit" });
|
|
108
108
|
tsup.on("exit", (tsupCode) => {
|
|
109
109
|
if (tsupCode === 0) {
|
|
110
|
-
console.log(
|
|
110
|
+
console.log(pc2.green("[EFC] Build complete \u2192 dist/"));
|
|
111
111
|
} else {
|
|
112
112
|
process.exit(tsupCode ?? 1);
|
|
113
113
|
}
|
|
@@ -118,21 +118,21 @@ function buildProd() {
|
|
|
118
118
|
// src/cli/commands/run.ts
|
|
119
119
|
import { Command as Command3 } from "commander";
|
|
120
120
|
import { spawn as spawn3 } from "child_process";
|
|
121
|
-
import
|
|
121
|
+
import pc3 from "picocolors";
|
|
122
122
|
function runCommand() {
|
|
123
123
|
const cmd = new Command3("run");
|
|
124
124
|
cmd.argument("<runner>", "tests").description("Run EFC sub-commands (tests)").allowUnknownOption().action((runner) => {
|
|
125
125
|
if (runner === "tests") {
|
|
126
126
|
runTests(cmd.args.slice(1));
|
|
127
127
|
} else {
|
|
128
|
-
console.error(
|
|
128
|
+
console.error(pc3.red(`Unknown runner: ${runner}. Use 'tests'.`));
|
|
129
129
|
process.exit(1);
|
|
130
130
|
}
|
|
131
131
|
});
|
|
132
132
|
return cmd;
|
|
133
133
|
}
|
|
134
134
|
function runTests(extraArgs) {
|
|
135
|
-
console.log(
|
|
135
|
+
console.log(pc3.cyan("[EFC] Running tests via Vitest\u2026"));
|
|
136
136
|
const child = spawn3("npx", ["vitest", "run", ...extraArgs], { stdio: "inherit" });
|
|
137
137
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
138
138
|
}
|
|
@@ -141,7 +141,7 @@ function runTests(extraArgs) {
|
|
|
141
141
|
import { Command as Command4 } from "commander";
|
|
142
142
|
import fs2 from "fs";
|
|
143
143
|
import path2 from "path";
|
|
144
|
-
import
|
|
144
|
+
import pc4 from "picocolors";
|
|
145
145
|
function generateCommand() {
|
|
146
146
|
const cmd = new Command4("generate").alias("g").description("Scaffold EFC modules");
|
|
147
147
|
cmd.command("route <routePath>").description("Scaffold a route module, e.g. users/[id]").action((routePath) => generateRoute(routePath));
|
|
@@ -153,11 +153,11 @@ function writeFile(filePath, content) {
|
|
|
153
153
|
const dir = path2.dirname(filePath);
|
|
154
154
|
fs2.mkdirSync(dir, { recursive: true });
|
|
155
155
|
if (fs2.existsSync(filePath)) {
|
|
156
|
-
console.error(
|
|
156
|
+
console.error(pc4.red(`File already exists: ${filePath}`));
|
|
157
157
|
process.exit(1);
|
|
158
158
|
}
|
|
159
159
|
fs2.writeFileSync(filePath, content, "utf8");
|
|
160
|
-
console.log(
|
|
160
|
+
console.log(pc4.green(` created ${path2.relative(process.cwd(), filePath)}`));
|
|
161
161
|
}
|
|
162
162
|
function generateRoute(routePath) {
|
|
163
163
|
const cwd = process.cwd();
|
|
@@ -173,7 +173,7 @@ export const POST = async (req: Request, res: Response) => {
|
|
|
173
173
|
};
|
|
174
174
|
`;
|
|
175
175
|
writeFile(filePath, content);
|
|
176
|
-
console.log(
|
|
176
|
+
console.log(pc4.cyan(`[EFC] Route scaffolded`));
|
|
177
177
|
}
|
|
178
178
|
function generateTask(name) {
|
|
179
179
|
const cwd = process.cwd();
|
|
@@ -190,7 +190,7 @@ export default defineTask<${name}Payload>(async (payload) => {
|
|
|
190
190
|
});
|
|
191
191
|
`;
|
|
192
192
|
writeFile(filePath, content);
|
|
193
|
-
console.log(
|
|
193
|
+
console.log(pc4.cyan(`[EFC] Task scaffolded`));
|
|
194
194
|
}
|
|
195
195
|
function generateMiddleware(name) {
|
|
196
196
|
const cwd = process.cwd();
|
|
@@ -203,14 +203,14 @@ export function ${name}(req: Request, res: Response, next: NextFunction): void {
|
|
|
203
203
|
}
|
|
204
204
|
`;
|
|
205
205
|
writeFile(filePath, content);
|
|
206
|
-
console.log(
|
|
206
|
+
console.log(pc4.cyan(`[EFC] Middleware scaffolded`));
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
// src/cli/commands/diagnostics.ts
|
|
210
210
|
import { Command as Command5 } from "commander";
|
|
211
211
|
import path3 from "path";
|
|
212
212
|
import fs3 from "fs";
|
|
213
|
-
import
|
|
213
|
+
import pc5 from "picocolors";
|
|
214
214
|
function diagnosticsCommands() {
|
|
215
215
|
return [routesCommand(), tasksCommand(), doctorCommand()];
|
|
216
216
|
}
|
|
@@ -218,22 +218,22 @@ function routesCommand() {
|
|
|
218
218
|
return new Command5("routes").description("Print the resolved route table").action(() => {
|
|
219
219
|
const apiDir = resolveApiDir();
|
|
220
220
|
if (!apiDir) {
|
|
221
|
-
console.error(
|
|
221
|
+
console.error(pc5.red("[EFC] Could not find apiDir (expected src/api)"));
|
|
222
222
|
process.exit(1);
|
|
223
223
|
}
|
|
224
224
|
const routes = scanDir(apiDir);
|
|
225
225
|
if (routes.length === 0) {
|
|
226
|
-
console.log(
|
|
226
|
+
console.log(pc5.yellow("No routes found."));
|
|
227
227
|
return;
|
|
228
228
|
}
|
|
229
|
-
console.log(
|
|
230
|
-
console.log(
|
|
229
|
+
console.log(pc5.bold("\n Route Table\n"));
|
|
230
|
+
console.log(pc5.dim(" " + "\u2500".repeat(60)));
|
|
231
231
|
for (const route of routes) {
|
|
232
232
|
const rel = path3.relative(process.cwd(), route.filePath);
|
|
233
|
-
console.log(` ${
|
|
233
|
+
console.log(` ${pc5.cyan(route.urlPath.padEnd(35))} ${pc5.dim(rel)}`);
|
|
234
234
|
}
|
|
235
|
-
console.log(
|
|
236
|
-
console.log(
|
|
235
|
+
console.log(pc5.dim(" " + "\u2500".repeat(60)));
|
|
236
|
+
console.log(pc5.dim(`
|
|
237
237
|
${routes.length} route(s) found
|
|
238
238
|
`));
|
|
239
239
|
});
|
|
@@ -242,17 +242,17 @@ function tasksCommand() {
|
|
|
242
242
|
return new Command5("tasks").description("List registered background tasks").action(() => {
|
|
243
243
|
const tasksDir = resolveTasksDir();
|
|
244
244
|
if (!tasksDir || !fs3.existsSync(tasksDir)) {
|
|
245
|
-
console.log(
|
|
245
|
+
console.log(pc5.yellow("No tasks directory found."));
|
|
246
246
|
return;
|
|
247
247
|
}
|
|
248
248
|
const files = fs3.readdirSync(tasksDir).filter((f) => /\.(ts|js)$/.test(f));
|
|
249
249
|
if (files.length === 0) {
|
|
250
|
-
console.log(
|
|
250
|
+
console.log(pc5.yellow("No tasks found."));
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
-
console.log(
|
|
253
|
+
console.log(pc5.bold("\n Background Tasks\n"));
|
|
254
254
|
for (const file of files) {
|
|
255
|
-
console.log(` ${
|
|
255
|
+
console.log(` ${pc5.cyan(path3.basename(file, path3.extname(file)))}`);
|
|
256
256
|
}
|
|
257
257
|
console.log();
|
|
258
258
|
});
|
|
@@ -286,21 +286,21 @@ function doctorCommand() {
|
|
|
286
286
|
hint: "Add JWT_SECRET to .env (generate: openssl rand -hex 64)"
|
|
287
287
|
}
|
|
288
288
|
];
|
|
289
|
-
console.log(
|
|
289
|
+
console.log(pc5.bold("\n EFC Doctor\n"));
|
|
290
290
|
let allOk = true;
|
|
291
291
|
for (const check of checks) {
|
|
292
|
-
const icon = check.ok ?
|
|
292
|
+
const icon = check.ok ? pc5.green("\u2713") : pc5.red("\u2717");
|
|
293
293
|
console.log(` ${icon} ${check.label}`);
|
|
294
294
|
if (!check.ok) {
|
|
295
295
|
allOk = false;
|
|
296
|
-
if (check.hint) console.log(
|
|
296
|
+
if (check.hint) console.log(pc5.dim(` \u2192 ${check.hint}`));
|
|
297
297
|
}
|
|
298
298
|
}
|
|
299
299
|
console.log();
|
|
300
300
|
if (allOk) {
|
|
301
|
-
console.log(
|
|
301
|
+
console.log(pc5.green(" All checks passed!\n"));
|
|
302
302
|
} else {
|
|
303
|
-
console.log(
|
|
303
|
+
console.log(pc5.yellow(" Some checks failed. Fix the issues above.\n"));
|
|
304
304
|
process.exit(1);
|
|
305
305
|
}
|
|
306
306
|
});
|