express-file-cluster 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/auth/index.cjs +98 -0
  2. package/dist/auth/index.cjs.map +1 -0
  3. package/dist/auth/index.d.cts +16 -0
  4. package/dist/auth/index.d.ts +16 -0
  5. package/dist/auth/index.js +59 -0
  6. package/dist/auth/index.js.map +1 -0
  7. package/dist/cli/index.cjs +380 -0
  8. package/dist/cli/index.cjs.map +1 -0
  9. package/dist/cli/index.d.cts +1 -0
  10. package/dist/cli/index.d.ts +1 -0
  11. package/dist/cli/index.js +357 -0
  12. package/dist/cli/index.js.map +1 -0
  13. package/dist/index.cjs +541 -0
  14. package/dist/index.cjs.map +1 -0
  15. package/dist/index.d.cts +23 -0
  16. package/dist/index.d.ts +23 -0
  17. package/dist/index.js +498 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/tasks/index.cjs +70 -0
  20. package/dist/tasks/index.cjs.map +1 -0
  21. package/dist/tasks/index.d.cts +16 -0
  22. package/dist/tasks/index.d.ts +16 -0
  23. package/dist/tasks/index.js +41 -0
  24. package/dist/tasks/index.js.map +1 -0
  25. package/dist/types-DNdkDUPX.d.cts +70 -0
  26. package/dist/types-DNdkDUPX.d.ts +70 -0
  27. package/package.json +69 -0
  28. package/src/auth/index.ts +71 -0
  29. package/src/cli/commands/build.ts +43 -0
  30. package/src/cli/commands/diagnostics.ts +124 -0
  31. package/src/cli/commands/generate.ts +91 -0
  32. package/src/cli/commands/run.ts +28 -0
  33. package/src/cli/commands/start.ts +74 -0
  34. package/src/cli/index.ts +22 -0
  35. package/src/cluster/index.ts +31 -0
  36. package/src/compose.ts +26 -0
  37. package/src/db/index.ts +31 -0
  38. package/src/db/model.ts +95 -0
  39. package/src/db/mongo.ts +22 -0
  40. package/src/errors.ts +10 -0
  41. package/src/index.ts +127 -0
  42. package/src/router/mount.test.ts +75 -0
  43. package/src/router/mount.ts +49 -0
  44. package/src/router/scan.test.ts +23 -0
  45. package/src/router/scan.ts +55 -0
  46. package/src/tasks/bullmq-backend.ts +76 -0
  47. package/src/tasks/index.ts +51 -0
  48. package/src/tasks/scanner.test.ts +58 -0
  49. package/src/tasks/scanner.ts +30 -0
  50. package/src/tasks/thread-runner.ts +40 -0
  51. package/src/types.ts +68 -0
  52. package/tsconfig.json +9 -0
  53. package/tsup.config.ts +26 -0
