mastercontroller 1.2.14 → 1.3.1

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/README.md CHANGED
@@ -1,58 +1,1654 @@
1
- ## MasterController Framework
1
+ # MasterController Framework
2
2
 
3
- MasterController is a lightweight MVC-style server framework for Node.js with routing, controllers, views, dependency injection, CORS, sessions, sockets, and more.
3
+ MasterController is a lightweight MVC-style server framework for Node.js with middleware pipeline, routing, controllers, views, dependency injection, CORS, sessions, sockets, and more.
4
4
 
5
- ### Install
6
- ```
5
+ ## Table of Contents
6
+ - [Installation](#installation)
7
+ - [Quickstart](#quickstart)
8
+ - [Middleware Pipeline](#middleware-pipeline)
9
+ - [Routing](#routing)
10
+ - [Controllers](#controllers)
11
+ - [Views and Templates](#views-and-templates)
12
+ - [View Pattern Hooks](#view-pattern-hooks)
13
+ - [Dependency Injection](#dependency-injection)
14
+ - [CORS](#cors)
15
+ - [Sessions](#sessions)
16
+ - [Security](#security)
17
+ - [Components](#components)
18
+ - [Timeout System](#timeout-system)
19
+ - [Error Handling](#error-handling)
20
+ - [HTTPS Setup](#https-setup)
21
+
22
+ ---
23
+
24
+ ## Installation
25
+
26
+ ```bash
7
27
  npm install mastercontroller
