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/.github/instructions/copilot.instructions.md +1 -0
- package/AGENTS.md +2 -0
- package/README.md +68 -13
- package/admin-ui/v1/controls/admin_shell.js +669 -669
- package/docs/api-reference.md +383 -303
- package/docs/books/creating-a-new-admin-ui/README.md +20 -20
- package/docs/comprehensive-documentation.md +220 -220
- package/docs/configuration-reference.md +227 -204
- package/docs/middleware-guide.md +236 -0
- package/docs/system-architecture.md +24 -18
- package/middleware/compression.js +217 -0
- package/middleware/index.js +15 -0
- package/module.js +3 -0
- package/package.json +1 -1
- package/serve-factory.js +28 -0
- package/server.js +81 -20
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
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
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
|
-
|
|
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
|
-
|
|
604
|
-
|
|
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;
|