jsgui3-server 0.0.150 → 0.0.151

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/server.js CHANGED
@@ -67,6 +67,12 @@ class JSGUI_Single_Process_Server extends Evented_Class {
67
67
  let name = spec.name || undefined;
68
68
  Object.defineProperty(this, 'name', { get: () => name, set: value => name = value })
69
69
  this.__type_name = __type_name || 'server';
70
+
71
+ // Middleware pipeline — an ordered array of (req, res, next) functions
72
+ // that run before every request reaches the router. Populated via
73
+ // server.use(fn). See docs/middleware-guide.md for details.
74
+ this._middleware = [];
75
+
70
76
  const resource_pool = this.resource_pool = new Server_Resource_Pool({
71
77
  'access': {
72
78
  'full': ['server_admin']
@@ -482,6 +488,27 @@ class JSGUI_Single_Process_Server extends Evented_Class {
482
488
  return this.publish_observable(route, obs, options);
483
489
  }
484
490
 
491
+ /**
492
+ * Register middleware to run before every request is routed.
493
+ *
494
+ * Middleware signature: `function (req, res, next) { ... }`
495
+ * Call `next()` to continue to the next middleware / router.
496
+ * Call `next(err)` to short-circuit into the error handler.
497
+ *
498
+ * @param {function} fn Middleware function.
499
+ * @returns {this} The server instance (for chaining).
500
+ *
501
+ * @example
502
+ * const { compression } = require('jsgui3-server/middleware');
503
+ * server.use(compression());
504
+ */
505
+ use(fn) {
506
+ if (typeof fn !== 'function') {
507
+ throw new Error('Middleware must be a function (req, res, next).');
508
+ }
509
+ this._middleware.push(fn);
510
+ return this;
511
+ }
485
512
 
486
513
  get resource_names() {
487
514
  return this.resource_pool.resource_names;
@@ -576,33 +603,63 @@ class JSGUI_Single_Process_Server extends Evented_Class {
576
603
  }
577
604
  };
578
605
 
606
+ // Central request handler — runs the middleware chain then
607
+ // forwards to the router. If the middleware array is empty
608
+ // (the common case before server.use() is called), the
609
+ // router is invoked directly with zero overhead.
579
610
  const process_request = (req, res) => {
580
- let outcome;
581
- try {
582
- outcome = server_router.process(req, res);
583
- } catch (err) {
584
- respond_error(res, err);
585
- return;
586
- }
587
- if (!outcome) {
588
- if (!res.writableEnded) {
589
- respond_not_found(res);
611
+ const route_request = () => {
612
+ let outcome;
613
+ try {
614
+ outcome = server_router.process(req, res);
615
+ } catch (err) {
616
+ respond_error(res, err);
617
+ return;
590
618
  }
591
- return;
592
- }
593
- if (typeof outcome === 'object') {
594
- if (outcome.status === 'error') {
595
- if (!res.writableEnded) {
596
- respond_error(res, outcome.error);
597
- }
598
- } else if (outcome.handled !== true && outcome.status === 'not-found') {
619
+ if (!outcome) {
599
620
  if (!res.writableEnded) {
600
621
  respond_not_found(res);
601
622
  }
623
+ return;
602
624
  }
603
- } else if (outcome === false && !res.writableEnded) {
604
- respond_not_found(res);
625
+ if (typeof outcome === 'object') {
626
+ if (outcome.status === 'error') {
627
+ if (!res.writableEnded) {
628
+ respond_error(res, outcome.error);
629
+ }
630
+ } else if (outcome.handled !== true && outcome.status === 'not-found') {
631
+ if (!res.writableEnded) {
632
+ respond_not_found(res);
633
+ }
634
+ }
635
+ } else if (outcome === false && !res.writableEnded) {
636
+ respond_not_found(res);
637
+ }
638
+ };
639
+
640
+ // ── Middleware chain ──────────────────────────
641
+ // Walk through this._middleware in order. Each
642
+ // middleware calls next() to advance; next(err)
643
+ // short-circuits into respond_error. After the
644
+ // last middleware calls next(), route_request()
645
+ // hands off to the router.
646
+ const middleware = this._middleware;
647
+ if (!middleware.length) {
648
+ route_request();
649
+ return;
605
650
  }
651
+ let idx = 0;
652
+ const next = (err) => {
653
+ if (err) { respond_error(res, err); return; }
654
+ if (idx >= middleware.length) { route_request(); return; }
655
+ const mw = middleware[idx++];
656
+ try {
657
+ mw(req, res, next);
658
+ } catch (e) {
659
+ respond_error(res, e);
660
+ }
661
+ };
662
+ next();
606
663
  };
607
664
 
608
665
  if (this.https_options) {
@@ -777,6 +834,10 @@ JSGUI_Single_Process_Server.Admin_Module_V1 = require('./admin-ui/v1/server');
777
834
  JSGUI_Single_Process_Server.Admin_Auth_Service = require('./admin-ui/v1/admin_auth_service');
778
835
  JSGUI_Single_Process_Server.Admin_User_Store = require('./admin-ui/v1/admin_user_store');
779
836
 
837
+ // Built-in middleware — accessed as Server.middleware.compression etc.
838
+ // See docs/middleware-guide.md for the full API reference.
839
+ JSGUI_Single_Process_Server.middleware = require('./middleware');
840
+
780
841
  JSGUI_Single_Process_Server.serve = require('./serve-factory')(JSGUI_Single_Process_Server);
781
842
 
782
843
  module.exports = JSGUI_Single_Process_Server;