8
28
  ```
9
29
 
10
- ### Quickstart
11
- ```js
30
+ ---
31
+
32
+ ## Quickstart
33
+
34
+ ```javascript
12
35
  // server.js
13
- const master = require('./MasterControl');
36
+ const master = require('mastercontroller');
37
+
38
+ master.root = __dirname;
39
+ master.environmentType = 'development'; // or process.env.NODE_ENV
14
40
 
15
- master.root = __dirname; // your project root
16
- master.environmentType = 'development'; // or process.env.NODE_ENV
41
+ const server = master.setupServer('http'); // or 'https'
42
+
43
+ // Load configuration (registers middleware, routes, DI services)
44
+ require('./config/initializers/config');
17
45
 
18
- const server = master.setupServer('http'); // or 'https'
19
46
  master.start(server);
20
- master.serverSettings({ httpPort: 3000, hostname: '127.0.0.1', requestTimeout: 60000 });
47
+ ```
48
+
49
+ ```javascript
50
+ // config/initializers/config.js
51
+ const master = require('mastercontroller');
52
+ const cors = require('./cors.json');
53
+
54
+ // Initialize CORS (auto-registers with pipeline)
55
+ master.cors.init(cors);
56
+
57
+ // Initialize sessions (auto-registers with pipeline)
58
+ master.sessions.init();
59
+
60
+ // Auto-discover custom middleware from middleware/ folder
61
+ master.pipeline.discoverMiddleware('middleware');
62
+
63
+ // Configure server settings
64
+ master.serverSettings({
65
+ httpPort: 3000,
66
+ hostname: '127.0.0.1',
67
+ requestTimeout: 60000
68
+ });
69
+
70
+ // Register routes
71
+ master.startMVC('config');
72
+ ```
73
+
74
+ ---
75
+
76
+ ## Middleware Pipeline
77
+
78
+ MasterController uses an ASP.NET Core-style middleware pipeline for request processing.
79
+
80
+ ### Core Methods
81
+
82
+ #### `master.pipeline.use(middleware)`
83
+ Add pass-through middleware that calls `next()` to continue the chain.
84
+
85
+ ```javascript
86
+ master.pipeline.use(async (ctx, next) => {
87
+ // Before request
88
+ console.log(`→ ${ctx.type.toUpperCase()} ${ctx.request.url}`);
89
+
90
+ await next(); // Continue to next middleware
91
+
92
+ // After response
93
+ console.log(`← ${ctx.response.statusCode}`);
94
+ });
95
+ ```
96
+
97
+ #### `master.pipeline.run(middleware)`
98
+ Add terminal middleware that ends the pipeline (does not call `next()`).
99
+
100
+ ```javascript
101
+ master.pipeline.run(async (ctx) => {
102
+ ctx.response.statusCode = 200;
103
+ ctx.response.end('Hello World');
104
+ });
105
+ ```
106
+
107
+ #### `master.pipeline.map(path, configure)`
108
+ Conditionally execute middleware only for matching paths.
109
+
110
+ ```javascript
111
+ // Apply authentication only to /api/* routes
112
+ master.pipeline.map('/api/*', (api) => {
113
+ api.use(async (ctx, next) => {
114
+ const token = ctx.request.headers['authorization'];
115
+ if (!token) {
116
+ ctx.response.statusCode = 401;
117
+ ctx.response.end('Unauthorized');
118
+ return;
119
+ }
120
+ ctx.state.user = await validateToken(token);
121
+ await next();
122
+ });
123
+
124
+ // Apply rate limiting to API
125
+ api.use(rateLimitMiddleware);
126
+ });
127
+ ```
128
+
129
+ #### `master.pipeline.useError(errorHandler)`
130
+ Add error handling middleware.
131
+
132
+ ```javascript
133
+ master.pipeline.useError(async (error, ctx, next) => {
134
+ console.error('Error:', error);
135
+
136
+ if (!ctx.response.headersSent) {
137
+ ctx.response.statusCode = 500;
138
+ ctx.response.end('Internal Server Error');
139
+ }
140
+ });
141
+ ```
142
+
143
+ #### `master.pipeline.discoverMiddleware(options)`
144
+ Auto-discover and load middleware from folders.
145
+
146
+ ```javascript
147
+ // Single folder
148
+ master.pipeline.discoverMiddleware('middleware');
149
+
150
+ // Multiple folders
151
+ master.pipeline.discoverMiddleware({
152
+ folders: ['middleware', 'app/middleware']
153
+ });
154
+ ```
155
+
156
+ ### Context Object
157
+
158
+ Middleware receives a context object:
159
+
160
+ ```javascript
161
+ {
162
+ request: req, // Node.js request object
163
+ response: res, // Node.js response object
164
+ requrl: parsedUrl, // Parsed URL with query
165
+ pathName: 'api/users', // Normalized path (lowercase)
166
+ type: 'get', // HTTP method (lowercase)
167
+ params: { // Route parameters + query + form data
168
+ query: {}, // Query string parameters
169
+ formData: {}, // POST body data
170
+ periodId: '123' // Route parameters (e.g., /period/:periodId)
171
+ },
172
+ state: {}, // Custom state to share between middleware
173
+ master: master, // Framework instance
174
+ isStatic: false // Is this a static file request?
175
+ }
176
+ ```
177
+
178
+ ### Custom Middleware Files
179
+
180
+ Create middleware files that are auto-discovered:
181
+
182
+ **Simple function export:**
183
+ ```javascript
184
+ // middleware/01-logger.js
185
+ module.exports = async (ctx, next) => {
186
+ const start = Date.now();
187
+ await next();
188
+ const duration = Date.now() - start;
189
+ console.log(`${ctx.type.toUpperCase()} ${ctx.request.url} - ${duration}ms`);
190
+ };
191
+ ```
192
+
193
+ **Object with register() method:**
194
+ ```javascript
195
+ // middleware/02-auth.js
196
+ module.exports = {
197
+ register: (master) => {
198
+ master.pipeline.map('/admin/*', (admin) => {
199
+ admin.use(async (ctx, next) => {
200
+ if (!ctx.state.user?.isAdmin) {
201
+ ctx.response.statusCode = 403;
202
+ ctx.response.end('Forbidden');
203
+ return;
204
+ }
205
+ await next();
206
+ });
207
+ });
208
+ }
209
+ };
210
+ ```
211
+
212
+ Files are loaded alphabetically (use `01-`, `02-` prefixes for ordering).
213
+
214
+ ---
215
+
216
+ ## Routing
217
+
218
+ ### Setup Routes
219
+
220
+ Create `config/routes.js`:
221
+
222
+ ```javascript
223
+ var master = require('mastercontroller');
224
+ var router = master.router.start();
225
+
226
+ // Basic route
227
+ router.route('/users', 'users#index', 'get');
228
+
229
+ // Route with parameters (preserves casing!)
230
+ router.route('/period/:periodId/items/:itemId', 'period#show', 'get');
231
+
232
+ // RESTful routes (generates 7 routes automatically)
233
+ router.resources('posts');
234
+ ```
235
+
236
+ ### API
237
+
238
+ #### `router.route(path, toPath, method, constraint)`
239
+ Register a single route.
240
+
241
+ - `path`: URL path (can include `:paramName`)
242
+ - `toPath`: Controller#action (e.g., `'users#index'`)
243
+ - `method`: HTTP method (`'get'`, `'post'`, `'put'`, `'delete'`, `'patch'`)
244
+ - `constraint`: Optional constraint function
245
+
246
+ **Parameter casing is preserved:**
247
+ ```javascript
248
+ router.route('/period/:periodId', 'period#show', 'get');
249
+ // In controller: obj.params.periodId (not periodid)
250
+ ```
251
+
252
+ #### `router.resources(routeName)`
253
+ Generate RESTful routes for a resource:
254
+
255
+ ```javascript
256
+ router.resources('posts');
257
+
258
+ // Generates:
259
+ // GET /posts -> posts#index
260
+ // GET /posts/new -> posts#new
261
+ // POST /posts -> posts#create
262
+ // GET /posts/:id -> posts#show
263
+ // GET /posts/:id/edit -> posts#edit
264
+ // PUT /posts/:id -> posts#update
265
+ // DELETE /posts/:id -> posts#destroy
266
+ ```
267
+
268
+ #### Route Constraints
269
+
270
+ Add custom logic to routes with constraints:
271
+
272
+ ```javascript
273
+ router.route('/admin', 'admin#index', 'get', function(requestObject) {
274
+ // Check authentication
275
+ if (!isAuthenticated(requestObject)) {
276
+ requestObject.response.statusCode = 401;
277
+ requestObject.response.end('Unauthorized');
278
+ return;
279
+ }
280
+
281
+ // Continue to controller
282
+ this.next();
283
+ });
284
+ ```
285
+
286
+ ---
287
+
288
+ ## Controllers
289
+
290
+ ### Creating Controllers
291
+
292
+ Create controllers in `app/controllers/`:
293
+
294
+ ```javascript
295
+ // app/controllers/usersController.js
296
+ class UsersController {
297
+ constructor(requestObject) {
298
+ // Called for every request
299
+ this.requestObject = requestObject;
300
+ }
301
+
302
+ // Actions
303
+ index(obj) {
304
+ // obj = requestObject
305
+ this.render('index', {
306
+ users: ['Alice', 'Bob', 'Charlie']
307
+ });
308
+ }
309
+
310
+ show(obj) {
311
+ const userId = obj.params.id;
312
+ this.render('show', { userId });
313
+ }
314
+
315
+ create(obj) {
316
+ const userData = obj.params.formData;
317
+ // Save user...
318
+ this.redirect('/users');
319
+ }
320
+ }
321
+
322
+ module.exports = UsersController;
323
+ ```
324
+
325
+ ### Controller API
326
+
327
+ #### `this.render(view, data)`
328
+ Render a view with data.
329
+
330
+ ```javascript
331
+ this.render('index', {
332
+ title: 'Users',
333
+ users: userList
334
+ });
335
+ ```
336
+
337
+ Views are located at: `app/views/<controller>/<view>.html`
338
+
339
+ #### `this.redirect(path)`
340
+ Redirect to another path.
341
+
342
+ ```javascript
343
+ this.redirect('/users');
344
+ this.redirect('/users/123');
345
+ ```
346
+
347
+ #### `this.renderComponent(componentName, viewName, data)`
348
+ Render a view from a component.
349
+
350
+ ```javascript
351
+ this.renderComponent('mail', 'inbox', { emails });
352
+ ```
353
+
354
+ #### `this.json(data)`
355
+ Send JSON response.
356
+
357
+ ```javascript
358
+ this.json({
359
+ success: true,
360
+ users: userList
361
+ });
362
+ ```
363
+
364
+ #### Access Request Data
365
+
366
+ ```javascript
367
+ class UsersController {
368
+ show(obj) {
369
+ // Route parameters
370
+ const userId = obj.params.id;
371
+ const periodId = obj.params.periodId; // Casing preserved!
372
+
373
+ // Query string
374
+ const search = obj.params.query.search;
375
+
376
+ // Form data
377
+ const email = obj.params.formData.email;
378
+
379
+ // Files (multipart/form-data)
380
+ const avatar = obj.params.formData.files.avatar;
381
+
382
+ // Request method
383
+ const method = obj.type; // 'get', 'post', etc.
384
+
385
+ // Full request/response
386
+ const req = obj.request;
387
+ const res = obj.response;
388
+ }
389
+ }
390
+ ```
391
+
392
+ ### Before/After Action Filters
393
+
394
+ Execute code before or after specific actions:
395
+
396
+ ```javascript
397
+ class UsersController {
398
+ constructor(requestObject) {
399
+ // Run before 'edit' and 'update' actions
400
+ this.beforeAction(['edit', 'update'], function(obj) {
401
+ if (!isAuthenticated(obj)) {
402
+ obj.response.statusCode = 401;
403
+ obj.response.end('Unauthorized');
404
+ return;
405
+ }
406
+
407
+ // Continue to action
408
+ this.next();
409
+ });
410
+
411
+ // Run after 'create' and 'update' actions
412
+ this.afterAction(['create', 'update'], function(obj) {
413
+ console.log('User saved');
414
+ });
415
+ }
416
+
417
+ edit(obj) {
418
+ // beforeAction runs first
419
+ this.render('edit');
420
+ }
421
+
422
+ update(obj) {
423
+ // beforeAction runs first
424
+ // ... update user ...
425
+ // afterAction runs after
426
+ this.redirect('/users');
427
+ }
428
+ }
429
+ ```
430
+
431
+ **Methods:**
432
+ - `this.beforeAction(actionList, callback)` - Run before specific actions
433
+ - `this.afterAction(actionList, callback)` - Run after specific actions
434
+ - `this.next()` - Continue from beforeAction to action
435
+
436
+ ---
437
+
438
+ ## Views and Templates
439
+
440
+ ### View Structure
441
+
442
+ ```
443
+ app/
444
+ views/
445
+ layouts/
446
+ master.html # Main layout
447
+ users/
448
+ index.html # Users index view
449
+ show.html # Users show view
450
+ ```
451
+
452
+ ### Layout (master.html)
453
+
454
+ ```html
455
+ <!DOCTYPE html>
456
+ <html>
457
+ <head>
458
+ <title>{{title}}</title>
459
+ </head>
460
+ <body>
461
+ <header>
462
+ <h1>My App</h1>
463
+ </header>
464
+
465
+ <main>
466
+ {{body}} <!-- View content inserted here -->
467
+ </main>
468
+
469
+ <footer>
470
+ &copy; 2025
471
+ </footer>
472
+ </body>
473
+ </html>
474
+ ```
475
+
476
+ ### View (users/index.html)
477
+
478
+ ```html
479
+ <h2>{{title}}</h2>
480
+
481
+ <ul>
482
+ {{#each users}}
483
+ <li>{{this}}</li>
484
+ {{/each}}
485
+ </ul>
486
+ ```
487
+
488
+ ### Template Syntax
489
+
490
+ MasterController uses Handlebars-style templates:
491
+
492
+ ```html
493
+ <!-- Variables -->
494
+ {{name}}
495
+ {{user.email}}
496
+
497
+ <!-- HTML escaping (automatic) -->
498
+ {{description}}
499
+
500
+ <!-- Conditionals -->
501
+ {{#if isAdmin}}
502
+ <a href="/admin">Admin Panel</a>
503
+ {{/if}}
504
+
505
+ {{#unless isGuest}}
506
+ <p>Welcome back!</p>
507
+ {{/unless}}
508
+
509
+ <!-- Loops -->
510
+ {{#each items}}
511
+ <div>{{this.name}}</div>
512
+ {{/each}}
513
+
514
+ <!-- Partials -->
515
+ {{> header}}
516
+ ```
517
+
518
+ ---
519
+
520
+ ## View Pattern Hooks
521
+
522
+ Extend views with custom methods using the **view pattern hook system**.
523
+
524
+ ### `master.extendView(name, ViewClass)`
525
+
526
+ Add custom methods that are available in all views via `this` keyword.
527
+
528
+ ```javascript
529
+ // Create a view helper class
530
+ class MyViewHelpers {
531
+ // Format currency
532
+ currency(amount) {
533
+ return `$${amount.toFixed(2)}`;
534
+ }
535
+
536
+ // Format date
537
+ formatDate(date) {
538
+ return new Date(date).toLocaleDateString();
539
+ }
540
+
541
+ // Truncate text
542
+ truncate(text, length) {
543
+ if (text.length <= length) return text;
544
+ return text.substring(0, length) + '...';
545
+ }
546
+
547
+ // Check if user has permission
548
+ can(permission) {
549
+ // Access request context if needed
550
+ return this.__requestObject.user?.permissions.includes(permission);
551
+ }
552
+ }
553
+
554
+ // Register the helpers
555
+ master.extendView('helpers', MyViewHelpers);
556
+ ```
557
+
558
+ **Use in views:**
559
+
560
+ ```html
561
+ <p>Price: {{helpers.currency(product.price)}}</p>
562
+ <p>Posted: {{helpers.formatDate(post.createdAt)}}</p>
563
+ <p>{{helpers.truncate(post.body, 100)}}</p>
564
+
565
+ {{#if helpers.can('edit')}}
566
+ <button>Edit</button>
567
+ {{/if}}
568
+ ```
569
+
570
+ ### Built-in View Context
571
+
572
+ View methods have access to:
573
+ - `this.__requestObject` - Full request object
574
+ - `this.__response` - Response object
575
+ - `this.__request` - Request object
576
+ - `this.__namespace` - Controller namespace
577
+ - All methods from registered view extensions
578
+
579
+ **Example: Access request data in view helpers**
580
+
581
+ ```javascript
582
+ class AuthHelpers {
583
+ currentUser() {
584
+ return this.__requestObject.session?.user;
585
+ }
586
+
587
+ isAuthenticated() {
588
+ return !!this.currentUser();
589
+ }
590
+
591
+ csrf() {
592
+ // Generate CSRF token
593
+ return this.__requestObject.csrfToken;
594
+ }
595
+ }
596
+
597
+ master.extendView('auth', AuthHelpers);
598
+ ```
599
+
600
+ ```html
601
+ <!-- In views -->
602
+ {{#if auth.isAuthenticated}}
603
+ <p>Welcome, {{auth.currentUser.name}}!</p>
604
+ {{else}}
605
+ <a href="/login">Login</a>
606
+ {{/if}}
607
+
608
+ <form method="post">
609
+ <input type="hidden" name="_csrf" value="{{auth.csrf}}">
610
+ <!-- form fields -->
611
+ </form>
612
+ ```
613
+
614
+ ---
615
+
616
+ ## Dependency Injection
617
+
618
+ MasterController provides three DI lifetimes:
619
+
620
+ ### `master.addSingleton(name, Class)`
621
+ One instance for the entire application lifetime.
622
+
623
+ ```javascript
624
+ class DatabaseConnection {
625
+ constructor() {
626
+ this.connection = createDbConnection();
627
+ }
628
+
629
+ query(sql) {
630
+ return this.connection.query(sql);
631
+ }
632
+ }
633
+
634
+ master.addSingleton('db', DatabaseConnection);
635
+ ```
636
+
637
+ **Usage in controllers:**
638
+ ```javascript
639
+ class UsersController {
640
+ index(obj) {
641
+ const users = this.db.query('SELECT * FROM users');
642
+ this.render('index', { users });
643
+ }
644
+ }
645
+ ```
646
+
647
+ ### `master.addScoped(name, Class)`
648
+ One instance per request (scoped to request lifetime).
649
+
650
+ ```javascript
651
+ class RequestLogger {
652
+ constructor() {
653
+ this.logs = [];
654
+ }
655
+
656
+ log(message) {
657
+ this.logs.push({ message, timestamp: Date.now() });
658
+ }
659
+
660
+ flush() {
661
+ console.log('Request logs:', this.logs);
662
+ }
663
+ }
664
+
665
+ master.addScoped('logger', RequestLogger);
666
+ ```
667
+
668
+ **Usage:**
669
+ ```javascript
670
+ class UsersController {
671
+ index(obj) {
672
+ this.logger.log('Fetching users');
673
+ const users = getUsers();
674
+ this.logger.log('Users fetched');
675
+ this.logger.flush();
676
+ this.render('index', { users });
677
+ }
678
+ }
679
+ ```
680
+
681
+ ### `master.addTransient(name, Class)`
682
+ New instance every time it's accessed.
683
+
684
+ ```javascript
685
+ class EmailService {
686
+ constructor() {
687
+ this.id = Math.random();
688
+ }
689
+
690
+ send(to, subject, body) {
691
+ console.log(`Sending email from instance ${this.id}`);
692
+ // Send email...
693
+ }
694
+ }
695
+
696
+ master.addTransient('email', EmailService);
697
+ ```
698
+
699
+ **Usage:**
700
+ ```javascript
701
+ class UsersController {
702
+ create(obj) {
703
+ // New instance each access
704
+ this.email.send(obj.params.formData.email, 'Welcome!', 'Thanks for joining');
705
+ }
706
+ }
707
+ ```
708
+
709
+ ### Accessing Services
710
+
711
+ Services are automatically available on `this` in controllers:
712
+
713
+ ```javascript
714
+ class UsersController {
715
+ index(obj) {
716
+ // Access singleton
717
+ const users = this.db.query('SELECT * FROM users');
718
+
719
+ // Access scoped
720
+ this.logger.log('Query executed');
721
+
722
+ // Access transient
723
+ this.email.send(user.email, 'Subject', 'Body');
724
+
725
+ this.render('index', { users });
726
+ }
727
+ }
728
+ ```
729
+
730
+ ---
731
+
732
+ ## CORS
733
+
734
+ ### `master.cors.init(options)`
735
+
736
+ Initialize CORS (auto-registers with middleware pipeline).
737
+
738
+ ```javascript
739
+ master.cors.init({
740
+ origin: true, // Reflect request origin, or '*', or ['https://example.com']
741
+ methods: ['GET', 'POST', 'PUT', 'DELETE'],
742
+ allowedHeaders: true, // Reflect requested headers, or specify array
743
+ exposeHeaders: ['X-Total-Count'],
744
+ credentials: true,
745
+ maxAge: 86400
746
+ });
747
+ ```
748
+
749
+ **Options:**
750
+
751
+ - `origin`:
752
+ - `true` - Reflect request origin (or `*` if no credentials)
753
+ - `false` - Remove CORS headers
754
+ - `'*'` - Allow all origins
755
+ - `'https://example.com'` - Specific origin
756
+ - `['https://example.com', 'https://app.com']` - Array of origins
757
+ - `function(origin, req)` - Custom function returning `true`, `false`, or origin string
758
+
759
+ - `methods`: Array of allowed HTTP methods
760
+ - `allowedHeaders`: `true` (all), `false` (none), array, or string
761
+ - `exposeHeaders`: Array of headers to expose to browser
762
+ - `credentials`: `true` to allow credentials (cookies, auth headers)
763
+ - `maxAge`: Preflight cache duration in seconds
764
+
765
+ **CORS automatically:**
766
+ - Handles preflight OPTIONS requests
767
+ - Sets appropriate headers
768
+ - Varies by Origin for security
769
+
770
+ ### Advanced CORS
771
+
772
+ ```javascript
773
+ // Function-based origin validation
774
+ master.cors.init({
775
+ origin: (origin, req) => {
776
+ // Custom validation logic
777
+ if (req.headers['x-api-key'] === 'secret') {
778
+ return true; // Reflect origin
779
+ }
780
+ if (origin === 'https://trusted.com') {
781
+ return origin;
782
+ }
783
+ return false; // Deny
784
+ },
785
+ credentials: true
786
+ });
787
+ ```
788
+
789
+ ---
790
+
791
+ ## Sessions
792
+
793
+ MasterController provides **two session systems**:
794
+ - **`master.session`** (NEW) - Secure, Rails/Django-style sessions with automatic regeneration and protection (RECOMMENDED)
795
+ - **`master.sessions`** (LEGACY) - Original cookie-based session API (backward compatibility only)
796
+
797
+ ### Secure Sessions (NEW - Recommended)
798
+
799
+ #### `master.session.init(options)`
800
+
801
+ Initialize secure sessions with Rails/Django-style `req.session` object (auto-registers with middleware pipeline).
802
+
803
+ ```javascript
804
+ // Environment-specific configuration
805
+ const isProduction = master.environmentType === 'production';
806
+
807
+ master.session.init({
808
+ cookieName: 'mc_session',
809
+ maxAge: isProduction ? 3600000 : 86400000, // Production: 1 hour, Dev: 24 hours
810
+ httpOnly: true, // Prevent JavaScript access (XSS protection)
811
+ secure: isProduction, // HTTPS only in production
812
+ sameSite: isProduction ? 'strict' : 'lax', // CSRF protection
813
+ rolling: true, // Extend session on each request
814
+ regenerateInterval: 900000, // Regenerate session ID every 15 minutes
815
+ useFingerprint: false // Session hijacking detection (opt-in)
816
+ });
817
+ ```
818
+
819
+ **Security Features:**
820
+ - ✅ 32-byte (256-bit) session IDs (cryptographically secure)
821
+ - ✅ Automatic session regeneration (prevents fixation attacks)
822
+ - ✅ HttpOnly cookies (prevents XSS cookie theft)
823
+ - ✅ Secure flag for HTTPS (prevents MITM attacks)
824
+ - ✅ SameSite CSRF protection
825
+ - ✅ Rolling sessions (extends expiry on activity)
826
+ - ✅ Automatic cleanup of expired sessions
827
+ - ✅ Optional fingerprinting (detects hijacking)
828
+
829
+ #### Using Sessions in Controllers
830
+
831
+ Sessions are accessed via `obj.request.session` object:
21
832
 
