@djangocfg/nextjs 2.1.427 → 2.1.429
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 +33 -0
- package/dist/config/index.d.mts +12 -3
- package/dist/config/index.mjs +39 -21
- package/dist/config/index.mjs.map +1 -1
- package/dist/i18n/request.d.mts +3 -3
- package/dist/i18n/request.mjs.map +1 -1
- package/dist/index.mjs +39 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/config/constants.ts +0 -6
- package/src/config/createNextConfig.ts +71 -19
- package/src/i18n/request.ts +3 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/nextjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.429",
|
|
4
4
|
"description": "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nextjs",
|
|
@@ -143,9 +143,9 @@
|
|
|
143
143
|
"ai-docs": "tsx src/ai/cli.ts"
|
|
144
144
|
},
|
|
145
145
|
"peerDependencies": {
|
|
146
|
-
"@djangocfg/i18n": "^2.1.
|
|
147
|
-
"@djangocfg/monitor": "^2.1.
|
|
148
|
-
"@djangocfg/ui-core": "^2.1.
|
|
146
|
+
"@djangocfg/i18n": "^2.1.429",
|
|
147
|
+
"@djangocfg/monitor": "^2.1.429",
|
|
148
|
+
"@djangocfg/ui-core": "^2.1.429",
|
|
149
149
|
"next": "^16.2.2"
|
|
150
150
|
},
|
|
151
151
|
"peerDependenciesMeta": {
|
|
@@ -167,11 +167,11 @@
|
|
|
167
167
|
"serwist": "^9.2.3"
|
|
168
168
|
},
|
|
169
169
|
"devDependencies": {
|
|
170
|
-
"@djangocfg/i18n": "^2.1.
|
|
171
|
-
"@djangocfg/monitor": "^2.1.
|
|
172
|
-
"@djangocfg/ui-core": "^2.1.
|
|
173
|
-
"@djangocfg/layouts": "^2.1.
|
|
174
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
170
|
+
"@djangocfg/i18n": "^2.1.429",
|
|
171
|
+
"@djangocfg/monitor": "^2.1.429",
|
|
172
|
+
"@djangocfg/ui-core": "^2.1.429",
|
|
173
|
+
"@djangocfg/layouts": "^2.1.429",
|
|
174
|
+
"@djangocfg/typescript-config": "^2.1.429",
|
|
175
175
|
"@types/node": "^25.2.3",
|
|
176
176
|
"@types/react": "^19.2.15",
|
|
177
177
|
"@types/react-dom": "^19.2.3",
|
package/src/config/constants.ts
CHANGED
|
@@ -21,7 +21,6 @@ export const DJANGO_CFG_BANNER = `
|
|
|
21
21
|
// All @djangocfg packages that can be updated together
|
|
22
22
|
export const DJANGOCFG_PACKAGES = [
|
|
23
23
|
'@djangocfg/ui-core',
|
|
24
|
-
'@djangocfg/ui-nextjs',
|
|
25
24
|
'@djangocfg/layouts',
|
|
26
25
|
'@djangocfg/nextjs',
|
|
27
26
|
'@djangocfg/api',
|
|
@@ -35,22 +34,17 @@ export const DJANGOCFG_PACKAGES = [
|
|
|
35
34
|
export const DEFAULT_TRANSPILE_PACKAGES = [
|
|
36
35
|
'@djangocfg/i18n',
|
|
37
36
|
'@djangocfg/ui-core',
|
|
38
|
-
'@djangocfg/ui-nextjs',
|
|
39
37
|
'@djangocfg/layouts',
|
|
40
38
|
'@djangocfg/ui-tools',
|
|
41
39
|
'@djangocfg/api',
|
|
42
40
|
'@djangocfg/centrifugo',
|
|
43
41
|
'@djangocfg/debuger',
|
|
44
42
|
'@djangocfg/monitor',
|
|
45
|
-
// Extensions (for source imports without build)
|
|
46
|
-
'@djangocfg/ext-support',
|
|
47
|
-
'@djangocfg/ext-payments',
|
|
48
43
|
] as const;
|
|
49
44
|
|
|
50
45
|
// Default packages to optimize imports
|
|
51
46
|
export const DEFAULT_OPTIMIZE_PACKAGES = [
|
|
52
47
|
'@djangocfg/ui-core',
|
|
53
|
-
'@djangocfg/ui-nextjs',
|
|
54
48
|
'@djangocfg/layouts',
|
|
55
49
|
'lucide-react',
|
|
56
50
|
'recharts',
|
|
@@ -58,6 +58,15 @@ export interface BaseNextConfigOptions {
|
|
|
58
58
|
* Set to ['*'] to allow all origins, or specify domains like ['https://djangocfg.com']
|
|
59
59
|
*/
|
|
60
60
|
allowIframeFrom?: string[];
|
|
61
|
+
/**
|
|
62
|
+
* Enable DPoP (RFC 9449) sender-constrained tokens on the generated API
|
|
63
|
+
* client. When true, the client holds a non-extractable key and signs a
|
|
64
|
+
* per-request `DPoP` proof so a stolen token is useless. Must be paired with
|
|
65
|
+
* `jwt = JWTConfig(dpop_enabled=True)` on the Django backend. Default: false.
|
|
66
|
+
*
|
|
67
|
+
* Inlines `NEXT_PUBLIC_DPOP_ENABLED='true'` so the generated auth.ts activates.
|
|
68
|
+
*/
|
|
69
|
+
dpop?: boolean;
|
|
61
70
|
/**
|
|
62
71
|
* PWA configuration options
|
|
63
72
|
* Set to false to disable PWA, or provide custom options
|
|
@@ -121,6 +130,11 @@ export function createBaseNextConfig(
|
|
|
121
130
|
reactStrictMode: true,
|
|
122
131
|
trailingSlash: true,
|
|
123
132
|
|
|
133
|
+
// Dev indicator position — set explicitly so it's managed from one place
|
|
134
|
+
// across every @djangocfg app. Apps can override via `devIndicators` in
|
|
135
|
+
// their options (deep-merged over this). Kept bottom-left for now.
|
|
136
|
+
devIndicators: { position: 'bottom-left' },
|
|
137
|
+
|
|
124
138
|
// Static export configuration
|
|
125
139
|
...(isStaticBuild && {
|
|
126
140
|
output: 'export' as const,
|
|
@@ -142,6 +156,9 @@ export function createBaseNextConfig(
|
|
|
142
156
|
NEXT_PUBLIC_BASE_PATH: basePath,
|
|
143
157
|
NEXT_PUBLIC_API_URL: apiUrl,
|
|
144
158
|
NEXT_PUBLIC_SITE_URL: siteUrl,
|
|
159
|
+
// DPoP toggle for the generated auth client (RFC 9449). Only inlined when
|
|
160
|
+
// explicitly enabled, so non-DPoP apps stay on the plain Bearer path.
|
|
161
|
+
...(options.dpop ? { NEXT_PUBLIC_DPOP_ENABLED: 'true' } : {}),
|
|
145
162
|
// Disable Next.js telemetry (Next.js 15+ uses env var instead of config option)
|
|
146
163
|
NEXT_TELEMETRY_DISABLED: '1',
|
|
147
164
|
...options.env,
|
|
@@ -165,26 +182,60 @@ export function createBaseNextConfig(
|
|
|
165
182
|
},
|
|
166
183
|
];
|
|
167
184
|
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
185
|
+
// ── Baseline security headers on every route ──────────────────────────
|
|
186
|
+
// First line of defence against XSS/clickjacking/sniffing. The CSP here is
|
|
187
|
+
// a PRAGMATIC baseline: it kills the high-value injection vectors
|
|
188
|
+
// (plugins/objects, <base> hijacking, form-action exfiltration, iframe
|
|
189
|
+
// embedding) while still allowing the inline/eval scripts a Next.js app
|
|
190
|
+
// needs in dev. A fully strict nonce-based `script-src` is a follow-up
|
|
191
|
+
// (needs middleware + per-request nonce wiring) — tracked in the
|
|
192
|
+
// auth-hardening plan. `allowIframeFrom` (below) overrides frame-ancestors.
|
|
193
|
+
const hasIframeAllowlist =
|
|
194
|
+
!!options.allowIframeFrom && options.allowIframeFrom.length > 0;
|
|
195
|
+
const frameAncestors = hasIframeAllowlist
|
|
196
|
+
? (options.allowIframeFrom!.includes('*')
|
|
197
|
+
? '*'
|
|
198
|
+
: `'self' ${options.allowIframeFrom!.join(' ')}`)
|
|
199
|
+
: "'none'";
|
|
200
|
+
|
|
201
|
+
// In dev the backend (Django, Centrifugo) is plain http/ws on localhost,
|
|
202
|
+
// so connect/img must allow http:/ws:. Production stays strict (https/wss
|
|
203
|
+
// only) to forbid downgrade/cleartext exfiltration.
|
|
204
|
+
const connectSrc = isDev
|
|
205
|
+
? "connect-src 'self' http: https: ws: wss:"
|
|
206
|
+
: "connect-src 'self' https: wss:";
|
|
207
|
+
const imgSrc = isDev
|
|
208
|
+
? "img-src 'self' data: blob: http: https:"
|
|
209
|
+
: "img-src 'self' data: blob: https:";
|
|
210
|
+
|
|
211
|
+
const cspDirectives = [
|
|
212
|
+
"default-src 'self'",
|
|
213
|
+
// Next.js requires inline + eval for its runtime/HMR. Tighten to nonces later.
|
|
214
|
+
"script-src 'self' 'unsafe-inline' 'unsafe-eval'",
|
|
215
|
+
"style-src 'self' 'unsafe-inline'",
|
|
216
|
+
imgSrc,
|
|
217
|
+
"font-src 'self' data:",
|
|
218
|
+
// API/websocket calls go cross-origin to Django/Centrifugo.
|
|
219
|
+
connectSrc,
|
|
220
|
+
"object-src 'none'",
|
|
221
|
+
"base-uri 'self'",
|
|
222
|
+
"form-action 'self'",
|
|
223
|
+
`frame-ancestors ${frameAncestors}`,
|
|
224
|
+
];
|
|
173
225
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
),
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
226
|
+
headers.push({
|
|
227
|
+
source: '/:path*',
|
|
228
|
+
headers: [
|
|
229
|
+
{ key: 'X-Content-Type-Options', value: 'nosniff' },
|
|
230
|
+
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
|
|
231
|
+
{ key: 'Content-Security-Policy', value: cspDirectives.join('; ') },
|
|
232
|
+
// X-Frame-Options for older browsers. Omitted when a wildcard iframe
|
|
233
|
+
// allowlist is set (browsers then rely on CSP frame-ancestors).
|
|
234
|
+
...(hasIframeAllowlist && options.allowIframeFrom!.includes('*')
|
|
235
|
+
? []
|
|
236
|
+
: [{ key: 'X-Frame-Options', value: hasIframeAllowlist ? 'SAMEORIGIN' : 'DENY' }]),
|
|
237
|
+
],
|
|
238
|
+
});
|
|
188
239
|
|
|
189
240
|
// Merge with user-provided headers
|
|
190
241
|
const userHeaders = options.headers ? await options.headers() : [];
|
|
@@ -308,6 +359,7 @@ export function createBaseNextConfig(
|
|
|
308
359
|
checkPackages,
|
|
309
360
|
autoInstall,
|
|
310
361
|
allowIframeFrom,
|
|
362
|
+
dpop,
|
|
311
363
|
...nextConfigOptions
|
|
312
364
|
} = options;
|
|
313
365
|
|
package/src/i18n/request.ts
CHANGED
|
@@ -8,11 +8,9 @@
|
|
|
8
8
|
* // i18n/request.ts in your app
|
|
9
9
|
* import { createRequestConfig } from '@djangocfg/nextjs/i18n';
|
|
10
10
|
* import { en, ru, ko } from '@djangocfg/i18n';
|
|
11
|
-
* import { leadsI18n } from '@djangocfg/ext-leads';
|
|
12
11
|
*
|
|
13
12
|
* export default createRequestConfig({
|
|
14
13
|
* locales: { en, ru, ko },
|
|
15
|
-
* extensions: [leadsI18n],
|
|
16
14
|
* });
|
|
17
15
|
* ```
|
|
18
16
|
*/
|
|
@@ -101,11 +99,11 @@ function loadMessages(
|
|
|
101
99
|
* ```ts
|
|
102
100
|
* // i18n/request.ts
|
|
103
101
|
* import { createRequestConfig } from '@djangocfg/nextjs/i18n';
|
|
104
|
-
* import { leadsI18n } from '@djangocfg/ext-leads';
|
|
105
|
-
* import { paymentsI18n } from '@djangocfg/ext-payments';
|
|
106
102
|
*
|
|
103
|
+
* // `extensions` merges extra namespaced translation bundles, each shaped
|
|
104
|
+
* // as `{ namespace: string, locales: Record<LocaleCode, Messages> }`.
|
|
107
105
|
* export default createRequestConfig({
|
|
108
|
-
* extensions: [
|
|
106
|
+
* extensions: [myFeatureI18n],
|
|
109
107
|
* });
|
|
110
108
|
* ```
|
|
111
109
|
*/
|