express-file-cluster 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.cjs +19 -11
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +19 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +31 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +31 -22
- package/dist/index.js.map +1 -1
- package/package.json +3 -1
- package/src/cli/commands/start.ts +21 -11
- package/src/ignite.test.ts +193 -0
- package/src/index.ts +26 -15
package/dist/cli/index.cjs
CHANGED
|
@@ -46,9 +46,20 @@ function startCommand() {
|
|
|
46
46
|
});
|
|
47
47
|
return cmd;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function parseDotenv(cwd) {
|
|
50
50
|
const envFile = import_node_path.default.join(cwd, ".env");
|
|
51
|
-
|
|
51
|
+
if (!import_node_fs.default.existsSync(envFile)) return {};
|
|
52
|
+
const vars = {};
|
|
53
|
+
for (const line of import_node_fs.default.readFileSync(envFile, "utf8").split("\n")) {
|
|
54
|
+
const trimmed = line.trim();
|
|
55
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
56
|
+
const eq = trimmed.indexOf("=");
|
|
57
|
+
if (eq === -1) continue;
|
|
58
|
+
const key = trimmed.slice(0, eq).trim();
|
|
59
|
+
const raw = trimmed.slice(eq + 1).trim();
|
|
60
|
+
vars[key] = raw.replace(/^(['"])(.*)\1$/, "$2");
|
|
61
|
+
}
|
|
62
|
+
return vars;
|
|
52
63
|
}
|
|
53
64
|
function startDev() {
|
|
54
65
|
const entry = resolveEntry();
|
|
@@ -59,11 +70,10 @@ function startDev() {
|
|
|
59
70
|
console.log(import_chalk.default.cyan("[EFC] Starting development server\u2026"));
|
|
60
71
|
console.log(import_chalk.default.dim(` Entry: ${entry}`));
|
|
61
72
|
const cwd = process.cwd();
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
);
|
|
73
|
+
const localTsx = import_node_path.default.join(cwd, "node_modules", ".bin", "tsx");
|
|
74
|
+
const tsx = import_node_fs.default.existsSync(localTsx) ? localTsx : "tsx";
|
|
75
|
+
const env = { ...parseDotenv(cwd), ...process.env, NODE_ENV: "development" };
|
|
76
|
+
const child = (0, import_node_child_process.spawn)(tsx, ["watch", entry], { stdio: "inherit", env });
|
|
67
77
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
68
78
|
}
|
|
69
79
|
function startProd() {
|
|
@@ -74,10 +84,8 @@ function startProd() {
|
|
|
74
84
|
process.exit(1);
|
|
75
85
|
}
|
|
76
86
|
console.log(import_chalk.default.cyan("[EFC] Starting production server\u2026"));
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
env: { ...process.env, NODE_ENV: "production" }
|
|
80
|
-
});
|
|
87
|
+
const env = { ...parseDotenv(cwd), ...process.env, NODE_ENV: "production" };
|
|
88
|
+
const child = (0, import_node_child_process.spawn)("node", [distEntry], { stdio: "inherit", env });
|
|
81
89
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
82
90
|
}
|
|
83
91
|
function resolveEntry() {
|
package/dist/cli/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../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","../../src/router/scan.ts"],"sourcesContent":["#!/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 buildEnvFileArgs(cwd: string): string[] {\n const envFile = path.join(cwd, '.env');\n return fs.existsSync(envFile) ? ['--env-file', envFile] : [];\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 child = spawn(\n 'node',\n [...buildEnvFileArgs(cwd), '--import', 'tsx/esm', '--watch', entry],\n { stdio: 'inherit', env: { ...process.env, NODE_ENV: 'development' } },\n );\n\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 const child = spawn('node', [...buildEnvFileArgs(cwd), distEntry], {\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'production' },\n });\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","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { RouteEntry } from '../types.js';\n\nconst ROUTE_FILE_RE = /\\.(ts|js|mts|mjs|cts|cjs)$/;\nconst DYNAMIC_SEGMENT_RE = /\\[([^\\]]+)\\]/g;\n\nfunction filePathToUrlPath(relativePath: string): string {\n let p = relativePath.replace(ROUTE_FILE_RE, '');\n // index files map to parent path\n p = p.replace(/\\/index$/, '');\n // [param] → :param\n p = p.replace(DYNAMIC_SEGMENT_RE, ':$1');\n return p === '' ? '/' : p.startsWith('/') ? p : `/${p}`;\n}\n\nfunction extractParams(relativePath: string): string[] {\n const params: string[] = [];\n let match: RegExpExecArray | null;\n const re = new RegExp(DYNAMIC_SEGMENT_RE.source, 'g');\n while ((match = re.exec(relativePath)) !== null) {\n if (match[1]) params.push(match[1]);\n }\n return params;\n}\n\nexport function scanDir(dir: string, base: string = dir): RouteEntry[] {\n if (!fs.existsSync(dir)) return [];\n\n const entries: RouteEntry[] = [];\n const items = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n if (item.isDirectory()) {\n entries.push(...scanDir(fullPath, base));\n } else if (ROUTE_FILE_RE.test(item.name)) {\n const relative = '/' + path.relative(base, fullPath).replace(/\\\\/g, '/');\n entries.push({\n urlPath: filePathToUrlPath(relative),\n filePath: fullPath,\n params: extractParams(relative),\n });\n }\n }\n\n // Sort: static routes before dynamic ones at each segment level\n return entries.sort((a, b) => {\n const aDynamic = a.urlPath.includes(':') ? 1 : 0;\n const bDynamic = b.urlPath.includes(':') ? 1 : 0;\n return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);\n });\n}\n\nexport { filePathToUrlPath };\n"],"mappings":"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","names":["import_commander","chalk","path","fs","import_commander","import_node_child_process","import_chalk","chalk","import_commander","import_node_child_process","import_chalk","chalk","import_commander","import_node_fs","import_node_path","import_chalk","path","fs","chalk","import_commander","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_chalk","chalk","path","fs"]}
|
|
1
|
+
{"version":3,"sources":["../../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","../../src/router/scan.ts"],"sourcesContent":["#!/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', 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 const env: NodeJS.ProcessEnv = { ...parseDotenv(cwd), ...process.env, NODE_ENV: 'production' };\n\n const child = spawn('node', [distEntry], { stdio: 'inherit', env });\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","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { RouteEntry } from '../types.js';\n\nconst ROUTE_FILE_RE = /\\.(ts|js|mts|mjs|cts|cjs)$/;\nconst DYNAMIC_SEGMENT_RE = /\\[([^\\]]+)\\]/g;\n\nfunction filePathToUrlPath(relativePath: string): string {\n let p = relativePath.replace(ROUTE_FILE_RE, '');\n // index files map to parent path\n p = p.replace(/\\/index$/, '');\n // [param] → :param\n p = p.replace(DYNAMIC_SEGMENT_RE, ':$1');\n return p === '' ? '/' : p.startsWith('/') ? p : `/${p}`;\n}\n\nfunction extractParams(relativePath: string): string[] {\n const params: string[] = [];\n let match: RegExpExecArray | null;\n const re = new RegExp(DYNAMIC_SEGMENT_RE.source, 'g');\n while ((match = re.exec(relativePath)) !== null) {\n if (match[1]) params.push(match[1]);\n }\n return params;\n}\n\nexport function scanDir(dir: string, base: string = dir): RouteEntry[] {\n if (!fs.existsSync(dir)) return [];\n\n const entries: RouteEntry[] = [];\n const items = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n if (item.isDirectory()) {\n entries.push(...scanDir(fullPath, base));\n } else if (ROUTE_FILE_RE.test(item.name)) {\n const relative = '/' + path.relative(base, fullPath).replace(/\\\\/g, '/');\n entries.push({\n urlPath: filePathToUrlPath(relative),\n filePath: fullPath,\n params: extractParams(relative),\n });\n }\n }\n\n // Sort: static routes before dynamic ones at each segment level\n return entries.sort((a, b) => {\n const aDynamic = a.urlPath.includes(':') ? 1 : 0;\n const bDynamic = b.urlPath.includes(':') ? 1 : 0;\n return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);\n });\n}\n\nexport { filePathToUrlPath };\n"],"mappings":"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","names":["import_commander","chalk","path","fs","import_commander","import_node_child_process","import_chalk","chalk","import_commander","import_node_child_process","import_chalk","chalk","import_commander","import_node_fs","import_node_path","import_chalk","path","fs","chalk","import_commander","import_node_fs","import_node_path","fs","path","import_node_path","import_node_fs","import_chalk","chalk","path","fs"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -23,9 +23,20 @@ function startCommand() {
|
|
|
23
23
|
});
|
|
24
24
|
return cmd;
|
|
25
25
|
}
|
|
26
|
-
function
|
|
26
|
+
function parseDotenv(cwd) {
|
|
27
27
|
const envFile = path.join(cwd, ".env");
|
|
28
|
-
|
|
28
|
+
if (!fs.existsSync(envFile)) return {};
|
|
29
|
+
const vars = {};
|
|
30
|
+
for (const line of fs.readFileSync(envFile, "utf8").split("\n")) {
|
|
31
|
+
const trimmed = line.trim();
|
|
32
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
33
|
+
const eq = trimmed.indexOf("=");
|
|
34
|
+
if (eq === -1) continue;
|
|
35
|
+
const key = trimmed.slice(0, eq).trim();
|
|
36
|
+
const raw = trimmed.slice(eq + 1).trim();
|
|
37
|
+
vars[key] = raw.replace(/^(['"])(.*)\1$/, "$2");
|
|
38
|
+
}
|
|
39
|
+
return vars;
|
|
29
40
|
}
|
|
30
41
|
function startDev() {
|
|
31
42
|
const entry = resolveEntry();
|
|
@@ -36,11 +47,10 @@ function startDev() {
|
|
|
36
47
|
console.log(chalk.cyan("[EFC] Starting development server\u2026"));
|
|
37
48
|
console.log(chalk.dim(` Entry: ${entry}`));
|
|
38
49
|
const cwd = process.cwd();
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
);
|
|
50
|
+
const localTsx = path.join(cwd, "node_modules", ".bin", "tsx");
|
|
51
|
+
const tsx = fs.existsSync(localTsx) ? localTsx : "tsx";
|
|
52
|
+
const env = { ...parseDotenv(cwd), ...process.env, NODE_ENV: "development" };
|
|
53
|
+
const child = spawn(tsx, ["watch", entry], { stdio: "inherit", env });
|
|
44
54
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
45
55
|
}
|
|
46
56
|
function startProd() {
|
|
@@ -51,10 +61,8 @@ function startProd() {
|
|
|
51
61
|
process.exit(1);
|
|
52
62
|
}
|
|
53
63
|
console.log(chalk.cyan("[EFC] Starting production server\u2026"));
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
env: { ...process.env, NODE_ENV: "production" }
|
|
57
|
-
});
|
|
64
|
+
const env = { ...parseDotenv(cwd), ...process.env, NODE_ENV: "production" };
|
|
65
|
+
const child = spawn("node", [distEntry], { stdio: "inherit", env });
|
|
58
66
|
child.on("exit", (code) => process.exit(code ?? 0));
|
|
59
67
|
}
|
|
60
68
|
function resolveEntry() {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../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","../../src/router/scan.ts"],"sourcesContent":["#!/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 buildEnvFileArgs(cwd: string): string[] {\n const envFile = path.join(cwd, '.env');\n return fs.existsSync(envFile) ? ['--env-file', envFile] : [];\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 child = spawn(\n 'node',\n [...buildEnvFileArgs(cwd), '--import', 'tsx/esm', '--watch', entry],\n { stdio: 'inherit', env: { ...process.env, NODE_ENV: 'development' } },\n );\n\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 const child = spawn('node', [...buildEnvFileArgs(cwd), distEntry], {\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'production' },\n });\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","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { RouteEntry } from '../types.js';\n\nconst ROUTE_FILE_RE = /\\.(ts|js|mts|mjs|cts|cjs)$/;\nconst DYNAMIC_SEGMENT_RE = /\\[([^\\]]+)\\]/g;\n\nfunction filePathToUrlPath(relativePath: string): string {\n let p = relativePath.replace(ROUTE_FILE_RE, '');\n // index files map to parent path\n p = p.replace(/\\/index$/, '');\n // [param] → :param\n p = p.replace(DYNAMIC_SEGMENT_RE, ':$1');\n return p === '' ? '/' : p.startsWith('/') ? p : `/${p}`;\n}\n\nfunction extractParams(relativePath: string): string[] {\n const params: string[] = [];\n let match: RegExpExecArray | null;\n const re = new RegExp(DYNAMIC_SEGMENT_RE.source, 'g');\n while ((match = re.exec(relativePath)) !== null) {\n if (match[1]) params.push(match[1]);\n }\n return params;\n}\n\nexport function scanDir(dir: string, base: string = dir): RouteEntry[] {\n if (!fs.existsSync(dir)) return [];\n\n const entries: RouteEntry[] = [];\n const items = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n if (item.isDirectory()) {\n entries.push(...scanDir(fullPath, base));\n } else if (ROUTE_FILE_RE.test(item.name)) {\n const relative = '/' + path.relative(base, fullPath).replace(/\\\\/g, '/');\n entries.push({\n urlPath: filePathToUrlPath(relative),\n filePath: fullPath,\n params: extractParams(relative),\n });\n }\n }\n\n // Sort: static routes before dynamic ones at each segment level\n return entries.sort((a, b) => {\n const aDynamic = a.urlPath.includes(':') ? 1 : 0;\n const bDynamic = b.urlPath.includes(':') ? 1 : 0;\n return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);\n });\n}\n\nexport { filePathToUrlPath };\n"],"mappings":"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","names":["Command","Command","spawn","chalk","Command","spawn","chalk","Command","fs","path","chalk","Command","fs","path","path","fs","chalk","Command","Command"]}
|
|
1
|
+
{"version":3,"sources":["../../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","../../src/router/scan.ts"],"sourcesContent":["#!/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', 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 const env: NodeJS.ProcessEnv = { ...parseDotenv(cwd), ...process.env, NODE_ENV: 'production' };\n\n const child = spawn('node', [distEntry], { stdio: 'inherit', env });\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","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { RouteEntry } from '../types.js';\n\nconst ROUTE_FILE_RE = /\\.(ts|js|mts|mjs|cts|cjs)$/;\nconst DYNAMIC_SEGMENT_RE = /\\[([^\\]]+)\\]/g;\n\nfunction filePathToUrlPath(relativePath: string): string {\n let p = relativePath.replace(ROUTE_FILE_RE, '');\n // index files map to parent path\n p = p.replace(/\\/index$/, '');\n // [param] → :param\n p = p.replace(DYNAMIC_SEGMENT_RE, ':$1');\n return p === '' ? '/' : p.startsWith('/') ? p : `/${p}`;\n}\n\nfunction extractParams(relativePath: string): string[] {\n const params: string[] = [];\n let match: RegExpExecArray | null;\n const re = new RegExp(DYNAMIC_SEGMENT_RE.source, 'g');\n while ((match = re.exec(relativePath)) !== null) {\n if (match[1]) params.push(match[1]);\n }\n return params;\n}\n\nexport function scanDir(dir: string, base: string = dir): RouteEntry[] {\n if (!fs.existsSync(dir)) return [];\n\n const entries: RouteEntry[] = [];\n const items = fs.readdirSync(dir, { withFileTypes: true });\n\n for (const item of items) {\n const fullPath = path.join(dir, item.name);\n if (item.isDirectory()) {\n entries.push(...scanDir(fullPath, base));\n } else if (ROUTE_FILE_RE.test(item.name)) {\n const relative = '/' + path.relative(base, fullPath).replace(/\\\\/g, '/');\n entries.push({\n urlPath: filePathToUrlPath(relative),\n filePath: fullPath,\n params: extractParams(relative),\n });\n }\n }\n\n // Sort: static routes before dynamic ones at each segment level\n return entries.sort((a, b) => {\n const aDynamic = a.urlPath.includes(':') ? 1 : 0;\n const bDynamic = b.urlPath.includes(':') ? 1 : 0;\n return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);\n });\n}\n\nexport { filePathToUrlPath };\n"],"mappings":"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","names":["Command","Command","spawn","chalk","Command","spawn","chalk","Command","fs","path","chalk","Command","fs","path","path","fs","chalk","Command","Command"]}
|
package/dist/index.cjs
CHANGED
|
@@ -156,17 +156,6 @@ function configureAuth(config) {
|
|
|
156
156
|
_config = config;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
// src/errors.ts
|
|
160
|
-
var HttpError = class _HttpError extends Error {
|
|
161
|
-
statusCode;
|
|
162
|
-
constructor(statusCode, message) {
|
|
163
|
-
super(message);
|
|
164
|
-
this.name = "HttpError";
|
|
165
|
-
this.statusCode = statusCode;
|
|
166
|
-
Error.captureStackTrace(this, _HttpError);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
|
|
170
159
|
// src/db/mongo.ts
|
|
171
160
|
var mongoose;
|
|
172
161
|
async function loadMongoose() {
|
|
@@ -428,6 +417,17 @@ function parseRedisUrl(url) {
|
|
|
428
417
|
}
|
|
429
418
|
}
|
|
430
419
|
|
|
420
|
+
// src/errors.ts
|
|
421
|
+
var HttpError = class _HttpError extends Error {
|
|
422
|
+
statusCode;
|
|
423
|
+
constructor(statusCode, message) {
|
|
424
|
+
super(message);
|
|
425
|
+
this.name = "HttpError";
|
|
426
|
+
this.statusCode = statusCode;
|
|
427
|
+
Error.captureStackTrace(this, _HttpError);
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
|
|
431
431
|
// src/compose.ts
|
|
432
432
|
function compose(...handlers) {
|
|
433
433
|
return (req, res, next) => {
|
|
@@ -453,20 +453,28 @@ function compose(...handlers) {
|
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
// src/index.ts
|
|
456
|
+
function detectDatabase(url) {
|
|
457
|
+
if (!url) return void 0;
|
|
458
|
+
if (url.startsWith("mongodb")) return "mongodb";
|
|
459
|
+
if (url.startsWith("postgres")) return "postgresql";
|
|
460
|
+
return void 0;
|
|
461
|
+
}
|
|
456
462
|
async function ignite(config) {
|
|
457
463
|
const {
|
|
458
464
|
port: _port,
|
|
459
|
-
cluster: clusterEnabled = true,
|
|
460
465
|
workers,
|
|
461
466
|
apiDir,
|
|
462
|
-
jwtSecret,
|
|
463
|
-
authStrategy = "http-only",
|
|
464
467
|
globalMiddlewares = [],
|
|
465
468
|
onWorkerReady,
|
|
466
469
|
onWorkerCrash,
|
|
467
470
|
onError
|
|
468
471
|
} = config;
|
|
469
472
|
const port = _port != null && !Number.isNaN(_port) ? _port : Number(process.env["PORT"]) || 3e3;
|
|
473
|
+
const databaseUrl = config.databaseUrl ?? process.env["DATABASE_URL"];
|
|
474
|
+
const database = config.database ?? detectDatabase(databaseUrl);
|
|
475
|
+
const jwtSecret = config.jwtSecret ?? process.env["JWT_SECRET"];
|
|
476
|
+
const authStrategy = config.authStrategy ?? "http-only";
|
|
477
|
+
const clusterEnabled = config.cluster ?? process.env["NODE_ENV"] === "production";
|
|
470
478
|
if (clusterEnabled && import_node_cluster2.default.isPrimary) {
|
|
471
479
|
runMaster({
|
|
472
480
|
workers: workers ?? import_node_os2.default.cpus().length,
|
|
@@ -482,7 +490,7 @@ async function ignite(config) {
|
|
|
482
490
|
let origin;
|
|
483
491
|
if (envOrigins) {
|
|
484
492
|
const list = envOrigins.split(",").map((o) => o.trim()).filter(Boolean);
|
|
485
|
-
origin = list
|
|
493
|
+
origin = list;
|
|
486
494
|
} else if (typeof corsOption === "object" && corsOption.origin !== void 0) {
|
|
487
495
|
origin = corsOption.origin;
|
|
488
496
|
} else {
|
|
@@ -497,8 +505,8 @@ async function ignite(config) {
|
|
|
497
505
|
for (const mw of globalMiddlewares) {
|
|
498
506
|
app.use(mw);
|
|
499
507
|
}
|
|
500
|
-
if (
|
|
501
|
-
const conn = await connectMongo(
|
|
508
|
+
if (database === "mongodb" && databaseUrl) {
|
|
509
|
+
const conn = await connectMongo(databaseUrl);
|
|
502
510
|
setDbClient(conn);
|
|
503
511
|
}
|
|
504
512
|
if (jwtSecret) {
|
|
@@ -528,8 +536,9 @@ async function ignite(config) {
|
|
|
528
536
|
} else {
|
|
529
537
|
app.use(
|
|
530
538
|
(err, _req, res, _next) => {
|
|
531
|
-
|
|
532
|
-
|
|
539
|
+
const asHttp = err instanceof Error && "statusCode" in err ? err : null;
|
|
540
|
+
if (asHttp) {
|
|
541
|
+
res.status(asHttp.statusCode).json({ error: asHttp.message, statusCode: asHttp.statusCode });
|
|
533
542
|
} else {
|
|
534
543
|
console.error("[EFC] Unhandled error:", err);
|
|
535
544
|
res.status(500).json({ error: "Internal Server Error", statusCode: 500 });
|
|
@@ -537,11 +546,11 @@ async function ignite(config) {
|
|
|
537
546
|
}
|
|
538
547
|
);
|
|
539
548
|
}
|
|
540
|
-
|
|
541
|
-
app.listen(port, () => {
|
|
549
|
+
return new Promise((resolve) => {
|
|
550
|
+
const server = app.listen(port, () => {
|
|
542
551
|
const wid = import_node_cluster2.default.worker?.id ?? "primary";
|
|
543
552
|
console.log(`[EFC] Worker ${wid} listening on :${port}`);
|
|
544
|
-
resolve();
|
|
553
|
+
resolve(server);
|
|
545
554
|
});
|
|
546
555
|
});
|
|
547
556
|
}
|