22
- // Or load from config/environments/env.<env>.json
23
- // master.serverSettings(master.env.server);
833
+ ```javascript
834
+ class AuthController {
835
+ login(obj) {
836
+ const user = authenticateUser(obj.params.formData);
24
837
 
25
- // Load your routes
26
- master.startMVC('app');
838
+ // Set session data (Rails/Express style)
839
+ obj.request.session.userId = user.id;
840
+ obj.request.session.username = user.name;
841
+ obj.request.session.loggedInAt = Date.now();
842
+
843
+ this.redirect('/dashboard');
844
+ }
845
+
846
+ logout(obj) {
847
+ // Destroy entire session
848
+ master.session.destroy(obj.request, obj.response);
849
+ this.redirect('/');
850
+ }
851
+ }
852
+ ```
853
+
854
+ ```javascript
855
+ class DashboardController {
856
+ index(obj) {
857
+ // Read session data
858
+ const userId = obj.request.session.userId;
859
+
860
+ if (!userId) {
861
+ this.redirect('/login');
862
+ return;
863
+ }
864
+
865
+ this.render('dashboard', { userId });
866
+ }
867
+ }
868
+ ```
869
+
870
+ #### Session Management API
871
+
872
+ **`master.session.destroy(req, res)`** - Destroy session completely
873
+
874
+ ```javascript
875
+ master.session.destroy(obj.request, obj.response);
876
+ ```
877
+
878
+ **`master.session.touch(sessionId)`** - Extend session expiry
879
+
880
+ ```javascript
881
+ master.session.touch(obj.request.sessionId);
882
+ ```
883
+
884
+ **`master.session.getSessionCount()`** - Get active session count (monitoring)
885
+
886
+ ```javascript
887
+ const count = master.session.getSessionCount();
888
+ console.log(`Active sessions: ${count}`);
889
+ ```
890
+
891
+ **`master.session.clearAllSessions()`** - Clear all sessions (testing only)
892
+
893
+ ```javascript
894
+ master.session.clearAllSessions();
895
+ ```
896
+
897
+ #### Environment-Specific Best Practices
898
+
899
+ ```javascript
900
+ // Get recommended settings
901
+ const settings = master.session.getBestPractices('production');
902
+ master.session.init(settings);
903
+ ```
904
+
905
+ **Production Settings:**
906
+ - Secure: true (HTTPS only)
907
+ - SameSite: 'strict' (maximum CSRF protection)
908
+ - MaxAge: 1 hour (short-lived sessions)
909
+ - RegenerateInterval: 15 minutes
910
+
911
+ **Development Settings:**
912
+ - Secure: false (allow HTTP)
913
+ - SameSite: 'lax' (easier testing)
914
+ - MaxAge: 24 hours (convenient for development)
915
+ - RegenerateInterval: 1 hour
916
+
917
+ ---
918
+
919
+ ### Legacy Sessions (Backward Compatibility)
920
+
921
+ **⚠️ DEPRECATED: Use `master.session` (singular) for new projects.**
922
+
923
+ The original `master.sessions` (plural) API is maintained for backward compatibility but lacks modern security features.
924
+
925
+ #### `master.sessions.init(options)`
926
+
927
+ Initialize legacy sessions (auto-registers with middleware pipeline).
928
+
929
+ ```javascript
930
+ master.sessions.init({
931
+ secret: 'your-secret-key',
932
+ maxAge: 900000, // 15 minutes
933
+ httpOnly: true,
934
+ secure: true, // HTTPS only
935
+ sameSite: 'strict', // Must be string: 'strict', 'lax', or 'none'
936
+ path: '/'
937
+ });
938
+ ```
939
+
940
+ #### Legacy Session API
941
+
942
+ **`master.sessions.set(name, data, response, secret, options)`** - Create a session
943
+
944
+ ```javascript
945
+ master.sessions.set('user', userData, obj.response);
946
+ ```
947
+
948
+ **`master.sessions.get(name, request, secret)`** - Retrieve session data
949
+
950
+ ```javascript
951
+ const user = master.sessions.get('user', obj.request);
952
+ ```
953
+
954
+ **`master.sessions.delete(name, response)`** - Delete a session
955
+
956
+ ```javascript
957
+ master.sessions.delete('user', obj.response);
958
+ ```
959
+
960
+ **`master.sessions.reset()`** - Clear all sessions
961
+
962
+ ```javascript
963
+ master.sessions.reset();
964
+ ```
965
+
966
+ #### Legacy Cookie Methods
967
+
968
+ **`master.sessions.setCookie(name, value, response, options)`**
969
+ ```javascript
970
+ master.sessions.setCookie('theme', 'dark', obj.response);
971
+ ```
972
+
973
+ **`master.sessions.getCookie(name, request, secret)`**
974
+ ```javascript
975
+ const theme = master.sessions.getCookie('theme', obj.request);
976
+ ```
977
+
978
+ **`master.sessions.deleteCookie(name, response, options)`**
979
+ ```javascript
980
+ master.sessions.deleteCookie('theme', obj.response);
981
+ ```
982
+
983
+ #### Migration Guide: Legacy → Secure Sessions
984
+
985
+ **Old (master.sessions):**
986
+ ```javascript
987
+ // Set
988
+ master.sessions.set('user', userData, obj.response);
989
+
990
+ // Get
991
+ const user = master.sessions.get('user', obj.request);
992
+
993
+ // Delete
994
+ master.sessions.delete('user', obj.response);
995
+ ```
996
+
997
+ **New (master.session):**
998
+ ```javascript
999
+ // Set (Rails/Express style)
1000
+ obj.request.session.user = userData;
1001
+
1002
+ // Get
1003
+ const user = obj.request.session.user;
1004
+
1005
+ // Delete
1006
+ master.session.destroy(obj.request, obj.response);
1007
+ ```
1008
+
1009
+ **Benefits of migration:**
1010
+ - ✅ Automatic session regeneration (prevents fixation)
1011
+ - ✅ 32-byte session IDs (stronger than 20-byte)
1012
+ - ✅ Rolling sessions (better UX)
1013
+ - ✅ Automatic cleanup (no memory leaks)
1014
+ - ✅ Rails/Express-style API (more familiar)
1015
+ - ✅ No broken encryption (legacy has crypto bugs)
1016
+
1017
+ ---
1018
+
1019
+ ## Security
1020
+
1021
+ MasterController includes built-in security middleware.
1022
+
1023
+ ### Security Headers
1024
+
1025
+ ```javascript
1026
+ const { pipelineSecurityHeaders } = require('./security/SecurityMiddleware');
1027
+
1028
+ master.pipeline.use(pipelineSecurityHeaders());
1029
+ ```
1030
+
1031
+ **Applied headers:**
1032
+ - `X-XSS-Protection: 1; mode=block`
1033
+ - `X-Frame-Options: SAMEORIGIN`
1034
+ - `X-Content-Type-Options: nosniff`
1035
+ - `X-DNS-Prefetch-Control: off`
1036
+ - `Permissions-Policy: geolocation=(), microphone=(), camera=()`
1037
+ - `Referrer-Policy: strict-origin-when-cross-origin`
1038
+ - `Strict-Transport-Security` (HTTPS production only)
1039
+
1040
+ ### Rate Limiting
1041
+
1042
+ ```javascript
1043
+ const { pipelineRateLimit } = require('./security/SecurityMiddleware');
1044
+
1045
+ master.pipeline.use(pipelineRateLimit({
1046
+ rateLimitWindow: 60000, // 1 minute
1047
+ rateLimitMax: 100 // 100 requests per window
1048
+ }));
1049
+ ```
1050
+
1051
+ **Rate limit headers:**
1052
+ - `X-RateLimit-Limit` - Maximum requests allowed
1053
+ - `X-RateLimit-Remaining` - Requests remaining in window
1054
+ - `X-RateLimit-Reset` - When the limit resets
1055
+ - `Retry-After` - Seconds until retry (when blocked)
1056
+
1057
+ ### CSRF Protection
1058
+
1059
+ ```javascript
1060
+ const { pipelineCsrf, generateCSRFToken } = require('./security/SecurityMiddleware');
1061
+
1062
+ // Apply to all routes
1063
+ master.pipeline.use(pipelineCsrf());
1064
+
1065
+ // Or only to specific routes
1066
+ master.pipeline.map('/admin/*', (admin) => {
1067
+ admin.use(pipelineCsrf());
1068
+ });
1069
+ ```
1070
+
1071
+ **Generate token:**
1072
+ ```javascript
1073
+ const token = generateCSRFToken(sessionId);
1074
+
1075
+ // In controller
1076
+ class FormController {
1077
+ show(obj) {
1078
+ const csrfToken = generateCSRFToken();
1079
+ this.render('form', { csrfToken });
1080
+ }
1081
+ }
1082
+ ```
1083
+
1084
+ **In forms:**
1085
+ ```html
1086
+ <form method="post">
1087
+ <input type="hidden" name="_csrf" value="{{csrfToken}}">
1088
+ <!-- or -->
1089
+ <!-- Send as header: x-csrf-token -->
1090
+ <!-- or -->
1091
+ <!-- Send as query: ?_csrf=token -->
1092
+ </form>
1093
+ ```
1094
+
1095
+ ### Input Validation
1096
+
1097
+ ```javascript
1098
+ const { validator } = require('./security/MasterValidator');
1099
+
1100
+ class UsersController {
1101
+ create(obj) {
1102
+ const email = obj.params.formData.email;
1103
+
1104
+ // Validate email
1105
+ const emailCheck = validator.isEmail(email);
1106
+ if (!emailCheck.valid) {
1107
+ this.json({ error: emailCheck.error });
1108
+ return;
1109
+ }
1110
+
1111
+ // Continue with valid data
1112
+ // ...
1113
+ }
1114
+ }
1115
+ ```
1116
+
1117
+ **Available validators:**
1118
+ - `validator.isEmail(email)`
1119
+ - `validator.isURL(url)`
1120
+ - `validator.isAlphanumeric(str)`
1121
+ - `validator.isLength(str, min, max)`
1122
+ - `detectPathTraversal(path)` - Detect `../` attacks
1123
+ - `detectSQLInjection(input)` - Detect SQL injection
1124
+ - `detectCommandInjection(input)` - Detect command injection
1125
+
1126
+ ---
1127
+
1128
+ ## Components
1129
+
1130
+ Components are self-contained modules with their own routes, controllers, and views.
1131
+
1132
+ ### Structure
1133
+
1134
+ ```
1135
+ components/
1136
+ user/
1137
+ config/
1138
+ initializers/
1139
+ config.js
1140
+ routes.js
1141
+ app/
1142
+ controllers/
1143
+ authController.js
1144
+ views/
1145
+ auth/
1146
+ login.html
1147
+ models/
1148
+ userContext.js
1149
+ ```
1150
+
1151
+ ### Register Component
1152
+
1153
+ ```javascript
1154
+ // In config/initializers/config.js
1155
+ master.component('components', 'user');
1156
+ master.component('components', 'mail');
1157
+ ```
1158
+
1159
+ ### Absolute Path Components
1160
+
1161
+ ```javascript
1162
+ // Load component from absolute path
1163
+ master.component('/var/www/shared-components', 'analytics');
1164
+ ```
1165
+
1166
+ Components are isolated and can be reused across projects.
1167
+
1168
+ ---
1169
+
1170
+ ## Timeout System
1171
+
1172
+ MasterController v2.0 includes a professional timeout system with per-request tracking (Rails/Django style).
1173
+
1174
+ ### Configuration
1175
+
1176
+ ```javascript
1177
+ // config/initializers/config.js
1178
+ master.timeout.init({
1179
+ globalTimeout: 120000, // 120 seconds (2 minutes) default
1180
+ enabled: true,
1181
+ onTimeout: (ctx, timeoutInfo) => {
1182
+ // Optional custom timeout handler
1183
+ console.log(`Request timeout: ${timeoutInfo.path}`);
1184
+ }
1185
+ });
1186
+
1187
+ // Register timeout middleware
1188
+ master.pipeline.use(master.timeout.middleware());
1189
+ ```
1190
+
1191
+ ### Route-Specific Timeouts
1192
+
1193
+ ```javascript
1194
+ // Short timeout for API endpoints
1195
+ master.timeout.setRouteTimeout('/api/*', 30000); // 30 seconds
1196
+
1197
+ // Long timeout for reports
1198
+ master.timeout.setRouteTimeout('/admin/reports', 300000); // 5 minutes
1199
+
1200
+ // Very long timeout for batch operations
1201
+ master.timeout.setRouteTimeout('/batch/process', 600000); // 10 minutes
1202
+ ```
1203
+
1204
+ ### Timeout Statistics
1205
+
1206
+ ```javascript
1207
+ const stats = master.timeout.getStats();
1208
+
1209
+ console.log(stats);
1210
+ // {
1211
+ // enabled: true,
1212
+ // globalTimeout: 120000,
1213
+ // routeTimeouts: [
1214
+ // { pattern: '/api/*', timeout: 30000 }
1215
+ // ],
1216
+ // activeRequests: 5,
1217
+ // requests: [
1218
+ // {
1219
+ // requestId: 'req_1234567890_abc123',
1220
+ // path: 'api/users',
1221
+ // method: 'get',
1222
+ // timeout: 30000,
1223
+ // elapsed: 15000,
1224
+ // remaining: 15000
1225
+ // }
1226
+ // ]
1227
+ // }
1228
+ ```
1229
+
1230
+ ### Disable/Enable Timeouts
1231
+
1232
+ ```javascript
1233
+ // Disable for debugging
1234
+ master.timeout.disable();
1235
+
1236
+ // Re-enable
1237
+ master.timeout.enable();
1238
+ ```
1239
+
1240
+ ---
1241
+
1242
+ ## Error Handling
1243
+
1244
+ MasterController v2.0 includes a professional error template system inspired by Rails and Django.
1245
+
1246
+ ### Error Renderer Configuration
1247
+
1248
+ ```javascript
1249
+ // config/initializers/config.js
1250
+ master.errorRenderer.init({
1251
+ templateDir: 'public/errors', // Error templates directory
1252
+ environment: master.environmentType,
1253
+ showStackTrace: master.environmentType === 'development' // Dev only
1254
+ });
1255
+ ```
1256
+
1257
+ ### Using Error Renderer
1258
+
1259
+ ```javascript
1260
+ // In middleware
1261
+ master.pipeline.use(async (ctx, next) => {
1262
+ if (!isAuthenticated(ctx)) {
1263
+ master.errorRenderer.send(ctx, 401, {
1264
+ message: 'Please log in to access this resource',
1265
+ suggestions: [
1266
+ 'Sign in with your credentials',
1267
+ 'Request a password reset if forgotten'
1268
+ ]
1269
+ });
1270
+ return;
1271
+ }
1272
+ await next();
1273
+ });
1274
+
1275
+ // In controllers
1276
+ class UsersController {
1277
+ async show(obj) {
1278
+ const userId = obj.params.userId;
1279
+ const user = await this.db.query('SELECT * FROM users WHERE id = ?', [userId]);
1280
+
1281
+ if (!user) {
1282
+ master.errorRenderer.send(obj, 404, {
1283
+ message: `User #${userId} not found`,
1284
+ suggestions: [
1285
+ 'Check the user ID',
1286
+ 'Browse all users',
1287
+ 'Search for the user by name'
1288
+ ]
1289
+ });
1290
+ return;
1291
+ }
1292
+
1293
+ this.render('show', { user });
1294
+ }
1295
+ }
1296
+ ```
1297
+
1298
+ ### Error Templates
1299
+
1300
+ Create templates in `public/errors/`:
1301
+
1302
+ ```
1303
+ public/errors/
1304
+ ├── 400.html # Bad Request
1305
+ ├── 401.html # Unauthorized
1306
+ ├── 403.html # Forbidden
1307
+ ├── 404.html # Not Found
1308
+ ├── 405.html # Method Not Allowed
1309
+ ├── 422.html # Unprocessable Entity
1310
+ ├── 429.html # Too Many Requests
1311
+ ├── 500.html # Internal Server Error
1312
+ ├── 502.html # Bad Gateway
1313
+ ├── 503.html # Service Unavailable
1314
+ └── 504.html # Gateway Timeout
1315
+ ```
1316
+
1317
+ **Template Variables:**
1318
+
1319
+ ```html
1320
+ <!DOCTYPE html>
1321
+ <html>
1322
+ <head>
1323
+ <title>{{title}} ({{statusCode}})</title>
1324
+ </head>
1325
+ <body>
1326
+ <h1>{{statusCode}} - {{title}}</h1>
1327
+ <p>{{message}}</p>
1328
+
1329
+ <!-- Conditionals (dev only) -->
1330
+ {{#if showStackTrace}}
1331
+ <pre>{{stack}}</pre>
1332
+ {{/if}}
1333
+
1334
+ <!-- Loops -->
1335
+ {{#each suggestions}}
1336
+ <li>{{this}}</li>
1337
+ {{/each}}
1338
+ </body>
1339
+ </html>
1340
+ ```
1341
+
1342
+ **Available Variables:**
1343
+ - `{{statusCode}}` - HTTP status code (404, 500, etc.)
1344
+ - `{{title}}` - Error title
1345
+ - `{{message}}` - Error message
1346
+ - `{{code}}` - Error code
1347
+ - `{{stack}}` - Stack trace (development only)
1348
+ - `{{suggestions}}` - Array of suggestions
1349
+ - `{{environment}}` - Current environment
1350
+
1351
+ ### Custom Error Handlers
1352
+
1353
+ ```javascript
1354
+ // Register custom handler for specific status code
1355
+ master.errorRenderer.registerHandler(503, (ctx, errorData) => {
1356
+ return `
1357
+ <!DOCTYPE html>
1358
+ <html>
1359
+ <body>
1360
+ <h1>Maintenance Mode</h1>
1361
+ <p>We'll be back soon! Expected completion: 2:00 PM EST</p>
1362
+ </body>
1363
+ </html>
1364
+ `;
1365
+ });
1366
+ ```
1367
+
1368
+ ### Content Negotiation
1369
+
1370
+ The error renderer automatically detects API requests and returns JSON:
1371
+
1372
+ ```javascript
1373
+ // Browser request → HTML
1374
+ GET /users/999
1375
+ Accept: text/html
1376
+ → Returns beautiful HTML error page
1377
+
1378
+ // API request → JSON
1379
+ GET /api/users/999
1380
+ Accept: application/json
1381
+ → Returns JSON error response
1382
+ {
1383
+ "error": "Page Not Found",
1384
+ "statusCode": 404,
1385
+ "code": "MC_HTTP_ERROR",
1386
+ "message": "The user you're looking for doesn't exist."
1387
+ }
1388
+ ```
1389
+
1390
+ ### Global Error Handler (Pipeline)
1391
+
1392
+ ```javascript
1393
+ master.pipeline.useError(async (error, ctx, next) => {
1394
+ console.error('Pipeline error:', error);
1395
+
1396
+ // Use error renderer for HTTP errors
1397
+ master.errorRenderer.send(ctx, 500, {
1398
+ message: error.message,
1399
+ code: error.code,
1400
+ stack: error.stack
1401
+ });
1402
+ });
27
1403
  ```
28
1404
 
29
- ### Routes
30
- Create `app/config/routes.js` and define routes with `master.router.start()` API.
1405
+ ### Controller Error Handling
1406
+
1407
+ ```javascript
1408
+ class UsersController {
1409
+ async index(obj) {
1410
+ try {
1411
+ const users = await this.db.query('SELECT * FROM users');
1412
+ this.render('index', { users });
1413
+ } catch (error) {
1414
+ console.error('Database error:', error);
1415
+
1416
+ master.errorRenderer.send(obj, 500, {
1417
+ message: 'Failed to load users',
1418
+ code: 'DB_ERROR',
1419
+ stack: error.stack
1420
+ });
1421
+ }
1422
+ }
1423
+ }
1424
+ ```
31
1425
 
32
- ### Controllers
33
- Place controllers under `app/controllers/*.js` and export methods matching your routes.
1426
+ ### Logging
34
1427
 
35
- ### Views and Templates
36
- Views live under `app/views/<controller>/<action>.html` with a layout at `app/views/layouts/master.html`.
1428
+ ```javascript
1429
+ const { logger } = require('./error/MasterErrorLogger');
37
1430
 
38
- ### CORS and Preflight
39
- `MasterCors` configures CORS headers. Preflight `OPTIONS` requests are short-circuited with 204.
1431
+ // In controllers or middleware
1432
+ logger.info({
1433
+ code: 'USER_LOGIN',
1434
+ message: 'User logged in',
1435
+ userId: user.id
1436
+ });
1437
+
1438
+ logger.warn({
1439
+ code: 'INVALID_INPUT',
1440
+ message: 'Invalid email format',
1441
+ email: input
1442
+ });
1443
+
1444
+ logger.error({
1445
+ code: 'DB_ERROR',
1446
+ message: 'Database query failed',
1447
+ error: error.message,
1448
+ stack: error.stack
1449
+ });
1450
+ ```
40
1451
 
41
- ### HTTPS
42
- Use `setupServer('https', credentials)` or configure via environment TLS; see docs in `docs/` for multiple setups.
1452
+ ---
43
1453
 
44
- ### Docs
45
- - `docs/server-setup-http.md`
46
- - `docs/server-setup-https-credentials.md`
47
- - `docs/server-setup-https-env-tls-sni.md`
48
- - `docs/server-setup-hostname-binding.md`
49
- - `docs/server-setup-nginx-reverse-proxy.md`
50
- - `docs/environment-tls-reference.md`
1454
+ ## HTTPS Setup
51
1455
 
52
- ### Production tips
53
- - Prefer a reverse proxy for TLS and serve Node on a high port.
54
- - If keeping TLS in Node, harden TLS and manage cert rotation.
1456
+ ### Basic HTTPS
1457
+
1458
+ ```javascript
1459
+ const fs = require('fs');
1460
+
1461
+ const credentials = {
1462
+ key: fs.readFileSync('path/to/key.pem'),
1463
+ cert: fs.readFileSync('path/to/cert.pem')
1464
+ };
1465
+
1466
+ const server = master.setupServer('https', credentials);
1467
+ ```
1468
+
1469
+ ### Environment-based TLS
1470
+
1471
+ Configure TLS in `config/environments/env.production.json`:
1472
+
1473
+ ```json
1474
+ {
1475
+ "server": {
1476
+ "httpPort": 443,
1477
+ "tls": {
1478
+ "default": {
1479
+ "keyPath": "/path/to/default.key",
1480
+ "certPath": "/path/to/default.crt"
1481
+ },
1482
+ "sni": {
1483
+ "example.com": {
1484
+ "keyPath": "/path/to/example.key",
1485
+ "certPath": "/path/to/example.crt"
1486
+ },
1487
+ "app.example.com": {
1488
+ "keyPath": "/path/to/app.key",
1489
+ "certPath": "/path/to/app.crt"
1490
+ }
1491
+ }
1492
+ }
1493
+ }
1494
+ }
1495
+ ```
1496
+
1497
+ ```javascript
1498
+ const server = master.setupServer('https');
1499
+ master.serverSettings(master.env.server);
1500
+ ```
1501
+
1502
+ ### HTTP to HTTPS Redirect
1503
+
1504
+ ```javascript
1505
+ // Start HTTPS server on 443
1506
+ const httpsServer = master.setupServer('https');
1507
+ master.start(httpsServer);
1508
+ master.serverSettings({ httpPort: 443 });
1509
+
1510
+ // Start redirect server on 80
1511
+ const redirectServer = master.startHttpToHttpsRedirect(80);
1512
+ ```
1513
+
1514
+ ### HSTS (HTTP Strict Transport Security)
1515
+
1516
+ ```javascript
1517
+ master.enableHSTS(); // In production HTTPS
1518
+ ```
1519
+
1520
+ ---
1521
+
1522
+ ## API Reference
1523
+
1524
+ ### Master Instance
1525
+
1526
+ - `master.root` - Project root directory
1527
+ - `master.environmentType` - Environment ('development', 'production', etc.)
1528
+ - `master.env` - Environment config from `config/environments/env.<env>.json`
1529
+ - `master.serverProtocol` - 'http' or 'https'
1530
+
1531
+ ### Setup Methods
1532
+
1533
+ - `master.setupServer(type, credentials)` - Create HTTP or HTTPS server
1534
+ - `master.start(server)` - Start the server
1535
+ - `master.serverSettings(options)` - Configure server (port, host, timeout)
1536
+ - `master.startMVC(folder)` - Load routes from folder
1537
+ - `master.component(folder, name)` - Load component
1538
+ - `master.enableHSTS()` - Enable HSTS for HTTPS
1539
+ - `master.startHttpToHttpsRedirect(port, host)` - Create redirect server
1540
+
1541
+ ### Middleware Pipeline
1542
+
1543
+ - `master.pipeline.use(middleware)` - Add middleware
1544
+ - `master.pipeline.run(middleware)` - Add terminal middleware
1545
+ - `master.pipeline.map(path, configure)` - Conditional middleware
1546
+ - `master.pipeline.useError(handler)` - Add error handler
1547
+ - `master.pipeline.discoverMiddleware(options)` - Auto-discover middleware
1548
+ - `master.pipeline.execute(context)` - Execute pipeline (internal)
1549
+ - `master.pipeline.clear()` - Clear all middleware (testing)
1550
+ - `master.pipeline.inspect()` - Inspect middleware stack (debugging)
1551
+
1552
+ ### Dependency Injection
1553
+
1554
+ - `master.addSingleton(name, Class)` - Register singleton service
1555
+ - `master.addScoped(name, Class)` - Register scoped service (per request)
1556
+ - `master.addTransient(name, Class)` - Register transient service (per access)
1557
+
1558
+ ### Extensions
1559
+
1560
+ - `master.extend(name, Class)` - Extend master with new functionality
1561
+ - `master.extendController(Class)` - Extend all controllers
1562
+ - `master.extendView(name, Class)` - Extend all views
1563
+
1564
+ ### Router
1565
+
1566
+ - `master.router.start()` - Get router API
1567
+ - `router.route(path, toPath, method, constraint)` - Register route
1568
+ - `router.resources(name)` - Register RESTful routes
1569
+ - `master.router.setup(options)` - Setup route namespace (internal)
1570
+ - `master.router.load(requestObject)` - Load and match routes (internal)
1571
+ - `master.router.currentRoute` - Current route info
1572
+ - `master.router.findMimeType(ext)` - Get MIME type for extension
1573
+ - `master.router.addMimeList(mimes)` - Add MIME type mappings
1574
+
1575
+ ### CORS
1576
+
1577
+ - `master.cors.init(options)` - Initialize CORS
1578
+ - `master.cors.load(params)` - Apply CORS headers (internal)
1579
+ - `master.cors.middleware()` - Get pipeline middleware
1580
+
1581
+ ### Sessions
1582
+
1583
+ - `master.sessions.init(options)` - Initialize sessions
1584
+ - `master.sessions.set(name, data, response, secret, options)` - Create session
1585
+ - `master.sessions.get(name, request, secret)` - Get session data
1586
+ - `master.sessions.delete(name, response)` - Delete session
1587
+ - `master.sessions.reset()` - Clear all sessions
1588
+ - `master.sessions.setCookie(name, value, response, options)` - Set cookie
1589
+ - `master.sessions.getCookie(name, request, secret)` - Get cookie
1590
+ - `master.sessions.deleteCookie(name, response, options)` - Delete cookie
1591
+ - `master.sessions.createSessionID()` - Generate random session ID
1592
+ - `master.sessions.middleware()` - Get pipeline middleware
1593
+
1594
+ ### Request
1595
+
1596
+ - `master.request.getRequestParam(request, response)` - Parse request body (internal)
1597
+
1598
+ ### HTML/Template
1599
+
1600
+ - `master.html.init(path)` - Set views path
1601
+ - `master.template.init(layout)` - Set layout template
1602
+
1603
+ ### Tools
1604
+
1605
+ - `master.tools.encrypt(data, secret)` - Encrypt data
1606
+ - `master.tools.decrypt(data, secret)` - Decrypt data
1607
+ - `master.tools.combineObjects(target, source)` - Merge objects
1608
+ - `master.tools.makeWordId(length)` - Generate random ID
1609
+
1610
+ ---
1611
+
1612
+ ## Production Tips
1613
+
1614
+ 1. **Use a reverse proxy** (nginx, Apache) for TLS termination
1615
+ 2. **Run Node.js on a high port** (3000, 8080) behind the proxy
1616
+ 3. **Enable HSTS** for HTTPS: `master.enableHSTS()`
1617
+ 4. **Use environment variables** for secrets and config
1618
+ 5. **Enable rate limiting** for public APIs
1619
+ 6. **Enable CSRF protection** for forms
1620
+ 7. **Use security headers** middleware
1621
+ 8. **Monitor logs** with `logger` module
1622
+ 9. **Use process manager** (PM2, systemd) for restarts
1623
+ 10. **Keep dependencies updated**
1624
+
1625
+ ---
1626
+
1627
+ ## Documentation
1628
+
1629
+ Detailed guides:
1630
+
1631
+ - [HTTP Server Setup](docs/server-setup-http.md)
1632
+ - [HTTPS with Credentials](docs/server-setup-https-credentials.md)
1633
+ - [HTTPS with Environment TLS & SNI](docs/server-setup-https-env-tls-sni.md)
1634
+ - [Hostname Binding](docs/server-setup-hostname-binding.md)
1635
+ - [Nginx Reverse Proxy](docs/server-setup-nginx-reverse-proxy.md)
1636
+ - [Environment TLS Reference](docs/environment-tls-reference.md)
1637
+
1638
+ ---
1639
+
1640
+ ## License
55
1641
 
56
- ### License
57
1642
  MIT
58
1643
 
1644
+ ---
1645
+
1646
+ ## Contributing
1647
+
1648
+ Contributions are welcome! Please open an issue or submit a pull request.
1649
+
1650
+ ---
1651
+
1652
+ ## Support
1653
+
1654
+ For issues and questions, please visit: [GitHub Issues](https://github.com/alexanderrich/MasterController/issues)