webspresso 0.0.1 → 0.0.2
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 +9 -0
- package/package.json +2 -1
- package/src/server.js +57 -2
package/README.md
CHANGED
|
@@ -180,6 +180,15 @@ Creates and configures the Express app.
|
|
|
180
180
|
- `viewsDir` (optional): Path to views/layouts directory
|
|
181
181
|
- `publicDir` (optional): Path to public/static directory
|
|
182
182
|
- `logging` (optional): Enable request logging (default: true in development)
|
|
183
|
+
- `helmet` (optional): Helmet security configuration
|
|
184
|
+
- `true` or `undefined`: Use default secure configuration
|
|
185
|
+
- `false`: Disable Helmet
|
|
186
|
+
- `Object`: Custom Helmet configuration (merged with defaults)
|
|
187
|
+
|
|
188
|
+
**Default Helmet Configuration:**
|
|
189
|
+
- CSP disabled in development, enabled in production
|
|
190
|
+
- HSTS, XSS protection, frame guard, and other security headers enabled
|
|
191
|
+
- Tailwind CSS inline styles allowed in CSP
|
|
183
192
|
|
|
184
193
|
**Returns:** `{ app, nunjucksEnv }`
|
|
185
194
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webspresso",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Minimal, production-ready SSR framework for Node.js with file-based routing, Nunjucks templating, built-in i18n, and CLI tooling",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"commander": "^11.1.0",
|
|
36
36
|
"express": "^4.18.2",
|
|
37
|
+
"helmet": "^7.2.0",
|
|
37
38
|
"inquirer": "^8.2.6",
|
|
38
39
|
"nunjucks": "^3.2.4"
|
|
39
40
|
},
|
package/src/server.js
CHANGED
|
@@ -4,10 +4,53 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const express = require('express');
|
|
7
|
+
const helmet = require('helmet');
|
|
7
8
|
const nunjucks = require('nunjucks');
|
|
8
|
-
|
|
9
|
+
|
|
9
10
|
const { mountPages } = require('./file-router');
|
|
10
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Get default Helmet configuration
|
|
14
|
+
* @param {boolean} isDev - Whether in development mode
|
|
15
|
+
* @returns {Object} Helmet configuration
|
|
16
|
+
*/
|
|
17
|
+
function getDefaultHelmetConfig(isDev) {
|
|
18
|
+
return {
|
|
19
|
+
// Disable CSP in development for easier development (Nunjucks hot reload, etc.)
|
|
20
|
+
contentSecurityPolicy: isDev ? false : {
|
|
21
|
+
directives: {
|
|
22
|
+
defaultSrc: ["'self'"],
|
|
23
|
+
styleSrc: ["'self'", "'unsafe-inline'"], // Allow inline styles for Tailwind
|
|
24
|
+
scriptSrc: ["'self'"],
|
|
25
|
+
imgSrc: ["'self'", "data:", "https:"],
|
|
26
|
+
fontSrc: ["'self'", "data:"],
|
|
27
|
+
connectSrc: ["'self'"],
|
|
28
|
+
frameSrc: ["'none'"],
|
|
29
|
+
objectSrc: ["'none'"],
|
|
30
|
+
upgradeInsecureRequests: []
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
// Other security headers
|
|
34
|
+
crossOriginEmbedderPolicy: false, // Disable for better compatibility
|
|
35
|
+
crossOriginOpenerPolicy: { policy: 'same-origin' },
|
|
36
|
+
crossOriginResourcePolicy: { policy: 'cross-origin' },
|
|
37
|
+
dnsPrefetchControl: true,
|
|
38
|
+
frameguard: { action: 'deny' },
|
|
39
|
+
hidePoweredBy: true,
|
|
40
|
+
hsts: {
|
|
41
|
+
maxAge: 31536000,
|
|
42
|
+
includeSubDomains: true,
|
|
43
|
+
preload: true
|
|
44
|
+
},
|
|
45
|
+
ieNoOpen: true,
|
|
46
|
+
noSniff: true,
|
|
47
|
+
originAgentCluster: true,
|
|
48
|
+
permittedCrossDomainPolicies: false,
|
|
49
|
+
referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
|
|
50
|
+
xssFilter: true
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
11
54
|
/**
|
|
12
55
|
* Create and configure the Express app
|
|
13
56
|
* @param {Object} options - Configuration options
|
|
@@ -15,6 +58,7 @@ const { mountPages } = require('./file-router');
|
|
|
15
58
|
* @param {string} options.viewsDir - Path to views directory
|
|
16
59
|
* @param {string} options.publicDir - Path to public/static directory
|
|
17
60
|
* @param {boolean} options.logging - Enable request logging (default: isDev)
|
|
61
|
+
* @param {Object|boolean} options.helmet - Helmet configuration (default: auto-configured, false to disable)
|
|
18
62
|
* @returns {Object} { app, nunjucksEnv }
|
|
19
63
|
*/
|
|
20
64
|
function createApp(options = {}) {
|
|
@@ -26,7 +70,8 @@ function createApp(options = {}) {
|
|
|
26
70
|
pagesDir,
|
|
27
71
|
viewsDir,
|
|
28
72
|
publicDir,
|
|
29
|
-
logging = isDev && !isTest
|
|
73
|
+
logging = isDev && !isTest,
|
|
74
|
+
helmet: helmetConfig
|
|
30
75
|
} = options;
|
|
31
76
|
|
|
32
77
|
if (!pagesDir) {
|
|
@@ -35,6 +80,16 @@ function createApp(options = {}) {
|
|
|
35
80
|
|
|
36
81
|
const app = express();
|
|
37
82
|
|
|
83
|
+
// Security headers with Helmet
|
|
84
|
+
if (helmetConfig !== false) {
|
|
85
|
+
const defaultConfig = getDefaultHelmetConfig(isDev);
|
|
86
|
+
const finalConfig = helmetConfig === undefined || helmetConfig === true
|
|
87
|
+
? defaultConfig
|
|
88
|
+
: { ...defaultConfig, ...helmetConfig };
|
|
89
|
+
|
|
90
|
+
app.use(helmet(finalConfig));
|
|
91
|
+
}
|
|
92
|
+
|
|
38
93
|
// Trust proxy (for correct req.ip, req.protocol behind reverse proxy)
|
|
39
94
|
app.set('trust proxy', 1);
|
|
40
95
|
|