@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.
@@ -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
  }
@@ -1171,6 +1172,278 @@ function isCompressionAvailable() {
1171
1172
  return isPackageInstalled("compression-webpack-plugin");
1172
1173
  }
1173
1174
 
1175
+ // src/config/plugins/pwa.ts
1176
+ import { consola as consola4 } from "consola";
1177
+ function isPWAAvailable() {
1178
+ try {
1179
+ __require.resolve("@ducanh2912/next-pwa");
1180
+ return true;
1181
+ } catch {
1182
+ try {
1183
+ __require.resolve("next-pwa");
1184
+ consola4.warn(
1185
+ "Found legacy next-pwa. Please use @ducanh2912/next-pwa for Next.js 13+ support.\nRun: pnpm remove next-pwa && pnpm add @ducanh2912/next-pwa"
1186
+ );
1187
+ return true;
1188
+ } catch {
1189
+ return false;
1190
+ }
1191
+ }
1192
+ }
1193
+ function withPWA(nextConfig, options = {}) {
1194
+ if (!isPWAAvailable()) {
1195
+ consola4.error(
1196
+ "@ducanh2912/next-pwa is missing!\nThis is unexpected as it should be installed automatically.\nTry: pnpm install --force\nPWA features will be disabled."
1197
+ );
1198
+ return nextConfig;
1199
+ }
1200
+ const isDev2 = process.env.NODE_ENV === "development";
1201
+ const defaultOptions = {
1202
+ dest: "public",
1203
+ disable: options.disable !== void 0 ? options.disable : isDev2,
1204
+ register: true,
1205
+ skipWaiting: true,
1206
+ clientsClaim: true,
1207
+ cleanupOutdatedCaches: true,
1208
+ publicExcludes: ["!noprecache/**/*"],
1209
+ buildExcludes: [/middleware-manifest\.json$/, /build-manifest\.json$/],
1210
+ cacheStartUrl: true,
1211
+ dynamicStartUrl: true,
1212
+ reloadOnOnline: true,
1213
+ ...options
1214
+ };
1215
+ try {
1216
+ const withPWAImport = __require("@ducanh2912/next-pwa").default;
1217
+ return withPWAImport(defaultOptions)(nextConfig);
1218
+ } catch {
1219
+ try {
1220
+ const withPWAImport = __require("next-pwa");
1221
+ consola4.warn("Using legacy next-pwa. Upgrade to @ducanh2912/next-pwa for Next.js 13+ support");
1222
+ return withPWAImport(defaultOptions)(nextConfig);
1223
+ } catch (error) {
1224
+ consola4.error("Failed to load next-pwa:", error);
1225
+ return nextConfig;
1226
+ }
1227
+ }
1228
+ }
1229
+ var defaultRuntimeCaching = [
1230
+ {
1231
+ urlPattern: /^https:\/\/fonts\.(?:gstatic)\.com\/.*/i,
1232
+ handler: "CacheFirst",
1233
+ options: {
1234
+ cacheName: "google-fonts-webfonts",
1235
+ expiration: {
1236
+ maxEntries: 4,
1237
+ maxAgeSeconds: 365 * 24 * 60 * 60
1238
+ // 1 year
1239
+ }
1240
+ }
1241
+ },
1242
+ {
1243
+ urlPattern: /^https:\/\/fonts\.(?:googleapis)\.com\/.*/i,
1244
+ handler: "StaleWhileRevalidate",
1245
+ options: {
1246
+ cacheName: "google-fonts-stylesheets",
1247
+ expiration: {
1248
+ maxEntries: 4,
1249
+ maxAgeSeconds: 7 * 24 * 60 * 60
1250
+ // 1 week
1251
+ }
1252
+ }
1253
+ },
1254
+ {
1255
+ urlPattern: /\.(?:eot|otf|ttc|ttf|woff|woff2|font.css)$/i,
1256
+ handler: "StaleWhileRevalidate",
1257
+ options: {
1258
+ cacheName: "static-font-assets",
1259
+ expiration: {
1260
+ maxEntries: 4,
1261
+ maxAgeSeconds: 7 * 24 * 60 * 60
1262
+ // 1 week
1263
+ }
1264
+ }
1265
+ },
1266
+ {
1267
+ urlPattern: /\.(?:jpg|jpeg|gif|png|svg|ico|webp)$/i,
1268
+ handler: "StaleWhileRevalidate",
1269
+ options: {
1270
+ cacheName: "static-image-assets",
1271
+ expiration: {
1272
+ maxEntries: 64,
1273
+ maxAgeSeconds: 24 * 60 * 60
1274
+ // 24 hours
1275
+ }
1276
+ }
1277
+ },
1278
+ {
1279
+ urlPattern: /\/_next\/image\?url=.+$/i,
1280
+ handler: "StaleWhileRevalidate",
1281
+ options: {
1282
+ cacheName: "next-image",
1283
+ expiration: {
1284
+ maxEntries: 64,
1285
+ maxAgeSeconds: 24 * 60 * 60
1286
+ // 24 hours
1287
+ }
1288
+ }
1289
+ },
1290
+ {
1291
+ urlPattern: /\.(?:mp3|wav|ogg)$/i,
1292
+ handler: "CacheFirst",
1293
+ options: {
1294
+ rangeRequests: true,
1295
+ cacheName: "static-audio-assets",
1296
+ expiration: {
1297
+ maxEntries: 32,
1298
+ maxAgeSeconds: 24 * 60 * 60
1299
+ // 24 hours
1300
+ }
1301
+ }
1302
+ },
1303
+ {
1304
+ urlPattern: /\.(?:mp4)$/i,
1305
+ handler: "CacheFirst",
1306
+ options: {
1307
+ rangeRequests: true,
1308
+ cacheName: "static-video-assets",
1309
+ expiration: {
1310
+ maxEntries: 32,
1311
+ maxAgeSeconds: 24 * 60 * 60
1312
+ // 24 hours
1313
+ }
1314
+ }
1315
+ },
1316
+ {
1317
+ urlPattern: /\.(?:js)$/i,
1318
+ handler: "StaleWhileRevalidate",
1319
+ options: {
1320
+ cacheName: "static-js-assets",
1321
+ expiration: {
1322
+ maxEntries: 32,
1323
+ maxAgeSeconds: 24 * 60 * 60
1324
+ // 24 hours
1325
+ }
1326
+ }
1327
+ },
1328
+ {
1329
+ urlPattern: /\.(?:css|less)$/i,
1330
+ handler: "StaleWhileRevalidate",
1331
+ options: {
1332
+ cacheName: "static-style-assets",
1333
+ expiration: {
1334
+ maxEntries: 32,
1335
+ maxAgeSeconds: 24 * 60 * 60
1336
+ // 24 hours
1337
+ }
1338
+ }
1339
+ },
1340
+ {
1341
+ urlPattern: /\/_next\/data\/.+\/.+\.json$/i,
1342
+ handler: "StaleWhileRevalidate",
1343
+ options: {
1344
+ cacheName: "next-data",
1345
+ expiration: {
1346
+ maxEntries: 32,
1347
+ maxAgeSeconds: 24 * 60 * 60
1348
+ // 24 hours
1349
+ }
1350
+ }
1351
+ },
1352
+ {
1353
+ urlPattern: /\.(?:json|xml|csv)$/i,
1354
+ handler: "NetworkFirst",
1355
+ options: {
1356
+ cacheName: "static-data-assets",
1357
+ expiration: {
1358
+ maxEntries: 32,
1359
+ maxAgeSeconds: 24 * 60 * 60
1360
+ // 24 hours
1361
+ }
1362
+ }
1363
+ },
1364
+ {
1365
+ urlPattern: ({ url }) => {
1366
+ const isSameOrigin = self.origin === url.origin;
1367
+ if (!isSameOrigin) return false;
1368
+ const pathname = url.pathname;
1369
+ if (pathname.startsWith("/api/")) return false;
1370
+ return true;
1371
+ },
1372
+ handler: "NetworkFirst",
1373
+ options: {
1374
+ cacheName: "pages",
1375
+ expiration: {
1376
+ maxEntries: 32,
1377
+ maxAgeSeconds: 24 * 60 * 60
1378
+ // 24 hours
1379
+ }
1380
+ }
1381
+ }
1382
+ ];
1383
+ function createApiCacheRule(apiUrl, options = {}) {
1384
+ const {
1385
+ strategy = "NetworkFirst",
1386
+ maxAge = 300,
1387
+ maxEntries = 50,
1388
+ cacheName = "api-cache"
1389
+ } = options;
1390
+ return {
1391
+ urlPattern: new RegExp(`^${apiUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/.*`, "i"),
1392
+ handler: strategy,
1393
+ options: {
1394
+ cacheName,
1395
+ expiration: {
1396
+ maxEntries,
1397
+ maxAgeSeconds: maxAge
1398
+ },
1399
+ networkTimeoutSeconds: 10
1400
+ }
1401
+ };
1402
+ }
1403
+ function createStaticAssetRule(extensions, options = {}) {
1404
+ const {
1405
+ strategy = "CacheFirst",
1406
+ maxAge = 86400,
1407
+ maxEntries = 64,
1408
+ cacheName = "static-assets"
1409
+ } = options;
1410
+ const pattern = extensions.map((ext) => ext.replace(".", "")).join("|");
1411
+ return {
1412
+ urlPattern: new RegExp(`\\.(?:${pattern})$`, "i"),
1413
+ handler: strategy,
1414
+ options: {
1415
+ cacheName,
1416
+ expiration: {
1417
+ maxEntries,
1418
+ maxAgeSeconds: maxAge
1419
+ }
1420
+ }
1421
+ };
1422
+ }
1423
+ function createCdnCacheRule(cdnUrl, options = {}) {
1424
+ const {
1425
+ strategy = "CacheFirst",
1426
+ maxAge = 2592e3,
1427
+ // 30 days
1428
+ maxEntries = 100,
1429
+ cacheName = "cdn-cache"
1430
+ } = options;
1431
+ return {
1432
+ urlPattern: new RegExp(`^${cdnUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}/.*`, "i"),
1433
+ handler: strategy,
1434
+ options: {
1435
+ cacheName,
1436
+ expiration: {
1437
+ maxEntries,
1438
+ maxAgeSeconds: maxAge
1439
+ },
1440
+ cacheableResponse: {
1441
+ statuses: [0, 200]
1442
+ }
1443
+ }
1444
+ };
1445
+ }
1446
+
1174
1447
  // src/config/createNextConfig.ts
