@reldens/cms 0.52.0 → 0.53.0

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.
@@ -0,0 +1,450 @@
1
+ # Architecture Guide
2
+
3
+ ## Core Orchestrators
4
+
5
+ ### Manager
6
+
7
+ **File:** `lib/manager.js`
8
+
9
+ Main CMS orchestrator that:
10
+
11
+ - Initializes all services (data server, admin, frontend)
12
+ - Handles configuration and environment variables
13
+ - Manages multi-domain setup and security
14
+ - Coordinates service lifecycle
15
+ - Initializes password encryption handler
16
+ - Defines default templateExtensions: `['.html', '.mustache', '.template', '.txt', '.xml', '.json']`
17
+ - Passes templateExtensions to all frontend components ensuring consistency
18
+
19
+ ### Frontend
20
+
21
+ **File:** `lib/frontend.js`
22
+
23
+ Frontend orchestrator that:
24
+
25
+ - Coordinates all frontend operations
26
+ - Manages template engine, cache, and rendering
27
+ - Handles search and dynamic forms
28
+ - Routes requests to appropriate handlers
29
+ - Receives templateExtensions from Manager and passes to TemplateResolver and TemplateCache
30
+ - Handles Content-Type detection based on request path extensions
31
+
32
+ ### Admin Manager
33
+
34
+ **File:** `lib/admin-manager.js`
35
+
36
+ Admin panel orchestrator that:
37
+
38
+ - Manages admin panel routes and authentication
39
+ - Handles entity CRUD operations
40
+ - Processes file uploads
41
+ - Builds admin UI from entity configurations
42
+
43
+ ### Password Encryption Handler
44
+
45
+ **File:** `lib/password-encryption-handler.js`
46
+
47
+ Password encryption handler that:
48
+
49
+ - Automatic password encryption for users entity
50
+ - Event-driven architecture
51
+ - PBKDF2 encryption with 100k iterations
52
+ - Detects and skips already-encrypted passwords
53
+ - Configurable entity and field names
54
+
55
+ ### Admin Router Contents
56
+
57
+ **File:** `lib/admin-manager/router-contents.js`
58
+
59
+ Admin routing and form handling that:
60
+
61
+ - Password field handling (type="password", empty on edit)
62
+ - Password updates optional (skip if empty when editing)
63
+ - Configurable password field names via passwordFieldNames
64
+
65
+ ## Installation & Setup
66
+
67
+ ### Installer
68
+
69
+ **File:** `lib/installer.js`
70
+
71
+ Installation orchestrator that:
72
+
73
+ - Web-based installer with subprocess management
74
+ - Dependency checking and installation
75
+ - Database schema creation
76
+ - Environment file generation
77
+ - Post-installation callbacks
78
+
79
+ ### MySQL Installer
80
+
81
+ **File:** `lib/mysql-installer.js`
82
+
83
+ Database-specific installation that:
84
+
85
+ - MySQL schema creation
86
+ - Schema migration support
87
+ - Database validation
88
+
89
+ ### Prisma Subprocess Worker
90
+
91
+ **File:** `lib/prisma-subprocess-worker.js`
92
+
93
+ Subprocess worker that:
94
+
95
+ - Handles Prisma client generation
96
+ - Progress tracking for long operations
97
+
98
+ ## Frontend Architecture
99
+
100
+ ### Template Resolver
101
+
102
+ **File:** `lib/frontend/template-resolver.js`
103
+
104
+ Template discovery that:
105
+
106
+ - Domain-aware template resolution with fallback system (domain → default domain → base)
107
+ - Automatic extension resolution (tries `.html`, `.mustache`, `.template`, `.txt`, `.xml`, `.json`)
108
+ - Layout and partial template lookup
109
+ - Path-to-template mapping
110
+ - Logs warnings when templates are not found in any location
111
+
112
+ ### Template Cache
113
+
114
+ **File:** `lib/frontend/template-cache.js`
115
+
116
+ Template caching that:
117
+
118
+ - Loads and caches partials
119
+ - Domain-specific template management
120
+ - Partial inheritance and overrides
121
+ - Uses templateExtensions to discover partial files in directories
122
+ - Supports all configured extensions for partial templates
123
+
124
+ ### Request Processor
125
+
126
+ **File:** `lib/frontend/request-processor.js`
127
+
128
+ Request routing that:
129
+
130
+ - Route database lookup
131
+ - Domain extraction from requests
132
+ - Path normalization
133
+ - Cache key generation
134
+
135
+ ### Entity Access Manager
136
+
137
+ **File:** `lib/frontend/entity-access-manager.js`
138
+
139
+ Entity access control that:
140
+
141
+ - Loads entity access rules
142
+ - Public/private entity validation
143
+ - Entity lookup by path
144
+
145
+ ### Content Renderer
146
+
147
+ **File:** `lib/frontend/content-renderer.js`
148
+
149
+ Content generation that:
150
+
151
+ - Main content rendering logic
152
+ - Route-based content generation
153
+ - Template processing
154
+ - Meta field handling
155
+
156
+ ### Response Manager
157
+
158
+ **File:** `lib/frontend/response-manager.js`
159
+
160
+ Response handling that:
161
+
162
+ - HTTP response management
163
+ - Cache integration
164
+ - Error handling (404, 500)
165
+
166
+ ## Template Engine
167
+
168
+ ### Template Engine Core
169
+
170
+ **File:** `lib/template-engine.js`
171
+
172
+ Core template processor that:
173
+
174
+ - Orchestrates all template transformers
175
+ - System variables injection
176
+ - Event-driven rendering pipeline
177
+ - Mustache integration
178
+
179
+ ### Template Transformers
180
+
181
+ **Entities Transformer**
182
+ - File: `lib/template-engine/entities-transformer.js`
183
+ - Single entity rendering `<entity name="cmsBlocks" field="name" value="header"/>`
184
+
185
+ **Collections Transformer**
186
+ - File: `lib/template-engine/collections-transformer.js`
187
+ - Collection loops with pagination
188
+
189
+ **Collections Single Transformer**
190
+ - File: `lib/template-engine/collections-single-transformer.js`
191
+ - Single field collections
192
+
193
+ **Partials Transformer**
194
+ - File: `lib/template-engine/partials-transformer.js`
195
+ - Partial template processing
196
+
197
+ **Forms Transformer**
198
+ - File: `lib/template-engine/forms-transformer.js`
199
+ - Dynamic forms rendering `<cmsForm key="contact"/>`
200
+
201
+ **URL Transformer**
202
+ - File: `lib/template-engine/url-transformer.js`
203
+ - URL generation `[url(/path)]`
204
+
205
+ **Asset Transformer**
206
+ - File: `lib/template-engine/asset-transformer.js`
207
+ - Asset URLs `[asset(/img/logo.png)]`
208
+
209
+ **CDN Transformer**
210
+ - File: `lib/template-engine/cdn-transformer.js`
211
+ - CDN URL transformation
212
+
213
+ **Date Transformer**
214
+ - File: `lib/template-engine/date-transformer.js`
215
+ - Date formatting `[date(now, Y-m-d)]`
216
+
217
+ **Translate Transformer**
218
+ - File: `lib/template-engine/translate-transformer.js`
219
+ - Internationalization `[translate(key)]`
220
+
221
+ ### System Variables Provider
222
+
223
+ **File:** `lib/template-engine/system-variables-provider.js`
224
+
225
+ System variables that:
226
+
227
+ - Current request context (host, path, protocol)
228
+ - Current route data
229
+ - Current domain information
230
+ - System information (environment, timestamp)
231
+
232
+ ### Translation Service
233
+
234
+ **File:** `lib/template-engine/translation-service.js`
235
+
236
+ Translation loading that:
237
+
238
+ - JSON translation file management
239
+ - Locale detection
240
+ - Fallback handling
241
+
242
+ ## Dynamic Forms System
243
+
244
+ ### Dynamic Form
245
+
246
+ **File:** `lib/dynamic-form.js`
247
+
248
+ Form validation and processing that:
249
+
250
+ - Schema-based validation
251
+ - Honeypot protection
252
+ - Rate limiting integration
253
+ - Data sanitization
254
+ - Database storage
255
+
256
+ ### Dynamic Form Renderer
257
+
258
+ **File:** `lib/dynamic-form-renderer.js`
259
+
260
+ Form template rendering that:
261
+
262
+ - Domain-aware form templates
263
+ - Field type templates
264
+ - Error display
265
+ - Form attribute handling
266
+
267
+ ### Dynamic Form Request Handler
268
+
269
+ **File:** `lib/dynamic-form-request-handler.js`
270
+
271
+ Form request handling that:
272
+
273
+ - POST request processing
274
+ - Validation orchestration
275
+ - Success/error redirects
276
+ - JSON response support
277
+
278
+ ## Search System
279
+
280
+ ### Search
281
+
282
+ **File:** `lib/search.js`
283
+
284
+ Search functionality that:
285
+
286
+ - Multi-entity search
287
+ - Custom search sets
288
+ - Query parameter parsing
289
+ - Pagination support
290
+
291
+ ### Search Renderer
292
+
293
+ **File:** `lib/search-renderer.js`
294
+
295
+ Search result rendering that:
296
+
297
+ - Template-based result display
298
+ - Custom column classes
299
+ - Domain-aware templates
300
+
301
+ ### Search Request Handler
302
+
303
+ **File:** `lib/search-request-handler.js`
304
+
305
+ Search request handling that:
306
+
307
+ - Query processing
308
+ - Template data support
309
+ - Error handling
310
+
311
+ ## Cache System
312
+
313
+ ### Cache Manager
314
+
315
+ **File:** `lib/cache/cache-manager.js`
316
+
317
+ Cache orchestrator that:
318
+
319
+ - Domain and path-based caching
320
+ - Cache invalidation
321
+ - Enable/disable functionality
322
+
323
+ ### Cache Routes Handler
324
+
325
+ **File:** `lib/cache/cache-routes-handler.js`
326
+
327
+ Cache admin routes that:
328
+
329
+ - Cache clearing endpoints
330
+ - Cache management UI integration
331
+
332
+ ### Add Cache Button Subscriber
333
+
334
+ **File:** `lib/cache/add-cache-button-subscriber.js`
335
+
336
+ Cache UI integration that:
337
+
338
+ - Adds cache buttons to admin panel
339
+ - Event-driven cache controls
340
+
341
+ ## Admin System
342
+
343
+ ### Router
344
+
345
+ **File:** `lib/admin-manager/router.js`
346
+
347
+ Admin routing that:
348
+
349
+ - Authentication middleware
350
+ - Session management
351
+ - CRUD route setup
352
+ - File upload handling
353
+
354
+ ### Router Contents
355
+
356
+ **File:** `lib/admin-manager/router-contents.js`
357
+
358
+ Admin content generation that:
359
+
360
+ - List view generation
361
+ - Edit form generation
362
+ - Relation handling
363
+ - Save/delete processing
364
+
365
+ ### Contents Builder
366
+
367
+ **File:** `lib/admin-manager/contents-builder.js`
368
+
369
+ Admin UI builder that:
370
+
371
+ - Sidebar navigation
372
+ - Entity list/edit views
373
+ - Form field generation
374
+ - Branding and styling
375
+
376
+ ### Admin Filters Manager
377
+
378
+ **File:** `lib/admin-manager/admin-filters-manager.js`
379
+
380
+ Entity filtering that:
381
+
382
+ - Filter UI generation
383
+ - Query building
384
+
385
+ ### Default Translations
386
+
387
+ **File:** `lib/admin-manager/default-translations.js`
388
+
389
+ Admin translations that:
390
+
391
+ - Default English labels
392
+ - Extensible translation system
393
+
394
+ ## Utility Classes
395
+
396
+ **Entities Loader**
397
+ - File: `lib/entities-loader.js`
398
+ - Entity loading from files
399
+
400
+ **Loaded Entities Processor**
401
+ - File: `lib/loaded-entities-processor.js`
402
+ - Entity configuration processing
403
+
404
+ **Admin Entities Generator**
405
+ - File: `lib/admin-entities-generator.js`
406
+ - Admin entity configuration
407
+
408
+ **Admin Templates Loader**
409
+ - File: `lib/admin-templates-loader.js`
410
+ - Admin template loading
411
+
412
+ **Templates To Path Mapper**
413
+ - File: `lib/templates-to-path-mapper.js`
414
+ - Template path mapping
415
+
416
+ **Templates List**
417
+ - File: `lib/templates-list.js`
418
+ - Template file list
419
+
420
+ **JSON Fields Parser**
421
+ - File: `lib/json-fields-parser.js`
422
+ - JSON field parsing
423
+
424
+ **Pagination Handler**
425
+ - File: `lib/pagination-handler.js`
426
+ - Pagination logic
427
+
428
+ **Template Reloader**
429
+ - File: `lib/template-reloader.js`
430
+ - Development template reloading
431
+
432
+ **CMS Pages Route Manager**
433
+ - File: `lib/cms-pages-route-manager.js`
434
+ - CMS page routing
435
+
436
+ **Admin Manager Validator**
437
+ - File: `lib/admin-manager-validator.js`
438
+ - Admin config validation
439
+
440
+ **Admin Dist Helper**
441
+ - File: `lib/admin-dist-helper.js`
442
+ - Admin asset distribution
443
+
444
+ **MIME Types**
445
+ - File: `lib/mime-types.js`
446
+ - File type definitions
447
+
448
+ **Allowed Extensions**
449
+ - File: `lib/allowed-extensions.js`
450
+ - Upload extension whitelist
@@ -0,0 +1,102 @@
1
+ # Security Guide
2
+
3
+ ## Authentication
4
+
5
+ **Role-based admin access:**
6
+ - Admin panel protected by authentication middleware
7
+ - Session-based authentication
8
+ - Configurable admin role ID
9
+ - Custom authentication callbacks supported
10
+
11
+ ## Password Encryption
12
+
13
+ **Algorithm:** PBKDF2 (Password-Based Key Derivation Function 2)
14
+ - Iterations: 100,000
15
+ - Key Length: 64 bytes
16
+ - Digest: SHA-512
17
+ - Salt Length: 32 bytes (randomly generated)
18
+ - Storage Format: `salt:hash` (192 characters total)
19
+
20
+ **Automatic Password Encryption:**
21
+ - Event-driven encryption on save
22
+ - Enabled by default via `PasswordEncryptionHandler`
23
+ - Can be disabled with `enablePasswordEncryption: false` in Manager config
24
+
25
+ See `.claude/password-management-guide.md` for comprehensive password management documentation.
26
+
27
+ ## CSRF Protection
28
+
29
+ **Session-based CSRF tokens:**
30
+ - CSRF tokens generated per session
31
+ - Validated on form submissions
32
+ - Integrated with Express session middleware
33
+
34
+ ## File Upload Validation
35
+
36
+ **MIME type checking:**
37
+ - Validates file MIME types against allowed types
38
+ - Extension whitelist validation
39
+ - Configurable allowed extensions per field
40
+
41
+ **Upload field configuration:**
42
+ - `allowedTypes`: Must be a STRING ('image', 'audio', 'text'), NOT an array
43
+ - `bucket`: Relative path from projectRoot
44
+ - `bucketPath`: URL path for display
45
+
46
+ ## Entity Access Control
47
+
48
+ **Public/private entity rules:**
49
+ - Configured via `entities_access` table
50
+ - Per-entity operation rules (read, write, update, delete)
51
+ - Public entities accessible without authentication
52
+ - Private entities require authentication
53
+
54
+ ## Honeypot Protection
55
+
56
+ **Bot detection in forms:**
57
+ - Hidden honeypot fields in dynamic forms
58
+ - Submission rejected if honeypot field is filled
59
+ - Transparent to legitimate users
60
+
61
+ ## Rate Limiting
62
+
63
+ **Via @reldens/server-utils:**
64
+ - Configurable rate limits per endpoint
65
+ - IP-based rate limiting
66
+ - Prevents brute force attacks
67
+
68
+ ## XSS Protection
69
+
70
+ **Input sanitization:**
71
+ - Via @reldens/server-utils
72
+ - HTML entity encoding
73
+ - Script tag removal
74
+ - Event handler attribute removal
75
+
76
+ ## SQL Injection Prevention
77
+
78
+ **Via Prisma ORM:**
79
+ - Parameterized queries
80
+ - No raw SQL execution
81
+ - Type-safe query building
82
+
83
+ ## Path Validation
84
+
85
+ **File path security:**
86
+ - Path traversal prevention
87
+ - Restricted file access
88
+ - Validated upload paths
89
+
90
+ ## CSP Headers
91
+
92
+ **Content Security Policy via Helmet:**
93
+ - Configurable CSP directives
94
+ - Script source restrictions
95
+ - Style source restrictions
96
+
97
+ ## HTTPS Support
98
+
99
+ **SSL/TLS configuration:**
100
+ - HTTPS server support
101
+ - Configurable SSL certificates
102
+ - Automatic HTTP to HTTPS redirect
@@ -0,0 +1,167 @@
1
+ # SEO Guide: Sitemaps and Robots.txt
2
+
3
+ ## Overview
4
+
5
+ The CMS provides built-in support for dynamic robots.txt and sitemap.xml generation using CMS pages and templates.
6
+
7
+ ## Installation
8
+
9
+ During CMS installation, check the **"Install SEO files (robots.txt and sitemap.xml)"** option to automatically create:
10
+
11
+ - `/robots.txt` route and page (available to all domains)
12
+ - `/sitemap.xml` route and page (available to all domains)
13
+
14
+ ## Robots.txt
15
+
16
+ ### How It Works
17
+
18
+ **Route:** `/robots.txt`
19
+
20
+ **Database Configuration:**
21
+ - Template field: `'robots'` (extension omitted)
22
+ - Resolved template file: `templates/robots.txt`
23
+ - Layout: `'raw'` (passthrough only, no HTML wrapping)
24
+ - Content-Type: Automatically detected as `text/plain`
25
+
26
+ **Characteristics:**
27
+ - Simple static template pointing to `/sitemap.xml`
28
+ - Each domain serves its own robots.txt with a link to its own sitemap
29
+ - No database queries - pure static content
30
+
31
+ ### Template Example
32
+
33
+ ```
34
+ User-agent: *
35
+ Allow: /
36
+ Sitemap: {{currentRequest.publicUrl}}/sitemap.xml
37
+ ```
38
+
39
+ ## Sitemap.xml
40
+
41
+ ### How It Works
42
+
43
+ **Route:** `/sitemap.xml`
44
+
45
+ **Database Configuration:**
46
+ - Template field: `'sitemap'` (extension omitted)
47
+ - Resolved template file: `templates/sitemap.xml`
48
+ - Layout: `'raw'` (passthrough only, no HTML wrapping)
49
+ - Content-Type: Automatically detected as `application/xml`
50
+
51
+ **Data Loading:**
52
+ - Uses `SitemapLoader` class to load data via `reldens.afterVariablesCreated` event
53
+ - Queries `routes` table with `cms_pages` relation using OR condition
54
+ - Includes routes where `domain IS NULL` OR `domain = mappedDomain`
55
+ - Excludes redirect routes (`redirect_url` and `redirect_type` must be null)
56
+ - Excludes pages with `meta_robots = 'noindex,nofollow'` (utility files like ads.txt)
57
+ - Lists only enabled routes with associated cms_pages
58
+ - Includes `path` and `updated_at` fields from routes table
59
+ - No arbitrary limits - fetches all matching routes
60
+ - Caches results on request object to avoid duplicate queries during multi-pass rendering
61
+ - Automatically leverages the CMS cache system (1 hour TTL)
62
+
63
+ ### Template Example
64
+
65
+ ```xml
66
+ <?xml version="1.0" encoding="UTF-8"?>
67
+ <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
68
+ {{#sitemapPages}}
69
+ <url>
70
+ <loc>{{&currentRequest.publicUrl}}{{&path}}</loc>
71
+ <lastmod>{{&updated_at}}</lastmod>
72
+ </url>
73
+ {{/sitemapPages}}
74
+ </urlset>
75
+ ```
76
+
77
+ The `sitemapPages` variable is automatically populated by `SitemapLoader` class which:
78
+
79
+ 1. Listens to `reldens.afterVariablesCreated` event
80
+ 2. Loads routes with `cms_pages` relation from database
81
+ 3. Filters by domain and excludes noindex pages
82
+ 4. Caches results on `req.sitemapPages` for subsequent renders
83
+
84
+ ## Multi-Domain Setup
85
+
86
+ For multi-domain sites, each domain automatically gets its own filtered sitemap:
87
+
88
+ ### Installation Creates Shared Route
89
+
90
+ Installation creates one shared route with `domain: NULL`
91
+ - This makes `/sitemap.xml` available to all domains
92
+ - Each domain serves the same URL but gets filtered results
93
+
94
+ ### Automatic Domain Filtering
95
+
96
+ SitemapLoader automatically handles domain filtering:
97
+ - Uses `domainMapping` to resolve dev domains to production domains (e.g., `reldens.new` → `reldens.com`)
98
+ - Queries routes where `domain IS NULL` (shared) OR `domain = mappedDomain` (domain-specific)
99
+ - Excludes routes without cms_pages or with `meta_robots = 'noindex,nofollow'`
100
+
101
+ ### No Additional Configuration Needed
102
+
103
+ Each domain accessing `/sitemap.xml` gets its own filtered results automatically.
104
+
105
+ ## Implementation Details
106
+
107
+ ### SitemapLoader Filter Logic
108
+
109
+ ```javascript
110
+ {
111
+ enabled: 1,
112
+ redirect_url: null,
113
+ redirect_type: null,
114
+ OR: [
115
+ {domain: null},
116
+ {domain: mappedDomain}
117
+ ]
118
+ }
119
+ ```
120
+
121
+ ### Database Query
122
+
123
+ - Queries `routes` table with `loadWithRelations(filters, 'cms_pages')`
124
+ - Translates to: `WHERE enabled=1 AND redirect_url IS NULL AND redirect_type IS NULL AND (domain IS NULL OR domain = mappedDomain)`
125
+ - Loads associated `cms_pages` in single query using Prisma/ObjectionJS/MikroORM relations
126
+
127
+ ### JavaScript Post-Filter
128
+
129
+ - Excludes routes without `cms_pages` relation
130
+ - Excludes routes where `cms_pages[0].meta_robots === 'noindex,nofollow'`
131
+ - This avoids polluting sitemap with utility files (robots.txt, ads.txt, sitemap.xml itself)
132
+
133
+ ## Benefits
134
+
135
+ **Dynamic:**
136
+ - Sitemaps update automatically when routes change
137
+
138
+ **Cached:**
139
+ - Route-level cache (1 hour TTL)
140
+ - Request-level cache to avoid duplicate queries
141
+
142
+ **SEO-friendly:**
143
+ - Standard XML sitemap format
144
+ - Proper lastmod dates
145
+
146
+ **Multi-domain:**
147
+ - Each domain gets its own sitemap
148
+ - Domain-specific + shared routes included
149
+
150
+ **Domain Mapping:**
151
+ - Automatically resolves dev domains to production domains for queries
152
+
153
+ **Smart Filtering:**
154
+ - Excludes utility files (robots.txt, ads.txt) via meta_robots field
155
+
156
+ **Event-driven:**
157
+ - Uses `reldens.afterVariablesCreated` event for extensibility
158
+
159
+ **No limits:**
160
+ - Fetches all matching routes (no arbitrary pagination)
161
+
162
+ **Efficient:**
163
+ - Single database query with relation loading
164
+ - JavaScript post-filter for meta_robots
165
+
166
+ **Cross-driver:**
167
+ - Works with Prisma, ObjectionJS, and MikroORM storage drivers