@djangocfg/nextjs 2.1.30 → 2.1.31

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/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.30",
17
+ version: "2.1.31",
18
18
  description: "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
19
19
  keywords: [
20
20
  "nextjs",
@@ -115,6 +115,13 @@ var require_package = __commonJS({
115
115
  peerDependencies: {
116
116
  next: "^15.5.9"
117
117
  },
118
+ dependencies: {
119
+ "@ducanh2912/next-pwa": "^5.6.0",
120
+ chalk: "^5.3.0",
121
+ conf: "^15.0.2",
122
+ consola: "^3.4.2",
123
+ semver: "^7.7.3"
124
+ },
118
125
  devDependencies: {
119
126
  "@djangocfg/imgai": "workspace:*",
120
127
  "@djangocfg/layouts": "workspace:*",
@@ -136,12 +143,6 @@ var require_package = __commonJS({
136
143
  },
137
144
  publishConfig: {
138
145
  access: "public"
139
- },
140
- dependencies: {
141
- chalk: "^5.3.0",
142
- conf: "^15.0.2",
143
- consola: "^3.4.2",
144
- semver: "^7.7.3"
145
146
  }
146
147
  };
147
148
  }
@@ -2152,6 +2153,278 @@ function isCompressionAvailable() {
2152
2153
  return isPackageInstalled("compression-webpack-plugin");
2153
2154
  }
2154
2155
 
2156
+ // src/config/plugins/pwa.ts
2157
+ import { consola as consola4 } from "consola";
2158
+ function isPWAAvailable() {
2159
+ try {
2160
+ __require.resolve("@ducanh2912/next-pwa");
2161
+ return true;
2162
+ } catch {
2163
+ try {
2164
+ __require.resolve("next-pwa");
2165
+ consola4.warn(
2166
+ "Found legacy next-pwa. Please use @ducanh2912/next-pwa for Next.js 13+ support.\nRun: pnpm remove next-pwa && pnpm add @ducanh2912/next-pwa"
2167
+ );
2168
+ return true;
2169
+ } catch {
2170
+ return false;
2171
+ }
2172
+ }
2173
+ }
2174
+ function withPWA(nextConfig, options = {}) {
2175
+ if (!isPWAAvailable()) {
2176
+ consola4.error(
2177
+ "@ducanh2912/next-pwa is missing!\nThis is unexpected as it should be installed automatically.\nTry: pnpm install --force\nPWA features will be disabled."
2178
+ );
2179
+ return nextConfig;
2180
+ }
2181
+ const isDev2 = process.env.NODE_ENV === "development";
2182
+ const defaultOptions = {
2183
+ dest: "public",
2184
+ disable: options.disable !== void 0 ? options.disable : isDev2,
2185
+ register: true,
2186
+ skipWaiting: true,
2187
+ clientsClaim: true,
2188
+ cleanupOutdatedCaches: true,
2189
+ publicExcludes: ["!noprecache/**/*"],
2190
+ buildExcludes: [/middleware-manifest\.json$/, /build-manifest\.json$/],
2191
+ cacheStartUrl: true,
2192
+ dynamicStartUrl: true,
2193
+ reloadOnOnline: true,
2194
+ ...options
2195
+ };
2196
+ try {
2197
+ const withPWAImport = __require("@ducanh2912/next-pwa").default;
2198
+ return withPWAImport(defaultOptions)(nextConfig);
2199
+ } catch {
2200
+ try {
2201
+ const withPWAImport = __require("next-pwa");
2202
+ consola4.warn("Using legacy next-pwa. Upgrade to @ducanh2912/next-pwa for Next.js 13+ support");
2203
+ return withPWAImport(defaultOptions)(nextConfig);
2204
+ } catch (error) {
2205
+ consola4.error("Failed to load next-pwa:", error);
2206
+ return nextConfig;
2207
+ }
2208
+ }
2209
+ }
2210
+ var defaultRuntimeCaching = [
2211
+ {
2212
+ urlPattern: /^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,
2213
+ handler: "CacheFirst",
2214
+ options: {
2215
+ cacheName: "google-fonts-webfonts",
2216
+ expiration: {
2217
+ maxEntries: 4,
2218
+ maxAgeSeconds: 365 * 24 * 60 * 60
2219
+ // 1 year
2220
+ }
2221
+ }
2222
+ },
2223
+ {
2224
+ urlPattern: /^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,
2225
+ handler: "StaleWhileRevalidate",
2226
+ options: {
2227
+ cacheName: "google-fonts-stylesheets",
2228
+ expiration: {
2229
+ maxEntries: 4,
2230
+ maxAgeSeconds: 7 * 24 * 60 * 60
2231
+ // 1 week
2232
+ }
2233
+ }
2234
+ },
2235
+ {
2236
+ urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
2237
+ handler: "StaleWhileRevalidate",
2238
+ options: {
2239
+ cacheName: "static-font-assets",
2240
+ expiration: {
2241
+ maxEntries: 4,
2242
+ maxAgeSeconds: 7 * 24 * 60 * 60
2243
+ // 1 week
2244
+ }
2245
+ }
2246
+ },
2247
+ {
2248
+ urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
2249
+ handler: "StaleWhileRevalidate",
2250
+ options: {
2251
+ cacheName: "static-image-assets",
2252
+ expiration: {
2253
+ maxEntries: 64,
2254
+ maxAgeSeconds: 24 * 60 * 60
2255
+ // 24 hours
2256
+ }
2257
+ }
2258
+ },
2259
+ {
2260
+ urlPattern: /\/_next\/image\?url=.+$/i,
2261
+ handler: "StaleWhileRevalidate",
2262
+ options: {
2263
+ cacheName: "next-image",
2264
+ expiration: {
2265
+ maxEntries: 64,
2266
+ maxAgeSeconds: 24 * 60 * 60
2267
+ // 24 hours
2268
+ }
2269
+ }
2270
+ },
2271
+ {
2272
+ urlPattern: /\.(?:mp3|wav|ogg)$/i,
2273
+ handler: "CacheFirst",
2274
+ options: {
2275
+ rangeRequests: true,
2276
+ cacheName: "static-audio-assets",
2277
+ expiration: {
2278
+ maxEntries: 32,
2279
+ maxAgeSeconds: 24 * 60 * 60
2280
+ // 24 hours
2281
+ }
2282
+ }
2283
+ },
2284
+ {
2285
+ urlPattern: /\.(?:mp4)$/i,
2286
+ handler: "CacheFirst",
2287
+ options: {
2288
+ rangeRequests: true,
2289
+ cacheName: "static-video-assets",
2290
+ expiration: {
2291
+ maxEntries: 32,
2292
+ maxAgeSeconds: 24 * 60 * 60
2293
+ // 24 hours
2294
+ }
2295
+ }
2296
+ },
2297
+ {
2298
+ urlPattern: /\.(?:js)$/i,
2299
+ handler: "StaleWhileRevalidate",
2300
+ options: {
2301
+ cacheName: "static-js-assets",
2302
+ expiration: {
2303
+ maxEntries: 32,
2304
+ maxAgeSeconds: 24 * 60 * 60
2305
+ // 24 hours
2306
+ }
2307
+ }
2308
+ },
2309
+ {
2310
+ urlPattern: /\.(?:css|less)$/i,
2311
+ handler: "StaleWhileRevalidate",
2312
+ options: {
2313
+ cacheName: "static-style-assets",
2314
+ expiration: {
2315
+ maxEntries: 32,
2316
+ maxAgeSeconds: 24 * 60 * 60
2317
+ // 24 hours
2318
+ }
2319
+ }
2320
+ },
2321
+ {
2322
+ urlPattern: /\/_next\/data\/.+\/.+\.json$/i,
2323
+ handler: "StaleWhileRevalidate",
2324
+ options: {
2325
+ cacheName: "next-data",
2326
+ expiration: {
2327
+ maxEntries: 32,
2328
+ maxAgeSeconds: 24 * 60 * 60
2329
+ // 24 hours
2330
+ }
2331
+ }
2332
+ },
2333
+ {
2334
+ urlPattern: /\.(?:json|xml|csv)$/i,
2335
+ handler: "NetworkFirst",
2336
+ options: {
2337
+ cacheName: "static-data-assets",
2338
+ expiration: {
2339
+ maxEntries: 32,
2340
+ maxAgeSeconds: 24 * 60 * 60
2341
+ // 24 hours
2342
+ }
2343
+ }
2344
+ },
2345
+ {
2346
+ urlPattern: ({ url }) => {
2347
+ const isSameOrigin = self.origin === url.origin;
2348
+ if (!isSameOrigin) return false;
2349
+ const pathname = url.pathname;
2350
+ if (pathname.startsWith("/api/")) return false;
2351
+ return true;
2352
+ },
2353
+ handler: "NetworkFirst",
2354
+ options: {
2355
+ cacheName: "pages",
2356
+ expiration: {
2357
+ maxEntries: 32,
2358
+ maxAgeSeconds: 24 * 60 * 60
2359
+ // 24 hours
2360
+ }
2361
+ }
2362
+ }
2363
+ ];
2364
+ function createApiCacheRule(apiUrl, options = {}) {
2365
+ const {
2366
+ strategy = "NetworkFirst",
2367
+ maxAge = 300,
2368
+ maxEntries = 50,
2369
+ cacheName = "api-cache"
2370
+ } = options;
2371
+ return {
2372
+ urlPattern: new RegExp(`^${apiUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/.*`, "i"),
2373
+ handler: strategy,
2374
+ options: {
2375
+ cacheName,
2376
+ expiration: {
2377
+ maxEntries,
2378
+ maxAgeSeconds: maxAge
2379
+ },
2380
+ networkTimeoutSeconds: 10
2381
+ }
2382
+ };
2383
+ }
2384
+ function createStaticAssetRule(extensions, options = {}) {
2385
+ const {
2386
+ strategy = "CacheFirst",
2387
+ maxAge = 86400,
2388
+ maxEntries = 64,
2389
+ cacheName = "static-assets"
2390
+ } = options;
2391
+ const pattern = extensions.map((ext) => ext.replace(".", "")).join("|");
2392
+ return {
2393
+ urlPattern: new RegExp(`\\.(?:${pattern})$`, "i"),
2394
+ handler: strategy,
2395
+ options: {
2396
+ cacheName,
2397
+ expiration: {
2398
+ maxEntries,
2399
+ maxAgeSeconds: maxAge
2400
+ }
2401
+ }
2402
+ };
2403
+ }
2404
+ function createCdnCacheRule(cdnUrl, options = {}) {
2405
+ const {
2406
+ strategy = "CacheFirst",
2407
+ maxAge = 2592e3,
2408
+ // 30 days
2409
+ maxEntries = 100,
2410
+ cacheName = "cdn-cache"
2411
+ } = options;
2412
+ return {
2413
+ urlPattern: new RegExp(`^${cdnUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/.*`, "i"),
2414
+ handler: strategy,
2415
+ options: {
2416
+ cacheName,
2417
+ expiration: {
2418
+ maxEntries,
2419
+ maxAgeSeconds: maxAge
2420
+ },
2421
+ cacheableResponse: {
2422
+ statuses: [0, 200]
2423
+ }
2424
+ }
2425
+ };
2426
+ }
2427
+
2155
2428
  // src/config/createNextConfig.ts
2156
2429
  function createBaseNextConfig(options = {}) {
2157
2430
  const basePath = getBasePath(options.isDefaultCfgAdmin);
@@ -2275,7 +2548,7 @@ function createBaseNextConfig(options = {}) {
2275
2548
  return config;
2276
2549
  }
2277
2550
  };
2278
- const finalConfig = deepMerge(baseConfig, options);
2551
+ let finalConfig = deepMerge(baseConfig, options);
2279
2552
  delete finalConfig.optimizePackageImports;
2280
2553
  delete finalConfig.isDefaultCfgAdmin;
2281
2554
  delete finalConfig.openBrowser;
@@ -2285,9 +2558,106 @@ function createBaseNextConfig(options = {}) {
2285
2558
  delete finalConfig.checkPackages;
2286
2559
  delete finalConfig.autoInstall;
2287
2560
  delete finalConfig.allowIframeFrom;
2561
+ if (options.pwa !== false) {
2562
+ const pwaOptions = typeof options.pwa === "object" ? options.pwa : {};
2563
+ finalConfig = withPWA(finalConfig, pwaOptions);
2564
+ }
2565
+ delete finalConfig.pwa;
2288
2566
  return finalConfig;
2289
2567
  }
2290
2568
 
2569
+ // src/config/utils/manifest.ts
2570
+ function createManifestMetadata(config) {
2571
+ return {
2572
+ manifest: "/manifest.json",
2573
+ themeColor: config.themeColor || "#000000",
2574
+ appleWebApp: {
2575
+ capable: true,
2576
+ statusBarStyle: "default",
2577
+ title: config.shortName || config.name
2578
+ },
2579
+ applicationName: config.name,
2580
+ formatDetection: {
2581
+ telephone: false
2582
+ },
2583
+ viewport: {
2584
+ width: "device-width",
2585
+ initialScale: 1,
2586
+ maximumScale: 1
2587
+ }
2588
+ };
2589
+ }
2590
+ function createManifest(config) {
2591
+ return () => {
2592
+ let manifestIcons;
2593
+ if (Array.isArray(config.icons)) {
2594
+ manifestIcons = config.icons;
2595
+ } else if (config.icons) {
2596
+ const { logo192, logo384, logo512 } = config.icons;
2597
+ manifestIcons = [
2598
+ ...logo192 ? [
2599
+ {
2600
+ src: logo192,
2601
+ sizes: "192x192",
2602
+ type: "image/png",
2603
+ purpose: "maskable"
2604
+ }
2605
+ ] : [],
2606
+ ...logo384 ? [
2607
+ {
2608
+ src: logo384,
2609
+ sizes: "384x384",
2610
+ type: "image/png"
2611
+ }
2612
+ ] : [],
2613
+ ...logo512 ? [
2614
+ {
2615
+ src: logo512,
2616
+ sizes: "512x512",
2617
+ type: "image/png"
2618
+ }
2619
+ ] : []
2620
+ ];
2621
+ } else {
2622
+ manifestIcons = [
2623
+ {
2624
+ src: "/static/logos/192x192.png",
2625
+ sizes: "192x192",
2626
+ type: "image/png",
2627
+ purpose: "maskable"
2628
+ },
2629
+ {
2630
+ src: "/static/logos/384x384.png",
2631
+ sizes: "384x384",
2632
+ type: "image/png"
2633
+ },
2634
+ {
2635
+ src: "/static/logos/512x512.png",
2636
+ sizes: "512x512",
2637
+ type: "image/png"
2638
+ }
2639
+ ];
2640
+ }
2641
+ return {
2642
+ name: config.name,
2643
+ short_name: config.shortName || config.name,
2644
+ description: config.description || config.name,
2645
+ start_url: config.startUrl || "/",
2646
+ scope: config.scope || "/",
2647
+ display: config.display || "standalone",
2648
+ orientation: config.orientation || "portrait",
2649
+ background_color: config.backgroundColor || "#000000",
2650
+ theme_color: config.themeColor || "#ffffff",
2651
+ lang: config.lang || "en",
2652
+ dir: config.dir || "ltr",
2653
+ icons: manifestIcons
2654
+ };
2655
+ };
2656
+ }
2657
+ function generateManifest(config) {
2658
+ return createManifest(config)();
2659
+ }
2660
+
2291
2661
  // src/ai/client.ts
2292
2662
  var DjangoCfgDocsClient = class {
2293
2663
  constructor(baseUrl = MCP_BASE_URL, timeout = DEFAULT_TIMEOUT) {
@@ -2417,22 +2787,29 @@ export {
2417
2787
  checkForUpdate,
2418
2788
  checkForUpdates,
2419
2789
  checkPackages,
2790
+ createApiCacheRule,
2420
2791
  createBaseNextConfig,
2792
+ createCdnCacheRule,
2421
2793
  createFontLoader,
2422
2794
  createHealthHandler,
2795
+ createManifest,
2796
+ createManifestMetadata,
2423
2797
  createOgImageDynamicRoute,
2424
2798
  createOgImageHandler,
2425
2799
  createOgImageMetadataGenerator,
2426
2800
  createOgImageUrlBuilder,
2427
2801
  createSitemapHandler,
2802
+ createStaticAssetRule,
2428
2803
  decodeBase64,
2429
2804
  deepMerge,
2805
+ defaultRuntimeCaching,
2430
2806
  defineRoute,
2431
2807
  detectPackageManager,
2432
2808
  encodeBase64,
2433
2809
  fetchLatestVersion,
2434
2810
  findRoute,
2435
2811
  findRouteByPattern,
2812
+ generateManifest,
2436
2813
  generateOgImageMetadata,
2437
2814
  generateOgImageUrl,
2438
2815
  generateSitemapXml,
@@ -2457,6 +2834,7 @@ export {
2457
2834
  isCI,
2458
2835
  isCompressionAvailable,
2459
2836
  isDev,
2837
+ isPWAAvailable,
2460
2838
  isPackageInstalled,
2461
2839
  isProduction,
2462
2840
  isStaticBuild,
@@ -2472,6 +2850,7 @@ export {
2472
2850
  resetUpdaterPreferences,
2473
2851
  routesToMenuItems,
2474
2852
  search,
2475
- updatePackagesWithProgress
2853
+ updatePackagesWithProgress,
2854
+ withPWA
2476
2855
  };
2477
2856
  //# sourceMappingURL=index.mjs.map