@djangocfg/nextjs 2.1.542 → 2.1.543

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.
@@ -182,7 +182,17 @@ declare function resolveCspVendors(vendors: readonly string[] | undefined, warnU
182
182
  * ```
183
183
  */
184
184
 
185
- interface BaseNextConfigOptions {
185
+ /**
186
+ * Second argument Next.js passes to the `webpack` hook. Derived from Next's own
187
+ * signature rather than re-declared, so it tracks upstream.
188
+ */
189
+ type WebpackContext = Parameters<NonNullable<NextConfig['webpack']>>[1];
190
+ /**
191
+ * DjangoCFG-specific options. Every other Next.js option passes through via the
192
+ * `NextConfig` half of `BaseNextConfigOptions`; the keys redeclared here are
193
+ * omitted from it because this package narrows or re-purposes them.
194
+ */
195
+ interface DjangoCfgNextOptions {
186
196
  /** Static build path (used when NEXT_PUBLIC_STATIC_BUILD=true) */
187
197
  isDefaultCfgAdmin?: boolean;
188
198
  /** Additional transpile packages (merged with defaults) */
@@ -314,11 +324,7 @@ interface BaseNextConfigOptions {
314
324
  /** Turbopack configuration (Next.js 16+ default bundler) */
315
325
  turbopack?: NextConfig['turbopack'];
316
326
  /** Custom webpack configuration function (called after base webpack logic) */
317
- webpack?: (config: Configuration, options: {
318
- isServer: boolean;
319
- dev: boolean;
320
- [key: string]: any;
321
- }) => Configuration | void;
327
+ webpack?: (config: Configuration, options: WebpackContext) => Configuration | void;
322
328
  /** Custom experimental options (merged with defaults) */
323
329
  experimental?: NextConfig['experimental'];
324
330
  /** Custom env variables (merged with defaults) */
@@ -329,9 +335,11 @@ interface BaseNextConfigOptions {
329
335
  headers?: NextConfig['headers'];
330
336
  /** Additional rewrites */
331
337
  rewrites?: NextConfig['rewrites'];
332
- /** Override any Next.js config option */
333
- [key: string]: any;
334
338
  }
339
+ /**
340
+ * DjangoCFG options plus every remaining Next.js config option.
341
+ */
342
+ type BaseNextConfigOptions = DjangoCfgNextOptions & Omit<NextConfig, keyof DjangoCfgNextOptions>;
335
343
  /**
336
344
  * Create base Next.js configuration with standard DjangoCFG settings
337
345
  *
@@ -354,7 +362,12 @@ declare const DEFAULT_OPTIMIZE_PACKAGES: readonly ["@djangocfg/ui-core", "@djang
354
362
  *
355
363
  * Recursively merges objects, replacing arrays instead of merging them.
356
364
  */
357
- declare function deepMerge<T extends Record<string, any>>(target: T, source: Partial<T>): T;
365
+ /**
366
+ * `T extends object` rather than `Record<string, unknown>`: call sites pass
367
+ * Next.js config interfaces, which have declared keys and no index signature —
368
+ * they are not assignable to `Record<string, unknown>`.
369
+ */
370
+ declare function deepMerge<T extends object>(target: T, source: Partial<T>): T;
358
371
 
359
372
  /**
360
373
  * Environment Variable Utilities
@@ -349,7 +349,7 @@ function addCompressionPlugins(config, options = {}) {
349
349
  );
350
350
  }
351
351
  return true;
352
- } catch (error) {
352
+ } catch {
353
353
  return false;
354
354
  }
355
355
  }
@@ -557,7 +557,7 @@ async function installSinglePackage(pkg, pm, index, total) {
557
557
  const spinner = createSpinner(`${chalk.dim(progress)} Installing ${chalk.cyan(pkg.name)}...`);
558
558
  spinner.start();
559
559
  return new Promise((resolve) => {
560
- const [cmd, ...args] = command.split(" ");
560
+ const [cmd = pm, ...args] = command.split(" ");
561
561
  const proc = spawn(cmd, args, {
562
562
  shell: true,
563
563
  cwd: process.cwd(),
@@ -593,13 +593,13 @@ async function installPackagesWithProgress(packages) {
593
593
  console.log(chalk.bold(` Installing ${total} package${total > 1 ? "s" : ""}...`));
594
594
  console.log("");
595
595
  let successCount = 0;
596
- let failedPackages = [];
597
- for (let i = 0; i < packages.length; i++) {
598
- const success = await installSinglePackage(packages[i], pm, i, total);
596
+ const failedPackages = [];
597
+ for (const [i, pkg] of packages.entries()) {
598
+ const success = await installSinglePackage(pkg, pm, i, total);
599
599
  if (success) {
600
600
  successCount++;
601
601
  } else {
602
- failedPackages.push(packages[i].name);
602
+ failedPackages.push(pkg.name);
603
603
  }
604
604
  }
605
605
  console.log("");
@@ -964,12 +964,12 @@ async function updatePackagesWithProgress(packages) {
964
964
  console.log("");
965
965
  let successCount = 0;
966
966
  const failedPackages = [];
967
- for (let i = 0; i < packages.length; i++) {
968
- const success = await updateSinglePackage(packages[i], pm, i, total);
967
+ for (const [i, pkg] of packages.entries()) {
968
+ const success = await updateSinglePackage(pkg, pm, i, total);
969
969
  if (success) {
970
970
  successCount++;
971
971
  } else {
972
- failedPackages.push(packages[i].name);
972
+ failedPackages.push(pkg.name);
973
973
  }
974
974
  }
975
975
  console.log("");
@@ -1225,22 +1225,17 @@ function resetDevStartupState() {
1225
1225
  }
1226
1226
 
1227
1227
  // src/config/utils/deepMerge.ts
1228
+ function isPlainObject(value) {
1229
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1230
+ }
1228
1231
  function deepMerge(target, source) {
1229
1232
  const output = { ...target };
1230
- for (const key in source) {
1231
- if (source[key] === void 0) continue;
1232
- if (Array.isArray(source[key])) {
1233
- output[key] = source[key];
1234
- } else if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1235
- const targetValue = output[key];
1236
- if (targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
1237
- output[key] = deepMerge(targetValue, source[key]);
1238
- } else {
1239
- output[key] = source[key];
1240
- }
1241
- } else {
1242
- output[key] = source[key];
1243
- }
1233
+ for (const key of Object.keys(source)) {
1234
+ const sourceValue = source[key];
1235
+ if (sourceValue === void 0) continue;
1236
+ const targetValue = output[key];
1237
+ const merged = isPlainObject(sourceValue) && isPlainObject(targetValue) ? deepMerge(targetValue, sourceValue) : sourceValue;
1238
+ output[key] = merged;
1244
1239
  }
1245
1240
  return output;
1246
1241
  }
@@ -1450,23 +1445,28 @@ function createBaseNextConfig(options = {}) {
1450
1445
  return config;
1451
1446
  }
1452
1447
  };
1453
- const {
1454
- i18n: i18nOptions,
1455
- pwa: pwaOptions,
1456
- transpilePackages,
1457
- optimizePackageImports,
1458
- isDefaultCfgAdmin,
1459
- checkUpdates,
1460
- autoUpdate,
1461
- forceCheckWorkspace,
1462
- checkPackages: checkPackages2,
1463
- autoInstall,
1464
- allowIframeFrom,
1465
- dpop,
1466
- stripe,
1467
- csp,
1468
- ...nextConfigOptions
1469
- } = options;
1448
+ const { i18n: i18nOptions, pwa: pwaOptions } = options;
1449
+ const DJANGOCFG_ONLY_KEYS = [
1450
+ "i18n",
1451
+ "pwa",
1452
+ "transpilePackages",
1453
+ "optimizePackageImports",
1454
+ "isDefaultCfgAdmin",
1455
+ "checkUpdates",
1456
+ "autoUpdate",
1457
+ "forceCheckWorkspace",
1458
+ "checkPackages",
1459
+ "autoInstall",
1460
+ "allowIframeFrom",
1461
+ "dpop",
1462
+ "stripe",
1463
+ "csp"
1464
+ ];
1465
+ const nextConfigOptions = Object.fromEntries(
1466
+ Object.entries(options).filter(
1467
+ ([key]) => !DJANGOCFG_ONLY_KEYS.includes(key)
1468
+ )
1469
+ );
1470
1470
  let finalConfig = deepMerge(baseConfig, nextConfigOptions);
1471
1471
  if (pwaOptions) {
1472
1472
  finalConfig = withPWA(finalConfig, pwaOptions);