@djangocfg/nextjs 2.1.482 → 2.1.484
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 +1 -2
- package/dist/config/index.d.mts +18 -0
- package/dist/config/index.mjs +35 -24
- package/dist/config/index.mjs.map +1 -1
- package/dist/health/index.d.mts +1 -1
- package/dist/health/index.mjs.map +1 -1
- package/dist/index.mjs +35 -24
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -9
- package/src/config/createNextConfig.ts +9 -1
- package/src/config/utils/env.ts +59 -0
- package/src/health/route.ts +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/nextjs",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.484",
|
|
4
4
|
"description": "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nextjs",
|
|
@@ -144,9 +144,9 @@
|
|
|
144
144
|
"ai-docs": "tsx src/ai/cli.ts"
|
|
145
145
|
},
|
|
146
146
|
"peerDependencies": {
|
|
147
|
-
"@djangocfg/devtools": "^2.1.
|
|
148
|
-
"@djangocfg/i18n": "^2.1.
|
|
149
|
-
"@djangocfg/ui-core": "^2.1.
|
|
147
|
+
"@djangocfg/devtools": "^2.1.484",
|
|
148
|
+
"@djangocfg/i18n": "^2.1.484",
|
|
149
|
+
"@djangocfg/ui-core": "^2.1.484",
|
|
150
150
|
"next": "^16.2.2"
|
|
151
151
|
},
|
|
152
152
|
"peerDependenciesMeta": {
|
|
@@ -168,11 +168,11 @@
|
|
|
168
168
|
"serwist": "^9.5.11"
|
|
169
169
|
},
|
|
170
170
|
"devDependencies": {
|
|
171
|
-
"@djangocfg/devtools": "^2.1.
|
|
172
|
-
"@djangocfg/i18n": "^2.1.
|
|
173
|
-
"@djangocfg/layouts": "^2.1.
|
|
174
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
175
|
-
"@djangocfg/ui-core": "^2.1.
|
|
171
|
+
"@djangocfg/devtools": "^2.1.484",
|
|
172
|
+
"@djangocfg/i18n": "^2.1.484",
|
|
173
|
+
"@djangocfg/layouts": "^2.1.484",
|
|
174
|
+
"@djangocfg/typescript-config": "^2.1.484",
|
|
175
|
+
"@djangocfg/ui-core": "^2.1.484",
|
|
176
176
|
"@types/node": "^25.9.5",
|
|
177
177
|
"@types/react": "19.2.15",
|
|
178
178
|
"@types/react-dom": "19.2.3",
|
|
@@ -31,7 +31,14 @@ import { CSP_BASELINE_VENDORS, type CspVendor, resolveCspVendors } from './csp';
|
|
|
31
31
|
import { addCompressionPlugins } from './plugins/compression';
|
|
32
32
|
import { DevStartupPlugin } from './plugins/devStartup';
|
|
33
33
|
import { deepMerge } from './utils/deepMerge';
|
|
34
|
-
import {
|
|
34
|
+
import {
|
|
35
|
+
getApiUrl,
|
|
36
|
+
getBasePath,
|
|
37
|
+
getSiteUrl,
|
|
38
|
+
isDev,
|
|
39
|
+
isStaticBuild,
|
|
40
|
+
warnIfApiUrlMissing,
|
|
41
|
+
} from './utils/env';
|
|
35
42
|
|
|
36
43
|
// ─────────────────────────────────────────────────────────────────────────
|
|
37
44
|
// Configuration Options
|
|
@@ -204,6 +211,7 @@ export function createBaseNextConfig(
|
|
|
204
211
|
): NextConfig {
|
|
205
212
|
|
|
206
213
|
const basePath = getBasePath(options.isDefaultCfgAdmin);
|
|
214
|
+
warnIfApiUrlMissing();
|
|
207
215
|
const apiUrl = getApiUrl();
|
|
208
216
|
const siteUrl = getSiteUrl();
|
|
209
217
|
|
package/src/config/utils/env.ts
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Environment Variable Utilities
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
+
import consola from 'consola';
|
|
6
|
+
|
|
5
7
|
export const isStaticBuild = process.env.NEXT_PUBLIC_STATIC_BUILD === 'true';
|
|
6
8
|
export const isDev = process.env.NODE_ENV === 'development';
|
|
7
9
|
export const isProduction = !isDev;
|
|
@@ -12,10 +14,67 @@ export function getBasePath(isDefaultCfgAdmin?: boolean): string {
|
|
|
12
14
|
return isDefaultCfgAdmin ? '/cfg/admin' : '/cfg/nextjs-admin';
|
|
13
15
|
}
|
|
14
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Resolve the API origin that gets inlined into the client bundle.
|
|
19
|
+
*
|
|
20
|
+
* `NEXT_PUBLIC_*` is substituted at BUILD time, so a value supplied only at
|
|
21
|
+
* container runtime (a compose `environment:` entry, a `docker run -e`) arrives
|
|
22
|
+
* far too late — the bundle already shipped with whatever was present during
|
|
23
|
+
* `next build`.
|
|
24
|
+
*
|
|
25
|
+
* An empty result means "no API origin is configured". Callers MUST treat that
|
|
26
|
+
* as *do not send the request* rather than falling back to a relative path: the
|
|
27
|
+
* browser resolves a relative URL against the CURRENT page, so on an
|
|
28
|
+
* i18n-prefixed route `/cfg/accounts/profile` silently becomes
|
|
29
|
+
* `https://site.com/<locale>/cfg/accounts/profile` — a 404 that reproduces only
|
|
30
|
+
* in production. Use {@link hasApiUrl} to gate those call sites.
|
|
31
|
+
*
|
|
32
|
+
* The one case where empty legitimately means "relative": a static build served
|
|
33
|
+
* from the same origin as Django.
|
|
34
|
+
*/
|
|
15
35
|
export function getApiUrl(): string {
|
|
16
36
|
return isStaticBuild ? '' : (process.env.NEXT_PUBLIC_API_URL || '');
|
|
17
37
|
}
|
|
18
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Whether a usable API origin is configured for this build.
|
|
41
|
+
*
|
|
42
|
+
* Gate every network call that targets Django on this. An app with no backend
|
|
43
|
+
* (a pure marketing site) then needs no configuration at all — its optional
|
|
44
|
+
* transports simply stay dormant instead of firing requests at the page's own
|
|
45
|
+
* origin.
|
|
46
|
+
*
|
|
47
|
+
* A static build is same-origin by design, so relative paths ARE the intent
|
|
48
|
+
* there and this reports true despite the empty string.
|
|
49
|
+
*/
|
|
50
|
+
export function hasApiUrl(): boolean {
|
|
51
|
+
return isStaticBuild || Boolean(process.env.NEXT_PUBLIC_API_URL);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Warn once, at build time, when no API origin is configured.
|
|
56
|
+
*
|
|
57
|
+
* Not an error: an app with no backend is a legitimate configuration. But the
|
|
58
|
+
* same empty value also appears when a build *should* have had an API URL and
|
|
59
|
+
* lost it — a `.dockerignore` rule stripping `.env.production`, or a value
|
|
60
|
+
* supplied only through a runtime `environment:` entry. Both produce a bundle
|
|
61
|
+
* whose API-backed features are silently inert, so say so while the build log
|
|
62
|
+
* is still being read.
|
|
63
|
+
*/
|
|
64
|
+
export function warnIfApiUrlMissing(): void {
|
|
65
|
+
if (hasApiUrl() || isDev) return;
|
|
66
|
+
|
|
67
|
+
consola.warn(
|
|
68
|
+
'NEXT_PUBLIC_API_URL is not set — API-backed features are disabled in this build.\n' +
|
|
69
|
+
'Requests that need it are skipped rather than sent to a relative path.\n' +
|
|
70
|
+
'If this app DOES have a backend, the value must be present at BUILD time:\n' +
|
|
71
|
+
' • commit it to the app\'s `.env.production`, and check no `.dockerignore`\n' +
|
|
72
|
+
' rule (e.g. `**/.env*`) strips that file from the build context;\n' +
|
|
73
|
+
' • or pass it as a Dockerfile ARG/ENV before the build step.\n' +
|
|
74
|
+
'A compose `environment:` entry is too late — it only exists at runtime.',
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
19
78
|
export function getSiteUrl(): string {
|
|
20
79
|
return isStaticBuild ? '' : (process.env.NEXT_PUBLIC_SITE_URL || '');
|
|
21
80
|
}
|
package/src/health/route.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Usage:
|
|
5
5
|
* ```tsx
|
|
6
|
-
* // app/
|
|
6
|
+
* // app/healthz/route.ts
|
|
7
7
|
* import { createHealthHandler } from '@djangocfg/nextjs/health';
|
|
8
8
|
*
|
|
9
9
|
* export const GET = createHealthHandler({
|
|
@@ -63,4 +63,3 @@ export function createHealthHandler(config: HealthConfig = {}) {
|
|
|
63
63
|
return NextResponse.json(response, { status: statusCode });
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
|
-
|