@meridianjs/framework 0.1.6 → 0.1.8

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/index.d.ts CHANGED
@@ -120,7 +120,7 @@ declare function loadRoutes(app: Express, container: MeridianContainer, apiDir:
120
120
  * - default: async function handler({ event, container }) { ... }
121
121
  * - config: { event: "event.name" | string[] }
122
122
  */
123
- declare function loadSubscribers(container: MeridianContainer, subscribersDir: string): Promise<void>;
123
+ declare function loadSubscribers(container: MeridianContainer, subscribersDir: string, disabledEvents?: string[]): Promise<void>;
124
124
 
125
125
  /**
126
126
  * Scans src/jobs/ for scheduled job files and registers them with the scheduler.
package/dist/index.js CHANGED
@@ -32,6 +32,9 @@ function wrapContainer(raw) {
32
32
  },
33
33
  createScope() {
34
34
  return wrapContainer(raw.createScope());
35
+ },
36
+ async dispose() {
37
+ await raw.dispose();
35
38
  }
36
39
  };
37
40
  return container;
@@ -230,7 +233,7 @@ function filePathToRoutePath(filePath, baseDir) {
230
233
  import fs2 from "fs/promises";
231
234
  import path4 from "path";
232
235
  import { pathToFileURL as pathToFileURL4 } from "url";
233
- async function loadSubscribers(container, subscribersDir) {
236
+ async function loadSubscribers(container, subscribersDir, disabledEvents = []) {
234
237
  const logger = container.resolve("logger");
235
238
  try {
236
239
  await fs2.access(subscribersDir);
@@ -263,6 +266,10 @@ async function loadSubscribers(container, subscribersDir) {
263
266
  }
264
267
  const events = Array.isArray(config.event) ? config.event : [config.event];
265
268
  for (const eventName of events) {
269
+ if (disabledEvents.includes(eventName)) {
270
+ logger.debug(`Subscriber ${file} skipped (disabled by plugin config)`);
271
+ continue;
272
+ }
266
273
  eventBus.subscribe(
267
274
  eventName,
268
275
  (args) => handler({ ...args, container })
@@ -444,12 +451,12 @@ async function loadPlugins(container, plugins, rootDir, server) {
444
451
  }
445
452
  }
446
453
  if (scanRoot) {
447
- await autoScanPlugin(scanRoot, container, logger, server);
454
+ await autoScanPlugin(scanRoot, container, logger, server, plugin.disableSubscribers ?? []);
448
455
  }
449
456
  logger.info(`Plugin loaded: ${plugin.resolve}`);
450
457
  }
451
458
  }
452
- async function autoScanPlugin(scanRoot, container, logger, server) {
459
+ async function autoScanPlugin(scanRoot, container, logger, server, disabledEvents = []) {
453
460
  const candidates = [
454
461
  scanRoot,
455
462
  // pluginRoot already points to compiled dir
@@ -467,7 +474,7 @@ async function autoScanPlugin(scanRoot, container, logger, server) {
467
474
  }
468
475
  await Promise.all([
469
476
  server ? loadRoutes(server, container, apiDir) : Promise.resolve(),
470
- loadSubscribers(container, path7.join(candidate, "subscribers")),
477
+ loadSubscribers(container, path7.join(candidate, "subscribers"), disabledEvents),
471
478
  loadJobs(container, path7.join(candidate, "jobs")),
472
479
  loadLinks(container, path7.join(candidate, "links"))
473
480
  ]);
@@ -506,6 +513,7 @@ import cors from "cors";
506
513
  import helmet from "helmet";
507
514
  function createServer(container, config) {
508
515
  const app = express();
516
+ app.set("trust proxy", 1);
509
517
  const logger = container.resolve("logger");
510
518
  app.use(express.json({ limit: "10mb" }));
511
519
  app.use(express.urlencoded({ extended: true, limit: "10mb" }));
@@ -536,8 +544,10 @@ function createServer(container, config) {
536
544
  exposedHeaders: ["X-RateLimit-Limit", "X-RateLimit-Remaining", "X-RateLimit-Reset"]
537
545
  })
538
546
  );
539
- app.use((req, _res, next) => {
547
+ app.use((req, res, next) => {
540
548
  req.scope = container.createScope();
549
+ res.on("finish", () => req.scope.dispose?.());
550
+ res.on("close", () => req.scope.dispose?.());
541
551
  next();
542
552
  });
543
553
  app.get("/health", (_req, res) => {
@@ -657,18 +667,34 @@ async function bootstrap(opts) {
657
667
  await bus.close?.();
658
668
  } catch {
659
669
  }
670
+ try {
671
+ const scheduler = container.resolve("scheduler");
672
+ await scheduler.close();
673
+ } catch {
674
+ }
660
675
  logger.info("Meridian server stopped.");
661
676
  }
662
677
  };
663
678
  }
664
679
  async function loadMiddlewares(server, container, apiDir) {
665
680
  const logger = container.resolve("logger");
666
- const middlewaresPath = path8.join(apiDir, "middlewares.ts");
667
- let mod;
668
- try {
669
- const { pathToFileURL: pathToFileURL8 } = await import("url");
670
- mod = await import(pathToFileURL8(middlewaresPath).href);
671
- } catch {
681
+ const candidates = [
682
+ path8.join(apiDir, "middlewares.ts"),
683
+ path8.join(apiDir, "middlewares.mts"),
684
+ path8.join(apiDir, "middlewares.js"),
685
+ path8.join(apiDir, "middlewares.mjs")
686
+ ];
687
+ let mod = null;
688
+ const { pathToFileURL: pathToFileURL8 } = await import("url");
689
+ for (const candidate of candidates) {
690
+ try {
691
+ mod = await import(pathToFileURL8(candidate).href);
692
+ break;
693
+ } catch (err) {
694
+ if (err.code !== "ERR_MODULE_NOT_FOUND" && err.code !== "MODULE_NOT_FOUND") throw err;
695
+ }
696
+ }
697
+ if (!mod) {
672
698
  return;
673
699
  }
674
700
  const config = mod.default;
@@ -751,7 +777,8 @@ var SseManager = class {
751
777
  broadcast(workspaceId, event, data) {
752
778
  const set = this.clients.get(workspaceId);
753
779
  if (!set?.size) return;
754
- const payload = `event: ${event}
780
+ const safeEvent = event.replace(/[\r\n]/g, "");
781
+ const payload = `event: ${safeEvent}
755
782
  data: ${JSON.stringify(data)}
756
783
 
757
784
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meridianjs/framework",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Core Meridian framework: bootstrap, DI container, module/route/subscriber/job loaders",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -8,8 +8,10 @@
8
8
  "type": "module",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./dist/index.d.ts",
12
- "import": "./dist/index.js"
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ }
13
15
  }
14
16
  },
15
17
  "scripts": {