@@ -0,0 +1,98 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/auth/index.ts
31
+ var auth_exports = {};
32
+ __export(auth_exports, {
33
+ configureAuth: () => configureAuth,
34
+ issueToken: () => issueToken,
35
+ requireAuth: () => requireAuth,
36
+ revokeToken: () => revokeToken,
37
+ signToken: () => signToken
38
+ });
39
+ module.exports = __toCommonJS(auth_exports);
40
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
41
+ var _config = null;
42
+ function configureAuth(config) {
43
+ _config = config;
44
+ }
45
+ function getConfig() {
46
+ if (!_config) throw new Error("[EFC] Auth not configured \u2014 pass jwtSecret to ignite()");
47
+ return _config;
48
+ }
49
+ function issueToken(res, payload) {
50
+ const { secret, expiresIn, cookieDomain } = getConfig();
51
+ const token = import_jsonwebtoken.default.sign(payload, secret, { expiresIn });
52
+ res.cookie("efc_token", token, {
53
+ httpOnly: true,
54
+ secure: process.env["NODE_ENV"] === "production",
55
+ sameSite: "strict",
56
+ ...cookieDomain !== void 0 && { domain: cookieDomain }
57
+ });
58
+ }
59
+ function revokeToken(res) {
60
+ res.clearCookie("efc_token");
61
+ }
62
+ function signToken(payload) {
63
+ const { secret, expiresIn } = getConfig();
64
+ return import_jsonwebtoken.default.sign(payload, secret, { expiresIn });
65
+ }
66
+ var requireAuth = (req, res, next) => {
67
+ const { secret, strategy } = getConfig();
68
+ try {
69
+ let token;
70
+ if (strategy === "http-only") {
71
+ const cookies = req.cookies;
72
+ token = cookies["efc_token"];
73
+ } else {
74
+ const auth = req.headers["authorization"];
75
+ if (typeof auth === "string" && auth.startsWith("Bearer ")) {
76
+ token = auth.slice(7);
77
+ }
78
+ }
79
+ if (!token) {
80
+ res.status(401).json({ error: "Unauthorized" });
81
+ return;
82
+ }
83
+ const decoded = import_jsonwebtoken.default.verify(token, secret);
84
+ req.user = decoded;
85
+ next();
86
+ } catch {
87
+ res.status(401).json({ error: "Unauthorized" });
88
+ }
89
+ };
90
+ // Annotate the CommonJS export names for ESM import in node:
91
+ 0 && (module.exports = {
92
+ configureAuth,
93
+ issueToken,
94
+ requireAuth,
95
+ revokeToken,
96
+ signToken
97
+ });
98
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import type { RequestHandler, Response } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type { AuthStrategy } from '../types.js';\n\ninterface AuthConfig {\n secret: string;\n strategy: AuthStrategy;\n expiresIn: string;\n cookieDomain?: string | undefined;\n}\n\nlet _config: AuthConfig | null = null;\n\nexport function configureAuth(config: AuthConfig): void {\n _config = config;\n}\n\nfunction getConfig(): AuthConfig {\n if (!_config) throw new Error('[EFC] Auth not configured — pass jwtSecret to ignite()');\n return _config;\n}\n\nexport function issueToken(res: Response, payload: Record<string, unknown>): void {\n const { secret, expiresIn, cookieDomain } = getConfig();\n // expiresIn is a plain string (e.g. '7d'); cast satisfies jwt's branded StringValue\n const token = jwt.sign(payload, secret, { expiresIn: expiresIn as jwt.SignOptions['expiresIn'] & string });\n res.cookie('efc_token', token, {\n httpOnly: true,\n secure: process.env['NODE_ENV'] === 'production',\n sameSite: 'strict',\n ...(cookieDomain !== undefined && { domain: cookieDomain }),\n });\n}\n\nexport function revokeToken(res: Response): void {\n res.clearCookie('efc_token');\n}\n\nexport function signToken(payload: Record<string, unknown>): string {\n const { secret, expiresIn } = getConfig();\n return jwt.sign(payload, secret, { expiresIn: expiresIn as jwt.SignOptions['expiresIn'] & string });\n}\n\nexport const requireAuth: RequestHandler = (req, res, next) => {\n const { secret, strategy } = getConfig();\n\n try {\n let token: string | undefined;\n\n if (strategy === 'http-only') {\n const cookies = (req as typeof req & { cookies: Record<string, string> }).cookies;\n token = cookies['efc_token'];\n } else {\n const auth = req.headers['authorization'];\n if (typeof auth === 'string' && auth.startsWith('Bearer ')) {\n token = auth.slice(7);\n }\n }\n\n if (!token) {\n res.status(401).json({ error: 'Unauthorized' });\n return;\n }\n\n const decoded = jwt.verify(token, secret);\n (req as typeof req & { user: unknown }).user = decoded;\n next();\n } catch {\n res.status(401).json({ error: 'Unauthorized' });\n }\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,0BAAgB;AAUhB,IAAI,UAA6B;AAE1B,SAAS,cAAc,QAA0B;AACtD,YAAU;AACZ;AAEA,SAAS,YAAwB;AAC/B,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,6DAAwD;AACtF,SAAO;AACT;AAEO,SAAS,WAAW,KAAe,SAAwC;AAChF,QAAM,EAAE,QAAQ,WAAW,aAAa,IAAI,UAAU;AAEtD,QAAM,QAAQ,oBAAAA,QAAI,KAAK,SAAS,QAAQ,EAAE,UAA8D,CAAC;AACzG,MAAI,OAAO,aAAa,OAAO;AAAA,IAC7B,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,UAAU,MAAM;AAAA,IACpC,UAAU;AAAA,IACV,GAAI,iBAAiB,UAAa,EAAE,QAAQ,aAAa;AAAA,EAC3D,CAAC;AACH;AAEO,SAAS,YAAY,KAAqB;AAC/C,MAAI,YAAY,WAAW;AAC7B;AAEO,SAAS,UAAU,SAA0C;AAClE,QAAM,EAAE,QAAQ,UAAU,IAAI,UAAU;AACxC,SAAO,oBAAAA,QAAI,KAAK,SAAS,QAAQ,EAAE,UAA8D,CAAC;AACpG;AAEO,IAAM,cAA8B,CAAC,KAAK,KAAK,SAAS;AAC7D,QAAM,EAAE,QAAQ,SAAS,IAAI,UAAU;AAEvC,MAAI;AACF,QAAI;AAEJ,QAAI,aAAa,aAAa;AAC5B,YAAM,UAAW,IAAyD;AAC1E,cAAQ,QAAQ,WAAW;AAAA,IAC7B,OAAO;AACL,YAAM,OAAO,IAAI,QAAQ,eAAe;AACxC,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,SAAS,GAAG;AAC1D,gBAAQ,KAAK,MAAM,CAAC;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,CAAC,OAAO;AACV,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAC9C;AAAA,IACF;AAEA,UAAM,UAAU,oBAAAA,QAAI,OAAO,OAAO,MAAM;AACxC,IAAC,IAAuC,OAAO;AAC/C,SAAK;AAAA,EACP,QAAQ;AACN,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,EAChD;AACF;","names":["jwt"]}
@@ -0,0 +1,16 @@
1
+ import { Response, RequestHandler } from 'express';
2
+ import { A as AuthStrategy } from '../types-DNdkDUPX.cjs';
3
+
4
+ interface AuthConfig {
5
+ secret: string;
6
+ strategy: AuthStrategy;
7
+ expiresIn: string;
8
+ cookieDomain?: string | undefined;
9
+ }
10
+ declare function configureAuth(config: AuthConfig): void;
11
+ declare function issueToken(res: Response, payload: Record<string, unknown>): void;
12
+ declare function revokeToken(res: Response): void;
13
+ declare function signToken(payload: Record<string, unknown>): string;
14
+ declare const requireAuth: RequestHandler;
15
+
16
+ export { configureAuth, issueToken, requireAuth, revokeToken, signToken };
@@ -0,0 +1,16 @@
1
+ import { Response, RequestHandler } from 'express';
2
+ import { A as AuthStrategy } from '../types-DNdkDUPX.js';
3
+
4
+ interface AuthConfig {
5
+ secret: string;
6
+ strategy: AuthStrategy;
7
+ expiresIn: string;
8
+ cookieDomain?: string | undefined;
9
+ }
10
+ declare function configureAuth(config: AuthConfig): void;
11
+ declare function issueToken(res: Response, payload: Record<string, unknown>): void;
12
+ declare function revokeToken(res: Response): void;
13
+ declare function signToken(payload: Record<string, unknown>): string;
14
+ declare const requireAuth: RequestHandler;
15
+
16
+ export { configureAuth, issueToken, requireAuth, revokeToken, signToken };
@@ -0,0 +1,59 @@
1
+ // src/auth/index.ts
2
+ import jwt from "jsonwebtoken";
3
+ var _config = null;
4
+ function configureAuth(config) {
5
+ _config = config;
6
+ }
7
+ function getConfig() {
8
+ if (!_config) throw new Error("[EFC] Auth not configured \u2014 pass jwtSecret to ignite()");
9
+ return _config;
10
+ }
11
+ function issueToken(res, payload) {
12
+ const { secret, expiresIn, cookieDomain } = getConfig();
13
+ const token = jwt.sign(payload, secret, { expiresIn });
14
+ res.cookie("efc_token", token, {
15
+ httpOnly: true,
16
+ secure: process.env["NODE_ENV"] === "production",
17
+ sameSite: "strict",
18
+ ...cookieDomain !== void 0 && { domain: cookieDomain }
19
+ });
20
+ }
21
+ function revokeToken(res) {
22
+ res.clearCookie("efc_token");
23
+ }
24
+ function signToken(payload) {
25
+ const { secret, expiresIn } = getConfig();
26
+ return jwt.sign(payload, secret, { expiresIn });
27
+ }
28
+ var requireAuth = (req, res, next) => {
29
+ const { secret, strategy } = getConfig();
30
+ try {
31
+ let token;
32
+ if (strategy === "http-only") {
33
+ const cookies = req.cookies;
34
+ token = cookies["efc_token"];
35
+ } else {
36
+ const auth = req.headers["authorization"];
37
+ if (typeof auth === "string" && auth.startsWith("Bearer ")) {
38
+ token = auth.slice(7);
39
+ }
40
+ }
41
+ if (!token) {
42
+ res.status(401).json({ error: "Unauthorized" });
43
+ return;
44
+ }
45
+ const decoded = jwt.verify(token, secret);
46
+ req.user = decoded;
47
+ next();
48
+ } catch {
49
+ res.status(401).json({ error: "Unauthorized" });
50
+ }
51
+ };
52
+ export {
53
+ configureAuth,
54
+ issueToken,
55
+ requireAuth,
56
+ revokeToken,
57
+ signToken
58
+ };
59
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["import type { RequestHandler, Response } from 'express';\nimport jwt from 'jsonwebtoken';\nimport type { AuthStrategy } from '../types.js';\n\ninterface AuthConfig {\n secret: string;\n strategy: AuthStrategy;\n expiresIn: string;\n cookieDomain?: string | undefined;\n}\n\nlet _config: AuthConfig | null = null;\n\nexport function configureAuth(config: AuthConfig): void {\n _config = config;\n}\n\nfunction getConfig(): AuthConfig {\n if (!_config) throw new Error('[EFC] Auth not configured — pass jwtSecret to ignite()');\n return _config;\n}\n\nexport function issueToken(res: Response, payload: Record<string, unknown>): void {\n const { secret, expiresIn, cookieDomain } = getConfig();\n // expiresIn is a plain string (e.g. '7d'); cast satisfies jwt's branded StringValue\n const token = jwt.sign(payload, secret, { expiresIn: expiresIn as jwt.SignOptions['expiresIn'] & string });\n res.cookie('efc_token', token, {\n httpOnly: true,\n secure: process.env['NODE_ENV'] === 'production',\n sameSite: 'strict',\n ...(cookieDomain !== undefined && { domain: cookieDomain }),\n });\n}\n\nexport function revokeToken(res: Response): void {\n res.clearCookie('efc_token');\n}\n\nexport function signToken(payload: Record<string, unknown>): string {\n const { secret, expiresIn } = getConfig();\n return jwt.sign(payload, secret, { expiresIn: expiresIn as jwt.SignOptions['expiresIn'] & string });\n}\n\nexport const requireAuth: RequestHandler = (req, res, next) => {\n const { secret, strategy } = getConfig();\n\n try {\n let token: string | undefined;\n\n if (strategy === 'http-only') {\n const cookies = (req as typeof req & { cookies: Record<string, string> }).cookies;\n token = cookies['efc_token'];\n } else {\n const auth = req.headers['authorization'];\n if (typeof auth === 'string' && auth.startsWith('Bearer ')) {\n token = auth.slice(7);\n }\n }\n\n if (!token) {\n res.status(401).json({ error: 'Unauthorized' });\n return;\n }\n\n const decoded = jwt.verify(token, secret);\n (req as typeof req & { user: unknown }).user = decoded;\n next();\n } catch {\n res.status(401).json({ error: 'Unauthorized' });\n }\n};\n"],"mappings":";AACA,OAAO,SAAS;AAUhB,IAAI,UAA6B;AAE1B,SAAS,cAAc,QAA0B;AACtD,YAAU;AACZ;AAEA,SAAS,YAAwB;AAC/B,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,6DAAwD;AACtF,SAAO;AACT;AAEO,SAAS,WAAW,KAAe,SAAwC;AAChF,QAAM,EAAE,QAAQ,WAAW,aAAa,IAAI,UAAU;AAEtD,QAAM,QAAQ,IAAI,KAAK,SAAS,QAAQ,EAAE,UAA8D,CAAC;AACzG,MAAI,OAAO,aAAa,OAAO;AAAA,IAC7B,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,UAAU,MAAM;AAAA,IACpC,UAAU;AAAA,IACV,GAAI,iBAAiB,UAAa,EAAE,QAAQ,aAAa;AAAA,EAC3D,CAAC;AACH;AAEO,SAAS,YAAY,KAAqB;AAC/C,MAAI,YAAY,WAAW;AAC7B;AAEO,SAAS,UAAU,SAA0C;AAClE,QAAM,EAAE,QAAQ,UAAU,IAAI,UAAU;AACxC,SAAO,IAAI,KAAK,SAAS,QAAQ,EAAE,UAA8D,CAAC;AACpG;AAEO,IAAM,cAA8B,CAAC,KAAK,KAAK,SAAS;AAC7D,QAAM,EAAE,QAAQ,SAAS,IAAI,UAAU;AAEvC,MAAI;AACF,QAAI;AAEJ,QAAI,aAAa,aAAa;AAC5B,YAAM,UAAW,IAAyD;AAC1E,cAAQ,QAAQ,WAAW;AAAA,IAC7B,OAAO;AACL,YAAM,OAAO,IAAI,QAAQ,eAAe;AACxC,UAAI,OAAO,SAAS,YAAY,KAAK,WAAW,SAAS,GAAG;AAC1D,gBAAQ,KAAK,MAAM,CAAC;AAAA,MACtB;AAAA,IACF;AAEA,QAAI,CAAC,OAAO;AACV,UAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAC9C;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,OAAO,OAAO,MAAM;AACxC,IAAC,IAAuC,OAAO;AAC/C,SAAK;AAAA,EACP,QAAQ;AACN,QAAI,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,eAAe,CAAC;AAAA,EAChD;AACF;","names":[]}
@@ -0,0 +1,380 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
18
+ // If the importer is in node compatibility mode or this is not an ESM
19
+ // file that has been converted to a CommonJS file using a Babel-
20
+ // compatible transform (i.e. "__esModule" has not been set), then set
21
+ // "default" to the CommonJS "module.exports" for node compatibility.
22
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
23
+ mod
24
+ ));
25
+
26
+ // src/cli/index.ts
27
+ var import_commander6 = require("commander");
28
+
29
+ // src/cli/commands/start.ts
30
+ var import_commander = require("commander");
31
+ var import_node_child_process = require("child_process");
32
+ var import_node_path = __toESM(require("path"), 1);
33
+ var import_node_fs = __toESM(require("fs"), 1);
34
+ var import_chalk = __toESM(require("chalk"), 1);
35
+ function startCommand() {
36
+ const cmd = new import_commander.Command("start");
37
+ cmd.argument("<mode>", "dev | prod").description("Start the EFC server").action((mode) => {
38
+ if (mode === "dev") {
39
+ startDev();
40
+ } else if (mode === "prod") {
41
+ startProd();
42
+ } else {
43
+ console.error(import_chalk.default.red(`Unknown mode: ${mode}. Use 'dev' or 'prod'.`));
44
+ process.exit(1);
45
+ }
46
+ });
47
+ return cmd;
48
+ }
49
+ function startDev() {
50
+ const entry = resolveEntry();
51
+ if (!entry) {
52
+ console.error(import_chalk.default.red("[EFC] Could not find entry point. Expected src/index.ts or index.ts"));
53
+ process.exit(1);
54
+ }
55
+ console.log(import_chalk.default.cyan("[EFC] Starting development server\u2026"));
56
+ console.log(import_chalk.default.dim(` Entry: ${entry}`));
57
+ const child = (0, import_node_child_process.spawn)(
58
+ "node",
59
+ ["--import", "tsx/esm", "--watch", entry],
60
+ { stdio: "inherit", env: { ...process.env, NODE_ENV: "development" } }
61
+ );
62
+ child.on("exit", (code) => process.exit(code ?? 0));
63
+ }
64
+ function startProd() {
65
+ const cwd = process.cwd();
66
+ const distEntry = import_node_path.default.join(cwd, "dist", "index.js");
67
+ if (!import_node_fs.default.existsSync(distEntry)) {
68
+ console.error(import_chalk.default.red("[EFC] dist/index.js not found. Run `efc build prod` first."));
69
+ process.exit(1);
70
+ }
71
+ console.log(import_chalk.default.cyan("[EFC] Starting production server\u2026"));
72
+ const child = (0, import_node_child_process.spawn)("node", [distEntry], {
73
+ stdio: "inherit",
74
+ env: { ...process.env, NODE_ENV: "production" }
75
+ });
76
+ child.on("exit", (code) => process.exit(code ?? 0));
77
+ }
78
+ function resolveEntry() {
79
+ const cwd = process.cwd();
80
+ const candidates = [
81
+ import_node_path.default.join(cwd, "src", "index.ts"),
82
+ import_node_path.default.join(cwd, "index.ts"),
83
+ import_node_path.default.join(cwd, "src", "index.js"),
84
+ import_node_path.default.join(cwd, "index.js")
85
+ ];
86
+ return candidates.find((f) => import_node_fs.default.existsSync(f)) ?? null;
87
+ }
88
+
89
+ // src/cli/commands/build.ts
90
+ var import_commander2 = require("commander");
91
+ var import_node_child_process2 = require("child_process");
92
+ var import_chalk2 = __toESM(require("chalk"), 1);
93
+ function buildCommand() {
94
+ const cmd = new import_commander2.Command("build");
95
+ cmd.argument("<mode>", "prod").description("Build the application for production").action((mode) => {
96
+ if (mode !== "prod") {
97
+ console.error(import_chalk2.default.red(`Unknown build mode: ${mode}. Use 'prod'.`));
98
+ process.exit(1);
99
+ }
100
+ buildProd();
101
+ });
102
+ return cmd;
103
+ }
104
+ function buildProd() {
105
+ console.log(import_chalk2.default.cyan("[EFC] Building for production\u2026"));
106
+ const tsc = (0, import_node_child_process2.spawn)("npx", ["tsc", "--noEmit"], { stdio: "inherit" });
107
+ tsc.on("exit", (code) => {
108
+ if (code !== 0) {
109
+ console.error(import_chalk2.default.red("[EFC] TypeScript errors found. Fix them before building."));
110
+ process.exit(1);
111
+ }
112
+ const tsup = (0, import_node_child_process2.spawn)("npx", ["tsup"], { stdio: "inherit" });
113
+ tsup.on("exit", (tsupCode) => {
114
+ if (tsupCode === 0) {
115
+ console.log(import_chalk2.default.green("[EFC] Build complete \u2192 dist/"));
116
+ } else {
117
+ process.exit(tsupCode ?? 1);
118
+ }
119
+ });
120
+ });
121
+ }
122
+
123
+ // src/cli/commands/run.ts
124
+ var import_commander3 = require("commander");
125
+ var import_node_child_process3 = require("child_process");
126
+ var import_chalk3 = __toESM(require("chalk"), 1);
127
+ function runCommand() {
128
+ const cmd = new import_commander3.Command("run");
129
+ cmd.argument("<runner>", "tests").description("Run EFC sub-commands (tests)").allowUnknownOption().action((runner) => {
130
+ if (runner === "tests") {
131
+ runTests(cmd.args.slice(1));
132
+ } else {
133
+ console.error(import_chalk3.default.red(`Unknown runner: ${runner}. Use 'tests'.`));
134
+ process.exit(1);
135
+ }
136
+ });
137
+ return cmd;
138
+ }
139
+ function runTests(extraArgs) {
140
+ console.log(import_chalk3.default.cyan("[EFC] Running tests via Vitest\u2026"));
141
+ const child = (0, import_node_child_process3.spawn)("npx", ["vitest", "run", ...extraArgs], { stdio: "inherit" });
142
+ child.on("exit", (code) => process.exit(code ?? 0));
143
+ }
144
+
145
+ // src/cli/commands/generate.ts
146
+ var import_commander4 = require("commander");
147
+ var import_node_fs2 = __toESM(require("fs"), 1);
148
+ var import_node_path2 = __toESM(require("path"), 1);
149
+ var import_chalk4 = __toESM(require("chalk"), 1);
150
+ function generateCommand() {
151
+ const cmd = new import_commander4.Command("generate").alias("g").description("Scaffold EFC modules");
152
+ cmd.command("route <routePath>").description("Scaffold a route module, e.g. users/[id]").action((routePath) => generateRoute(routePath));
153
+ cmd.command("task <name>").description("Scaffold a background task module").action((name) => generateTask(name));
154
+ cmd.command("middleware <name>").description("Scaffold a middleware module").action((name) => generateMiddleware(name));
155
+ return cmd;
156
+ }
157
+ function writeFile(filePath, content) {
158
+ const dir = import_node_path2.default.dirname(filePath);
159
+ import_node_fs2.default.mkdirSync(dir, { recursive: true });
160
+ if (import_node_fs2.default.existsSync(filePath)) {
161
+ console.error(import_chalk4.default.red(`File already exists: ${filePath}`));
162
+ process.exit(1);
163
+ }
164
+ import_node_fs2.default.writeFileSync(filePath, content, "utf8");
165
+ console.log(import_chalk4.default.green(` created ${import_node_path2.default.relative(process.cwd(), filePath)}`));
166
+ }
167
+ function generateRoute(routePath) {
168
+ const cwd = process.cwd();
169
+ const filePath = import_node_path2.default.join(cwd, "src", "api", `${routePath}.ts`);
170
+ const content = `import type { Request, Response } from 'express';
171
+
172
+ export const GET = async (req: Request, res: Response) => {
173
+ res.json({ message: 'OK' });
174
+ };
175
+
176
+ export const POST = async (req: Request, res: Response) => {
177
+ res.status(201).json({ message: 'Created' });
178
+ };
179
+ `;
180
+ writeFile(filePath, content);
181
+ console.log(import_chalk4.default.cyan(`[EFC] Route scaffolded`));
182
+ }
183
+ function generateTask(name) {
184
+ const cwd = process.cwd();
185
+ const filePath = import_node_path2.default.join(cwd, "src", "tasks", `${name}.ts`);
186
+ const content = `import { defineTask } from 'express-file-cluster/tasks';
187
+
188
+ interface ${name}Payload {
189
+ // TODO: define payload fields
190
+ }
191
+
192
+ export default defineTask<${name}Payload>(async (payload) => {
193
+ // TODO: implement task logic
194
+ console.log('[Task:${name}]', payload);
195
+ });
196
+ `;
197
+ writeFile(filePath, content);
198
+ console.log(import_chalk4.default.cyan(`[EFC] Task scaffolded`));
199
+ }
200
+ function generateMiddleware(name) {
201
+ const cwd = process.cwd();
202
+ const filePath = import_node_path2.default.join(cwd, "src", "middlewares", `${name}.ts`);
203
+ const content = `import type { Request, Response, NextFunction } from 'express';
204
+
205
+ export function ${name}(req: Request, res: Response, next: NextFunction): void {
206
+ // TODO: implement middleware logic
207
+ next();
208
+ }
209
+ `;
210
+ writeFile(filePath, content);
211
+ console.log(import_chalk4.default.cyan(`[EFC] Middleware scaffolded`));
212
+ }
213
+
214
+ // src/cli/commands/diagnostics.ts
215
+ var import_commander5 = require("commander");
216
+
217
+ // src/router/scan.ts
218
+ var import_node_fs3 = __toESM(require("fs"), 1);
219
+ var import_node_path3 = __toESM(require("path"), 1);
220
+ var ROUTE_FILE_RE = /\.(ts|js|mts|mjs|cts|cjs)$/;
221
+ var DYNAMIC_SEGMENT_RE = /\[([^\]]+)\]/g;
222
+ function filePathToUrlPath(relativePath) {
223
+ let p = relativePath.replace(ROUTE_FILE_RE, "");
224
+ p = p.replace(/\/index$/, "");
225
+ p = p.replace(DYNAMIC_SEGMENT_RE, ":$1");
226
+ return p === "" ? "/" : p.startsWith("/") ? p : `/${p}`;
227
+ }
228
+ function extractParams(relativePath) {
229
+ const params = [];
230
+ let match;
231
+ const re = new RegExp(DYNAMIC_SEGMENT_RE.source, "g");
232
+ while ((match = re.exec(relativePath)) !== null) {
233
+ if (match[1]) params.push(match[1]);
234
+ }
235
+ return params;
236
+ }
237
+ function scanDir(dir, base = dir) {
238
+ if (!import_node_fs3.default.existsSync(dir)) return [];
239
+ const entries = [];
240
+ const items = import_node_fs3.default.readdirSync(dir, { withFileTypes: true });
241
+ for (const item of items) {
242
+ const fullPath = import_node_path3.default.join(dir, item.name);
243
+ if (item.isDirectory()) {
244
+ entries.push(...scanDir(fullPath, base));
245
+ } else if (ROUTE_FILE_RE.test(item.name)) {
246
+ const relative = "/" + import_node_path3.default.relative(base, fullPath).replace(/\\/g, "/");
247
+ entries.push({
248
+ urlPath: filePathToUrlPath(relative),
249
+ filePath: fullPath,
250
+ params: extractParams(relative)
251
+ });
252
+ }
253
+ }
254
+ return entries.sort((a, b) => {
255
+ const aDynamic = a.urlPath.includes(":") ? 1 : 0;
256
+ const bDynamic = b.urlPath.includes(":") ? 1 : 0;
257
+ return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);
258
+ });
259
+ }
260
+
261
+ // src/cli/commands/diagnostics.ts
262
+ var import_node_path4 = __toESM(require("path"), 1);
263
+ var import_node_fs4 = __toESM(require("fs"), 1);
264
+ var import_chalk5 = __toESM(require("chalk"), 1);
265
+ function diagnosticsCommands() {
266
+ return [routesCommand(), tasksCommand(), doctorCommand()];
267
+ }
268
+ function routesCommand() {
269
+ return new import_commander5.Command("routes").description("Print the resolved route table").action(() => {
270
+ const apiDir = resolveApiDir();
271
+ if (!apiDir) {
272
+ console.error(import_chalk5.default.red("[EFC] Could not find apiDir (expected src/api)"));
273
+ process.exit(1);
274
+ }
275
+ const routes = scanDir(apiDir);
276
+ if (routes.length === 0) {
277
+ console.log(import_chalk5.default.yellow("No routes found."));
278
+ return;
279
+ }
280
+ console.log(import_chalk5.default.bold("\n Route Table\n"));
281
+ console.log(import_chalk5.default.dim(" " + "\u2500".repeat(60)));
282
+ for (const route of routes) {
283
+ const rel = import_node_path4.default.relative(process.cwd(), route.filePath);
284
+ console.log(` ${import_chalk5.default.cyan(route.urlPath.padEnd(35))} ${import_chalk5.default.dim(rel)}`);
285
+ }
286
+ console.log(import_chalk5.default.dim(" " + "\u2500".repeat(60)));
287
+ console.log(import_chalk5.default.dim(`
288
+ ${routes.length} route(s) found
289
+ `));
290
+ });
291
+ }
292
+ function tasksCommand() {
293
+ return new import_commander5.Command("tasks").description("List registered background tasks").action(() => {
294
+ const tasksDir = resolveTasksDir();
295
+ if (!tasksDir || !import_node_fs4.default.existsSync(tasksDir)) {
296
+ console.log(import_chalk5.default.yellow("No tasks directory found."));
297
+ return;
298
+ }
299
+ const files = import_node_fs4.default.readdirSync(tasksDir).filter((f) => /\.(ts|js)$/.test(f));
300
+ if (files.length === 0) {
301
+ console.log(import_chalk5.default.yellow("No tasks found."));
302
+ return;
303
+ }
304
+ console.log(import_chalk5.default.bold("\n Background Tasks\n"));
305
+ for (const file of files) {
306
+ console.log(` ${import_chalk5.default.cyan(import_node_path4.default.basename(file, import_node_path4.default.extname(file)))}`);
307
+ }
308
+ console.log();
309
+ });
310
+ }
311
+ function doctorCommand() {
312
+ return new import_commander5.Command("doctor").description("Validate config, env vars, and project setup").action(() => {
313
+ const cwd = process.cwd();
314
+ const checks = [
315
+ {
316
+ label: "package.json exists",
317
+ ok: import_node_fs4.default.existsSync(import_node_path4.default.join(cwd, "package.json"))
318
+ },
319
+ {
320
+ label: "tsconfig.json exists",
321
+ ok: import_node_fs4.default.existsSync(import_node_path4.default.join(cwd, "tsconfig.json")),
322
+ hint: "Run `tsc --init` to create one"
323
+ },
324
+ {
325
+ label: "src/api directory exists",
326
+ ok: import_node_fs4.default.existsSync(import_node_path4.default.join(cwd, "src", "api")),
327
+ hint: "Create src/api/ and add route files"
328
+ },
329
+ {
330
+ label: "DATABASE_URL set",
331
+ ok: Boolean(process.env["DATABASE_URL"]),
332
+ hint: "Add DATABASE_URL to .env"
333
+ },
334
+ {
335
+ label: "JWT_SECRET set",
336
+ ok: Boolean(process.env["JWT_SECRET"]),
337
+ hint: "Add JWT_SECRET to .env (generate: openssl rand -hex 64)"
338
+ }
339
+ ];
340
+ console.log(import_chalk5.default.bold("\n EFC Doctor\n"));
341
+ let allOk = true;
342
+ for (const check of checks) {
343
+ const icon = check.ok ? import_chalk5.default.green("\u2713") : import_chalk5.default.red("\u2717");
344
+ console.log(` ${icon} ${check.label}`);
345
+ if (!check.ok) {
346
+ allOk = false;
347
+ if (check.hint) console.log(import_chalk5.default.dim(` \u2192 ${check.hint}`));
348
+ }
349
+ }
350
+ console.log();
351
+ if (allOk) {
352
+ console.log(import_chalk5.default.green(" All checks passed!\n"));
353
+ } else {
354
+ console.log(import_chalk5.default.yellow(" Some checks failed. Fix the issues above.\n"));
355
+ process.exit(1);
356
+ }
357
+ });
358
+ }
359
+ function resolveApiDir() {
360
+ const cwd = process.cwd();
361
+ const candidates = [import_node_path4.default.join(cwd, "src", "api"), import_node_path4.default.join(cwd, "api")];
362
+ return candidates.find((d) => import_node_fs4.default.existsSync(d)) ?? null;
363
+ }
364
+ function resolveTasksDir() {
365
+ const cwd = process.cwd();
366
+ const candidates = [import_node_path4.default.join(cwd, "src", "tasks"), import_node_path4.default.join(cwd, "tasks")];
367
+ return candidates.find((d) => import_node_fs4.default.existsSync(d)) ?? null;
368
+ }
369
+
370
+ // src/cli/index.ts
371
+ var program = new import_commander6.Command("efc").description("Express File Cluster CLI").version("0.1.0");
372
+ program.addCommand(startCommand());
373
+ program.addCommand(buildCommand());
374
+ program.addCommand(runCommand());
375
+ program.addCommand(generateCommand());
376
+ for (const cmd of diagnosticsCommands()) {
377
+ program.addCommand(cmd);
378
+ }
379
+ program.parse(process.argv);
380
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +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 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 child = spawn(\n 'node',\n ['--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', [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"]}
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node