@djangocfg/nextjs 2.1.479 → 2.1.481

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.
@@ -24,6 +24,7 @@ declare function createRouting(config?: Partial<I18nConfig>): {
24
24
  localePrefix?: next_intl_routing.LocalePrefix<string[], "always" | "as-needed" | "never">;
25
25
  domains?: never;
26
26
  localeCookie?: boolean | {
27
+ name?: string;
27
28
  maxAge?: number | undefined;
28
29
  priority?: "low" | "medium" | "high" | undefined;
29
30
  domain?: string | undefined;
@@ -31,7 +32,6 @@ declare function createRouting(config?: Partial<I18nConfig>): {
31
32
  secure?: boolean | undefined;
32
33
  sameSite?: true | false | "lax" | "strict" | "none" | undefined;
33
34
  partitioned?: boolean | undefined;
34
- name?: string;
35
35
  };
36
36
  alternateLinks?: boolean;
37
37
  localeDetection?: boolean;
@@ -46,6 +46,7 @@ declare const routing: {
46
46
  localePrefix?: next_intl_routing.LocalePrefix<string[], "always" | "as-needed" | "never">;
47
47
  domains?: never;
48
48
  localeCookie?: boolean | {
49
+ name?: string;
49
50
  maxAge?: number | undefined;
50
51
  priority?: "low" | "medium" | "high" | undefined;
51
52
  domain?: string | undefined;
@@ -53,7 +54,6 @@ declare const routing: {
53
54
  secure?: boolean | undefined;
54
55
  sameSite?: true | false | "lax" | "strict" | "none" | undefined;
55
56
  partitioned?: boolean | undefined;
56
- name?: string;
57
57
  };
58
58
  alternateLinks?: boolean;
59
59
  localeDetection?: boolean;
package/dist/index.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { CreateDjangoSitemapOptions, CreateRobotsOptions, CreateSitemapIndexOptions, SitemapChunkInfo, SitemapEntry, SitemapFeedPage, SitemapIndex, SitemapSourceInfo, StaticRoute, createDjangoSitemap, createRobots, createSitemapIndex, decodeChunkId, encodeChunkId, fetchSitemapFeed, fetchSitemapIndex } from './sitemap/index.mjs';
2
2
  export { HealthCheck, HealthConfig, createHealthHandler } from './health/index.mjs';
3
3
  export { BreadcrumbItem, MenuGroup, MenuItem, NavGroup, NavGroupWithRoutes, NavigationItem, NavigationSection, RouteDefinition, RouteMetadata, defineRoute, findRoute, findRouteByPattern, getPageTitle, getUnauthenticatedRedirect, groupRoutesByNavGroups, isActive, redirectToAuth, routesToMenuItems } from './navigation/index.mjs';
4
- export { BaseNextConfigOptions, CompressionPluginOptions, DEFAULT_OPTIMIZE_PACKAGES, DEFAULT_TRANSPILE_PACKAGES, DJANGOCFG_PACKAGES, DJANGO_CFG_BANNER, DevStartupPlugin, DevStartupPluginOptions, InstallOptions, InstallProgress, MissingPackage, OPTIONAL_PACKAGES, PACKAGE_NAME, PEER_DEPENDENCIES, PackageDefinition, PackageVersion, UpdateOptions, addCompressionPlugins, buildInstallCommand, buildSingleInstallCommand, checkAndInstallPackages, checkAndUpdatePackages, checkForUpdate, checkForUpdates, checkPackages, createBaseNextConfig, deepMerge, detectPackageManager, fetchLatestVersion, getApiUrl, getBasePath, getCurrentVersion, getInstalledVersion, getMissingPackages, getOutdatedPackages, getPackagesForContext, getSiteUrl, getUpdateCommand, installPackages, installPackagesWithProgress, isCI, isCompressionAvailable, isDev, isPackageInstalled, isProduction, isStaticBuild, printVersionInfo, resetDevStartupState, resetInstallerPreferences, resetUpdaterPreferences, updatePackagesWithProgress } from './config/index.mjs';
4
+ export { BaseNextConfigOptions, CSP_BASELINE_VENDORS, CSP_VENDOR_PRESETS, CompressionPluginOptions, CspOrigins, CspVendor, DEFAULT_OPTIMIZE_PACKAGES, DEFAULT_TRANSPILE_PACKAGES, DJANGOCFG_PACKAGES, DJANGO_CFG_BANNER, DevStartupPlugin, DevStartupPluginOptions, InstallOptions, InstallProgress, MissingPackage, OPTIONAL_PACKAGES, PACKAGE_NAME, PEER_DEPENDENCIES, PackageDefinition, PackageVersion, UpdateOptions, addCompressionPlugins, buildInstallCommand, buildSingleInstallCommand, checkAndInstallPackages, checkAndUpdatePackages, checkForUpdate, checkForUpdates, checkPackages, createBaseNextConfig, deepMerge, detectPackageManager, fetchLatestVersion, getApiUrl, getBasePath, getCurrentVersion, getInstalledVersion, getMissingPackages, getOutdatedPackages, getPackagesForContext, getSiteUrl, getUpdateCommand, installPackages, installPackagesWithProgress, isCI, isCompressionAvailable, isDev, isPackageInstalled, isProduction, isStaticBuild, printVersionInfo, resetDevStartupState, resetInstallerPreferences, resetUpdaterPreferences, resolveCspVendors, updatePackagesWithProgress } from './config/index.mjs';
5
5
  export { A as AI_DOCS_HINT, a as AI_HINT, M as MCP_API_URL, b as MCP_BASE_URL, c as MCP_SERVER_URL } from './constants-BDS8GXHN.mjs';
6
6
  export { DjangoCfgDocsClient, McpConfig, SearchOptions, SearchResult, getDocs, getInfo, getMcpConfig, search } from './ai/index.mjs';
7
7
  export { C as ChangeFreq, E as ErrorPageConfig, H as HealthResponse, S as SitemapConfig, a as SitemapUrl } from './types-l9x1Rkmf.mjs';
package/dist/index.mjs CHANGED
@@ -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.479",
17
+ version: "2.1.481",
18
18
  description: "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
19
19
  keywords: [
20
20
  "nextjs",
@@ -560,6 +560,106 @@ var DEFAULT_OPTIMIZE_PACKAGES = [
560
560
  "recharts"
561
561
  ];
562
562
 
563
+ // src/config/csp.ts
564
+ var CSP_VENDOR_PRESETS = {
565
+ /**
566
+ * Stripe.js / Checkout / Elements.
567
+ *
568
+ * `js.stripe.com` serves the SDK and also hosts the Elements iframes;
569
+ * `checkout.stripe.com` is the hosted Checkout iframe; `api.stripe.com`
570
+ * takes the tokenization/confirm XHR. Without all three the payment form
571
+ * silently fails to render.
572
+ */
573
+ stripe: {
574
+ scriptSrc: ["https://js.stripe.com"],
575
+ frameSrc: ["https://js.stripe.com", "https://checkout.stripe.com"],
576
+ connectSrc: ["https://api.stripe.com"]
577
+ },
578
+ /**
579
+ * Cloudflare Web Analytics (the RUM beacon).
580
+ *
581
+ * IMPORTANT: this script is NOT in the app's own HTML — when Web Analytics
582
+ * is enabled on the zone, Cloudflare INJECTS `beacon.min.js` into the
583
+ * response at the edge, after Next.js has already emitted the CSP header.
584
+ * So any app served through a Cloudflare zone with that feature on will
585
+ * violate its own CSP unless this preset is enabled, no matter what the
586
+ * source tree contains. The beacon also POSTs its payload back to
587
+ * `cloudflareinsights.com`, hence the `connect-src` entry.
588
+ */
589
+ cloudflare: {
590
+ scriptSrc: ["https://static.cloudflareinsights.com"],
591
+ connectSrc: ["https://cloudflareinsights.com", "https://static.cloudflareinsights.com"]
592
+ },
593
+ /** Google Analytics 4 / gtag.js. */
594
+ "google-analytics": {
595
+ scriptSrc: ["https://www.googletagmanager.com", "https://www.google-analytics.com"],
596
+ connectSrc: [
597
+ "https://www.google-analytics.com",
598
+ "https://analytics.google.com",
599
+ "https://region1.google-analytics.com"
600
+ ],
601
+ imgSrc: ["https://www.google-analytics.com", "https://www.googletagmanager.com"]
602
+ },
603
+ /** Google Tag Manager (the container itself; tags it loads may need more). */
604
+ "google-tag-manager": {
605
+ scriptSrc: ["https://www.googletagmanager.com"],
606
+ connectSrc: ["https://www.googletagmanager.com"],
607
+ imgSrc: ["https://www.googletagmanager.com"],
608
+ frameSrc: ["https://www.googletagmanager.com"]
609
+ },
610
+ /** Google Fonts (stylesheet host + the font files themselves). */
611
+ "google-fonts": {
612
+ fontSrc: ["https://fonts.gstatic.com"]
613
+ },
614
+ /** Sentry browser SDK — errors/traces are POSTed to the ingest host. */
615
+ sentry: {
616
+ connectSrc: ["https://*.ingest.sentry.io", "https://*.sentry.io"]
617
+ },
618
+ /** YouTube embeds (privacy-enhanced host included). */
619
+ youtube: {
620
+ frameSrc: ["https://www.youtube.com", "https://www.youtube-nocookie.com"],
621
+ imgSrc: ["https://i.ytimg.com"]
622
+ },
623
+ /** Vimeo embeds. */
624
+ vimeo: {
625
+ frameSrc: ["https://player.vimeo.com"],
626
+ imgSrc: ["https://i.vimeocdn.com"]
627
+ }
628
+ };
629
+ var CSP_BASELINE_VENDORS = ["cloudflare"];
630
+ function resolveCspVendors(vendors, warnUnknown = true) {
631
+ const merged = {
632
+ scriptSrc: [],
633
+ frameSrc: [],
634
+ connectSrc: [],
635
+ imgSrc: [],
636
+ fontSrc: []
637
+ };
638
+ if (!vendors?.length) return merged;
639
+ const unknown = [];
640
+ for (const name of vendors) {
641
+ const preset = CSP_VENDOR_PRESETS[name];
642
+ if (!preset) {
643
+ unknown.push(name);
644
+ continue;
645
+ }
646
+ for (const key of Object.keys(merged)) {
647
+ const origins = preset[key];
648
+ if (origins) merged[key].push(...origins);
649
+ }
650
+ }
651
+ if (unknown.length && warnUnknown) {
652
+ const known = Object.keys(CSP_VENDOR_PRESETS).join(", ");
653
+ console.warn(
654
+ `[djangocfg] Unknown CSP vendor(s): ${unknown.join(", ")}. Known vendors: ${known}`
655
+ );
656
+ }
657
+ for (const key of Object.keys(merged)) {
658
+ merged[key] = [...new Set(merged[key])];
659
+ }
660
+ return merged;
661
+ }
662
+
563
663
  // src/config/packages/checker.ts
564
664
  import { createRequire } from "module";
565
665
  import { join } from "path";
@@ -1673,29 +1773,36 @@ function createBaseNextConfig(options = {}) {
1673
1773
  const frameAncestors = hasIframeAllowlist ? options.allowIframeFrom.includes("*") ? "*" : `'self' ${options.allowIframeFrom.join(" ")}` : "'none'";
1674
1774
  const cspDisabled = options.csp === false;
1675
1775
  const cspExtra = typeof options.csp === "object" ? options.csp : void 0;
1676
- const stripeScript = options.stripe ? " https://js.stripe.com" : "";
1677
- const stripeConnect = options.stripe ? " https://api.stripe.com" : "";
1678
- const stripeFrame = options.stripe ? " https://js.stripe.com https://checkout.stripe.com" : "";
1679
- const extraScript = cspExtra?.scriptSrc?.length ? " " + cspExtra.scriptSrc.join(" ") : "";
1680
- const extraConnect = cspExtra?.connectSrc?.length ? " " + cspExtra.connectSrc.join(" ") : "";
1681
- const extraFrame = cspExtra?.frameSrc?.length ? " " + cspExtra.frameSrc.join(" ") : "";
1682
- const extraImg = cspExtra?.imgSrc?.length ? " " + cspExtra.imgSrc.join(" ") : "";
1683
- const extraFont = cspExtra?.fontSrc?.length ? " " + cspExtra.fontSrc.join(" ") : "";
1684
- const connectSrc = isDev ? `connect-src 'self' http: https: ws: wss:${stripeConnect}${extraConnect}` : `connect-src 'self' https: wss:${stripeConnect}${extraConnect}`;
1776
+ const vendorNames = [
1777
+ ...cspExtra?.cloudflare === false ? [] : CSP_BASELINE_VENDORS,
1778
+ ...options.stripe ? ["stripe"] : [],
1779
+ ...cspExtra?.vendors ?? []
1780
+ ];
1781
+ const vendor = resolveCspVendors(vendorNames);
1782
+ const join3 = (...groups) => {
1783
+ const all = [...new Set(groups.flatMap((g) => g ?? []))];
1784
+ return all.length ? " " + all.join(" ") : "";
1785
+ };
1786
+ const extraScript = join3(vendor.scriptSrc, cspExtra?.scriptSrc);
1787
+ const extraConnect = join3(vendor.connectSrc, cspExtra?.connectSrc);
1788
+ const extraFrame = join3(vendor.frameSrc, cspExtra?.frameSrc);
1789
+ const extraImg = join3(vendor.imgSrc, cspExtra?.imgSrc);
1790
+ const extraFont = join3(vendor.fontSrc, cspExtra?.fontSrc);
1791
+ const connectSrc = isDev ? `connect-src 'self' http: https: ws: wss:${extraConnect}` : `connect-src 'self' https: wss:${extraConnect}`;
1685
1792
  const imgSrc = isDev ? `img-src 'self' data: blob: http: https:${extraImg}` : `img-src 'self' data: blob: https:${extraImg}`;
1686
1793
  if (!cspDisabled) {
1687
1794
  const cspDirectives = [
1688
1795
  "default-src 'self'",
1689
1796
  // Next.js requires inline + eval for its runtime/HMR. Tighten to nonces later.
1690
- `script-src 'self' 'unsafe-inline' 'unsafe-eval'${stripeScript}${extraScript}`,
1797
+ `script-src 'self' 'unsafe-inline' 'unsafe-eval'${extraScript}`,
1691
1798
  "style-src 'self' 'unsafe-inline'",
1692
1799
  imgSrc,
1693
1800
  `font-src 'self' data:${extraFont}`,
1694
1801
  // API/websocket calls go cross-origin to Django/Centrifugo.
1695
1802
  connectSrc,
1696
- // Stripe Elements/Checkout and any app-declared trusted origins
1697
- // (options.csp.frameSrc) mount iframes; add their hosts when enabled.
1698
- `frame-src 'self'${stripeFrame}${extraFrame}`,
1803
+ // Declared vendors (Stripe Elements/Checkout, video embeds…) and any
1804
+ // app-declared trusted origins mount iframes; add their hosts here.
1805
+ `frame-src 'self'${extraFrame}`,
1699
1806
  "object-src 'none'",
1700
1807
  "base-uri 'self'",
1701
1808
  "form-action 'self'",
@@ -1948,6 +2055,8 @@ function getMcpConfig() {
1948
2055
  export {
1949
2056
  AI_DOCS_HINT,
1950
2057
  AI_HINT,
2058
+ CSP_BASELINE_VENDORS,
2059
+ CSP_VENDOR_PRESETS,
1951
2060
  DEFAULT_OPTIMIZE_PACKAGES,
1952
2061
  DEFAULT_TRANSPILE_PACKAGES,
1953
2062
  DJANGOCFG_PACKAGES,
@@ -2012,6 +2121,7 @@ export {
2012
2121
  resetDevStartupState,
2013
2122
  resetInstallerPreferences,
2014
2123
  resetUpdaterPreferences,
2124
+ resolveCspVendors,
2015
2125
  routesToMenuItems,
2016
2126
  search,
2017
2127
  updatePackagesWithProgress