@djangocfg/nextjs 2.1.483 → 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 CHANGED
@@ -370,7 +370,7 @@ registration, cache layers, and deployment notes.
370
370
  Create a health monitoring endpoint:
371
371
 
372
372
  ```tsx
373
- // app/api/health/route.ts
373
+ // app/healthz/route.ts
374
374
  import { createHealthHandler } from '@djangocfg/nextjs/health';
375
375
 
376
376
  export const GET = createHealthHandler({
@@ -717,4 +717,3 @@ Issues and pull requests are welcome at [GitHub](https://github.com/markolofsen/
717
717
  ## License
718
718
 
719
719
  MIT - see [LICENSE](./LICENSE) for details
720
-
@@ -361,6 +361,24 @@ declare const isDev: boolean;
361
361
  declare const isProduction: boolean;
362
362
  declare const isCI: boolean;
363
363
  declare function getBasePath(isDefaultCfgAdmin?: boolean): string;
364
+ /**
365
+ * Resolve the API origin that gets inlined into the client bundle.
366
+ *
367
+ * `NEXT_PUBLIC_*` is substituted at BUILD time, so a value supplied only at
368
+ * container runtime (a compose `environment:` entry, a `docker run -e`) arrives
369
+ * far too late — the bundle already shipped with whatever was present during
370
+ * `next build`.
371
+ *
372
+ * An empty result means "no API origin is configured". Callers MUST treat that
373
+ * as *do not send the request* rather than falling back to a relative path: the
374
+ * browser resolves a relative URL against the CURRENT page, so on an
375
+ * i18n-prefixed route `/cfg/accounts/profile` silently becomes
376
+ * `https://site.com/<locale>/cfg/accounts/profile` — a 404 that reproduces only
377
+ * in production. Use {@link hasApiUrl} to gate those call sites.
378
+ *
379
+ * The one case where empty legitimately means "relative": a static build served
380
+ * from the same origin as Django.
381
+ */
364
382
  declare function getApiUrl(): string;
365
383
  declare function getSiteUrl(): string;
366
384
 
