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.
@@ -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 _chalk = require('chalk'); var _chalk2 = _interopRequireDefault(_chalk);
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(_chalk2.default.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));
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(_chalk2.default.red("[EFC] Could not find entry point. Expected src/index.ts or index.ts"));
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(_chalk2.default.cyan("[EFC] Starting development server\u2026"));
51
- console.log(_chalk2.default.dim(` Entry: ${entry}`));
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(_chalk2.default.red("[EFC] dist/index.js not found. Run `efc build prod` first."));
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(_chalk2.default.cyan("[EFC] Starting production server\u2026"));
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(_chalk2.default.red(`Unknown build mode: ${mode}. Use 'prod'.`));
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(_chalk2.default.cyan("[EFC] Building for production\u2026"));
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(_chalk2.default.red("[EFC] TypeScript errors found. Fix them before building."));
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(_chalk2.default.green("[EFC] Build complete \u2192 dist/"));
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(_chalk2.default.red(`Unknown runner: ${runner}. Use 'tests'.`));
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(_chalk2.default.cyan("[EFC] Running tests via Vitest\u2026"));
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(_chalk2.default.red(`File already exists: ${filePath}`));
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(_chalk2.default.green(` created ${_path2.default.relative(process.cwd(), filePath)}`));
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(_chalk2.default.cyan(`[EFC] Route scaffolded`));
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(_chalk2.default.cyan(`[EFC] Task scaffolded`));
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(_chalk2.default.cyan(`[EFC] Middleware scaffolded`));
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(_chalk2.default.red("[EFC] Could not find apiDir (expected src/api)"));
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(_chalk2.default.yellow("No routes found."));
226
+ console.log(_picocolors2.default.yellow("No routes found."));
227
227
  return;
228
228
  }
229
- console.log(_chalk2.default.bold("\n Route Table\n"));
230
- console.log(_chalk2.default.dim(" " + "\u2500".repeat(60)));
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(` ${_chalk2.default.cyan(route.urlPath.padEnd(35))} ${_chalk2.default.dim(rel)}`);
233
+ console.log(` ${_picocolors2.default.cyan(route.urlPath.padEnd(35))} ${_picocolors2.default.dim(rel)}`);
234
234
  }
235
- console.log(_chalk2.default.dim(" " + "\u2500".repeat(60)));
236
- console.log(_chalk2.default.dim(`
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(_chalk2.default.yellow("No tasks directory found."));
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(_chalk2.default.yellow("No tasks found."));
250
+ console.log(_picocolors2.default.yellow("No tasks found."));
251
251
  return;
252
252
  }
253
- console.log(_chalk2.default.bold("\n Background Tasks\n"));
253
+ console.log(_picocolors2.default.bold("\n Background Tasks\n"));
254
254
  for (const file of files) {
255
- console.log(` ${_chalk2.default.cyan(_path2.default.basename(file, _path2.default.extname(file)))}`);
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(_chalk2.default.bold("\n EFC Doctor\n"));
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 ? _chalk2.default.green("\u2713") : _chalk2.default.red("\u2717");
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(_chalk2.default.dim(` \u2192 ${check.hint}`));
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(_chalk2.default.green(" All checks passed!\n"));
301
+ console.log(_picocolors2.default.green(" All checks passed!\n"));
302
302
  } else {
303
- console.log(_chalk2.default.yellow(" Some checks failed. Fix the issues above.\n"));
303
+ console.log(_picocolors2.default.yellow(" Some checks failed. Fix the issues above.\n"));
304
304
  process.exit(1);
305
305
  }
306
306
  });
@@ -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 chalk from "chalk";
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(chalk.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));
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(chalk.red("[EFC] Could not find entry point. Expected src/index.ts or index.ts"));
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(chalk.cyan("[EFC] Starting development server\u2026"));
51
- console.log(chalk.dim(` Entry: ${entry}`));
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(chalk.red("[EFC] dist/index.js not found. Run `efc build prod` first."));
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(chalk.cyan("[EFC] Starting production server\u2026"));
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 chalk2 from "chalk";
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(chalk2.red(`Unknown build mode: ${mode}. Use 'prod'.`));
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(chalk2.cyan("[EFC] Building for production\u2026"));
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(chalk2.red("[EFC] TypeScript errors found. Fix them before building."));
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(chalk2.green("[EFC] Build complete \u2192 dist/"));
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 chalk3 from "chalk";
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(chalk3.red(`Unknown runner: ${runner}. Use 'tests'.`));
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(chalk3.cyan("[EFC] Running tests via Vitest\u2026"));
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 chalk4 from "chalk";
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(chalk4.red(`File already exists: ${filePath}`));
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(chalk4.green(` created ${path2.relative(process.cwd(), filePath)}`));
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(chalk4.cyan(`[EFC] Route scaffolded`));
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(chalk4.cyan(`[EFC] Task scaffolded`));
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(chalk4.cyan(`[EFC] Middleware scaffolded`));
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 chalk5 from "chalk";
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(chalk5.red("[EFC] Could not find apiDir (expected src/api)"));
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(chalk5.yellow("No routes found."));
226
+ console.log(pc5.yellow("No routes found."));
227
227
  return;
228
228
  }
229
- console.log(chalk5.bold("\n Route Table\n"));
230
- console.log(chalk5.dim(" " + "\u2500".repeat(60)));
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(` ${chalk5.cyan(route.urlPath.padEnd(35))} ${chalk5.dim(rel)}`);
233
+ console.log(` ${pc5.cyan(route.urlPath.padEnd(35))} ${pc5.dim(rel)}`);
234
234
  }
235
- console.log(chalk5.dim(" " + "\u2500".repeat(60)));
236
- console.log(chalk5.dim(`
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(chalk5.yellow("No tasks directory found."));
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(chalk5.yellow("No tasks found."));
250
+ console.log(pc5.yellow("No tasks found."));
251
251
  return;
252
252
  }
253
- console.log(chalk5.bold("\n Background Tasks\n"));
253
+ console.log(pc5.bold("\n Background Tasks\n"));
254
254
  for (const file of files) {
255
- console.log(` ${chalk5.cyan(path3.basename(file, path3.extname(file)))}`);
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(chalk5.bold("\n EFC Doctor\n"));
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 ? chalk5.green("\u2713") : chalk5.red("\u2717");
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(chalk5.dim(` \u2192 ${check.hint}`));
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(chalk5.green(" All checks passed!\n"));
301
+ console.log(pc5.green(" All checks passed!\n"));
302
302
  } else {
303
- console.log(chalk5.yellow(" Some checks failed. Fix the issues above.\n"));
303
+ console.log(pc5.yellow(" Some checks failed. Fix the issues above.\n"));
304
304
  process.exit(1);
305
305
  }
306
306
  });