1175
1448
  function createBaseNextConfig(options = {}) {
1176
1449
  const basePath = getBasePath(options.isDefaultCfgAdmin);
@@ -1294,7 +1567,7 @@ function createBaseNextConfig(options = {}) {
1294
1567
  return config;
1295
1568
  }
1296
1569
  };
1297
- const finalConfig = deepMerge(baseConfig, options);
1570
+ let finalConfig = deepMerge(baseConfig, options);
1298
1571
  delete finalConfig.optimizePackageImports;
1299
1572
  delete finalConfig.isDefaultCfgAdmin;
1300
1573
  delete finalConfig.openBrowser;
@@ -1304,8 +1577,105 @@ function createBaseNextConfig(options = {}) {
1304
1577
  delete finalConfig.checkPackages;
1305
1578
  delete finalConfig.autoInstall;
1306
1579
  delete finalConfig.allowIframeFrom;
1580
+ if (options.pwa !== false) {
1581
+ const pwaOptions = typeof options.pwa === "object" ? options.pwa : {};
1582
+ finalConfig = withPWA(finalConfig, pwaOptions);
1583
+ }
1584
+ delete finalConfig.pwa;
1307
1585
  return finalConfig;
1308
1586
  }
1587
+
1588
+ // src/config/utils/manifest.ts
1589
+ function createManifestMetadata(config) {
1590
+ return {
1591
+ manifest: "/manifest.json",
1592
+ themeColor: config.themeColor || "#000000",
1593
+ appleWebApp: {
1594
+ capable: true,
1595
+ statusBarStyle: "default",
1596
+ title: config.shortName || config.name
1597
+ },
1598
+ applicationName: config.name,
1599
+ formatDetection: {
1600
+ telephone: false
1601
+ },
1602
+ viewport: {
1603
+ width: "device-width",
1604
+ initialScale: 1,
1605
+ maximumScale: 1
1606
+ }
1607
+ };
1608
+ }
1609
+ function createManifest(config) {
1610
+ return () => {
1611
+ let manifestIcons;
1612
+ if (Array.isArray(config.icons)) {
1613
+ manifestIcons = config.icons;
1614
+ } else if (config.icons) {
1615
+ const { logo192, logo384, logo512 } = config.icons;
1616
+ manifestIcons = [
1617
+ ...logo192 ? [
1618
+ {
1619
+ src: logo192,
1620
+ sizes: "192x192",
1621
+ type: "image/png",
1622
+ purpose: "maskable"
1623
+ }
1624
+ ] : [],
1625
+ ...logo384 ? [
1626
+ {
1627
+ src: logo384,
1628
+ sizes: "384x384",
1629
+ type: "image/png"
1630
+ }
1631
+ ] : [],
1632
+ ...logo512 ? [
1633
+ {
1634
+ src: logo512,
1635
+ sizes: "512x512",
1636
+ type: "image/png"
1637
+ }
1638
+ ] : []
1639
+ ];
1640
+ } else {
1641
+ manifestIcons = [
1642
+ {
1643
+ src: "/static/logos/192x192.png",
1644
+ sizes: "192x192",
1645
+ type: "image/png",
1646
+ purpose: "maskable"
1647
+ },
1648
+ {
1649
+ src: "/static/logos/384x384.png",
1650
+ sizes: "384x384",
1651
+ type: "image/png"
1652
+ },
1653
+ {
1654
+ src: "/static/logos/512x512.png",
1655
+ sizes: "512x512",
1656
+ type: "image/png"
1657
+ }
1658
+ ];
1659
+ }
1660
+ return {
1661
+ name: config.name,
1662
+ short_name: config.shortName || config.name,
1663
+ description: config.description || config.name,
1664
+ start_url: config.startUrl || "/",
1665
+ scope: config.scope || "/",
1666
+ display: config.display || "standalone",
1667
+ orientation: config.orientation || "portrait",
1668
+ background_color: config.backgroundColor || "#000000",
1669
+ theme_color: config.themeColor || "#ffffff",
1670
+ lang: config.lang || "en",
1671
+ dir: config.dir || "ltr",
1672
+ icons: manifestIcons
1673
+ };
1674
+ };
1675
+ }
1676
+ function generateManifest(config) {
1677
+ return createManifest(config)();
1678
+ }
1309
1679
  export {
1310
1680
  AI_DOCS_HINT,
1311
1681
  DEFAULT_OPTIMIZE_PACKAGES,
@@ -1327,10 +1697,17 @@ export {
1327
1697
  checkForUpdate,
1328
1698
  checkForUpdates,
1329
1699
  checkPackages,
1700
+ createApiCacheRule,
1330
1701
  createBaseNextConfig,
1702
+ createCdnCacheRule,
1703
+ createManifest,
1704
+ createManifestMetadata,
1705
+ createStaticAssetRule,
1331
1706
  deepMerge,
1707
+ defaultRuntimeCaching,
1332
1708
  detectPackageManager,
1333
1709
  fetchLatestVersion,
1710
+ generateManifest,
1334
1711
  getApiUrl,
1335
1712
  getBasePath,
1336
1713
  getCurrentVersion,
@@ -1345,6 +1722,7 @@ export {
1345
1722
  isCI,
1346
1723
  isCompressionAvailable,
1347
1724
  isDev,
1725
+ isPWAAvailable,
1348
1726
  isPackageInstalled,
1349
1727
  isProduction,
1350
1728
  isStaticBuild,
@@ -1352,6 +1730,7 @@ export {
1352
1730
  resetDevStartupState,
1353
1731
  resetInstallerPreferences,
1354
1732
  resetUpdaterPreferences,
1355
- updatePackagesWithProgress
1733
+ updatePackagesWithProgress,
1734
+ withPWA
1356
1735
  };
1357
1736
  //# sourceMappingURL=index.mjs.map