@@ -14,7 +14,7 @@ var require_package = __commonJS({
14
14
  "package.json"(exports, module) {
15
15
  module.exports = {
16
16
  name: "@djangocfg/nextjs",
17
- version: "2.1.483",
17
+ version: "2.1.484",
18
18
  description: "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
19
19
  keywords: [
20
20
  "nextjs",
@@ -399,6 +399,7 @@ import { createRequire } from "module";
399
399
  import { join } from "path";
400
400
 
401
401
  // src/config/utils/env.ts
402
+ import consola2 from "consola";
402
403
  var isStaticBuild = process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
403
404
  var isDev = process.env.NODE_ENV === "development";
404
405
  var isProduction = !isDev;
@@ -410,6 +411,15 @@ function getBasePath(isDefaultCfgAdmin) {
410
411
  function getApiUrl() {
411
412
  return isStaticBuild ? "" : process.env.NEXT_PUBLIC_API_URL || "";
412
413
  }
414
+ function hasApiUrl() {
415
+ return isStaticBuild || Boolean(process.env.NEXT_PUBLIC_API_URL);
416
+ }
417
+ function warnIfApiUrlMissing() {
418
+ if (hasApiUrl() || isDev) return;
419
+ consola2.warn(
420
+ "NEXT_PUBLIC_API_URL is not set \u2014 API-backed features are disabled in this build.\nRequests that need it are skipped rather than sent to a relative path.\nIf this app DOES have a backend, the value must be present at BUILD time:\n \u2022 commit it to the app's `.env.production`, and check no `.dockerignore`\n rule (e.g. `**/.env*`) strips that file from the build context;\n \u2022 or pass it as a Dockerfile ARG/ENV before the build step.\nA compose `environment:` entry is too late \u2014 it only exists at runtime."
421
+ );
422
+ }
413
423
  function getSiteUrl() {
414
424
  return isStaticBuild ? "" : process.env.NEXT_PUBLIC_SITE_URL || "";
415
425
  }
@@ -585,7 +595,7 @@ Example queries:
585
595
  import chalk from "chalk";
586
596
  import { execSync, spawn } from "child_process";
587
597
  import Conf from "conf";
588
- import consola2 from "consola";
598
+ import consola3 from "consola";
589
599
  import { createInterface } from "readline";
590
600
  function createMemoryCache() {
591
601
  const store = /* @__PURE__ */ new Map();
@@ -804,13 +814,13 @@ async function installPackagesWithProgress(packages) {
804
814
  }
805
815
  console.log("");
806
816
  if (failedPackages.length === 0) {
807
- consola2.success(`All ${total} packages installed successfully!`);
817
+ consola3.success(`All ${total} packages installed successfully!`);
808
818
  return true;
809
819
  } else if (successCount > 0) {
810
- consola2.warn(`${successCount}/${total} packages installed. Failed: ${failedPackages.join(", ")}`);
820
+ consola3.warn(`${successCount}/${total} packages installed. Failed: ${failedPackages.join(", ")}`);
811
821
  return false;
812
822
  } else {
813
- consola2.error(`Failed to install packages: ${failedPackages.join(", ")}`);
823
+ consola3.error(`Failed to install packages: ${failedPackages.join(", ")}`);
814
824
  return false;
815
825
  }
816
826
  }
@@ -821,7 +831,7 @@ async function installPackages(packages) {
821
831
  if (packages.length === 0) return true;
822
832
  const pm = detectPackageManager();
823
833
  const command = buildInstallCommand(packages, pm);
824
- consola2.info(`Installing: ${chalk.cyan(packages.map((p) => p.name).join(", "))}`);
834
+ consola3.info(`Installing: ${chalk.cyan(packages.map((p) => p.name).join(", "))}`);
825
835
  const spinner = createSpinner("Installing packages...");
826
836
  spinner.start();
827
837
  return new Promise((resolve) => {
@@ -861,7 +871,7 @@ async function checkAndInstallPackages(options = {}) {
861
871
  return installPackages(toInstall);
862
872
  }
863
873
  console.log("");
864
- consola2.box("\u{1F4E6} Missing Optional Packages");
874
+ consola3.box("\u{1F4E6} Missing Optional Packages");
865
875
  console.log("");
866
876
  for (const pkg of toInstall) {
867
877
  console.log(` ${chalk.yellow("\u2022")} ${chalk.bold(pkg.name)}`);
@@ -885,7 +895,7 @@ async function checkAndInstallPackages(options = {}) {
885
895
  );
886
896
  if (enableAuto) {
887
897
  installerCache.set("autoInstall", true);
888
- consola2.info("Auto-install enabled. Run with --no-auto-install to disable.");
898
+ consola3.info("Auto-install enabled. Run with --no-auto-install to disable.");
889
899
  }
890
900
  }
891
901
  return success;
@@ -896,7 +906,7 @@ async function checkAndInstallPackages(options = {}) {
896
906
  if (skipPermanently) {
897
907
  const currentSkip = installerCache.get("skipPackages") || [];
898
908
  installerCache.set("skipPackages", [...currentSkip, ...toInstall.map((p) => p.name)]);
899
- consola2.info("Packages added to skip list.");
909
+ consola3.info("Packages added to skip list.");
900
910
  }
901
911
  return false;
902
912
  }
@@ -904,19 +914,19 @@ function printMissingPackagesInfo(packages) {
904
914
  if (packages.length === 0) return;
905
915
  const pm = detectPackageManager();
906
916
  const command = buildInstallCommand(packages, pm);
907
- consola2.warn(`Missing optional packages: ${packages.map((p) => p.name).join(", ")}`);
908
- consola2.info(`Install with: ${chalk.cyan(command)}`);
917
+ consola3.warn(`Missing optional packages: ${packages.map((p) => p.name).join(", ")}`);
918
+ consola3.info(`Install with: ${chalk.cyan(command)}`);
909
919
  }
910
920
  function resetInstallerPreferences() {
911
921
  installerCache.clear();
912
- consola2.success("Installer preferences reset");
922
+ consola3.success("Installer preferences reset");
913
923
  }
914
924
 
915
925
  // src/config/packages/updater.ts
916
926
  import chalk2 from "chalk";
917
927
  import { spawn as spawn2 } from "child_process";
918
928
  import Conf2 from "conf";
919
- import consola3 from "consola";
929
+ import consola4 from "consola";
920
930
  import { createRequire as createRequire2 } from "module";
921
931
  import { join as join2 } from "path";
922
932
  import { createInterface as createInterface2 } from "readline";
@@ -1176,13 +1186,13 @@ async function updatePackagesWithProgress(packages) {
1176
1186
  }
1177
1187
  console.log("");
1178
1188
  if (failedPackages.length === 0) {
1179
- consola3.success(`All ${total} packages updated successfully!`);
1189
+ consola4.success(`All ${total} packages updated successfully!`);
1180
1190
  return true;
1181
1191
  } else if (successCount > 0) {
1182
- consola3.warn(`${successCount}/${total} packages updated. Failed: ${failedPackages.join(", ")}`);
1192
+ consola4.warn(`${successCount}/${total} packages updated. Failed: ${failedPackages.join(", ")}`);
1183
1193
  return false;
1184
1194
  } else {
1185
- consola3.error(`Failed to update packages: ${failedPackages.join(", ")}`);
1195
+ consola4.error(`Failed to update packages: ${failedPackages.join(", ")}`);
1186
1196
  return false;
1187
1197
  }
1188
1198
  }
@@ -1207,7 +1217,7 @@ async function checkAndUpdatePackages(options = {}) {
1207
1217
  return updatePackagesWithProgress(outdated);
1208
1218
  }
1209
1219
  console.log("");
1210
- consola3.box("\u{1F4E6} Updates Available");
1220
+ consola4.box("\u{1F4E6} Updates Available");
1211
1221
  console.log("");
1212
1222
  for (const pkg of outdated) {
1213
1223
  console.log(
@@ -1226,7 +1236,7 @@ async function checkAndUpdatePackages(options = {}) {
1226
1236
  );
1227
1237
  if (enableAuto) {
1228
1238
  updaterCache.set("autoUpdate", true);
1229
- consola3.info("Auto-update enabled.");
1239
+ consola4.info("Auto-update enabled.");
1230
1240
  }
1231
1241
  }
1232
1242
  return success;
@@ -1242,19 +1252,19 @@ async function checkAndUpdatePackages(options = {}) {
1242
1252
  }
1243
1253
  }
1244
1254
  updaterCache.set("skippedVersions", skipped);
1245
- consola3.info("Versions skipped. Will prompt again for newer versions.");
1255
+ consola4.info("Versions skipped. Will prompt again for newer versions.");
1246
1256
  }
1247
1257
  return false;
1248
1258
  }
1249
1259
  function resetUpdaterPreferences() {
1250
1260
  updaterCache.clear();
1251
- consola3.success("Updater preferences reset");
1261
+ consola4.success("Updater preferences reset");
1252
1262
  }
1253
1263
 
1254
1264
  // src/config/utils/version.ts
1255
1265
  import chalk3 from "chalk";
1256
1266
  import Conf3 from "conf";
1257
- import consola4 from "consola";
1267
+ import consola5 from "consola";
1258
1268
  import semver2 from "semver";
1259
1269
  function createMemoryCache3() {
1260
1270
  const store = /* @__PURE__ */ new Map();
@@ -1346,10 +1356,10 @@ function getUpdateCommand() {
1346
1356
  async function printVersionInfo() {
1347
1357
  const { hasUpdate, currentVersion, latestVersion } = await checkForUpdate();
1348
1358
  if (!currentVersion) return;
1349
- consola4.box(`\u{1F4E6} @djangocfg/nextjs v${currentVersion}`);
1359
+ consola5.box(`\u{1F4E6} @djangocfg/nextjs v${currentVersion}`);
1350
1360
  if (hasUpdate && latestVersion) {
1351
- consola4.warn(`Update Available! ${chalk3.red(currentVersion)} \u2192 ${chalk3.green(latestVersion)}`);
1352
- consola4.info(`Run: ${chalk3.cyan(getUpdateCommand())}`);
1361
+ consola5.warn(`Update Available! ${chalk3.red(currentVersion)} \u2192 ${chalk3.green(latestVersion)}`);
1362
+ consola5.info(`Run: ${chalk3.cyan(getUpdateCommand())}`);
1353
1363
  console.log("");
1354
1364
  }
1355
1365
  }
@@ -1449,6 +1459,7 @@ function deepMerge(target, source) {
1449
1459
  // src/config/createNextConfig.ts
1450
1460
  function createBaseNextConfig(options = {}) {
1451
1461
  const basePath = getBasePath(options.isDefaultCfgAdmin);
1462
+ warnIfApiUrlMissing();
1452
1463
  const apiUrl = getApiUrl();
1453
1464
  const siteUrl = getSiteUrl();
1454
1465
  const baseConfig = {