kempo-server 2.1.1 → 3.0.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.
- package/CONFIG.md +295 -187
- package/README.md +31 -4
- package/SPA.md +14 -14
- package/UTILS.md +39 -0
- package/dist/defaultConfig.js +1 -1
- package/dist/index.js +1 -1
- package/dist/render.js +2 -0
- package/dist/rescan.js +1 -0
- package/dist/router.js +1 -1
- package/dist/serveFile.js +1 -1
- package/dist/templating/index.js +1 -0
- package/dist/templating/parse.js +1 -0
- package/docs/dist/caching.html +324 -0
- package/docs/dist/cli-utils.html +175 -0
- package/docs/dist/configuration.html +414 -0
- package/docs/dist/examples.html +296 -0
- package/docs/dist/fs-utils.html +206 -0
- package/docs/dist/getting-started.html +167 -0
- package/docs/dist/index.html +183 -0
- package/docs/dist/middleware.html +237 -0
- package/docs/dist/request-response.html +200 -0
- package/docs/dist/routing.html +177 -0
- package/docs/dist/templating.html +292 -0
- package/docs/{theme.css → dist/theme.css} +1 -3
- package/docs/src/.config.js +11 -0
- package/docs/{caching.html → src/caching.page.html} +4 -19
- package/docs/{cli-utils.html → src/cli-utils.page.html} +4 -20
- package/docs/{configuration.html → src/configuration.page.html} +4 -18
- package/docs/src/default.template.html +35 -0
- package/docs/{examples.html → src/examples.page.html} +9 -18
- package/docs/{fs-utils.html → src/fs-utils.page.html} +4 -20
- package/docs/{getting-started.html → src/getting-started.page.html} +4 -18
- package/docs/src/index.page.html +79 -0
- package/docs/{middleware.html → src/middleware.page.html} +4 -18
- package/docs/src/nav.fragment.html +73 -0
- package/docs/{request-response.html → src/request-response.page.html} +4 -18
- package/docs/{routing.html → src/routing.page.html} +4 -18
- package/docs/src/templating.page.html +188 -0
- package/{llm.txt → llms.txt} +100 -30
- package/package.json +7 -3
- package/scripts/build.js +19 -11
- package/scripts/render.js +58 -0
- package/src/defaultConfig.js +14 -2
- package/src/index.js +1 -1
- package/src/rescan.js +14 -0
- package/src/router.js +82 -11
- package/src/serveFile.js +27 -0
- package/src/templating/index.js +132 -0
- package/src/templating/parse.js +285 -0
- package/tests/cacheConfig.node-test.js +2 -2
- package/tests/config-flag.node-test.js +61 -25
- package/tests/customRoute-outside-root.node-test.js +1 -1
- package/tests/rescan.node-test.js +69 -0
- package/tests/router-wildcard.node-test.js +47 -2
- package/tests/templating-parse.node-test.js +243 -0
- package/tests/templating-render.node-test.js +188 -0
- package/tests/utils/test-scenario.js +4 -4
- package/docs/.config.json.example +0 -29
- package/docs/api/_admin/cache/DELETE.js +0 -28
- package/docs/api/_admin/cache/GET.js +0 -53
- package/docs/api/user/[id]/GET.js +0 -15
- package/docs/api/user/[id]/[info]/DELETE.js +0 -12
- package/docs/api/user/[id]/[info]/GET.js +0 -17
- package/docs/api/user/[id]/[info]/POST.js +0 -18
- package/docs/api/user/[id]/[info]/PUT.js +0 -19
- package/docs/index.html +0 -88
- package/docs/init.js +0 -0
- package/docs/kempo.min.css +0 -1
- package/docs/nav.inc.html +0 -41
- package/docs/nav.inc.js +0 -16
- /package/docs/{manifest.json → dist/manifest.json} +0 -0
- /package/docs/{media → dist/media}/hexagon.svg +0 -0
- /package/docs/{media → dist/media}/icon-maskable.png +0 -0
- /package/docs/{media → dist/media}/icon.svg +0 -0
- /package/docs/{media → dist/media}/icon128.png +0 -0
- /package/docs/{media → dist/media}/icon144.png +0 -0
- /package/docs/{media → dist/media}/icon152.png +0 -0
- /package/docs/{media → dist/media}/icon16-48.svg +0 -0
- /package/docs/{media → dist/media}/icon16.png +0 -0
- /package/docs/{media → dist/media}/icon192.png +0 -0
- /package/docs/{media → dist/media}/icon256.png +0 -0
- /package/docs/{media → dist/media}/icon32.png +0 -0
- /package/docs/{media → dist/media}/icon384.png +0 -0
- /package/docs/{media → dist/media}/icon48.png +0 -0
- /package/docs/{media → dist/media}/icon512.png +0 -0
- /package/docs/{media → dist/media}/icon64.png +0 -0
- /package/docs/{media → dist/media}/icon72.png +0 -0
- /package/docs/{media → dist/media}/icon96.png +0 -0
- /package/docs/{media → dist/media}/kempo-fist.svg +0 -0
package/CONFIG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Configuration
|
|
2
2
|
|
|
3
|
-
To configure the server, create a configuration file (by default `.config.
|
|
3
|
+
To configure the server, create a configuration file (by default `.config.js`) within the root directory of your server (`public` in the start example). The server also supports `.config.json` as a fallback. You can specify a different configuration file using the `--config` flag.
|
|
4
4
|
|
|
5
5
|
**Important:**
|
|
6
6
|
- When using a relative path for the `--config` flag, the config file must be located within the server root directory
|
|
@@ -13,21 +13,31 @@ You can specify different configuration files for different environments using t
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
# Development
|
|
16
|
-
kempo-server --root public --config dev.config.
|
|
16
|
+
kempo-server --root public --config dev.config.js
|
|
17
17
|
|
|
18
18
|
# Staging
|
|
19
|
-
kempo-server --root public --config staging.config.
|
|
19
|
+
kempo-server --root public --config staging.config.js
|
|
20
20
|
|
|
21
21
|
# Production with absolute path
|
|
22
|
-
kempo-server --root public --config /etc/kempo/production.config.
|
|
22
|
+
kempo-server --root public --config /etc/kempo/production.config.js
|
|
23
23
|
|
|
24
24
|
# Mix with other options
|
|
25
|
-
kempo-server --root dist --port 8080 --config production.config.
|
|
25
|
+
kempo-server --root dist --port 8080 --config production.config.js
|
|
26
|
+
|
|
27
|
+
# JSON config files are also supported
|
|
28
|
+
kempo-server --root public --config legacy.config.json
|
|
26
29
|
```
|
|
27
30
|
|
|
28
31
|
## Configuration File Structure
|
|
29
32
|
|
|
30
|
-
|
|
33
|
+
The config file exports a default object with any of the following properties. Any property not defined will use the "Default Config".
|
|
34
|
+
|
|
35
|
+
```javascript
|
|
36
|
+
// .config.js
|
|
37
|
+
export default {
|
|
38
|
+
// your config here
|
|
39
|
+
};
|
|
40
|
+
```
|
|
31
41
|
|
|
32
42
|
- [allowedMimes](#allowedmimes)
|
|
33
43
|
- [disallowedRegex](#disallowedregex)
|
|
@@ -38,6 +48,7 @@ This json file can have any of the following properties, any property not define
|
|
|
38
48
|
- [maxBodySize](#maxbodysize)
|
|
39
49
|
- [cache](#cache)
|
|
40
50
|
- [middleware](#middleware)
|
|
51
|
+
- [templating](#templating)
|
|
41
52
|
|
|
42
53
|
## Cache
|
|
43
54
|
|
|
@@ -50,18 +61,18 @@ Kempo Server includes an intelligent module caching system that dramatically imp
|
|
|
50
61
|
|
|
51
62
|
### Basic Cache Configuration
|
|
52
63
|
|
|
53
|
-
Enable caching in your `.config.
|
|
64
|
+
Enable caching in your `.config.js`:
|
|
54
65
|
|
|
55
|
-
```
|
|
56
|
-
{
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
```javascript
|
|
67
|
+
export default {
|
|
68
|
+
cache: {
|
|
69
|
+
enabled: true,
|
|
70
|
+
maxSize: 100,
|
|
71
|
+
maxMemoryMB: 50,
|
|
72
|
+
ttlMs: 300000,
|
|
73
|
+
watchFiles: true
|
|
63
74
|
}
|
|
64
|
-
}
|
|
75
|
+
};
|
|
65
76
|
```
|
|
66
77
|
|
|
67
78
|
### Cache Options
|
|
@@ -75,7 +86,7 @@ Enable caching in your `.config.json`:
|
|
|
75
86
|
- `watchFiles` (boolean) - Auto-invalidate on file changes (default: `true`)
|
|
76
87
|
- `enableMemoryMonitoring` (boolean) - Enable memory monitoring (default: `true`)
|
|
77
88
|
|
|
78
|
-
Run with specific config: `kempo-server --config prod.config.
|
|
89
|
+
Run with specific config: `kempo-server --config prod.config.js`
|
|
79
90
|
|
|
80
91
|
### Cache Monitoring
|
|
81
92
|
|
|
@@ -105,92 +116,92 @@ Kempo Server includes a powerful middleware system that allows you to add functi
|
|
|
105
116
|
#### CORS
|
|
106
117
|
Enable Cross-Origin Resource Sharing for your API:
|
|
107
118
|
|
|
108
|
-
```
|
|
109
|
-
{
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
119
|
+
```javascript
|
|
120
|
+
export default {
|
|
121
|
+
middleware: {
|
|
122
|
+
cors: {
|
|
123
|
+
enabled: true,
|
|
124
|
+
origin: '*',
|
|
125
|
+
methods: ['GET', 'POST', 'PUT', 'DELETE'],
|
|
126
|
+
headers: ['Content-Type', 'Authorization']
|
|
116
127
|
}
|
|
117
128
|
}
|
|
118
|
-
}
|
|
129
|
+
};
|
|
119
130
|
```
|
|
120
131
|
|
|
121
132
|
#### Compression
|
|
122
133
|
Automatically compress responses with gzip:
|
|
123
134
|
|
|
124
|
-
```
|
|
125
|
-
{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
135
|
+
```javascript
|
|
136
|
+
export default {
|
|
137
|
+
middleware: {
|
|
138
|
+
compression: {
|
|
139
|
+
enabled: true,
|
|
140
|
+
threshold: 1024
|
|
130
141
|
}
|
|
131
142
|
}
|
|
132
|
-
}
|
|
143
|
+
};
|
|
133
144
|
```
|
|
134
145
|
|
|
135
146
|
#### Rate Limiting
|
|
136
147
|
Limit requests per client to prevent abuse:
|
|
137
148
|
|
|
138
|
-
```
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
149
|
+
```javascript
|
|
150
|
+
export default {
|
|
151
|
+
middleware: {
|
|
152
|
+
rateLimit: {
|
|
153
|
+
enabled: true,
|
|
154
|
+
maxRequests: 100,
|
|
155
|
+
windowMs: 60000,
|
|
156
|
+
message: 'Too many requests'
|
|
146
157
|
}
|
|
147
158
|
}
|
|
148
|
-
}
|
|
159
|
+
};
|
|
149
160
|
```
|
|
150
161
|
|
|
151
162
|
#### Security Headers
|
|
152
163
|
Add security headers to all responses:
|
|
153
164
|
|
|
154
|
-
```
|
|
155
|
-
{
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
165
|
+
```javascript
|
|
166
|
+
export default {
|
|
167
|
+
middleware: {
|
|
168
|
+
security: {
|
|
169
|
+
enabled: true,
|
|
170
|
+
headers: {
|
|
171
|
+
'X-Content-Type-Options': 'nosniff',
|
|
172
|
+
'X-Frame-Options': 'DENY',
|
|
173
|
+
'X-XSS-Protection': '1; mode=block'
|
|
163
174
|
}
|
|
164
175
|
}
|
|
165
176
|
}
|
|
166
|
-
}
|
|
177
|
+
};
|
|
167
178
|
```
|
|
168
179
|
|
|
169
180
|
#### Request Logging
|
|
170
181
|
Log requests with configurable detail:
|
|
171
182
|
|
|
172
|
-
```
|
|
173
|
-
{
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
183
|
+
```javascript
|
|
184
|
+
export default {
|
|
185
|
+
middleware: {
|
|
186
|
+
logging: {
|
|
187
|
+
enabled: true,
|
|
188
|
+
includeUserAgent: true,
|
|
189
|
+
includeResponseTime: true
|
|
179
190
|
}
|
|
180
191
|
}
|
|
181
|
-
}
|
|
192
|
+
};
|
|
182
193
|
```
|
|
183
194
|
|
|
184
195
|
### Custom Middleware
|
|
185
196
|
|
|
186
197
|
Create your own middleware by writing JavaScript files and referencing them in your config:
|
|
187
198
|
|
|
188
|
-
```
|
|
189
|
-
{
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
```javascript
|
|
200
|
+
export default {
|
|
201
|
+
middleware: {
|
|
202
|
+
custom: ['./middleware/auth.js', './middleware/analytics.js']
|
|
192
203
|
}
|
|
193
|
-
}
|
|
204
|
+
};
|
|
194
205
|
```
|
|
195
206
|
|
|
196
207
|
#### Custom Middleware Example
|
|
@@ -284,62 +295,62 @@ export default (config) => {
|
|
|
284
295
|
|
|
285
296
|
An object mapping file extensions to their MIME types. Files with extensions not in this list will not be served.
|
|
286
297
|
|
|
287
|
-
```
|
|
288
|
-
{
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
298
|
+
```javascript
|
|
299
|
+
export default {
|
|
300
|
+
allowedMimes: {
|
|
301
|
+
html: 'text/html',
|
|
302
|
+
css: 'text/css',
|
|
303
|
+
js: 'application/javascript',
|
|
304
|
+
json: 'application/json',
|
|
305
|
+
png: 'image/png',
|
|
306
|
+
jpg: 'image/jpeg'
|
|
296
307
|
}
|
|
297
|
-
}
|
|
308
|
+
};
|
|
298
309
|
```
|
|
299
310
|
|
|
300
311
|
### disallowedRegex
|
|
301
312
|
|
|
302
313
|
An array of regular expressions that match paths that should never be served. This provides security by preventing access to sensitive files.
|
|
303
314
|
|
|
304
|
-
```
|
|
305
|
-
{
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
315
|
+
```javascript
|
|
316
|
+
export default {
|
|
317
|
+
disallowedRegex: [
|
|
318
|
+
'^/\\..*',
|
|
319
|
+
'\\.env$',
|
|
320
|
+
'\\.config$',
|
|
321
|
+
'password'
|
|
311
322
|
]
|
|
312
|
-
}
|
|
323
|
+
};
|
|
313
324
|
```
|
|
314
325
|
|
|
315
326
|
### routeFiles
|
|
316
327
|
|
|
317
328
|
An array of filenames that should be treated as route handlers and executed as JavaScript modules.
|
|
318
329
|
|
|
319
|
-
```
|
|
320
|
-
{
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
330
|
+
```javascript
|
|
331
|
+
export default {
|
|
332
|
+
routeFiles: [
|
|
333
|
+
'GET.js',
|
|
334
|
+
'POST.js',
|
|
335
|
+
'PUT.js',
|
|
336
|
+
'DELETE.js',
|
|
337
|
+
'index.js'
|
|
327
338
|
]
|
|
328
|
-
}
|
|
339
|
+
};
|
|
329
340
|
```
|
|
330
341
|
|
|
331
342
|
### noRescanPaths
|
|
332
343
|
|
|
333
344
|
An array of regex patterns for paths that should not trigger a file system rescan. This improves performance for common static assets.
|
|
334
345
|
|
|
335
|
-
```
|
|
336
|
-
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
346
|
+
```javascript
|
|
347
|
+
export default {
|
|
348
|
+
noRescanPaths: [
|
|
349
|
+
'/favicon\\.ico$',
|
|
350
|
+
'/robots\\.txt$',
|
|
351
|
+
'\\.map$'
|
|
341
352
|
]
|
|
342
|
-
}
|
|
353
|
+
};
|
|
343
354
|
```
|
|
344
355
|
|
|
345
356
|
### customRoutes
|
|
@@ -349,27 +360,27 @@ An object mapping custom route paths to file paths. Useful for aliasing or servi
|
|
|
349
360
|
**Note:** All file paths in customRoutes are resolved relative to the server root directory (the `--root` path). This allows you to reference files both inside and outside the document root.
|
|
350
361
|
|
|
351
362
|
**Basic Routes:**
|
|
352
|
-
```
|
|
353
|
-
{
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
363
|
+
```javascript
|
|
364
|
+
export default {
|
|
365
|
+
customRoutes: {
|
|
366
|
+
'/vendor/bootstrap.css': '../node_modules/bootstrap/dist/css/bootstrap.min.css',
|
|
367
|
+
'/api/status': './status.js'
|
|
357
368
|
}
|
|
358
|
-
}
|
|
369
|
+
};
|
|
359
370
|
```
|
|
360
371
|
|
|
361
372
|
**Wildcard Routes:**
|
|
362
373
|
Wildcard routes allow you to map entire directory structures using the `*` and `**` wildcards:
|
|
363
374
|
|
|
364
|
-
```
|
|
365
|
-
{
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
375
|
+
```javascript
|
|
376
|
+
export default {
|
|
377
|
+
customRoutes: {
|
|
378
|
+
'kempo/*': '../node_modules/kempo/dist/*',
|
|
379
|
+
'assets/*': '../static-files/*',
|
|
380
|
+
'docs/*': '../documentation/*',
|
|
381
|
+
'src/**': '../src/**'
|
|
371
382
|
}
|
|
372
|
-
}
|
|
383
|
+
};
|
|
373
384
|
```
|
|
374
385
|
|
|
375
386
|
With wildcard routes:
|
|
@@ -398,123 +409,220 @@ If the resolved path is a file whose name matches `routeFiles` (e.g. `GET.js`),
|
|
|
398
409
|
|
|
399
410
|
The maximum number of times to attempt rescanning the file system when a file is not found. Defaults to 3.
|
|
400
411
|
|
|
401
|
-
```
|
|
402
|
-
{
|
|
403
|
-
|
|
404
|
-
}
|
|
412
|
+
```javascript
|
|
413
|
+
export default {
|
|
414
|
+
maxRescanAttempts: 3
|
|
415
|
+
};
|
|
405
416
|
```
|
|
406
417
|
|
|
407
418
|
### maxBodySize
|
|
408
419
|
|
|
409
420
|
Maximum allowed request body size in bytes. If a request body exceeds this limit, the server responds with `413 Payload Too Large` before the route handler runs. Defaults to `1048576` (1 MB).
|
|
410
421
|
|
|
411
|
-
```
|
|
412
|
-
{
|
|
413
|
-
|
|
414
|
-
}
|
|
422
|
+
```javascript
|
|
423
|
+
export default {
|
|
424
|
+
maxBodySize: 1048576
|
|
425
|
+
};
|
|
415
426
|
```
|
|
416
427
|
|
|
428
|
+
### templating
|
|
429
|
+
|
|
430
|
+
The templating system lets you build HTML pages from reusable templates, fragments, and content blocks using valid XML syntax. Files use the conventions `*.template.html`, `*.page.html`, and `*.fragment.html`.
|
|
431
|
+
|
|
432
|
+
```javascript
|
|
433
|
+
export default {
|
|
434
|
+
templating: {
|
|
435
|
+
preRender: false,
|
|
436
|
+
ssr: false,
|
|
437
|
+
globals: {},
|
|
438
|
+
state: {},
|
|
439
|
+
maxFragmentDepth: 10
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
- `preRender` (boolean) - Render all `.page.html` files to `.html` on server start (default: `false`)
|
|
445
|
+
- `ssr` (boolean) - Render `.page.html` files on-the-fly when the corresponding `.html` file is not found (default: `false`)
|
|
446
|
+
- `globals` (object) - Variables available in all templates. Values can be functions (called with no args at render time).
|
|
447
|
+
- `state` (object) - Additional variables, typically CMS data. Merged after globals so state overrides globals.
|
|
448
|
+
- `maxFragmentDepth` (number) - Maximum nesting depth for fragment includes (default: `10`)
|
|
449
|
+
|
|
450
|
+
#### Pre-Render Mode
|
|
451
|
+
|
|
452
|
+
With `preRender: true`, the server renders all page files when it starts or rescans. This is ideal for static sites.
|
|
453
|
+
|
|
454
|
+
```javascript
|
|
455
|
+
export default {
|
|
456
|
+
templating: {
|
|
457
|
+
preRender: true,
|
|
458
|
+
globals: {
|
|
459
|
+
siteName: 'My Site',
|
|
460
|
+
year: () => String(new Date().getFullYear())
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
#### SSR Mode
|
|
467
|
+
|
|
468
|
+
With `ssr: true`, when a request comes in for `/about` and `about.html` does not exist but `about.page.html` does, the server renders it on-the-fly.
|
|
469
|
+
|
|
470
|
+
```javascript
|
|
471
|
+
export default {
|
|
472
|
+
templating: {
|
|
473
|
+
ssr: true,
|
|
474
|
+
globals: {
|
|
475
|
+
siteName: 'My Site'
|
|
476
|
+
},
|
|
477
|
+
state: {
|
|
478
|
+
currentUser: 'Guest'
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
#### CLI Rendering
|
|
485
|
+
|
|
486
|
+
You can also render pages without starting the server using the CLI script:
|
|
487
|
+
|
|
488
|
+
```bash
|
|
489
|
+
kempo-render <inputDir> [outputDir] [stateFile]
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
The script loads `.config.js` (or `.config.json`) from the input directory for `templating.globals`, `templating.state`, and `templating.maxFragmentDepth`. An optional state file (`.js` or `.json`) merges additional state variables.
|
|
493
|
+
|
|
494
|
+
#### Templating File Conventions
|
|
495
|
+
|
|
496
|
+
- **Templates** (`*.template.html`): Layout files with `<location>` placeholders
|
|
497
|
+
- **Pages** (`*.page.html`): Content files wrapped in `<page template="...">` with `<content location="...">` blocks
|
|
498
|
+
- **Fragments** (`*.fragment.html`): Reusable HTML snippets included via `<fragment name="..." />`
|
|
499
|
+
|
|
500
|
+
#### Built-in Variables
|
|
501
|
+
|
|
502
|
+
These variables are available in all templates:
|
|
503
|
+
- `{{pathToRoot}}` - Relative path to the root directory (e.g. `../../`)
|
|
504
|
+
- `{{year}}` - Current four-digit year
|
|
505
|
+
- `{{date}}` - Current date in ISO format (YYYY-MM-DD)
|
|
506
|
+
- `{{datetime}}` - Full ISO datetime string
|
|
507
|
+
- `{{timestamp}}` - Unix timestamp
|
|
508
|
+
- `{{version}}` - Version from `package.json`
|
|
509
|
+
- `{{env}}` - Value of `NODE_ENV`
|
|
510
|
+
|
|
511
|
+
#### Conditionals and Loops
|
|
512
|
+
|
|
513
|
+
```html
|
|
514
|
+
<if condition="env === 'development'">
|
|
515
|
+
<p>Debug mode</p>
|
|
516
|
+
</if>
|
|
517
|
+
|
|
518
|
+
<foreach in="items" as="item">
|
|
519
|
+
<li>{{item.name}}</li>
|
|
520
|
+
</foreach>
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
Conditions support `===`, `!==`, `>`, `<`, `>=`, `<=`, `&&`, `||`, `!`, parentheses, string/number/boolean literals, and dot-path variable references.
|
|
524
|
+
|
|
417
525
|
## Configuration Examples
|
|
418
526
|
|
|
419
527
|
### Development Environment
|
|
420
528
|
|
|
421
529
|
**Focus: Fast iteration and debugging**
|
|
422
|
-
```
|
|
423
|
-
{
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
530
|
+
```javascript
|
|
531
|
+
export default {
|
|
532
|
+
cache: {
|
|
533
|
+
enabled: true,
|
|
534
|
+
maxSize: 50,
|
|
535
|
+
ttlMs: 300000,
|
|
536
|
+
watchFiles: true
|
|
429
537
|
},
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
538
|
+
middleware: {
|
|
539
|
+
cors: {
|
|
540
|
+
enabled: true,
|
|
541
|
+
origin: '*'
|
|
434
542
|
},
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
543
|
+
logging: {
|
|
544
|
+
enabled: true,
|
|
545
|
+
includeUserAgent: true,
|
|
546
|
+
includeResponseTime: true
|
|
439
547
|
}
|
|
440
548
|
}
|
|
441
|
-
}
|
|
549
|
+
};
|
|
442
550
|
```
|
|
443
551
|
|
|
444
552
|
### Production Environment
|
|
445
553
|
|
|
446
554
|
**Focus: Performance, security, and stability**
|
|
447
|
-
```
|
|
448
|
-
{
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
555
|
+
```javascript
|
|
556
|
+
export default {
|
|
557
|
+
cache: {
|
|
558
|
+
enabled: true,
|
|
559
|
+
maxSize: 1000,
|
|
560
|
+
maxMemoryMB: 200,
|
|
561
|
+
ttlMs: 3600000,
|
|
562
|
+
maxHeapUsagePercent: 85,
|
|
563
|
+
memoryCheckInterval: 60000,
|
|
564
|
+
watchFiles: false
|
|
457
565
|
},
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
566
|
+
middleware: {
|
|
567
|
+
cors: {
|
|
568
|
+
enabled: true,
|
|
569
|
+
origin: ['https://myapp.com', 'https://www.myapp.com'],
|
|
570
|
+
credentials: true
|
|
463
571
|
},
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
572
|
+
compression: {
|
|
573
|
+
enabled: true,
|
|
574
|
+
threshold: 1024
|
|
467
575
|
},
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
576
|
+
security: {
|
|
577
|
+
enabled: true,
|
|
578
|
+
headers: {
|
|
579
|
+
'X-Content-Type-Options': 'nosniff',
|
|
580
|
+
'X-Frame-Options': 'DENY',
|
|
581
|
+
'X-XSS-Protection': '1; mode=block',
|
|
582
|
+
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains'
|
|
475
583
|
}
|
|
476
584
|
},
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
585
|
+
logging: {
|
|
586
|
+
enabled: true,
|
|
587
|
+
includeUserAgent: false,
|
|
588
|
+
includeResponseTime: true
|
|
481
589
|
}
|
|
482
590
|
}
|
|
483
|
-
}
|
|
591
|
+
};
|
|
484
592
|
```
|
|
485
593
|
|
|
486
594
|
### Low-Memory Environment
|
|
487
595
|
|
|
488
596
|
**Focus: Minimal resource usage**
|
|
489
|
-
```
|
|
490
|
-
{
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
597
|
+
```javascript
|
|
598
|
+
export default {
|
|
599
|
+
cache: {
|
|
600
|
+
enabled: true,
|
|
601
|
+
maxSize: 20,
|
|
602
|
+
maxMemoryMB: 5,
|
|
603
|
+
ttlMs: 120000,
|
|
604
|
+
maxHeapUsagePercent: 60,
|
|
605
|
+
memoryCheckInterval: 10000
|
|
498
606
|
}
|
|
499
|
-
}
|
|
607
|
+
};
|
|
500
608
|
```
|
|
501
609
|
|
|
502
610
|
### Debugging Environment
|
|
503
611
|
|
|
504
612
|
**Focus: Cache disabled for troubleshooting**
|
|
505
|
-
```
|
|
506
|
-
{
|
|
507
|
-
|
|
508
|
-
|
|
613
|
+
```javascript
|
|
614
|
+
export default {
|
|
615
|
+
cache: {
|
|
616
|
+
enabled: false
|
|
509
617
|
},
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
618
|
+
middleware: {
|
|
619
|
+
logging: {
|
|
620
|
+
enabled: true,
|
|
621
|
+
includeUserAgent: true,
|
|
622
|
+
includeResponseTime: true
|
|
515
623
|
}
|
|
516
624
|
}
|
|
517
|
-
}
|
|
625
|
+
};
|
|
518
626
|
```
|
|
519
627
|
|
|
520
628
|
## Additional Resources
|