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
package/dist/index.cjs ADDED
@@ -0,0 +1,541 @@
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/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ HttpError: () => HttpError,
34
+ compose: () => compose,
35
+ db: () => db,
36
+ defineModel: () => defineModel,
37
+ getDbClient: () => getDbClient,
38
+ ignite: () => ignite,
39
+ scanDir: () => scanDir,
40
+ setDbClient: () => setDbClient
41
+ });
42
+ module.exports = __toCommonJS(src_exports);
43
+ var import_express = __toESM(require("express"), 1);
44
+ var import_cookie_parser = __toESM(require("cookie-parser"), 1);
45
+ var import_node_cluster2 = __toESM(require("cluster"), 1);
46
+ var import_node_os2 = __toESM(require("os"), 1);
47
+
48
+ // src/router/scan.ts
49
+ var import_node_fs = __toESM(require("fs"), 1);
50
+ var import_node_path = __toESM(require("path"), 1);
51
+ var ROUTE_FILE_RE = /\.(ts|js|mts|mjs|cts|cjs)$/;
52
+ var DYNAMIC_SEGMENT_RE = /\[([^\]]+)\]/g;
53
+ function filePathToUrlPath(relativePath) {
54
+ let p = relativePath.replace(ROUTE_FILE_RE, "");
55
+ p = p.replace(/\/index$/, "");
56
+ p = p.replace(DYNAMIC_SEGMENT_RE, ":$1");
57
+ return p === "" ? "/" : p.startsWith("/") ? p : `/${p}`;
58
+ }
59
+ function extractParams(relativePath) {
60
+ const params = [];
61
+ let match;
62
+ const re = new RegExp(DYNAMIC_SEGMENT_RE.source, "g");
63
+ while ((match = re.exec(relativePath)) !== null) {
64
+ if (match[1]) params.push(match[1]);
65
+ }
66
+ return params;
67
+ }
68
+ function scanDir(dir, base = dir) {
69
+ if (!import_node_fs.default.existsSync(dir)) return [];
70
+ const entries = [];
71
+ const items = import_node_fs.default.readdirSync(dir, { withFileTypes: true });
72
+ for (const item of items) {
73
+ const fullPath = import_node_path.default.join(dir, item.name);
74
+ if (item.isDirectory()) {
75
+ entries.push(...scanDir(fullPath, base));
76
+ } else if (ROUTE_FILE_RE.test(item.name)) {
77
+ const relative = "/" + import_node_path.default.relative(base, fullPath).replace(/\\/g, "/");
78
+ entries.push({
79
+ urlPath: filePathToUrlPath(relative),
80
+ filePath: fullPath,
81
+ params: extractParams(relative)
82
+ });
83
+ }
84
+ }
85
+ return entries.sort((a, b) => {
86
+ const aDynamic = a.urlPath.includes(":") ? 1 : 0;
87
+ const bDynamic = b.urlPath.includes(":") ? 1 : 0;
88
+ return aDynamic - bDynamic || a.urlPath.localeCompare(b.urlPath);
89
+ });
90
+ }
91
+
92
+ // src/router/mount.ts
93
+ var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
94
+ function asyncWrap(handler) {
95
+ return (req, res, next) => {
96
+ Promise.resolve(handler(req, res, next)).catch(next);
97
+ };
98
+ }
99
+ async function mountRoutes(app, routes) {
100
+ for (const route of routes) {
101
+ const mod = await import(route.filePath);
102
+ const routeMiddlewares = Array.isArray(mod["middlewares"]) ? mod["middlewares"] : [];
103
+ const implemented = [];
104
+ const unimplemented = [];
105
+ for (const method of HTTP_METHODS) {
106
+ if (typeof mod[method] === "function") {
107
+ implemented.push(method);
108
+ app[method.toLowerCase()](
109
+ route.urlPath,
110
+ ...routeMiddlewares,
111
+ asyncWrap(mod[method])
112
+ );
113
+ } else {
114
+ unimplemented.push(method);
115
+ }
116
+ }
117
+ if (implemented.length > 0 && unimplemented.length > 0) {
118
+ const allowHeader = implemented.join(", ");
119
+ app.all(route.urlPath, (req, res, next) => {
120
+ if (unimplemented.includes(req.method)) {
121
+ res.set("Allow", allowHeader).status(405).json({ error: "Method Not Allowed" });
122
+ } else {
123
+ next();
124
+ }
125
+ });
126
+ }
127
+ }
128
+ }
129
+
130
+ // src/cluster/index.ts
131
+ var import_node_cluster = __toESM(require("cluster"), 1);
132
+ var import_node_os = __toESM(require("os"), 1);
133
+ function runMaster(options = {}) {
134
+ const count = options.workers ?? import_node_os.default.cpus().length;
135
+ console.log(`[EFC] Primary ${process.pid} starting ${count} workers`);
136
+ for (let i = 0; i < count; i++) {
137
+ import_node_cluster.default.fork();
138
+ }
139
+ import_node_cluster.default.on("online", (worker) => {
140
+ options.onWorkerReady?.(worker.id);
141
+ });
142
+ import_node_cluster.default.on("exit", (worker, code, signal) => {
143
+ const exitCode = code ?? (signal ? -1 : 0);
144
+ console.warn(`[EFC] Worker ${worker.id} exited (code=${exitCode}), respawning\u2026`);
145
+ options.onWorkerCrash?.(worker.id, exitCode);
146
+ import_node_cluster.default.fork();
147
+ });
148
+ }
149
+
150
+ // src/auth/index.ts
151
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
152
+ var _config = null;
153
+ function configureAuth(config) {
154
+ _config = config;
155
+ }
156
+
157
+ // src/errors.ts
158
+ var HttpError = class _HttpError extends Error {
159
+ statusCode;
160
+ constructor(statusCode, message) {
161
+ super(message);
162
+ this.name = "HttpError";
163
+ this.statusCode = statusCode;
164
+ Error.captureStackTrace(this, _HttpError);
165
+ }
166
+ };
167
+
168
+ // src/db/mongo.ts
169
+ var mongoose;
170
+ async function loadMongoose() {
171
+ if (mongoose) return mongoose;
172
+ try {
173
+ mongoose = await import("mongoose");
174
+ return mongoose;
175
+ } catch {
176
+ throw new Error(
177
+ "[EFC] mongoose is not installed. Run: npm install mongoose"
178
+ );
179
+ }
180
+ }
181
+ async function connectMongo(url) {
182
+ const mg = await loadMongoose();
183
+ await mg.connect(url);
184
+ console.log("[EFC] MongoDB connected");
185
+ return mg.connection;
186
+ }
187
+
188
+ // src/db/model.ts
189
+ function normalise(doc) {
190
+ const id = doc["_id"] ? String(doc["_id"]) : "";
191
+ return { ...doc, id };
192
+ }
193
+ async function getModel(name, schemaObj) {
194
+ let mg;
195
+ try {
196
+ mg = await import("mongoose");
197
+ } catch {
198
+ throw new Error("[EFC] mongoose is not installed. Run: npm install mongoose");
199
+ }
200
+ if (mg.models[name]) return mg.models[name];
201
+ const schema = new mg.Schema(schemaObj, { timestamps: true });
202
+ return mg.model(name, schema);
203
+ }
204
+ function buildMongooseSchema(schema) {
205
+ const out = {};
206
+ for (const [key, def] of Object.entries(schema)) {
207
+ const entry = {};
208
+ switch (def.type) {
209
+ case "string":
210
+ entry["type"] = String;
211
+ break;
212
+ case "number":
213
+ entry["type"] = Number;
214
+ break;
215
+ case "boolean":
216
+ entry["type"] = Boolean;
217
+ break;
218
+ case "date":
219
+ entry["type"] = Date;
220
+ break;
221
+ case "object":
222
+ entry["type"] = Object;
223
+ break;
224
+ case "array":
225
+ entry["type"] = Array;
226
+ break;
227
+ }
228
+ if (def.required !== void 0) entry["required"] = def.required;
229
+ if (def.unique !== void 0) entry["unique"] = def.unique;
230
+ if (def.default !== void 0) entry["default"] = def.default;
231
+ out[key] = entry;
232
+ }
233
+ return out;
234
+ }
235
+ function defineModel(name, schema) {
236
+ const mongooseSchema = buildMongooseSchema(schema);
237
+ return {
238
+ async find(filter = {}) {
239
+ const M = await getModel(name, mongooseSchema);
240
+ const docs = await M.find(filter).lean();
241
+ return docs.map(normalise);
242
+ },
243
+ async findById(id) {
244
+ const M = await getModel(name, mongooseSchema);
245
+ const doc = await M.findById(id).lean();
246
+ if (!doc) return null;
247
+ return normalise(doc);
248
+ },
249
+ async findOne(filter) {
250
+ const M = await getModel(name, mongooseSchema);
251
+ const doc = await M.findOne(filter).lean();
252
+ if (!doc) return null;
253
+ return normalise(doc);
254
+ },
255
+ async create(data) {
256
+ const M = await getModel(name, mongooseSchema);
257
+ const doc = await M.create(data);
258
+ return normalise(doc.toObject());
259
+ },
260
+ async update(id, data) {
261
+ const M = await getModel(name, mongooseSchema);
262
+ const doc = await M.findByIdAndUpdate(id, data, { new: true }).lean();
263
+ if (!doc) return null;
264
+ return normalise(doc);
265
+ },
266
+ async delete(id) {
267
+ const M = await getModel(name, mongooseSchema);
268
+ await M.findByIdAndDelete(id);
269
+ },
270
+ async count(filter = {}) {
271
+ const M = await getModel(name, mongooseSchema);
272
+ return M.countDocuments(filter);
273
+ }
274
+ };
275
+ }
276
+
277
+ // src/db/index.ts
278
+ var _client = null;
279
+ function setDbClient(client) {
280
+ _client = client;
281
+ }
282
+ function getDbClient() {
283
+ if (!_client) {
284
+ throw new Error("[EFC] db not ready \u2014 accessed before Pre-Flight completed");
285
+ }
286
+ return _client;
287
+ }
288
+ var db = new Proxy({}, {
289
+ get(_target, prop) {
290
+ return getDbClient()[prop];
291
+ },
292
+ set(_target, prop, value) {
293
+ getDbClient()[prop] = value;
294
+ return true;
295
+ }
296
+ });
297
+
298
+ // src/tasks/scanner.ts
299
+ var import_node_fs2 = __toESM(require("fs"), 1);
300
+ var import_node_path2 = __toESM(require("path"), 1);
301
+
302
+ // src/tasks/index.ts
303
+ var taskRegistry = /* @__PURE__ */ new Map();
304
+ var _impl = null;
305
+ function setEnqueueImpl(impl) {
306
+ _impl = impl;
307
+ }
308
+ function registerTask(name, def) {
309
+ taskRegistry.set(name, { ...def, name });
310
+ }
311
+
312
+ // src/tasks/scanner.ts
313
+ async function scanTasks(tasksDir) {
314
+ if (!import_node_fs2.default.existsSync(tasksDir)) return;
315
+ const files = import_node_fs2.default.readdirSync(tasksDir).filter((f) => /\.(ts|js|mts|mjs)$/.test(f));
316
+ for (const file of files) {
317
+ const filePath = import_node_path2.default.join(tasksDir, file);
318
+ const taskName = import_node_path2.default.basename(file, import_node_path2.default.extname(file));
319
+ try {
320
+ const mod = await import(filePath);
321
+ const def = mod["default"];
322
+ if (!def || typeof def.handler !== "function") {
323
+ console.warn(`[EFC] Task file ${file} has no valid default export \u2014 skipping`);
324
+ continue;
325
+ }
326
+ registerTask(taskName, { ...def, filePath });
327
+ console.log(`[EFC] Registered task: ${taskName}`);
328
+ } catch (err) {
329
+ console.warn(`[EFC] Failed to load task ${file}:`, err);
330
+ }
331
+ }
332
+ }
333
+
334
+ // src/tasks/thread-runner.ts
335
+ var import_node_worker_threads = require("worker_threads");
336
+ var import_meta = {};
337
+ if (!import_node_worker_threads.isMainThread) {
338
+ const { handlerPath, payload } = import_node_worker_threads.workerData;
339
+ (async () => {
340
+ try {
341
+ const mod = await import(handlerPath);
342
+ const def = mod["default"];
343
+ if (!def || typeof def.handler !== "function") {
344
+ throw new Error(`[EFC] Thread runner: no valid task export in ${handlerPath}`);
345
+ }
346
+ await def.handler(payload);
347
+ import_node_worker_threads.parentPort?.postMessage({ ok: true });
348
+ } catch (err) {
349
+ import_node_worker_threads.parentPort?.postMessage({ ok: false, error: String(err) });
350
+ }
351
+ })();
352
+ }
353
+ function runInThread(handlerPath, payload) {
354
+ return new Promise((resolve, reject) => {
355
+ const worker = new import_node_worker_threads.Worker(new URL("./thread-runner.js", import_meta.url), {
356
+ workerData: { handlerPath, payload }
357
+ });
358
+ worker.on("message", (msg) => {
359
+ if (msg.ok) resolve();
360
+ else reject(new Error(msg.error ?? "Thread task failed"));
361
+ });
362
+ worker.on("error", reject);
363
+ worker.on("exit", (code) => {
364
+ if (code !== 0) reject(new Error(`Thread worker exited with code ${code}`));
365
+ });
366
+ });
367
+ }
368
+
369
+ // src/tasks/bullmq-backend.ts
370
+ async function initBullMQ(opts) {
371
+ let bullmq;
372
+ try {
373
+ bullmq = await import("bullmq");
374
+ } catch {
375
+ throw new Error("[EFC] bullmq is not installed. Run: npm install bullmq");
376
+ }
377
+ const connection = parseRedisUrl(opts.redisUrl);
378
+ const queue = new bullmq.Queue("efc", { connection });
379
+ const worker = new bullmq.Worker(
380
+ "efc",
381
+ async (job) => {
382
+ const def = taskRegistry.get(job.name);
383
+ if (!def) {
384
+ throw new Error(`[EFC] No task registered for name: ${job.name}`);
385
+ }
386
+ if (def.options.thread && def.filePath) {
387
+ await runInThread(def.filePath, job.data);
388
+ } else {
389
+ await def.handler(job.data);
390
+ }
391
+ },
392
+ { connection, concurrency: opts.concurrency }
393
+ );
394
+ worker.on("failed", (job, err) => {
395
+ console.error(`[EFC] Task ${job?.name ?? "unknown"} failed:`, err.message);
396
+ });
397
+ worker.on("completed", (job) => {
398
+ console.log(`[EFC] Task ${job.name} completed (id=${job.id})`);
399
+ });
400
+ setEnqueueImpl(async (name, payload) => {
401
+ const def = taskRegistry.get(name);
402
+ if (!def) {
403
+ throw new Error(`[EFC] Cannot enqueue unknown task: "${name}". Is the task file in tasksDir?`);
404
+ }
405
+ await queue.add(name, payload, {
406
+ attempts: def.options.retries ?? 3,
407
+ backoff: {
408
+ type: def.options.backoff ?? "exponential",
409
+ delay: 1e3
410
+ }
411
+ });
412
+ });
413
+ console.log("[EFC] BullMQ backend initialised");
414
+ }
415
+ function parseRedisUrl(url) {
416
+ try {
417
+ const u = new URL(url);
418
+ const result = {
419
+ host: u.hostname || "localhost",
420
+ port: parseInt(u.port || "6379", 10)
421
+ };
422
+ if (u.password) result.password = u.password;
423
+ return result;
424
+ } catch {
425
+ return { host: "localhost", port: 6379 };
426
+ }
427
+ }
428
+
429
+ // src/compose.ts
430
+ function compose(...handlers) {
431
+ return (req, res, next) => {
432
+ let index = 0;
433
+ function dispatch(i) {
434
+ if (i >= handlers.length) {
435
+ next();
436
+ return;
437
+ }
438
+ const handler = handlers[i];
439
+ if (!handler) {
440
+ next();
441
+ return;
442
+ }
443
+ try {
444
+ Promise.resolve(handler(req, res, () => dispatch(i + 1))).catch(next);
445
+ } catch (err) {
446
+ next(err);
447
+ }
448
+ }
449
+ dispatch(index);
450
+ };
451
+ }
452
+
453
+ // src/index.ts
454
+ async function ignite(config) {
455
+ const {
456
+ port = 3e3,
457
+ cluster: clusterEnabled = true,
458
+ workers,
459
+ apiDir,
460
+ jwtSecret,
461
+ authStrategy = "http-only",
462
+ globalMiddlewares = [],
463
+ onWorkerReady,
464
+ onWorkerCrash,
465
+ onError
466
+ } = config;
467
+ if (clusterEnabled && import_node_cluster2.default.isPrimary) {
468
+ runMaster({
469
+ workers: workers ?? import_node_os2.default.cpus().length,
470
+ ...onWorkerReady !== void 0 && { onWorkerReady },
471
+ ...onWorkerCrash !== void 0 && { onWorkerCrash }
472
+ });
473
+ return;
474
+ }
475
+ const app = (0, import_express.default)();
476
+ app.use(import_express.default.json());
477
+ app.use(import_express.default.urlencoded({ extended: true }));
478
+ app.use((0, import_cookie_parser.default)());
479
+ for (const mw of globalMiddlewares) {
480
+ app.use(mw);
481
+ }
482
+ if (config.database === "mongodb" && config.databaseUrl) {
483
+ const conn = await connectMongo(config.databaseUrl);
484
+ setDbClient(conn);
485
+ }
486
+ if (jwtSecret) {
487
+ const cookieDomain = process.env["COOKIE_DOMAIN"];
488
+ configureAuth({
489
+ secret: jwtSecret,
490
+ strategy: authStrategy,
491
+ expiresIn: process.env["JWT_EXPIRES_IN"] ?? "7d",
492
+ ...cookieDomain !== void 0 && { cookieDomain }
493
+ });
494
+ }
495
+ if (config.tasksDir) {
496
+ await scanTasks(config.tasksDir);
497
+ }
498
+ if (config.tasks) {
499
+ if (config.tasks.backend === "bullmq") {
500
+ await initBullMQ({
501
+ redisUrl: config.tasks.redisUrl ?? "redis://localhost:6379",
502
+ concurrency: config.tasks.concurrency ?? 5
503
+ });
504
+ }
505
+ }
506
+ const routes = scanDir(apiDir);
507
+ await mountRoutes(app, routes);
508
+ if (onError) {
509
+ app.use(onError);
510
+ } else {
511
+ app.use(
512
+ (err, _req, res, _next) => {
513
+ if (err instanceof HttpError) {
514
+ res.status(err.statusCode).json({ error: err.message, statusCode: err.statusCode });
515
+ } else {
516
+ console.error("[EFC] Unhandled error:", err);
517
+ res.status(500).json({ error: "Internal Server Error", statusCode: 500 });
518
+ }
519
+ }
520
+ );
521
+ }
522
+ await new Promise((resolve) => {
523
+ app.listen(port, () => {
524
+ const wid = import_node_cluster2.default.worker?.id ?? "primary";
525
+ console.log(`[EFC] Worker ${wid} listening on :${port}`);
526
+ resolve();
527
+ });
528
+ });
529
+ }
530
+ // Annotate the CommonJS export names for ESM import in node:
531
+ 0 && (module.exports = {
532
+ HttpError,
533
+ compose,
534
+ db,
535
+ defineModel,
536
+ getDbClient,
537
+ ignite,
538
+ scanDir,
539
+ setDbClient
540
+ });
541
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/router/scan.ts","../src/router/mount.ts","../src/cluster/index.ts","../src/auth/index.ts","../src/errors.ts","../src/db/mongo.ts","../src/db/model.ts","../src/db/index.ts","../src/tasks/scanner.ts","../src/tasks/index.ts","../src/tasks/thread-runner.ts","../src/tasks/bullmq-backend.ts","../src/compose.ts"],"sourcesContent":["import express from 'express';\nimport cookieParser from 'cookie-parser';\nimport cluster from 'node:cluster';\nimport os from 'node:os';\nimport type { EFCConfig } from './types.js';\nimport { scanDir } from './router/scan.js';\nimport { mountRoutes } from './router/mount.js';\nimport { runMaster } from './cluster/index.js';\nimport { configureAuth } from './auth/index.js';\nimport { HttpError } from './errors.js';\nimport { connectMongo } from './db/mongo.js';\nimport { setDbClient } from './db/index.js';\nimport { scanTasks } from './tasks/scanner.js';\nimport { initBullMQ } from './tasks/bullmq-backend.js';\n\nexport async function ignite(config: EFCConfig): Promise<void> {\n const {\n port = 3000,\n cluster: clusterEnabled = true,\n workers,\n apiDir,\n jwtSecret,\n authStrategy = 'http-only',\n globalMiddlewares = [],\n onWorkerReady,\n onWorkerCrash,\n onError,\n } = config;\n\n if (clusterEnabled && cluster.isPrimary) {\n runMaster({\n workers: workers ?? os.cpus().length,\n ...(onWorkerReady !== undefined && { onWorkerReady }),\n ...(onWorkerCrash !== undefined && { onWorkerCrash }),\n });\n return;\n }\n\n const app = express();\n\n app.use(express.json());\n app.use(express.urlencoded({ extended: true }));\n app.use(cookieParser());\n\n for (const mw of globalMiddlewares) {\n app.use(mw);\n }\n\n // Pre-Flight step 1: Connect database\n if (config.database === 'mongodb' && config.databaseUrl) {\n const conn = await connectMongo(config.databaseUrl);\n setDbClient(conn as unknown as Record<string, unknown>);\n }\n\n // Pre-Flight step 2: Configure auth\n if (jwtSecret) {\n const cookieDomain = process.env['COOKIE_DOMAIN'];\n configureAuth({\n secret: jwtSecret,\n strategy: authStrategy,\n expiresIn: process.env['JWT_EXPIRES_IN'] ?? '7d',\n ...(cookieDomain !== undefined && { cookieDomain }),\n });\n }\n\n // Pre-Flight step 3: Scan and register tasks\n if (config.tasksDir) {\n await scanTasks(config.tasksDir);\n }\n\n // Pre-Flight step 4: Start task queue backend\n if (config.tasks) {\n if (config.tasks.backend === 'bullmq') {\n await initBullMQ({\n redisUrl: config.tasks.redisUrl ?? 'redis://localhost:6379',\n concurrency: config.tasks.concurrency ?? 5,\n });\n }\n }\n\n // Pre-Flight step 5: Scan routes and mount\n const routes = scanDir(apiDir);\n await mountRoutes(app, routes);\n\n if (onError) {\n app.use(onError);\n } else {\n app.use(\n (\n err: unknown,\n _req: express.Request,\n res: express.Response,\n _next: express.NextFunction,\n ) => {\n if (err instanceof HttpError) {\n res.status(err.statusCode).json({ error: err.message, statusCode: err.statusCode });\n } else {\n console.error('[EFC] Unhandled error:', err);\n res.status(500).json({ error: 'Internal Server Error', statusCode: 500 });\n }\n },\n );\n }\n\n await new Promise<void>((resolve) => {\n app.listen(port, () => {\n const wid = (cluster.worker as { id: number } | undefined)?.id ?? 'primary';\n console.log(`[EFC] Worker ${wid} listening on :${port}`);\n resolve();\n });\n });\n}\n\nexport { HttpError } from './errors.js';\nexport { compose } from './compose.js';\nexport { db, setDbClient, getDbClient, defineModel } from './db/index.js';\nexport { scanDir } from './router/scan.js';\nexport type {\n EFCConfig,\n RouteEntry,\n TaskOptions,\n TaskDefinition,\n DatabaseEngine,\n AuthStrategy,\n ModelSchema,\n ModelCRUD,\n} from './types.js';\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","import type { Application, RequestHandler } from 'express';\nimport type { RouteEntry } from '../types.js';\n\nconst HTTP_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'] as const;\ntype HttpMethod = (typeof HTTP_METHODS)[number];\n\nfunction asyncWrap(handler: RequestHandler): RequestHandler {\n return (req, res, next) => {\n Promise.resolve(handler(req, res, next)).catch(next);\n };\n}\n\nexport async function mountRoutes(app: Application, routes: RouteEntry[]): Promise<void> {\n for (const route of routes) {\n const mod = (await import(route.filePath)) as Record<string, unknown>;\n const routeMiddlewares: RequestHandler[] = Array.isArray(mod['middlewares'])\n ? (mod['middlewares'] as RequestHandler[])\n : [];\n\n const implemented: HttpMethod[] = [];\n const unimplemented: HttpMethod[] = [];\n\n for (const method of HTTP_METHODS) {\n if (typeof mod[method] === 'function') {\n implemented.push(method);\n app[method.toLowerCase() as Lowercase<HttpMethod>](\n route.urlPath,\n ...routeMiddlewares,\n asyncWrap(mod[method] as RequestHandler),\n );\n } else {\n unimplemented.push(method);\n }\n }\n\n if (implemented.length > 0 && unimplemented.length > 0) {\n const allowHeader = implemented.join(', ');\n app.all(route.urlPath, (req, res, next) => {\n if ((unimplemented as string[]).includes(req.method)) {\n res.set('Allow', allowHeader).status(405).json({ error: 'Method Not Allowed' });\n } else {\n next();\n }\n });\n }\n }\n}\n\nexport { asyncWrap };\n","import cluster from 'node:cluster';\nimport os from 'node:os';\n\ninterface ClusterOptions {\n workers?: number;\n onWorkerReady?: ((id: number) => void) | undefined;\n onWorkerCrash?: ((id: number, code: number) => void) | undefined;\n}\n\nexport function runMaster(options: ClusterOptions = {}): void {\n const count = options.workers ?? os.cpus().length;\n\n console.log(`[EFC] Primary ${process.pid} starting ${count} workers`);\n\n for (let i = 0; i < count; i++) {\n cluster.fork();\n }\n\n cluster.on('online', (worker) => {\n options.onWorkerReady?.(worker.id);\n });\n\n cluster.on('exit', (worker, code, signal) => {\n const exitCode = code ?? (signal ? -1 : 0);\n console.warn(`[EFC] Worker ${worker.id} exited (code=${exitCode}), respawning…`);\n options.onWorkerCrash?.(worker.id, exitCode);\n cluster.fork();\n });\n}\n\nexport { cluster };\n","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","export class HttpError extends Error {\n readonly statusCode: number;\n\n constructor(statusCode: number, message: string) {\n super(message);\n this.name = 'HttpError';\n this.statusCode = statusCode;\n Error.captureStackTrace(this, HttpError);\n }\n}\n","// Wraps mongoose connection for Pre-Flight. Throws clearly if mongoose isn't installed.\n\nlet mongoose: typeof import('mongoose');\n\nasync function loadMongoose(): Promise<typeof import('mongoose')> {\n if (mongoose) return mongoose;\n try {\n mongoose = await import('mongoose');\n return mongoose;\n } catch {\n throw new Error(\n '[EFC] mongoose is not installed. Run: npm install mongoose',\n );\n }\n}\n\nexport async function connectMongo(url: string): Promise<import('mongoose').Connection> {\n const mg = await loadMongoose();\n await mg.connect(url);\n console.log('[EFC] MongoDB connected');\n return mg.connection;\n}\n","import type { ModelSchema, ModelCRUD } from '../types.js';\n\ntype AnyRecord = Record<string, unknown> & { id: string };\n\nfunction normalise(doc: Record<string, unknown>): AnyRecord {\n const id = doc['_id'] ? String(doc['_id']) : '';\n return { ...doc, id } as AnyRecord;\n}\n\nasync function getModel(name: string, schemaObj: Record<string, unknown>): Promise<import('mongoose').Model<Record<string, unknown>>> {\n let mg: typeof import('mongoose');\n try {\n mg = await import('mongoose');\n } catch {\n throw new Error('[EFC] mongoose is not installed. Run: npm install mongoose');\n }\n\n if (mg.models[name]) return mg.models[name] as import('mongoose').Model<Record<string, unknown>>;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const schema = new mg.Schema(schemaObj as any, { timestamps: true });\n return mg.model<Record<string, unknown>>(name, schema);\n}\n\nfunction buildMongooseSchema(schema: ModelSchema): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, def] of Object.entries(schema)) {\n const entry: Record<string, unknown> = {};\n switch (def.type) {\n case 'string': entry['type'] = String; break;\n case 'number': entry['type'] = Number; break;\n case 'boolean': entry['type'] = Boolean; break;\n case 'date': entry['type'] = Date; break;\n case 'object': entry['type'] = Object; break;\n case 'array': entry['type'] = Array; break;\n }\n if (def.required !== undefined) entry['required'] = def.required;\n if (def.unique !== undefined) entry['unique'] = def.unique;\n if (def.default !== undefined) entry['default'] = def.default;\n out[key] = entry;\n }\n return out;\n}\n\nexport function defineModel<T extends Record<string, unknown>>(\n name: string,\n schema: ModelSchema,\n): ModelCRUD<T> {\n const mongooseSchema = buildMongooseSchema(schema);\n\n return {\n async find(filter = {}) {\n const M = await getModel(name, mongooseSchema);\n const docs = await M.find(filter as Record<string, unknown>).lean();\n return (docs as Record<string, unknown>[]).map(normalise) as (T & { id: string })[];\n },\n\n async findById(id) {\n const M = await getModel(name, mongooseSchema);\n const doc = await M.findById(id).lean();\n if (!doc) return null;\n return normalise(doc as Record<string, unknown>) as T & { id: string };\n },\n\n async findOne(filter) {\n const M = await getModel(name, mongooseSchema);\n const doc = await M.findOne(filter as Record<string, unknown>).lean();\n if (!doc) return null;\n return normalise(doc as Record<string, unknown>) as T & { id: string };\n },\n\n async create(data) {\n const M = await getModel(name, mongooseSchema);\n const doc = await M.create(data);\n return normalise(doc.toObject() as Record<string, unknown>) as T & { id: string };\n },\n\n async update(id, data) {\n const M = await getModel(name, mongooseSchema);\n const doc = await M.findByIdAndUpdate(id, data, { new: true }).lean();\n if (!doc) return null;\n return normalise(doc as Record<string, unknown>) as T & { id: string };\n },\n\n async delete(id) {\n const M = await getModel(name, mongooseSchema);\n await M.findByIdAndDelete(id);\n },\n\n async count(filter = {}) {\n const M = await getModel(name, mongooseSchema);\n return M.countDocuments(filter as Record<string, unknown>);\n },\n };\n}\n","// Thread-local DB client populated during Pre-Flight.\n// The Proxy ensures callers import `db` once and never null-check it —\n// it throws with a helpful message if accessed before Pre-Flight completes.\n\ntype AnyClient = Record<string, unknown>;\n\nlet _client: AnyClient | null = null;\n\nexport function setDbClient(client: AnyClient): void {\n _client = client;\n}\n\nexport function getDbClient(): AnyClient {\n if (!_client) {\n throw new Error('[EFC] db not ready — accessed before Pre-Flight completed');\n }\n return _client;\n}\n\nexport const db: AnyClient = new Proxy({} as AnyClient, {\n get(_target, prop: string) {\n return getDbClient()[prop];\n },\n set(_target, prop: string, value: unknown) {\n getDbClient()[prop] = value;\n return true;\n },\n});\n\nexport { connectMongo } from './mongo.js';\nexport { defineModel } from './model.js';\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { registerTask } from './index.js';\nimport type { TaskDefinition } from '../types.js';\n\nexport async function scanTasks(tasksDir: string): Promise<void> {\n if (!fs.existsSync(tasksDir)) return;\n\n const files = fs.readdirSync(tasksDir).filter((f) => /\\.(ts|js|mts|mjs)$/.test(f));\n\n for (const file of files) {\n const filePath = path.join(tasksDir, file);\n const taskName = path.basename(file, path.extname(file));\n\n try {\n const mod = await import(filePath) as Record<string, unknown>;\n const def = mod['default'] as TaskDefinition | undefined;\n\n if (!def || typeof def.handler !== 'function') {\n console.warn(`[EFC] Task file ${file} has no valid default export — skipping`);\n continue;\n }\n\n registerTask(taskName, { ...def, filePath });\n console.log(`[EFC] Registered task: ${taskName}`);\n } catch (err) {\n console.warn(`[EFC] Failed to load task ${file}:`, err);\n }\n }\n}\n","import type { TaskDefinition, TaskOptions } from '../types.js';\n\nexport const taskRegistry = new Map<string, TaskDefinition>();\n\ntype HandlerFn<T> = (payload: T) => Promise<void>;\ntype DefineTaskOverload = {\n <T>(handler: HandlerFn<T>): TaskDefinition<T>;\n <T>(options: TaskOptions, handler: HandlerFn<T>): TaskDefinition<T>;\n};\n\nexport const defineTask: DefineTaskOverload = <T>(\n handlerOrOptions: HandlerFn<T> | TaskOptions,\n maybeHandler?: HandlerFn<T>,\n): TaskDefinition<T> => {\n let options: TaskOptions = {};\n let handler: HandlerFn<T>;\n\n if (typeof handlerOrOptions === 'function') {\n handler = handlerOrOptions;\n } else {\n options = handlerOrOptions;\n if (!maybeHandler) throw new Error('[EFC] defineTask: handler function is required');\n handler = maybeHandler;\n }\n\n return {\n handler: handler as (payload: unknown) => Promise<void>,\n options,\n name: '',\n };\n};\n\ntype EnqueueImpl = (name: string, payload: unknown) => Promise<void>;\nlet _impl: EnqueueImpl | null = null;\n\nexport function setEnqueueImpl(impl: EnqueueImpl): void {\n _impl = impl;\n}\n\nexport async function enqueue<T>(name: string, payload: T): Promise<void> {\n if (!_impl) {\n throw new Error(\n `[EFC] Task queue not initialised. Set tasks.backend in ignite() config.`,\n );\n }\n return _impl(name, payload as unknown);\n}\n\nexport function registerTask(name: string, def: TaskDefinition): void {\n taskRegistry.set(name, { ...def, name });\n}\n","import { Worker, workerData, parentPort, isMainThread } from 'node:worker_threads';\nimport type { TaskDefinition } from '../types.js';\n\n// ── Worker-thread side ────────────────────────────────────────────────────────\nif (!isMainThread) {\n const { handlerPath, payload } = workerData as { handlerPath: string; payload: unknown };\n\n (async () => {\n try {\n const mod = await import(handlerPath) as Record<string, unknown>;\n const def = mod['default'] as TaskDefinition | undefined;\n if (!def || typeof def.handler !== 'function') {\n throw new Error(`[EFC] Thread runner: no valid task export in ${handlerPath}`);\n }\n await def.handler(payload);\n parentPort?.postMessage({ ok: true });\n } catch (err) {\n parentPort?.postMessage({ ok: false, error: String(err) });\n }\n })();\n}\n\n// ── Main-thread side ──────────────────────────────────────────────────────────\nexport function runInThread(handlerPath: string, payload: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(new URL('./thread-runner.js', import.meta.url), {\n workerData: { handlerPath, payload },\n });\n\n worker.on('message', (msg: { ok: boolean; error?: string }) => {\n if (msg.ok) resolve();\n else reject(new Error(msg.error ?? 'Thread task failed'));\n });\n\n worker.on('error', reject);\n worker.on('exit', (code) => {\n if (code !== 0) reject(new Error(`Thread worker exited with code ${code}`));\n });\n });\n}\n","import type { Job } from 'bullmq';\nimport { taskRegistry, setEnqueueImpl } from './index.js';\nimport { runInThread } from './thread-runner.js';\n\ninterface BullMQOpts {\n redisUrl: string;\n concurrency: number;\n}\n\nexport async function initBullMQ(opts: BullMQOpts): Promise<void> {\n let bullmq: typeof import('bullmq');\n try {\n bullmq = await import('bullmq');\n } catch {\n throw new Error('[EFC] bullmq is not installed. Run: npm install bullmq');\n }\n\n const connection = parseRedisUrl(opts.redisUrl);\n const queue = new bullmq.Queue('efc', { connection });\n\n const worker = new bullmq.Worker(\n 'efc',\n async (job: Job) => {\n const def = taskRegistry.get(job.name);\n if (!def) {\n throw new Error(`[EFC] No task registered for name: ${job.name}`);\n }\n\n if (def.options.thread && def.filePath) {\n await runInThread(def.filePath, job.data);\n } else {\n await def.handler(job.data);\n }\n },\n { connection, concurrency: opts.concurrency },\n );\n\n worker.on('failed', (job: Job | undefined, err: Error) => {\n console.error(`[EFC] Task ${job?.name ?? 'unknown'} failed:`, err.message);\n });\n\n worker.on('completed', (job: Job) => {\n console.log(`[EFC] Task ${job.name} completed (id=${job.id})`);\n });\n\n setEnqueueImpl(async (name, payload) => {\n const def = taskRegistry.get(name);\n if (!def) {\n throw new Error(`[EFC] Cannot enqueue unknown task: \"${name}\". Is the task file in tasksDir?`);\n }\n\n await queue.add(name, payload, {\n attempts: def.options.retries ?? 3,\n backoff: {\n type: def.options.backoff ?? 'exponential',\n delay: 1000,\n },\n });\n });\n\n console.log('[EFC] BullMQ backend initialised');\n}\n\nfunction parseRedisUrl(url: string): { host: string; port: number; password?: string } {\n try {\n const u = new URL(url);\n const result: { host: string; port: number; password?: string } = {\n host: u.hostname || 'localhost',\n port: parseInt(u.port || '6379', 10),\n };\n if (u.password) result.password = u.password;\n return result;\n } catch {\n return { host: 'localhost', port: 6379 };\n }\n}\n","import type { RequestHandler } from 'express';\n\nexport function compose(...handlers: RequestHandler[]): RequestHandler {\n return (req, res, next) => {\n let index = 0;\n\n function dispatch(i: number): void {\n if (i >= handlers.length) {\n next();\n return;\n }\n const handler = handlers[i];\n if (!handler) {\n next();\n return;\n }\n try {\n Promise.resolve(handler(req, res, () => dispatch(i + 1))).catch(next);\n } catch (err) {\n next(err);\n }\n }\n\n dispatch(index);\n };\n}\n"],"mappings":"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","names":["import_node_cluster","import_node_os","fs","path","os","cluster","import_node_fs","import_node_path","fs","path","cluster","os","express","cookieParser"]}
@@ -0,0 +1,23 @@
1
+ import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-DNdkDUPX.cjs';
2
+ export { A as AuthStrategy, D as DatabaseEngine, T as TaskDefinition, a as TaskOptions } from './types-DNdkDUPX.cjs';
3
+ import { RequestHandler } from 'express';
4
+
5
+ declare class HttpError extends Error {
6
+ readonly statusCode: number;
7
+ constructor(statusCode: number, message: string);
8
+ }
9
+
10
+ declare function compose(...handlers: RequestHandler[]): RequestHandler;
11
+
12
+ declare function defineModel<T extends Record<string, unknown>>(name: string, schema: ModelSchema): ModelCRUD<T>;
13
+
14
+ type AnyClient = Record<string, unknown>;
15
+ declare function setDbClient(client: AnyClient): void;
16
+ declare function getDbClient(): AnyClient;
17
+ declare const db: AnyClient;
18
+
19
+ declare function scanDir(dir: string, base?: string): RouteEntry[];
20
+
21
+ declare function ignite(config: EFCConfig): Promise<void>;
22
+
23
+ export { EFCConfig, HttpError, ModelCRUD, ModelSchema, RouteEntry, compose, db, defineModel, getDbClient, ignite, scanDir, setDbClient };
@@ -0,0 +1,23 @@
1
+ import { M as ModelSchema, b as ModelCRUD, R as RouteEntry, E as EFCConfig } from './types-DNdkDUPX.js';
2
+ export { A as AuthStrategy, D as DatabaseEngine, T as TaskDefinition, a as TaskOptions } from './types-DNdkDUPX.js';
3
+ import { RequestHandler } from 'express';
4
+
5
+ declare class HttpError extends Error {
6
+ readonly statusCode: number;
7
+ constructor(statusCode: number, message: string);
8
+ }
9
+
10
+ declare function compose(...handlers: RequestHandler[]): RequestHandler;
11
+
12
+ declare function defineModel<T extends Record<string, unknown>>(name: string, schema: ModelSchema): ModelCRUD<T>;
13
+
14
+ type AnyClient = Record<string, unknown>;
15
+ declare function setDbClient(client: AnyClient): void;
16
+ declare function getDbClient(): AnyClient;
17
+ declare const db: AnyClient;
18
+
19
+ declare function scanDir(dir: string, base?: string): RouteEntry[];
20
+
21
+ declare function ignite(config: EFCConfig): Promise<void>;
22
+
23
+ export { EFCConfig, HttpError, ModelCRUD, ModelSchema, RouteEntry, compose, db, defineModel, getDbClient, ignite, scanDir, setDbClient };