express-file-cluster 0.2.1 → 0.2.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/auth/index.cjs +2 -2
- package/dist/auth/index.d.cts +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/{chunk-DQGWFWBV.js → chunk-BHMFPULA.js} +1 -1
- package/dist/chunk-BHMFPULA.js.map +1 -0
- package/dist/{chunk-Z5YNIVQG.js → chunk-LPZEKFVN.js} +2 -4
- package/dist/{chunk-Z5YNIVQG.js.map → chunk-LPZEKFVN.js.map} +1 -1
- package/dist/{chunk-QB3X6LKZ.cjs → chunk-UUF2OYRW.cjs} +1 -1
- package/dist/{chunk-QB3X6LKZ.cjs.map → chunk-UUF2OYRW.cjs.map} +1 -1
- package/dist/{chunk-UDE6S53C.cjs → chunk-XH7O25BL.cjs} +2 -4
- package/dist/chunk-XH7O25BL.cjs.map +1 -0
- package/dist/cli/index.cjs +66 -5
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +89 -28
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +615 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +608 -10
- package/dist/index.js.map +1 -1
- package/dist/tasks/index.cjs +2 -2
- package/dist/tasks/index.d.cts +1 -1
- package/dist/tasks/index.d.ts +1 -1
- package/dist/tasks/index.js +1 -1
- package/dist/{types-Dj9-sLOK.d.cts → types-BZehD43d.d.cts} +16 -3
- package/dist/{types-Dj9-sLOK.d.ts → types-BZehD43d.d.ts} +16 -3
- package/package.json +8 -8
- package/dist/chunk-DQGWFWBV.js.map +0 -1
- package/dist/chunk-UDE6S53C.cjs.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkUUF2OYRWcjs = require('./chunk-UUF2OYRW.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
var
|
|
8
|
+
var _chunkXH7O25BLcjs = require('./chunk-XH7O25BL.cjs');
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
var _chunkMQNVNOH5cjs = require('./chunk-MQNVNOH5.cjs');
|
|
12
12
|
|
|
13
13
|
// src/index.ts
|
|
14
|
+
var _fs = require('fs'); var _fs2 = _interopRequireDefault(_fs);
|
|
14
15
|
var _express = require('express'); var _express2 = _interopRequireDefault(_express);
|
|
15
16
|
var _cors = require('cors'); var _cors2 = _interopRequireDefault(_cors);
|
|
16
17
|
var _cookieparser = require('cookie-parser'); var _cookieparser2 = _interopRequireDefault(_cookieparser);
|
|
17
18
|
var _cluster = require('cluster'); var _cluster2 = _interopRequireDefault(_cluster);
|
|
18
19
|
var _os = require('os'); var _os2 = _interopRequireDefault(_os);
|
|
20
|
+
var _path = require('path'); var _path2 = _interopRequireDefault(_path);
|
|
19
21
|
|
|
20
22
|
// src/router/mount.ts
|
|
21
23
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
@@ -25,9 +27,12 @@ function asyncWrap(handler) {
|
|
|
25
27
|
};
|
|
26
28
|
}
|
|
27
29
|
async function mountRoutes(app, routes) {
|
|
30
|
+
const mounted = [];
|
|
28
31
|
for (const route of routes) {
|
|
29
32
|
const mod = await Promise.resolve().then(() => _interopRequireWildcard(require(route.filePath)));
|
|
30
33
|
const routeMiddlewares = Array.isArray(mod["middlewares"]) ? mod["middlewares"] : [];
|
|
34
|
+
const raw = mod["meta"];
|
|
35
|
+
const meta = raw != null && typeof raw === "object" && !Array.isArray(raw) ? raw : void 0;
|
|
31
36
|
const implemented = [];
|
|
32
37
|
const unimplemented = [];
|
|
33
38
|
for (const method of HTTP_METHODS) {
|
|
@@ -52,7 +57,9 @@ async function mountRoutes(app, routes) {
|
|
|
52
57
|
}
|
|
53
58
|
});
|
|
54
59
|
}
|
|
60
|
+
mounted.push({ ...route, methods: implemented, ...meta !== void 0 && { meta } });
|
|
55
61
|
}
|
|
62
|
+
return mounted;
|
|
56
63
|
}
|
|
57
64
|
|
|
58
65
|
// src/cluster/index.ts
|
|
@@ -96,9 +103,7 @@ async function loadMongoose() {
|
|
|
96
103
|
mongoose = await Promise.resolve().then(() => _interopRequireWildcard(require("mongoose")));
|
|
97
104
|
return mongoose;
|
|
98
105
|
} catch (e) {
|
|
99
|
-
throw new Error(
|
|
100
|
-
"[EFC] mongoose is not installed. Run: npm install mongoose"
|
|
101
|
-
);
|
|
106
|
+
throw new Error("[EFC] mongoose is not installed. Run: npm install mongoose");
|
|
102
107
|
}
|
|
103
108
|
}
|
|
104
109
|
async function connectMongo(url) {
|
|
@@ -220,8 +225,8 @@ var db = new Proxy({}, {
|
|
|
220
225
|
});
|
|
221
226
|
|
|
222
227
|
// src/tasks/scanner.ts
|
|
223
|
-
|
|
224
|
-
|
|
228
|
+
|
|
229
|
+
|
|
225
230
|
async function scanTasks(tasksDir) {
|
|
226
231
|
if (!_fs2.default.existsSync(tasksDir)) return;
|
|
227
232
|
const files = _fs2.default.readdirSync(tasksDir).filter((f) => /\.(ts|js|mts|mjs)$/.test(f));
|
|
@@ -235,7 +240,7 @@ async function scanTasks(tasksDir) {
|
|
|
235
240
|
console.warn(`[EFC] Task file ${file} has no valid default export \u2014 skipping`);
|
|
236
241
|
continue;
|
|
237
242
|
}
|
|
238
|
-
|
|
243
|
+
_chunkXH7O25BLcjs.registerTask.call(void 0, taskName, { ...def, filePath });
|
|
239
244
|
console.log(`[EFC] Registered task: ${taskName}`);
|
|
240
245
|
} catch (err) {
|
|
241
246
|
console.warn(`[EFC] Failed to load task ${file}:`, err);
|
|
@@ -290,7 +295,7 @@ async function initBullMQ(opts) {
|
|
|
290
295
|
const worker = new bullmq.Worker(
|
|
291
296
|
"efc",
|
|
292
297
|
async (job) => {
|
|
293
|
-
const def =
|
|
298
|
+
const def = _chunkXH7O25BLcjs.taskRegistry.get(job.name);
|
|
294
299
|
if (!def) {
|
|
295
300
|
throw new Error(`[EFC] No task registered for name: ${job.name}`);
|
|
296
301
|
}
|
|
@@ -308,10 +313,12 @@ async function initBullMQ(opts) {
|
|
|
308
313
|
worker.on("completed", (job) => {
|
|
309
314
|
console.log(`[EFC] Task ${job.name} completed (id=${job.id})`);
|
|
310
315
|
});
|
|
311
|
-
|
|
312
|
-
const def =
|
|
316
|
+
_chunkXH7O25BLcjs.setEnqueueImpl.call(void 0, async (name, payload) => {
|
|
317
|
+
const def = _chunkXH7O25BLcjs.taskRegistry.get(name);
|
|
313
318
|
if (!def) {
|
|
314
|
-
throw new Error(
|
|
319
|
+
throw new Error(
|
|
320
|
+
`[EFC] Cannot enqueue unknown task: "${name}". Is the task file in tasksDir?`
|
|
321
|
+
);
|
|
315
322
|
}
|
|
316
323
|
await queue.add(name, payload, {
|
|
317
324
|
attempts: _nullishCoalesce(def.options.retries, () => ( 3)),
|
|
@@ -337,6 +344,568 @@ function parseRedisUrl(url) {
|
|
|
337
344
|
}
|
|
338
345
|
}
|
|
339
346
|
|
|
347
|
+
// src/dashboard.ts
|
|
348
|
+
var HTTP_STATUS = {
|
|
349
|
+
200: "OK",
|
|
350
|
+
201: "Created",
|
|
351
|
+
202: "Accepted",
|
|
352
|
+
204: "No Content",
|
|
353
|
+
400: "Bad Request",
|
|
354
|
+
401: "Unauthorized",
|
|
355
|
+
403: "Forbidden",
|
|
356
|
+
404: "Not Found",
|
|
357
|
+
405: "Method Not Allowed",
|
|
358
|
+
409: "Conflict",
|
|
359
|
+
422: "Unprocessable Entity",
|
|
360
|
+
500: "Internal Server Error",
|
|
361
|
+
503: "Service Unavailable"
|
|
362
|
+
};
|
|
363
|
+
function generateDashboard(routes, basePath, port, projectName, projectVersion) {
|
|
364
|
+
const safeRoutes = JSON.stringify(
|
|
365
|
+
routes.map((r) => ({ urlPath: r.urlPath, methods: r.methods, params: r.params, meta: _nullishCoalesce(r.meta, () => ( null)) }))
|
|
366
|
+
).replace(/<\/script>/gi, "<\\/script>");
|
|
367
|
+
const safeHttpStatus = JSON.stringify(HTTP_STATUS);
|
|
368
|
+
return `<!DOCTYPE html>
|
|
369
|
+
<html lang="en">
|
|
370
|
+
<head>
|
|
371
|
+
<meta charset="UTF-8" />
|
|
372
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
373
|
+
<title>${projectName} \u2014 API Reference</title>
|
|
374
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
375
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
376
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap" rel="stylesheet" />
|
|
377
|
+
<style>
|
|
378
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
379
|
+
:root {
|
|
380
|
+
--bg: #080b0f;
|
|
381
|
+
--bg-card: #0d1117;
|
|
382
|
+
--bg-raised: #111820;
|
|
383
|
+
--border: #1e2832;
|
|
384
|
+
--border-lit: #263040;
|
|
385
|
+
--text: #e2e8f0;
|
|
386
|
+
--text-dim: #64748b;
|
|
387
|
+
--text-muted: #334155;
|
|
388
|
+
--accent: #F0A030;
|
|
389
|
+
--accent-dim: rgba(240,160,48,.12);
|
|
390
|
+
--accent-glow: rgba(240,160,48,.22);
|
|
391
|
+
--purple: #a78bfa;
|
|
392
|
+
--blue: #60a5fa;
|
|
393
|
+
--orange: #fb923c;
|
|
394
|
+
--green: #7AAE8E;
|
|
395
|
+
--radius: 10px;
|
|
396
|
+
--radius-lg: 16px;
|
|
397
|
+
--font-mono: 'JetBrains Mono', monospace;
|
|
398
|
+
--font-sans: 'Inter', sans-serif;
|
|
399
|
+
}
|
|
400
|
+
html { scroll-behavior: smooth; }
|
|
401
|
+
body {
|
|
402
|
+
background: var(--bg); color: var(--text);
|
|
403
|
+
font-family: var(--font-sans); font-size: 16px;
|
|
404
|
+
line-height: 1.6; -webkit-font-smoothing: antialiased;
|
|
405
|
+
position: relative;
|
|
406
|
+
}
|
|
407
|
+
body::before {
|
|
408
|
+
content: ''; position: fixed; inset: 0; z-index: 0;
|
|
409
|
+
background-image:
|
|
410
|
+
linear-gradient(var(--border) 1px, transparent 1px),
|
|
411
|
+
linear-gradient(90deg, var(--border) 1px, transparent 1px);
|
|
412
|
+
background-size: 60px 60px; opacity: .28; pointer-events: none;
|
|
413
|
+
}
|
|
414
|
+
section, footer, .page-hero, .docs-layout { position: relative; z-index: 1; }
|
|
415
|
+
a { text-decoration: none; color: inherit; }
|
|
416
|
+
em { font-style: italic; }
|
|
417
|
+
code {
|
|
418
|
+
font-family: var(--font-mono); font-size: .85em;
|
|
419
|
+
background: var(--bg-raised); border: 1px solid var(--border);
|
|
420
|
+
border-radius: 4px; padding: 1px 6px; color: var(--accent);
|
|
421
|
+
}
|
|
422
|
+
.container { max-width: 1140px; margin: 0 auto; padding: 0 24px; }
|
|
423
|
+
::-webkit-scrollbar { width: 6px; }
|
|
424
|
+
::-webkit-scrollbar-track { background: var(--bg); }
|
|
425
|
+
::-webkit-scrollbar-thumb { background: var(--border-lit); border-radius: 3px; }
|
|
426
|
+
|
|
427
|
+
/* \u2500\u2500 PAGE HERO \u2500\u2500 */
|
|
428
|
+
.page-hero {
|
|
429
|
+
padding: 48px 0 56px; border-bottom: 1px solid var(--border);
|
|
430
|
+
}
|
|
431
|
+
.page-hero .hero-glow {
|
|
432
|
+
position: absolute; top: -40px; left: 10%; width: 500px; height: 350px;
|
|
433
|
+
background: radial-gradient(ellipse, rgba(240,160,48,.1) 0%, transparent 68%);
|
|
434
|
+
pointer-events: none;
|
|
435
|
+
}
|
|
436
|
+
.page-title {
|
|
437
|
+
font-size: clamp(2rem, 5vw, 3.4rem); font-weight: 800;
|
|
438
|
+
line-height: 1.1; letter-spacing: -.02em; margin-bottom: 24px;
|
|
439
|
+
display: flex; align-items: baseline; gap: 16px; flex-wrap: wrap;
|
|
440
|
+
}
|
|
441
|
+
.project-version {
|
|
442
|
+
font-family: var(--font-mono); font-size: clamp(.85rem, 2vw, 1.1rem);
|
|
443
|
+
font-weight: 500; color: var(--accent);
|
|
444
|
+
background: var(--accent-dim); border: 1px solid rgba(240,160,48,.3);
|
|
445
|
+
border-radius: 6px; padding: 2px 10px; letter-spacing: .5px;
|
|
446
|
+
}
|
|
447
|
+
.hero-meta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 40px; }
|
|
448
|
+
.base-url-pill {
|
|
449
|
+
display: flex; align-items: center; gap: 8px;
|
|
450
|
+
background: var(--bg-card); border: 1px solid var(--border);
|
|
451
|
+
border-radius: 7px; padding: 8px 14px;
|
|
452
|
+
}
|
|
453
|
+
.base-url-label { font-size: .72rem; font-family: var(--font-mono);
|
|
454
|
+
color: var(--text-muted); text-transform: uppercase; letter-spacing: .5px; }
|
|
455
|
+
.base-url-val { font-family: var(--font-mono); font-size: .8rem; color: var(--accent); }
|
|
456
|
+
.count-pill {
|
|
457
|
+
font-family: var(--font-mono); font-size: .72rem; color: var(--text-dim);
|
|
458
|
+
background: var(--bg-card); border: 1px solid var(--border);
|
|
459
|
+
border-radius: 7px; padding: 8px 14px;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/* \u2500\u2500 TOOLBAR \u2500\u2500 */
|
|
463
|
+
.toolbar {
|
|
464
|
+
display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
|
|
465
|
+
}
|
|
466
|
+
.method-filters { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
467
|
+
.filter-btn {
|
|
468
|
+
background: var(--bg-card); border: 1px solid var(--border);
|
|
469
|
+
color: var(--text-dim); font-family: var(--font-mono);
|
|
470
|
+
font-size: .72rem; font-weight: 600; letter-spacing: .5px;
|
|
471
|
+
padding: 6px 12px; border-radius: 6px; cursor: pointer;
|
|
472
|
+
transition: all .15s;
|
|
473
|
+
}
|
|
474
|
+
.filter-btn:hover { border-color: var(--border-lit); color: var(--text); }
|
|
475
|
+
.filter-btn.active { background: var(--accent); color: #0d0d1a; border-color: var(--accent); }
|
|
476
|
+
.filter-btn[data-method="GET"].active { background: rgba(96,165,250,.18); color: #60a5fa; border-color: rgba(96,165,250,.4); }
|
|
477
|
+
.filter-btn[data-method="POST"].active { background: rgba(122,174,142,.18); color: #7AAE8E; border-color: rgba(122,174,142,.4); }
|
|
478
|
+
.filter-btn[data-method="PUT"].active { background: rgba(240,160,48,.18); color: #F0A030; border-color: rgba(240,160,48,.4); }
|
|
479
|
+
.filter-btn[data-method="PATCH"].active { background: rgba(251,191,36,.18); color: #fbbf24; border-color: rgba(251,191,36,.4); }
|
|
480
|
+
.filter-btn[data-method="DELETE"].active { background: rgba(248,113,113,.18); color: #f87171; border-color: rgba(248,113,113,.4); }
|
|
481
|
+
.filter-btn[data-method="HEAD"].active { background: rgba(167,139,250,.18); color: #a78bfa; border-color: rgba(167,139,250,.4); }
|
|
482
|
+
.search-wrap { margin-left: auto; }
|
|
483
|
+
.search-input {
|
|
484
|
+
background: var(--bg-card); border: 1px solid var(--border);
|
|
485
|
+
color: var(--text); font-family: var(--font-sans); font-size: .85rem;
|
|
486
|
+
padding: 7px 14px; border-radius: 7px; width: 240px;
|
|
487
|
+
outline: none; transition: border-color .2s;
|
|
488
|
+
}
|
|
489
|
+
.search-input::placeholder { color: var(--text-muted); }
|
|
490
|
+
.search-input:focus { border-color: var(--border-lit); }
|
|
491
|
+
|
|
492
|
+
/* \u2500\u2500 DOCS LAYOUT \u2500\u2500 */
|
|
493
|
+
.docs-layout {
|
|
494
|
+
display: grid; grid-template-columns: 220px 1fr;
|
|
495
|
+
gap: 48px; padding: 52px 0 80px; max-width: 1140px;
|
|
496
|
+
margin: 0 auto; padding-left: 24px; padding-right: 24px;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/* \u2500\u2500 SIDEBAR \u2500\u2500 */
|
|
500
|
+
.docs-sidebar { position: sticky; top: 24px; height: fit-content; }
|
|
501
|
+
.sidebar-section { margin-bottom: 28px; }
|
|
502
|
+
.sidebar-label {
|
|
503
|
+
font-family: var(--font-mono); font-size: .68rem; font-weight: 600;
|
|
504
|
+
color: var(--text-muted); letter-spacing: 1.2px; text-transform: uppercase;
|
|
505
|
+
margin-bottom: 8px; padding: 0 4px;
|
|
506
|
+
}
|
|
507
|
+
.sidebar-link {
|
|
508
|
+
display: flex; align-items: center; gap: 8px;
|
|
509
|
+
padding: 7px 10px; border-radius: 6px;
|
|
510
|
+
border-left: 2px solid transparent;
|
|
511
|
+
font-size: .82rem; color: var(--text-dim); cursor: pointer;
|
|
512
|
+
transition: background .15s, color .15s, border-color .15s;
|
|
513
|
+
text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
|
|
514
|
+
}
|
|
515
|
+
.sidebar-link:hover { background: var(--bg-raised); color: var(--text); }
|
|
516
|
+
.sidebar-link.active { color: var(--accent); border-left-color: var(--accent); background: var(--accent-dim); }
|
|
517
|
+
.sidebar-method-dot {
|
|
518
|
+
width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
|
|
519
|
+
}
|
|
520
|
+
.sidebar-path { font-family: var(--font-mono); font-size: .75rem; }
|
|
521
|
+
|
|
522
|
+
/* \u2500\u2500 ENDPOINT CARDS \u2500\u2500 */
|
|
523
|
+
.endpoint-card {
|
|
524
|
+
background: var(--bg-card); border: 1px solid var(--border);
|
|
525
|
+
border-radius: var(--radius-lg); margin-bottom: 20px;
|
|
526
|
+
overflow: hidden; transition: border-color .2s;
|
|
527
|
+
animation: fadeUp .45s ease both;
|
|
528
|
+
}
|
|
529
|
+
.endpoint-card:hover { border-color: var(--border-lit); }
|
|
530
|
+
@keyframes fadeUp {
|
|
531
|
+
from { opacity: 0; transform: translateY(16px); }
|
|
532
|
+
to { opacity: 1; transform: translateY(0); }
|
|
533
|
+
}
|
|
534
|
+
@media (prefers-reduced-motion: reduce) {
|
|
535
|
+
.endpoint-card { animation: none; }
|
|
536
|
+
}
|
|
537
|
+
.endpoint-header {
|
|
538
|
+
display: flex; align-items: center; gap: 14px;
|
|
539
|
+
padding: 20px 24px 18px; border-bottom: 1px solid var(--border);
|
|
540
|
+
flex-wrap: wrap;
|
|
541
|
+
}
|
|
542
|
+
.method-badges { display: flex; gap: 6px; flex-wrap: wrap; }
|
|
543
|
+
.method-badge {
|
|
544
|
+
font-family: var(--font-mono); font-size: .7rem; font-weight: 600;
|
|
545
|
+
letter-spacing: .8px; padding: 4px 10px; border-radius: 5px;
|
|
546
|
+
border: 1px solid; text-transform: uppercase;
|
|
547
|
+
}
|
|
548
|
+
.endpoint-path {
|
|
549
|
+
font-family: var(--font-mono); font-size: .9rem; color: var(--text);
|
|
550
|
+
background: none; border: none; padding: 0;
|
|
551
|
+
word-break: break-all;
|
|
552
|
+
}
|
|
553
|
+
.endpoint-body { padding: 18px 24px 24px; }
|
|
554
|
+
.endpoint-desc { font-size: .9rem; color: var(--text-dim); line-height: 1.7; margin-bottom: 20px; }
|
|
555
|
+
|
|
556
|
+
/* \u2500\u2500 CODE BLOCKS \u2500\u2500 */
|
|
557
|
+
.example-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
|
|
558
|
+
.code-block-wrap {
|
|
559
|
+
background: var(--bg-raised); border: 1px solid var(--border);
|
|
560
|
+
border-radius: var(--radius); overflow: hidden;
|
|
561
|
+
}
|
|
562
|
+
.code-bar {
|
|
563
|
+
display: flex; align-items: center; gap: 6px;
|
|
564
|
+
padding: 9px 14px; border-bottom: 1px solid var(--border);
|
|
565
|
+
background: var(--bg-card);
|
|
566
|
+
}
|
|
567
|
+
.dot { width: 11px; height: 11px; border-radius: 50%; }
|
|
568
|
+
.dot-r { background: #ff5f57; }
|
|
569
|
+
.dot-y { background: #febc2e; }
|
|
570
|
+
.dot-g { background: #28c840; }
|
|
571
|
+
.code-label { font-family: var(--font-mono); font-size: .68rem; color: var(--text-dim); margin-left: 4px; }
|
|
572
|
+
pre.code-pre {
|
|
573
|
+
font-family: var(--font-mono); font-size: .78rem; line-height: 1.7;
|
|
574
|
+
padding: 16px 18px; overflow-x: auto; tab-size: 2; white-space: pre;
|
|
575
|
+
}
|
|
576
|
+
.c-dim { color: var(--text-muted); }
|
|
577
|
+
.c-green { color: #7AAE8E; }
|
|
578
|
+
.c-blue { color: #60a5fa; }
|
|
579
|
+
.c-orange { color: #fb923c; }
|
|
580
|
+
.c-purple { color: #a78bfa; }
|
|
581
|
+
.c-accent { color: var(--accent); }
|
|
582
|
+
.status-2xx { color: #7AAE8E; }
|
|
583
|
+
.status-4xx { color: #f87171; }
|
|
584
|
+
.status-5xx { color: #fb923c; }
|
|
585
|
+
|
|
586
|
+
/* \u2500\u2500 EMPTY STATE \u2500\u2500 */
|
|
587
|
+
.empty-state {
|
|
588
|
+
text-align: center; padding: 80px 24px;
|
|
589
|
+
color: var(--text-muted); font-size: .9rem;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/* \u2500\u2500 RESPONSIVE \u2500\u2500 */
|
|
593
|
+
@media (max-width: 900px) {
|
|
594
|
+
.docs-layout { grid-template-columns: 1fr; }
|
|
595
|
+
.docs-sidebar { position: static; }
|
|
596
|
+
.example-grid { grid-template-columns: 1fr; }
|
|
597
|
+
.search-wrap { margin-left: 0; width: 100%; }
|
|
598
|
+
.search-input { width: 100%; }
|
|
599
|
+
}
|
|
600
|
+
@media (max-width: 600px) {
|
|
601
|
+
.page-hero { padding: 32px 0 32px; }
|
|
602
|
+
.page-title { font-size: 2rem; }
|
|
603
|
+
}
|
|
604
|
+
</style>
|
|
605
|
+
</head>
|
|
606
|
+
<body>
|
|
607
|
+
|
|
608
|
+
<div class="page-hero">
|
|
609
|
+
<div class="hero-glow"></div>
|
|
610
|
+
<div class="container">
|
|
611
|
+
<h1 class="page-title">${projectName}${projectVersion ? `<span class="project-version">v${projectVersion}</span>` : ""}</h1>
|
|
612
|
+
<div class="hero-meta">
|
|
613
|
+
<div class="base-url-pill">
|
|
614
|
+
<span class="base-url-label">Base</span>
|
|
615
|
+
<span class="base-url-val">http://localhost:${port}${basePath}</span>
|
|
616
|
+
</div>
|
|
617
|
+
<div class="count-pill" id="countPill"></div>
|
|
618
|
+
</div>
|
|
619
|
+
<div class="toolbar">
|
|
620
|
+
<div class="method-filters" id="methodFilters">
|
|
621
|
+
<button class="filter-btn active" data-method="ALL">ALL</button>
|
|
622
|
+
</div>
|
|
623
|
+
<div class="search-wrap">
|
|
624
|
+
<input type="text" id="searchInput" class="search-input" placeholder="Search endpoints\u2026" />
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
</div>
|
|
628
|
+
</div>
|
|
629
|
+
|
|
630
|
+
<div class="docs-layout">
|
|
631
|
+
<aside class="docs-sidebar" id="sidebar"></aside>
|
|
632
|
+
<main id="endpoints"></main>
|
|
633
|
+
</div>
|
|
634
|
+
|
|
635
|
+
<script>
|
|
636
|
+
const ROUTES = ${safeRoutes};
|
|
637
|
+
const BASE_PATH = ${JSON.stringify(basePath)};
|
|
638
|
+
const HTTP_STATUS = ${safeHttpStatus};
|
|
639
|
+
|
|
640
|
+
const METHOD_STYLE = {
|
|
641
|
+
GET: { bg: 'rgba(96,165,250,.14)', color: '#60a5fa', border: 'rgba(96,165,250,.35)' },
|
|
642
|
+
POST: { bg: 'rgba(122,174,142,.14)', color: '#7AAE8E', border: 'rgba(122,174,142,.35)' },
|
|
643
|
+
PUT: { bg: 'rgba(240,160,48,.14)', color: '#F0A030', border: 'rgba(240,160,48,.35)' },
|
|
644
|
+
PATCH: { bg: 'rgba(251,191,36,.14)', color: '#fbbf24', border: 'rgba(251,191,36,.35)' },
|
|
645
|
+
DELETE: { bg: 'rgba(248,113,113,.14)', color: '#f87171', border: 'rgba(248,113,113,.35)' },
|
|
646
|
+
HEAD: { bg: 'rgba(167,139,250,.14)', color: '#a78bfa', border: 'rgba(167,139,250,.35)' },
|
|
647
|
+
OPTIONS: { bg: 'rgba(148,163,184,.14)', color: '#94a3b8', border: 'rgba(148,163,184,.35)' },
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
function esc(s) {
|
|
651
|
+
return String(s)
|
|
652
|
+
.replace(/&/g,'&').replace(/</g,'<')
|
|
653
|
+
.replace(/>/g,'>').replace(/"/g,'"');
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function methodBadge(m) {
|
|
657
|
+
const s = METHOD_STYLE[m] || METHOD_STYLE.GET;
|
|
658
|
+
return '<span class="method-badge" style="background:' + s.bg + ';color:' + s.color + ';border-color:' + s.border + '">' + m + '</span>';
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
function joinPath(base, p) {
|
|
662
|
+
return (base.replace(/\\/+$/, '') + p) || '/';
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function sidebarDot(method) {
|
|
666
|
+
const s = METHOD_STYLE[method] || METHOD_STYLE.GET;
|
|
667
|
+
return '<span class="sidebar-method-dot" style="background:' + s.color + '"></span>';
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
function statusClass(code) {
|
|
671
|
+
if (code >= 200 && code < 300) return 'status-2xx';
|
|
672
|
+
if (code >= 400 && code < 500) return 'status-4xx';
|
|
673
|
+
if (code >= 500) return 'status-5xx';
|
|
674
|
+
return '';
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
function renderSchema(val, indent) {
|
|
678
|
+
const pad = ' '.repeat(indent || 0);
|
|
679
|
+
if (val === null) return '<span class="c-dim">null</span>';
|
|
680
|
+
if (typeof val === 'string') {
|
|
681
|
+
const isDate = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(val);
|
|
682
|
+
return isDate ? '<span class="c-green">Date</span>' : '<span class="c-purple">String</span>';
|
|
683
|
+
}
|
|
684
|
+
if (typeof val === 'number') return '<span class="c-orange">Number</span>';
|
|
685
|
+
if (typeof val === 'boolean') return '<span class="c-purple">Boolean</span>';
|
|
686
|
+
if (Array.isArray(val)) {
|
|
687
|
+
if (!val.length) return '[]';
|
|
688
|
+
return '[\\n' + pad + ' ' + renderSchema(val[0], (indent || 0) + 1) + '\\n' + pad + ']';
|
|
689
|
+
}
|
|
690
|
+
if (typeof val === 'object') {
|
|
691
|
+
const keys = Object.keys(val);
|
|
692
|
+
if (!keys.length) return '{}';
|
|
693
|
+
const inner = keys.map(function(k) {
|
|
694
|
+
return pad + ' <span class="c-blue">"' + esc(k) + '"</span>: ' + renderSchema(val[k], (indent || 0) + 1);
|
|
695
|
+
}).join(',\\n');
|
|
696
|
+
return '{\\n' + inner + '\\n' + pad + '}';
|
|
697
|
+
}
|
|
698
|
+
return esc(String(val));
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
function codeBlock(label, content) {
|
|
702
|
+
return '<div class="code-block-wrap">' +
|
|
703
|
+
'<div class="code-bar">' +
|
|
704
|
+
'<span class="dot dot-r"></span>' +
|
|
705
|
+
'<span class="dot dot-y"></span>' +
|
|
706
|
+
'<span class="dot dot-g"></span>' +
|
|
707
|
+
'<span class="code-label">' + esc(label) + '</span>' +
|
|
708
|
+
'</div>' +
|
|
709
|
+
'<pre class="code-pre">' + content + '</pre>' +
|
|
710
|
+
'</div>';
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
function buildRequestContent(route, example) {
|
|
714
|
+
const req = example || {};
|
|
715
|
+
const method = route.methods[0] || 'GET';
|
|
716
|
+
let path = joinPath(BASE_PATH, route.urlPath);
|
|
717
|
+
if (req.params) {
|
|
718
|
+
for (const [k, v] of Object.entries(req.params)) {
|
|
719
|
+
path = path.replace(':' + k, String(v));
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
if (req.query && Object.keys(req.query).length) {
|
|
723
|
+
path += '?' + new URLSearchParams(req.query).toString();
|
|
724
|
+
}
|
|
725
|
+
let lines = '<span class="c-accent">' + esc(method) + '</span> <span class="c-blue">' + esc(path) + '</span>';
|
|
726
|
+
const headers = { ...(req.headers || {}) };
|
|
727
|
+
if (req.body !== undefined && !headers['Content-Type']) {
|
|
728
|
+
headers['Content-Type'] = 'application/json';
|
|
729
|
+
}
|
|
730
|
+
if (Object.keys(headers).length) {
|
|
731
|
+
lines += '\\n' + Object.entries(headers)
|
|
732
|
+
.map(([k, v]) => '<span class="c-dim">' + esc(k) + ':</span> ' + esc(String(v)))
|
|
733
|
+
.join('\\n');
|
|
734
|
+
}
|
|
735
|
+
if (req.body !== undefined) {
|
|
736
|
+
lines += '\\n\\n' + renderSchema(req.body, 0);
|
|
737
|
+
}
|
|
738
|
+
return lines;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
function buildResponseContent(example) {
|
|
742
|
+
const resp = example || {};
|
|
743
|
+
const code = resp.status || 200;
|
|
744
|
+
const text = HTTP_STATUS[code] || 'OK';
|
|
745
|
+
const cls = statusClass(code);
|
|
746
|
+
let lines = 'HTTP/1.1 <span class="' + cls + '">' + code + ' ' + esc(text) + '</span>';
|
|
747
|
+
if (resp.body !== undefined) {
|
|
748
|
+
lines += '\\n<span class="c-dim">Content-Type:</span> application/json\\n\\n';
|
|
749
|
+
lines += renderSchema(resp.body, 0);
|
|
750
|
+
}
|
|
751
|
+
return lines;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function renderCard(route, index) {
|
|
755
|
+
const id = 'ep-' + index;
|
|
756
|
+
const fullPath = joinPath(BASE_PATH, route.urlPath);
|
|
757
|
+
const badges = route.methods.map(methodBadge).join('');
|
|
758
|
+
const meta = route.meta;
|
|
759
|
+
const desc = meta && meta.description
|
|
760
|
+
? '<p class="endpoint-desc">' + esc(meta.description) + '</p>'
|
|
761
|
+
: '';
|
|
762
|
+
let examples = '';
|
|
763
|
+
if (meta) {
|
|
764
|
+
const reqHtml = meta.request !== undefined
|
|
765
|
+
? codeBlock('request', buildRequestContent(route, meta.request))
|
|
766
|
+
: '';
|
|
767
|
+
const respHtml = meta.response !== undefined
|
|
768
|
+
? codeBlock('response', buildResponseContent(meta.response))
|
|
769
|
+
: '';
|
|
770
|
+
if (reqHtml || respHtml) {
|
|
771
|
+
examples = '<div class="example-grid">' + reqHtml + respHtml + '</div>';
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
const delay = (index * 0.06).toFixed(2) + 's';
|
|
775
|
+
return '<div class="endpoint-card" id="' + id + '" data-methods="' + route.methods.join(',') + '" data-path="' + esc(fullPath) + '" style="animation-delay:' + delay + '">' +
|
|
776
|
+
'<div class="endpoint-header">' +
|
|
777
|
+
'<div class="method-badges">' + badges + '</div>' +
|
|
778
|
+
'<code class="endpoint-path">' + esc(fullPath) + '</code>' +
|
|
779
|
+
'</div>' +
|
|
780
|
+
'<div class="endpoint-body">' + desc + examples + '</div>' +
|
|
781
|
+
'</div>';
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
function buildMethodFilters() {
|
|
785
|
+
const allMethods = [...new Set(ROUTES.flatMap(r => r.methods))].sort();
|
|
786
|
+
const filtersEl = document.getElementById('methodFilters');
|
|
787
|
+
allMethods.forEach(m => {
|
|
788
|
+
const btn = document.createElement('button');
|
|
789
|
+
btn.className = 'filter-btn';
|
|
790
|
+
btn.dataset.method = m;
|
|
791
|
+
btn.textContent = m;
|
|
792
|
+
filtersEl.appendChild(btn);
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
function buildSidebar(routes) {
|
|
797
|
+
const sidebar = document.getElementById('sidebar');
|
|
798
|
+
if (!routes.length) { sidebar.innerHTML = ''; return; }
|
|
799
|
+
|
|
800
|
+
const label = document.createElement('div');
|
|
801
|
+
label.className = 'sidebar-label';
|
|
802
|
+
label.textContent = 'Endpoints';
|
|
803
|
+
sidebar.appendChild(label);
|
|
804
|
+
|
|
805
|
+
routes.forEach((route, i) => {
|
|
806
|
+
const link = document.createElement('div');
|
|
807
|
+
link.className = 'sidebar-link';
|
|
808
|
+
link.dataset.target = 'ep-' + ROUTES.indexOf(route);
|
|
809
|
+
link.innerHTML = sidebarDot(route.methods[0] || 'GET') +
|
|
810
|
+
'<span class="sidebar-path">' + esc(joinPath(BASE_PATH, route.urlPath)) + '</span>';
|
|
811
|
+
link.addEventListener('click', () => {
|
|
812
|
+
const target = document.getElementById(link.dataset.target);
|
|
813
|
+
if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
814
|
+
});
|
|
815
|
+
sidebar.appendChild(link);
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
let activeFilter = 'ALL';
|
|
820
|
+
let searchQuery = '';
|
|
821
|
+
|
|
822
|
+
function applyFilters() {
|
|
823
|
+
const cards = document.querySelectorAll('.endpoint-card');
|
|
824
|
+
let visible = 0;
|
|
825
|
+
cards.forEach(card => {
|
|
826
|
+
const methods = card.dataset.methods.split(',');
|
|
827
|
+
const path = card.dataset.path || '';
|
|
828
|
+
const matchMethod = activeFilter === 'ALL' || methods.includes(activeFilter);
|
|
829
|
+
const matchSearch = !searchQuery || path.toLowerCase().includes(searchQuery);
|
|
830
|
+
const show = matchMethod && matchSearch;
|
|
831
|
+
card.style.display = show ? '' : 'none';
|
|
832
|
+
if (show) visible++;
|
|
833
|
+
});
|
|
834
|
+
document.getElementById('empty-state').style.display = visible ? 'none' : 'block';
|
|
835
|
+
|
|
836
|
+
// Sync sidebar visibility
|
|
837
|
+
document.querySelectorAll('.sidebar-link').forEach(link => {
|
|
838
|
+
const targetId = link.dataset.target;
|
|
839
|
+
const targetCard = document.getElementById(targetId);
|
|
840
|
+
link.style.display = targetCard && targetCard.style.display !== 'none' ? '' : 'none';
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
function init() {
|
|
845
|
+
const count = ROUTES.length;
|
|
846
|
+
document.getElementById('countPill').textContent = count + ' endpoint' + (count !== 1 ? 's' : '');
|
|
847
|
+
|
|
848
|
+
buildMethodFilters();
|
|
849
|
+
|
|
850
|
+
const container = document.getElementById('endpoints');
|
|
851
|
+
container.innerHTML = ROUTES.map((r, i) => renderCard(r, i)).join('');
|
|
852
|
+
|
|
853
|
+
// Add empty state after cards
|
|
854
|
+
const emptyEl = document.createElement('div');
|
|
855
|
+
emptyEl.id = 'empty-state';
|
|
856
|
+
emptyEl.className = 'empty-state';
|
|
857
|
+
emptyEl.style.display = 'none';
|
|
858
|
+
emptyEl.innerHTML = '<p>No endpoints match your filter.</p>';
|
|
859
|
+
container.after(emptyEl);
|
|
860
|
+
|
|
861
|
+
buildSidebar(ROUTES);
|
|
862
|
+
|
|
863
|
+
// Method filter clicks
|
|
864
|
+
document.getElementById('methodFilters').addEventListener('click', e => {
|
|
865
|
+
const btn = e.target.closest('.filter-btn');
|
|
866
|
+
if (!btn) return;
|
|
867
|
+
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
|
868
|
+
btn.classList.add('active');
|
|
869
|
+
activeFilter = btn.dataset.method;
|
|
870
|
+
applyFilters();
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
// Search
|
|
874
|
+
document.getElementById('searchInput').addEventListener('input', e => {
|
|
875
|
+
searchQuery = e.target.value.trim().toLowerCase();
|
|
876
|
+
applyFilters();
|
|
877
|
+
});
|
|
878
|
+
|
|
879
|
+
// Scroll spy for sidebar
|
|
880
|
+
const cardEls = document.querySelectorAll('.endpoint-card');
|
|
881
|
+
const sidebarLinks = document.querySelectorAll('.sidebar-link');
|
|
882
|
+
const observer = new IntersectionObserver(entries => {
|
|
883
|
+
entries.forEach(entry => {
|
|
884
|
+
if (entry.isIntersecting) {
|
|
885
|
+
const id = entry.target.id;
|
|
886
|
+
sidebarLinks.forEach(l => l.classList.toggle('active', l.dataset.target === id));
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
}, { rootMargin: '-80px 0px -60% 0px' });
|
|
890
|
+
cardEls.forEach(el => observer.observe(el));
|
|
891
|
+
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
try {
|
|
895
|
+
init();
|
|
896
|
+
} catch (e) {
|
|
897
|
+
document.body.insertAdjacentHTML('afterbegin',
|
|
898
|
+
'<div style="position:fixed;top:60px;left:0;right:0;z-index:9999;background:#7f1d1d;color:#fca5a5;padding:16px 24px;font-family:monospace;font-size:13px;border-bottom:1px solid #ef4444">' +
|
|
899
|
+
'<strong>Dashboard JS error:</strong> ' + (e && e.message ? e.message : String(e)) +
|
|
900
|
+
(e && e.stack ? '<pre style="margin-top:8px;white-space:pre-wrap">' + e.stack + '</pre>' : '') +
|
|
901
|
+
'</div>'
|
|
902
|
+
);
|
|
903
|
+
}
|
|
904
|
+
</script>
|
|
905
|
+
</body>
|
|
906
|
+
</html>`;
|
|
907
|
+
}
|
|
908
|
+
|
|
340
909
|
// src/errors.ts
|
|
341
910
|
var HttpError = class _HttpError extends Error {
|
|
342
911
|
|
|
@@ -383,12 +952,32 @@ async function ignite(config) {
|
|
|
383
952
|
const {
|
|
384
953
|
port: _port,
|
|
385
954
|
workers,
|
|
386
|
-
apiDir,
|
|
387
955
|
globalMiddlewares = [],
|
|
388
956
|
onWorkerReady,
|
|
389
957
|
onWorkerCrash,
|
|
390
958
|
onError
|
|
391
959
|
} = config;
|
|
960
|
+
function resolveConventionDir(name) {
|
|
961
|
+
const candidates = [
|
|
962
|
+
...process.argv[1] ? [_path2.default.join(_path2.default.dirname(process.argv[1]), name)] : [],
|
|
963
|
+
_path2.default.join(process.cwd(), "src", name),
|
|
964
|
+
_path2.default.join(process.cwd(), name),
|
|
965
|
+
_path2.default.join(process.cwd(), "dist", name)
|
|
966
|
+
];
|
|
967
|
+
return _nullishCoalesce(candidates.find((c) => _fs2.default.existsSync(c)), () => ( candidates[0]));
|
|
968
|
+
}
|
|
969
|
+
const apiDir = resolveConventionDir("api");
|
|
970
|
+
const tasksDir = resolveConventionDir("tasks");
|
|
971
|
+
const basePath = _nullishCoalesce(config.basePath, () => ( "/v1/api"));
|
|
972
|
+
function readProjectMeta() {
|
|
973
|
+
try {
|
|
974
|
+
const raw = _fs2.default.readFileSync(_path2.default.join(process.cwd(), "package.json"), "utf8");
|
|
975
|
+
const pkg = JSON.parse(raw);
|
|
976
|
+
return { name: _nullishCoalesce(pkg.name, () => ( "API")), version: _nullishCoalesce(pkg.version, () => ( "")) };
|
|
977
|
+
} catch (e5) {
|
|
978
|
+
return { name: "API", version: "" };
|
|
979
|
+
}
|
|
980
|
+
}
|
|
392
981
|
const envPort = process.env["PORT"] != null ? Number(process.env["PORT"]) : NaN;
|
|
393
982
|
const port = _port != null && !Number.isNaN(_port) ? _port : !Number.isNaN(envPort) ? envPort : 3e3;
|
|
394
983
|
const databaseUrl = _nullishCoalesce(config.databaseUrl, () => ( process.env["DATABASE_URL"]));
|
|
@@ -432,15 +1021,15 @@ async function ignite(config) {
|
|
|
432
1021
|
}
|
|
433
1022
|
if (jwtSecret) {
|
|
434
1023
|
const cookieDomain = process.env["COOKIE_DOMAIN"];
|
|
435
|
-
|
|
1024
|
+
_chunkUUF2OYRWcjs.configureAuth.call(void 0, {
|
|
436
1025
|
secret: jwtSecret,
|
|
437
1026
|
strategy: authStrategy,
|
|
438
1027
|
expiresIn: _nullishCoalesce(process.env["JWT_EXPIRES_IN"], () => ( "7d")),
|
|
439
1028
|
...cookieDomain !== void 0 && { cookieDomain }
|
|
440
1029
|
});
|
|
441
1030
|
}
|
|
442
|
-
if (
|
|
443
|
-
await scanTasks(
|
|
1031
|
+
if (tasksDir) {
|
|
1032
|
+
await scanTasks(tasksDir);
|
|
444
1033
|
}
|
|
445
1034
|
if (config.tasks) {
|
|
446
1035
|
if (config.tasks.backend === "bullmq") {
|
|
@@ -451,7 +1040,16 @@ async function ignite(config) {
|
|
|
451
1040
|
}
|
|
452
1041
|
}
|
|
453
1042
|
const routes = _chunkMQNVNOH5cjs.scanDir.call(void 0, apiDir);
|
|
454
|
-
|
|
1043
|
+
const apiRouter = _express2.default.Router();
|
|
1044
|
+
const mounted = await mountRoutes(apiRouter, routes);
|
|
1045
|
+
app.use(basePath, apiRouter);
|
|
1046
|
+
if (config.dashboard && process.env["NODE_ENV"] === "development") {
|
|
1047
|
+
app.get("/", (_req, res) => {
|
|
1048
|
+
const { name, version } = readProjectMeta();
|
|
1049
|
+
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
1050
|
+
res.send(generateDashboard(mounted, basePath, port, name, version));
|
|
1051
|
+
});
|
|
1052
|
+
}
|
|
455
1053
|
if (onError) {
|
|
456
1054
|
app.use(onError);
|
|
457
1055
|
} else {
|