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 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.1",
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
- const path = require('path');
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