@djangocfg/nextjs 2.1.42 → 2.1.43

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.42",
17
+ version: "2.1.43",
18
18
  description: "Next.js server utilities: sitemap, health, OG images, contact forms, navigation, config",
19
19
  keywords: [
20
20
  "nextjs",
@@ -289,309 +289,6 @@ function createHealthHandler(config = {}) {
289
289
  import { ImageResponse } from "next/og";
290
290
  import { NextRequest } from "next/server";
291
291
 
292
- // src/og-image/utils/fonts.ts
293
- async function loadGoogleFont(font, text, weight = 700) {
294
- let url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weight}`;
295
- if (text) {
296
- url += `&text=${encodeURIComponent(text)}`;
297
- }
298
- try {
299
- const css = await fetch(url, {
300
- headers: {
301
- // Required to get TTF format instead of WOFF2
302
- "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
303
- }
304
- }).then((res) => res.text());
305
- const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
306
- if (!resource || !resource[1]) {
307
- throw new Error(`Failed to parse font URL from CSS for font: ${font}`);
308
- }
309
- const response = await fetch(resource[1]);
310
- if (response.status !== 200) {
311
- throw new Error(`Failed to fetch font data: HTTP ${response.status}`);
312
- }
313
- return await response.arrayBuffer();
314
- } catch (error) {
315
- console.error(`Error loading Google Font "${font}":`, error);
316
- throw new Error(`Failed to load font "${font}": ${error instanceof Error ? error.message : "Unknown error"}`);
317
- }
318
- }
319
- async function loadGoogleFonts(fonts) {
320
- const fontConfigs = await Promise.all(
321
- fonts.map(async ({ family, weight = 700, style = "normal", text }) => {
322
- const data = await loadGoogleFont(family, text, weight);
323
- return {
324
- name: family,
325
- weight,
326
- style,
327
- data
328
- };
329
- })
330
- );
331
- return fontConfigs;
332
- }
333
- function createFontLoader() {
334
- const cache = /* @__PURE__ */ new Map();
335
- return {
336
- /**
337
- * Load a font with caching
338
- */
339
- async load(family, weight = 700, text) {
340
- const cacheKey = `${family}-${weight}-${text || "all"}`;
341
- if (!cache.has(cacheKey)) {
342
- cache.set(cacheKey, loadGoogleFont(family, text, weight));
343
- }
344
- return cache.get(cacheKey);
345
- },
346
- /**
347
- * Clear the cache
348
- */
349
- clear() {
350
- cache.clear();
351
- },
352
- /**
353
- * Get cache size
354
- */
355
- size() {
356
- return cache.size;
357
- }
358
- };
359
- }
360
-
361
- // src/og-image/utils/url.ts
362
- var DEFAULT_OG_IMAGE_BASE_URL = "https://djangocfg.com/api/og";
363
- function encodeBase64(str) {
364
- if (typeof Buffer !== "undefined") {
365
- return Buffer.from(str, "utf-8").toString("base64");
366
- }
367
- return btoa(unescape(encodeURIComponent(str)));
368
- }
369
- function decodeBase64(str) {
370
- if (typeof Buffer !== "undefined") {
371
- return Buffer.from(str, "base64").toString("utf-8");
372
- }
373
- try {
374
- const binaryString = atob(str);
375
- return decodeURIComponent(
376
- binaryString.split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
377
- );
378
- } catch (error) {
379
- return decodeURIComponent(escape(atob(str)));
380
- }
381
- }
382
- function generateOgImageUrl(params, options = {}) {
383
- const {
384
- baseUrl = DEFAULT_OG_IMAGE_BASE_URL,
385
- useBase64 = true
386
- } = options;
387
- if (useBase64) {
388
- const cleanParams = {};
389
- Object.entries(params).forEach(([key, value]) => {
390
- if (value !== void 0 && value !== null && value !== "") {
391
- cleanParams[key] = value;
392
- }
393
- });
394
- const jsonString = JSON.stringify(cleanParams);
395
- const base64Data = encodeBase64(jsonString);
396
- return `${baseUrl}/${base64Data}`;
397
- } else {
398
- const searchParams = new URLSearchParams();
399
- Object.entries(params).forEach(([key, value]) => {
400
- if (value !== void 0 && value !== null && value !== "") {
401
- searchParams.append(key, String(value));
402
- }
403
- });
404
- const query = searchParams.toString();
405
- return query ? `${baseUrl}?${query}` : baseUrl;
406
- }
407
- }
408
- function getAbsoluteOgImageUrl(relativePath, siteUrl) {
409
- if (relativePath.startsWith("http://") || relativePath.startsWith("https://")) {
410
- return relativePath;
411
- }
412
- const cleanSiteUrl = siteUrl.replace(/\/$/, "");
413
- const cleanPath = relativePath.startsWith("/") ? relativePath : `/${relativePath}`;
414
- return `${cleanSiteUrl}${cleanPath}`;
415
- }
416
- function createOgImageUrlBuilder(defaults = {}, options = {}) {
417
- return (params) => {
418
- return generateOgImageUrl(
419
- { ...defaults, ...params },
420
- options
421
- );
422
- };
423
- }
424
- function parseOgImageUrl(url) {
425
- try {
426
- const urlObj = new URL(url, "http://dummy.com");
427
- const params = {};
428
- urlObj.searchParams.forEach((value, key) => {
429
- params[key] = value;
430
- });
431
- return params;
432
- } catch {
433
- return {};
434
- }
435
- }
436
- function parseOgImageData(searchParams) {
437
- try {
438
- let params;
439
- if (searchParams instanceof URLSearchParams) {
440
- params = {};
441
- for (const [key, value] of searchParams.entries()) {
442
- params[key] = value;
443
- }
444
- } else {
445
- params = searchParams;
446
- }
447
- if (process.env.NODE_ENV === "development") {
448
- console.log("[parseOgImageData] Input params keys:", Object.keys(params));
449
- console.log("[parseOgImageData] Input params:", params);
450
- }
451
- const dataParam = params.data;
452
- if (dataParam && typeof dataParam === "string" && dataParam.trim() !== "") {
453
- if (process.env.NODE_ENV === "development") {
454
- console.log("[parseOgImageData] Found data param, length:", dataParam.length);
455
- }
456
- try {
457
- const decoded = decodeBase64(dataParam);
458
- if (process.env.NODE_ENV === "development") {
459
- console.log("[parseOgImageData] Decoded string:", decoded.substring(0, 100));
460
- }
461
- const parsed = JSON.parse(decoded);
462
- if (process.env.NODE_ENV === "development") {
463
- console.log("[parseOgImageData] Parsed JSON:", parsed);
464
- }
465
- const result2 = {};
466
- for (const [key, value] of Object.entries(parsed)) {
467
- if (value !== void 0 && value !== null) {
468
- result2[key] = String(value);
469
- }
470
- }
471
- if (process.env.NODE_ENV === "development") {
472
- console.log("[parseOgImageData] Result:", result2);
473
- }
474
- return result2;
475
- } catch (decodeError) {
476
- console.error("[parseOgImageData] Error decoding/parsing data param:", decodeError);
477
- if (decodeError instanceof Error) {
478
- console.error("[parseOgImageData] Error message:", decodeError.message);
479
- }
480
- }
481
- } else {
482
- if (process.env.NODE_ENV === "development") {
483
- console.log("[parseOgImageData] No data param found or empty");
484
- }
485
- }
486
- const result = {};
487
- for (const [key, value] of Object.entries(params)) {
488
- if (key !== "data" && value !== void 0 && value !== null) {
489
- result[key] = Array.isArray(value) ? value[0] : String(value);
490
- }
491
- }
492
- if (process.env.NODE_ENV === "development") {
493
- console.log("[parseOgImageData] Fallback result:", result);
494
- }
495
- return result;
496
- } catch (error) {
497
- console.error("[parseOgImageData] Unexpected error:", error);
498
- return {};
499
- }
500
- }
501
-
502
- // src/og-image/utils/metadata.ts
503
- function extractTitle(metadata) {
504
- if (typeof metadata.title === "string") {
505
- return metadata.title;
506
- }
507
- if (metadata.title) {
508
- if ("default" in metadata.title) {
509
- return metadata.title.default;
510
- }
511
- if ("absolute" in metadata.title) {
512
- return metadata.title.absolute;
513
- }
514
- }
515
- return "";
516
- }
517
- function extractDescription(metadata) {
518
- if (typeof metadata.description === "string") {
519
- return metadata.description;
520
- }
521
- return "";
522
- }
523
- function getSiteUrl() {
524
- if (typeof process !== "undefined" && process.env.NEXT_PUBLIC_SITE_URL) {
525
- return process.env.NEXT_PUBLIC_SITE_URL;
526
- }
527
- return "";
528
- }
529
- function generateOgImageMetadata(metadata, ogImageParams, options = {}) {
530
- const {
531
- ogImageBaseUrl = "https://djangocfg.com/api/og",
532
- siteUrl: providedSiteUrl,
533
- defaultParams = {},
534
- useBase64 = true
535
- } = options;
536
- const siteUrl = providedSiteUrl && providedSiteUrl !== "undefined" ? providedSiteUrl : getSiteUrl();
537
- const extractedTitle = extractTitle(metadata);
538
- const extractedDescription = extractDescription(metadata);
539
- const finalOgImageParams = {
540
- ...defaultParams,
541
- title: ogImageParams?.title || extractedTitle || defaultParams.title || "",
542
- description: ogImageParams?.description || extractedDescription || defaultParams.description || "",
543
- ...ogImageParams
544
- };
545
- const imageAlt = finalOgImageParams.title || finalOgImageParams.siteName;
546
- const relativeOgImageUrl = generateOgImageUrl(
547
- finalOgImageParams,
548
- { baseUrl: ogImageBaseUrl, useBase64 }
549
- );
550
- const ogImageUrl = siteUrl ? getAbsoluteOgImageUrl(relativeOgImageUrl, siteUrl) : relativeOgImageUrl;
551
- const existingOgImages = metadata.openGraph?.images ? Array.isArray(metadata.openGraph.images) ? metadata.openGraph.images : [metadata.openGraph.images] : [];
552
- const existingTwitterImages = metadata.twitter?.images ? Array.isArray(metadata.twitter.images) ? metadata.twitter.images : [metadata.twitter.images] : [];
553
- const finalMetadata = {
554
- ...metadata,
555
- openGraph: {
556
- ...metadata.openGraph,
557
- images: [
558
- ...existingOgImages,
559
- {
560
- url: ogImageUrl,
561
- width: 1200,
562
- height: 630,
563
- alt: imageAlt
564
- }
565
- ]
566
- },
567
- twitter: {
568
- ...metadata.twitter,
569
- card: "summary_large_image",
570
- images: [
571
- ...existingTwitterImages,
572
- {
573
- url: ogImageUrl,
574
- alt: imageAlt
575
- }
576
- ]
577
- }
578
- };
579
- if (!finalMetadata.metadataBase && siteUrl) {
580
- if (siteUrl.startsWith("http://") || siteUrl.startsWith("https://")) {
581
- try {
582
- finalMetadata.metadataBase = new URL(siteUrl);
583
- } catch (e) {
584
- }
585
- }
586
- }
587
- return finalMetadata;
588
- }
589
- function createOgImageMetadataGenerator(options) {
590
- return (metadata, ogImageParams) => {
591
- return generateOgImageMetadata(metadata, ogImageParams, options);
592
- };
593
- }
594
-
595
292
  // src/og-image/components/DefaultTemplate.tsx
596
293
  import { jsx, jsxs } from "react/jsx-runtime";
597
294
  function DefaultTemplate({
@@ -923,7 +620,310 @@ function LightTemplate({
923
620
  )
924
621
  ]
925
622
  }
926
- );
623
+ );
624
+ }
625
+
626
+ // src/og-image/utils/fonts.ts
627
+ async function loadGoogleFont(font, text, weight = 700) {
628
+ let url = `https://fonts.googleapis.com/css2?family=${font}:wght@${weight}`;
629
+ if (text) {
630
+ url += `&text=${encodeURIComponent(text)}`;
631
+ }
632
+ try {
633
+ const css = await fetch(url, {
634
+ headers: {
635
+ // Required to get TTF format instead of WOFF2
636
+ "User-Agent": "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; de-at) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1"
637
+ }
638
+ }).then((res) => res.text());
639
+ const resource = css.match(/src: url\((.+)\) format\('(opentype|truetype)'\)/);
640
+ if (!resource || !resource[1]) {
641
+ throw new Error(`Failed to parse font URL from CSS for font: ${font}`);
642
+ }
643
+ const response = await fetch(resource[1]);
644
+ if (response.status !== 200) {
645
+ throw new Error(`Failed to fetch font data: HTTP ${response.status}`);
646
+ }
647
+ return await response.arrayBuffer();
648
+ } catch (error) {
649
+ console.error(`Error loading Google Font "${font}":`, error);
650
+ throw new Error(`Failed to load font "${font}": ${error instanceof Error ? error.message : "Unknown error"}`);
651
+ }
652
+ }
653
+ async function loadGoogleFonts(fonts) {
654
+ const fontConfigs = await Promise.all(
655
+ fonts.map(async ({ family, weight = 700, style = "normal", text }) => {
656
+ const data = await loadGoogleFont(family, text, weight);
657
+ return {
658
+ name: family,
659
+ weight,
660
+ style,
661
+ data
662
+ };
663
+ })
664
+ );
665
+ return fontConfigs;
666
+ }
667
+ function createFontLoader() {
668
+ const cache = /* @__PURE__ */ new Map();
669
+ return {
670
+ /**
671
+ * Load a font with caching
672
+ */
673
+ async load(family, weight = 700, text) {
674
+ const cacheKey = `${family}-${weight}-${text || "all"}`;
675
+ if (!cache.has(cacheKey)) {
676
+ cache.set(cacheKey, loadGoogleFont(family, text, weight));
677
+ }
678
+ return cache.get(cacheKey);
679
+ },
680
+ /**
681
+ * Clear the cache
682
+ */
683
+ clear() {
684
+ cache.clear();
685
+ },
686
+ /**
687
+ * Get cache size
688
+ */
689
+ size() {
690
+ return cache.size;
691
+ }
692
+ };
693
+ }
694
+
695
+ // src/og-image/utils/url.ts
696
+ var DEFAULT_OG_IMAGE_BASE_URL = "https://djangocfg.com/api/og";
697
+ function encodeBase64(str) {
698
+ if (typeof Buffer !== "undefined") {
699
+ return Buffer.from(str, "utf-8").toString("base64");
700
+ }
701
+ return btoa(unescape(encodeURIComponent(str)));
702
+ }
703
+ function decodeBase64(str) {
704
+ if (typeof Buffer !== "undefined") {
705
+ return Buffer.from(str, "base64").toString("utf-8");
706
+ }
707
+ try {
708
+ const binaryString = atob(str);
709
+ return decodeURIComponent(
710
+ binaryString.split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join("")
711
+ );
712
+ } catch (error) {
713
+ return decodeURIComponent(escape(atob(str)));
714
+ }
715
+ }
716
+ function generateOgImageUrl(params, options = {}) {
717
+ const {
718
+ baseUrl = DEFAULT_OG_IMAGE_BASE_URL,
719
+ useBase64 = true
720
+ } = options;
721
+ if (useBase64) {
722
+ const cleanParams = {};
723
+ Object.entries(params).forEach(([key, value]) => {
724
+ if (value !== void 0 && value !== null && value !== "") {
725
+ cleanParams[key] = value;
726
+ }
727
+ });
728
+ const jsonString = JSON.stringify(cleanParams);
729
+ const base64Data = encodeBase64(jsonString);
730
+ return `${baseUrl}/${base64Data}`;
731
+ } else {
732
+ const searchParams = new URLSearchParams();
733
+ Object.entries(params).forEach(([key, value]) => {
734
+ if (value !== void 0 && value !== null && value !== "") {
735
+ searchParams.append(key, String(value));
736
+ }
737
+ });
738
+ const query = searchParams.toString();
739
+ return query ? `${baseUrl}?${query}` : baseUrl;
740
+ }
741
+ }
742
+ function getAbsoluteOgImageUrl(relativePath, siteUrl) {
743
+ if (relativePath.startsWith("http://") || relativePath.startsWith("https://")) {
744
+ return relativePath;
745
+ }
746
+ const cleanSiteUrl = siteUrl.replace(/\/$/, "");
747
+ const cleanPath = relativePath.startsWith("/") ? relativePath : `/${relativePath}`;
748
+ return `${cleanSiteUrl}${cleanPath}`;
749
+ }
750
+ function createOgImageUrlBuilder(defaults = {}, options = {}) {
751
+ return (params) => {
752
+ return generateOgImageUrl(
753
+ { ...defaults, ...params },
754
+ options
755
+ );
756
+ };
757
+ }
758
+ function parseOgImageUrl(url) {
759
+ try {
760
+ const urlObj = new URL(url, "http://dummy.com");
761
+ const params = {};
762
+ urlObj.searchParams.forEach((value, key) => {
763
+ params[key] = value;
764
+ });
765
+ return params;
766
+ } catch {
767
+ return {};
768
+ }
769
+ }
770
+ function parseOgImageData(searchParams) {
771
+ try {
772
+ let params;
773
+ if (searchParams instanceof URLSearchParams) {
774
+ params = {};
775
+ for (const [key, value] of searchParams.entries()) {
776
+ params[key] = value;
777
+ }
778
+ } else {
779
+ params = searchParams;
780
+ }
781
+ if (process.env.NODE_ENV === "development") {
782
+ console.log("[parseOgImageData] Input params keys:", Object.keys(params));
783
+ console.log("[parseOgImageData] Input params:", params);
784
+ }
785
+ const dataParam = params.data;
786
+ if (dataParam && typeof dataParam === "string" && dataParam.trim() !== "") {
787
+ if (process.env.NODE_ENV === "development") {
788
+ console.log("[parseOgImageData] Found data param, length:", dataParam.length);
789
+ }
790
+ try {
791
+ const decoded = decodeBase64(dataParam);
792
+ if (process.env.NODE_ENV === "development") {
793
+ console.log("[parseOgImageData] Decoded string:", decoded.substring(0, 100));
794
+ }
795
+ const parsed = JSON.parse(decoded);
796
+ if (process.env.NODE_ENV === "development") {
797
+ console.log("[parseOgImageData] Parsed JSON:", parsed);
798
+ }
799
+ const result2 = {};
800
+ for (const [key, value] of Object.entries(parsed)) {
801
+ if (value !== void 0 && value !== null) {
802
+ result2[key] = String(value);
803
+ }
804
+ }
805
+ if (process.env.NODE_ENV === "development") {
806
+ console.log("[parseOgImageData] Result:", result2);
807
+ }
808
+ return result2;
809
+ } catch (decodeError) {
810
+ console.error("[parseOgImageData] Error decoding/parsing data param:", decodeError);
811
+ if (decodeError instanceof Error) {
812
+ console.error("[parseOgImageData] Error message:", decodeError.message);
813
+ }
814
+ }
815
+ } else {
816
+ if (process.env.NODE_ENV === "development") {
817
+ console.log("[parseOgImageData] No data param found or empty");
818
+ }
819
+ }
820
+ const result = {};
821
+ for (const [key, value] of Object.entries(params)) {
822
+ if (key !== "data" && value !== void 0 && value !== null) {
823
+ result[key] = Array.isArray(value) ? value[0] : String(value);
824
+ }
825
+ }
826
+ if (process.env.NODE_ENV === "development") {
827
+ console.log("[parseOgImageData] Fallback result:", result);
828
+ }
829
+ return result;
830
+ } catch (error) {
831
+ console.error("[parseOgImageData] Unexpected error:", error);
832
+ return {};
833
+ }
834
+ }
835
+
836
+ // src/og-image/utils/metadata.ts
837
+ function extractTitle(metadata) {
838
+ if (typeof metadata.title === "string") {
839
+ return metadata.title;
840
+ }
841
+ if (metadata.title) {
842
+ if ("default" in metadata.title) {
843
+ return metadata.title.default;
844
+ }
845
+ if ("absolute" in metadata.title) {
846
+ return metadata.title.absolute;
847
+ }
848
+ }
849
+ return "";
850
+ }
851
+ function extractDescription(metadata) {
852
+ if (typeof metadata.description === "string") {
853
+ return metadata.description;
854
+ }
855
+ return "";
856
+ }
857
+ function getSiteUrl() {
858
+ if (typeof process !== "undefined" && process.env.NEXT_PUBLIC_SITE_URL) {
859
+ return process.env.NEXT_PUBLIC_SITE_URL;
860
+ }
861
+ return "";
862
+ }
863
+ function generateOgImageMetadata(metadata, ogImageParams, options = {}) {
864
+ const {
865
+ ogImageBaseUrl = "https://djangocfg.com/api/og",
866
+ siteUrl: providedSiteUrl,
867
+ defaultParams = {},
868
+ useBase64 = true
869
+ } = options;
870
+ const siteUrl = providedSiteUrl && providedSiteUrl !== "undefined" ? providedSiteUrl : getSiteUrl();
871
+ const extractedTitle = extractTitle(metadata);
872
+ const extractedDescription = extractDescription(metadata);
873
+ const finalOgImageParams = {
874
+ ...defaultParams,
875
+ title: ogImageParams?.title || extractedTitle || defaultParams.title || "",
876
+ description: ogImageParams?.description || extractedDescription || defaultParams.description || "",
877
+ ...ogImageParams
878
+ };
879
+ const imageAlt = finalOgImageParams.title || finalOgImageParams.siteName;
880
+ const relativeOgImageUrl = generateOgImageUrl(
881
+ finalOgImageParams,
882
+ { baseUrl: ogImageBaseUrl, useBase64 }
883
+ );
884
+ const ogImageUrl = siteUrl ? getAbsoluteOgImageUrl(relativeOgImageUrl, siteUrl) : relativeOgImageUrl;
885
+ const existingOgImages = metadata.openGraph?.images ? Array.isArray(metadata.openGraph.images) ? metadata.openGraph.images : [metadata.openGraph.images] : [];
886
+ const existingTwitterImages = metadata.twitter?.images ? Array.isArray(metadata.twitter.images) ? metadata.twitter.images : [metadata.twitter.images] : [];
887
+ const finalMetadata = {
888
+ ...metadata,
889
+ openGraph: {
890
+ ...metadata.openGraph,
891
+ images: [
892
+ ...existingOgImages,
893
+ {
894
+ url: ogImageUrl,
895
+ width: 1200,
896
+ height: 630,
897
+ alt: imageAlt
898
+ }
899
+ ]
900
+ },
901
+ twitter: {
902
+ ...metadata.twitter,
903
+ card: "summary_large_image",
904
+ images: [
905
+ ...existingTwitterImages,
906
+ {
907
+ url: ogImageUrl,
908
+ alt: imageAlt
909
+ }
910
+ ]
911
+ }
912
+ };
913
+ if (!finalMetadata.metadataBase && siteUrl) {
914
+ if (siteUrl.startsWith("http://") || siteUrl.startsWith("https://")) {
915
+ try {
916
+ finalMetadata.metadataBase = new URL(siteUrl);
917
+ } catch (e) {
918
+ }
919
+ }
920
+ }
921
+ return finalMetadata;
922
+ }
923
+ function createOgImageMetadataGenerator(options) {
924
+ return (metadata, ogImageParams) => {
925
+ return generateOgImageMetadata(metadata, ogImageParams, options);
926
+ };
927
927
  }
928
928
 
929
929
  // src/og-image/route.tsx
@@ -1157,6 +1157,37 @@ function routesToMenuItems(routes, groupName) {
1157
1157
  }));
1158
1158
  }
1159
1159
 
1160
+ // src/pwa/plugin.ts
1161
+ import { consola } from "consola";
1162
+ function withPWA(nextConfig, options = {}) {
1163
+ const isDev2 = process.env.NODE_ENV === "development";
1164
+ const isStaticBuild2 = process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
1165
+ const shouldDisable = options.disable !== void 0 ? options.disable : isDev2 || isStaticBuild2;
1166
+ const defaultOptions = {
1167
+ swSrc: "app/sw.ts",
1168
+ swDest: "public/sw.js",
1169
+ disable: shouldDisable,
1170
+ cacheOnNavigation: true,
1171
+ reloadOnOnline: true,
1172
+ ...options
1173
+ };
1174
+ try {
1175
+ const withSerwistInit = __require("@serwist/next").default;
1176
+ const withSerwist = withSerwistInit({
1177
+ swSrc: defaultOptions.swSrc,
1178
+ swDest: defaultOptions.swDest,
1179
+ disable: defaultOptions.disable,
1180
+ cacheOnNavigation: defaultOptions.cacheOnNavigation,
1181
+ reloadOnOnline: defaultOptions.reloadOnOnline,
1182
+ ...defaultOptions.serwistOptions
1183
+ });
1184
+ return withSerwist(nextConfig);
1185
+ } catch (error) {
1186
+ consola.error("Failed to configure Serwist:", error);
1187
+ return nextConfig;
1188
+ }
1189
+ }
1190
+
1160
1191
  // src/config/constants.ts
1161
1192
  var PACKAGE_NAME = "@djangocfg/nextjs";
1162
1193
  var VERSION_CACHE_TTL_MS = 60 * 60 * 1e3;
@@ -1193,26 +1224,9 @@ var DEFAULT_OPTIMIZE_PACKAGES = [
1193
1224
  "recharts"
1194
1225
  ];
1195
1226
 
1196
- // src/config/utils/deepMerge.ts
1197
- function deepMerge(target, source) {
1198
- const output = { ...target };
1199
- for (const key in source) {
1200
- if (source[key] === void 0) continue;
1201
- if (Array.isArray(source[key])) {
1202
- output[key] = source[key];
1203
- } else if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
1204
- const targetValue = output[key];
1205
- if (targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
1206
- output[key] = deepMerge(targetValue, source[key]);
1207
- } else {
1208
- output[key] = source[key];
1209
- }
1210
- } else {
1211
- output[key] = source[key];
1212
- }
1213
- }
1214
- return output;
1215
- }
1227
+ // src/config/packages/checker.ts
1228
+ import { createRequire } from "module";
1229
+ import { join } from "path";
1216
1230
 
1217
1231
  // src/config/utils/env.ts
1218
1232
  var isStaticBuild = process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
@@ -1230,124 +1244,6 @@ function getSiteUrl2() {
1230
1244
  return isStaticBuild ? "" : process.env.NEXT_PUBLIC_SITE_URL || "";
1231
1245
  }
1232
1246
 
1233
- // src/config/plugins/devStartup.ts
1234
- import chalk4 from "chalk";
1235
-
1236
- // src/ai/constants.ts
1237
- var MCP_BASE_URL = "https://mcp.djangocfg.com";
1238
- var MCP_SERVER_URL = `${MCP_BASE_URL}/mcp`;
1239
- var MCP_API_URL = `${MCP_BASE_URL}/api/search`;
1240
- var API_SEARCH_ENDPOINT = "/api/search";
1241
- var API_INFO_ENDPOINT = "/api/info";
1242
- var DEFAULT_TIMEOUT = 1e4;
1243
- var AI_DOCS_HINT = `\u{1F916} AI Docs: ${MCP_SERVER_URL} | pnpm ai-docs search "query"`;
1244
- var AI_HINT = `
1245
- DjangoCFG Documentation is available via MCP server.
1246
-
1247
- To get help with DjangoCFG configuration:
1248
- 1. Use the MCP server: ${MCP_SERVER_URL}
1249
- 2. Or search directly: ${MCP_API_URL}?q=YOUR_QUERY&limit=5
1250
-
1251
- Example queries:
1252
- - "How to configure PostgreSQL database?"
1253
- - "What is DatabaseConfig?"
1254
- - "How to setup Redis cache?"
1255
- - "Email configuration with SMTP"
1256
- `;
1257
-
1258
- // src/config/utils/version.ts
1259
- import chalk from "chalk";
1260
- import semver from "semver";
1261
- import consola from "consola";
1262
- import Conf from "conf";
1263
- var versionCache = new Conf({
1264
- projectName: "djangocfg-nextjs",
1265
- projectVersion: "1.0.0"
1266
- });
1267
- function getCurrentVersion() {
1268
- try {
1269
- const packageJson = require_package();
1270
- return packageJson.version || null;
1271
- } catch {
1272
- return null;
1273
- }
1274
- }
1275
- async function fetchLatestVersion() {
1276
- const lastCheck = versionCache.get("lastCheck") || 0;
1277
- const cachedVersion = versionCache.get("latestVersion");
1278
- if (cachedVersion && Date.now() - lastCheck < VERSION_CACHE_TTL_MS) {
1279
- return cachedVersion;
1280
- }
1281
- try {
1282
- const https = await import("https");
1283
- return new Promise((resolve) => {
1284
- const req = https.get(
1285
- `https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
1286
- { timeout: 5e3 },
1287
- (res) => {
1288
- let data = "";
1289
- res.on("data", (chunk) => {
1290
- data += chunk;
1291
- });
1292
- res.on("end", () => {
1293
- try {
1294
- const json = JSON.parse(data);
1295
- const version = json.version || null;
1296
- if (version) {
1297
- versionCache.set("latestVersion", version);
1298
- versionCache.set("lastCheck", Date.now());
1299
- }
1300
- resolve(version);
1301
- } catch {
1302
- resolve(cachedVersion || null);
1303
- }
1304
- });
1305
- }
1306
- );
1307
- req.on("error", () => resolve(cachedVersion || null));
1308
- req.on("timeout", () => {
1309
- req.destroy();
1310
- resolve(cachedVersion || null);
1311
- });
1312
- });
1313
- } catch {
1314
- return cachedVersion || null;
1315
- }
1316
- }
1317
- async function checkForUpdate() {
1318
- const currentVersion = getCurrentVersion();
1319
- if (!currentVersion) {
1320
- return { hasUpdate: false, currentVersion: null, latestVersion: null };
1321
- }
1322
- const latestVersion = await fetchLatestVersion();
1323
- const hasUpdate = !!(latestVersion && semver.gt(latestVersion, currentVersion));
1324
- return { hasUpdate, currentVersion, latestVersion };
1325
- }
1326
- function getUpdateCommand() {
1327
- return `pnpm add ${DJANGOCFG_PACKAGES.map((p) => `${p}@latest`).join(" ")}`;
1328
- }
1329
- async function printVersionInfo() {
1330
- const { hasUpdate, currentVersion, latestVersion } = await checkForUpdate();
1331
- if (!currentVersion) return;
1332
- consola.box(`\u{1F4E6} @djangocfg/nextjs v${currentVersion}`);
1333
- if (hasUpdate && latestVersion) {
1334
- consola.warn(`Update Available! ${chalk.red(currentVersion)} \u2192 ${chalk.green(latestVersion)}`);
1335
- consola.info(`Run: ${chalk.cyan(getUpdateCommand())}`);
1336
- console.log("");
1337
- }
1338
- }
1339
-
1340
- // src/config/packages/installer.ts
1341
- import { execSync, spawn } from "child_process";
1342
- import { createInterface } from "readline";
1343
- import chalk2 from "chalk";
1344
- import consola2 from "consola";
1345
- import Conf2 from "conf";
1346
-
1347
- // src/config/packages/checker.ts
1348
- import { createRequire } from "module";
1349
- import { join } from "path";
1350
-
1351
1247
  // src/config/packages/definitions.ts
1352
1248
  var OPTIONAL_PACKAGES = [
1353
1249
  {
@@ -1426,23 +1322,105 @@ function checkPackages(packageNames) {
1426
1322
  });
1427
1323
  }
1428
1324
  }
1429
- return missing;
1325
+ return missing;
1326
+ }
1327
+ function getReasonText(pkg) {
1328
+ switch (pkg.condition) {
1329
+ case "static-build":
1330
+ return "Required for static build (NEXT_PUBLIC_STATIC_BUILD=true)";
1331
+ case "dev":
1332
+ return "Required for development mode";
1333
+ case "always":
1334
+ return "Required for all builds";
1335
+ default:
1336
+ return "Optional feature";
1337
+ }
1338
+ }
1339
+
1340
+ // src/config/plugins/compression.ts
1341
+ var DEFAULT_OPTIONS = {
1342
+ gzip: true,
1343
+ brotli: true,
1344
+ threshold: 8192,
1345
+ minRatio: 0.8,
1346
+ brotliLevel: 8
1347
+ };
1348
+ function addCompressionPlugins(config, options = {}) {
1349
+ if (!isPackageInstalled("compression-webpack-plugin")) {
1350
+ return false;
1351
+ }
1352
+ const opts = { ...DEFAULT_OPTIONS, ...options };
1353
+ try {
1354
+ const CompressionPlugin = __require("compression-webpack-plugin");
1355
+ if (!config.plugins) {
1356
+ config.plugins = [];
1357
+ }
1358
+ if (opts.gzip) {
1359
+ config.plugins.push(
1360
+ new CompressionPlugin({
1361
+ filename: "[path][base].gz",
1362
+ algorithm: "gzip",
1363
+ test: /\.(js|css|html|svg|json)$/,
1364
+ threshold: opts.threshold,
1365
+ minRatio: opts.minRatio
1366
+ })
1367
+ );
1368
+ }
1369
+ if (opts.brotli) {
1370
+ config.plugins.push(
1371
+ new CompressionPlugin({
1372
+ filename: "[path][base].br",
1373
+ algorithm: "brotliCompress",
1374
+ test: /\.(js|css|html|svg|json)$/,
1375
+ threshold: opts.threshold,
1376
+ minRatio: opts.minRatio,
1377
+ compressionOptions: {
1378
+ level: opts.brotliLevel
1379
+ }
1380
+ })
1381
+ );
1382
+ }
1383
+ return true;
1384
+ } catch (error) {
1385
+ return false;
1386
+ }
1430
1387
  }
1431
- function getReasonText(pkg) {
1432
- switch (pkg.condition) {
1433
- case "static-build":
1434
- return "Required for static build (NEXT_PUBLIC_STATIC_BUILD=true)";
1435
- case "dev":
1436
- return "Required for development mode";
1437
- case "always":
1438
- return "Required for all builds";
1439
- default:
1440
- return "Optional feature";
1441
- }
1388
+ function isCompressionAvailable() {
1389
+ return isPackageInstalled("compression-webpack-plugin");
1442
1390
  }
1443
1391
 
1392
+ // src/config/plugins/devStartup.ts
1393
+ import chalk4 from "chalk";
1394
+
1395
+ // src/ai/constants.ts
1396
+ var MCP_BASE_URL = "https://mcp.djangocfg.com";
1397
+ var MCP_SERVER_URL = `${MCP_BASE_URL}/mcp`;
1398
+ var MCP_API_URL = `${MCP_BASE_URL}/api/search`;
1399
+ var API_SEARCH_ENDPOINT = "/api/search";
1400
+ var API_INFO_ENDPOINT = "/api/info";
1401
+ var DEFAULT_TIMEOUT = 1e4;
1402
+ var AI_DOCS_HINT = `\u{1F916} AI Docs: ${MCP_SERVER_URL} | pnpm ai-docs search "query"`;
1403
+ var AI_HINT = `
1404
+ DjangoCFG Documentation is available via MCP server.
1405
+
1406
+ To get help with DjangoCFG configuration:
1407
+ 1. Use the MCP server: ${MCP_SERVER_URL}
1408
+ 2. Or search directly: ${MCP_API_URL}?q=YOUR_QUERY&limit=5
1409
+
1410
+ Example queries:
1411
+ - "How to configure PostgreSQL database?"
1412
+ - "What is DatabaseConfig?"
1413
+ - "How to setup Redis cache?"
1414
+ - "Email configuration with SMTP"
1415
+ `;
1416
+
1444
1417
  // src/config/packages/installer.ts
1445
- var installerCache = new Conf2({
1418
+ import chalk from "chalk";
1419
+ import { execSync, spawn } from "child_process";
1420
+ import Conf from "conf";
1421
+ import consola2 from "consola";
1422
+ import { createInterface } from "readline";
1423
+ var installerCache = new Conf({
1446
1424
  projectName: "djangocfg-nextjs-installer",
1447
1425
  projectVersion: "1.0.0"
1448
1426
  });
@@ -1536,7 +1514,7 @@ function createSpinner(text) {
1536
1514
  let currentText = text;
1537
1515
  const render = () => {
1538
1516
  const frame = SPINNER_FRAMES[frameIndex];
1539
- process.stdout.write(`\r${chalk2.cyan(frame)} ${currentText}`);
1517
+ process.stdout.write(`\r${chalk.cyan(frame)} ${currentText}`);
1540
1518
  frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
1541
1519
  };
1542
1520
  return {
@@ -1559,20 +1537,20 @@ function createSpinner(text) {
1559
1537
  succeed(text2) {
1560
1538
  if (interval) clearInterval(interval);
1561
1539
  if (process.stdout.isTTY) {
1562
- process.stdout.write(`\r${chalk2.green("\u2713")} ${text2 || currentText}
1540
+ process.stdout.write(`\r${chalk.green("\u2713")} ${text2 || currentText}
1563
1541
  `);
1564
1542
  } else {
1565
- console.log(` ${chalk2.green("\u2713")} ${text2 || currentText}`);
1543
+ console.log(` ${chalk.green("\u2713")} ${text2 || currentText}`);
1566
1544
  }
1567
1545
  return this;
1568
1546
  },
1569
1547
  fail(text2) {
1570
1548
  if (interval) clearInterval(interval);
1571
1549
  if (process.stdout.isTTY) {
1572
- process.stdout.write(`\r${chalk2.red("\u2717")} ${text2 || currentText}
1550
+ process.stdout.write(`\r${chalk.red("\u2717")} ${text2 || currentText}
1573
1551
  `);
1574
1552
  } else {
1575
- console.log(` ${chalk2.red("\u2717")} ${text2 || currentText}`);
1553
+ console.log(` ${chalk.red("\u2717")} ${text2 || currentText}`);
1576
1554
  }
1577
1555
  return this;
1578
1556
  },
@@ -1588,7 +1566,7 @@ function createSpinner(text) {
1588
1566
  async function installSinglePackage(pkg, pm, index, total) {
1589
1567
  const command = buildSingleInstallCommand(pkg.name, pkg.devDependency, pm);
1590
1568
  const progress = `[${index + 1}/${total}]`;
1591
- const spinner = createSpinner(`${chalk2.dim(progress)} Installing ${chalk2.cyan(pkg.name)}...`);
1569
+ const spinner = createSpinner(`${chalk.dim(progress)} Installing ${chalk.cyan(pkg.name)}...`);
1592
1570
  spinner.start();
1593
1571
  return new Promise((resolve) => {
1594
1572
  const [cmd, ...args] = command.split(" ");
@@ -1603,18 +1581,18 @@ async function installSinglePackage(pkg, pm, index, total) {
1603
1581
  });
1604
1582
  proc.on("close", (code) => {
1605
1583
  if (code === 0) {
1606
- spinner.succeed(`${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.green("installed")}`);
1584
+ spinner.succeed(`${chalk.dim(progress)} ${chalk.cyan(pkg.name)} ${chalk.green("installed")}`);
1607
1585
  resolve(true);
1608
1586
  } else {
1609
- spinner.fail(`${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.red("failed")}`);
1587
+ spinner.fail(`${chalk.dim(progress)} ${chalk.cyan(pkg.name)} ${chalk.red("failed")}`);
1610
1588
  if (stderr) {
1611
- console.log(chalk2.dim(` ${stderr.split("\n")[0]}`));
1589
+ console.log(chalk.dim(` ${stderr.split("\n")[0]}`));
1612
1590
  }
1613
1591
  resolve(false);
1614
1592
  }
1615
1593
  });
1616
1594
  proc.on("error", () => {
1617
- spinner.fail(`${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.red("failed")}`);
1595
+ spinner.fail(`${chalk.dim(progress)} ${chalk.cyan(pkg.name)} ${chalk.red("failed")}`);
1618
1596
  resolve(false);
1619
1597
  });
1620
1598
  });
@@ -1624,7 +1602,7 @@ async function installPackagesWithProgress(packages) {
1624
1602
  const pm = detectPackageManager();
1625
1603
  const total = packages.length;
1626
1604
  console.log("");
1627
- console.log(chalk2.bold(` Installing ${total} package${total > 1 ? "s" : ""}...`));
1605
+ console.log(chalk.bold(` Installing ${total} package${total > 1 ? "s" : ""}...`));
1628
1606
  console.log("");
1629
1607
  let successCount = 0;
1630
1608
  let failedPackages = [];
@@ -1655,7 +1633,7 @@ async function installPackages(packages) {
1655
1633
  if (packages.length === 0) return true;
1656
1634
  const pm = detectPackageManager();
1657
1635
  const command = buildInstallCommand(packages, pm);
1658
- consola2.info(`Installing: ${chalk2.cyan(packages.map((p) => p.name).join(", "))}`);
1636
+ consola2.info(`Installing: ${chalk.cyan(packages.map((p) => p.name).join(", "))}`);
1659
1637
  const spinner = createSpinner("Installing packages...");
1660
1638
  spinner.start();
1661
1639
  return new Promise((resolve) => {
@@ -1698,24 +1676,24 @@ async function checkAndInstallPackages(options = {}) {
1698
1676
  consola2.box("\u{1F4E6} Missing Optional Packages");
1699
1677
  console.log("");
1700
1678
  for (const pkg of toInstall) {
1701
- console.log(` ${chalk2.yellow("\u2022")} ${chalk2.bold(pkg.name)}`);
1702
- console.log(` ${chalk2.dim(pkg.description)}`);
1703
- console.log(` ${chalk2.dim(pkg.reason)}`);
1679
+ console.log(` ${chalk.yellow("\u2022")} ${chalk.bold(pkg.name)}`);
1680
+ console.log(` ${chalk.dim(pkg.description)}`);
1681
+ console.log(` ${chalk.dim(pkg.reason)}`);
1704
1682
  console.log("");
1705
1683
  }
1706
1684
  const pm = detectPackageManager();
1707
1685
  const command = buildInstallCommand(toInstall, pm);
1708
- console.log(` ${chalk2.cyan("Command:")} ${command}`);
1686
+ console.log(` ${chalk.cyan("Command:")} ${command}`);
1709
1687
  console.log("");
1710
1688
  installerCache.set("lastPrompt", Date.now());
1711
1689
  const shouldInstall = await askConfirmation(
1712
- `${chalk2.green("?")} Install these packages now? ${chalk2.dim("[Y/n]")} `
1690
+ `${chalk.green("?")} Install these packages now? ${chalk.dim("[Y/n]")} `
1713
1691
  );
1714
1692
  if (shouldInstall) {
1715
1693
  const success = await installPackages(toInstall);
1716
1694
  if (success) {
1717
1695
  const enableAuto = await askConfirmation(
1718
- `${chalk2.green("?")} Enable auto-install for future? ${chalk2.dim("[y/N]")} `
1696
+ `${chalk.green("?")} Enable auto-install for future? ${chalk.dim("[y/N]")} `
1719
1697
  );
1720
1698
  if (enableAuto) {
1721
1699
  installerCache.set("autoInstall", true);
@@ -1725,7 +1703,7 @@ async function checkAndInstallPackages(options = {}) {
1725
1703
  return success;
1726
1704
  }
1727
1705
  const skipPermanently = await askConfirmation(
1728
- `${chalk2.green("?")} Skip these packages in future prompts? ${chalk2.dim("[y/N]")} `
1706
+ `${chalk.green("?")} Skip these packages in future prompts? ${chalk.dim("[y/N]")} `
1729
1707
  );
1730
1708
  if (skipPermanently) {
1731
1709
  const currentSkip = installerCache.get("skipPackages") || [];
@@ -1739,7 +1717,7 @@ function printMissingPackagesInfo(packages) {
1739
1717
  const pm = detectPackageManager();
1740
1718
  const command = buildInstallCommand(packages, pm);
1741
1719
  consola2.warn(`Missing optional packages: ${packages.map((p) => p.name).join(", ")}`);
1742
- consola2.info(`Install with: ${chalk2.cyan(command)}`);
1720
+ consola2.info(`Install with: ${chalk.cyan(command)}`);
1743
1721
  }
1744
1722
  function resetInstallerPreferences() {
1745
1723
  installerCache.clear();
@@ -1747,15 +1725,15 @@ function resetInstallerPreferences() {
1747
1725
  }
1748
1726
 
1749
1727
  // src/config/packages/updater.ts
1728
+ import chalk2 from "chalk";
1750
1729
  import { spawn as spawn2 } from "child_process";
1751
- import { createInterface as createInterface2 } from "readline";
1730
+ import Conf2 from "conf";
1731
+ import consola3 from "consola";
1752
1732
  import { createRequire as createRequire2 } from "module";
1753
1733
  import { join as join2 } from "path";
1754
- import chalk3 from "chalk";
1755
- import consola3 from "consola";
1756
- import Conf3 from "conf";
1757
- import semver2 from "semver";
1758
- var updaterCache = new Conf3({
1734
+ import { createInterface as createInterface2 } from "readline";
1735
+ import semver from "semver";
1736
+ var updaterCache = new Conf2({
1759
1737
  projectName: "djangocfg-nextjs-updater",
1760
1738
  projectVersion: "1.0.0"
1761
1739
  });
@@ -1802,7 +1780,7 @@ function getInstalledVersion(packageName) {
1802
1780
  function shouldCheckUpdates(packageName) {
1803
1781
  return !isWorkspacePackage(packageName);
1804
1782
  }
1805
- async function fetchLatestVersion2(packageName) {
1783
+ async function fetchLatestVersion(packageName) {
1806
1784
  try {
1807
1785
  const https = await import("https");
1808
1786
  return new Promise((resolve) => {
@@ -1836,7 +1814,7 @@ async function fetchLatestVersion2(packageName) {
1836
1814
  }
1837
1815
  async function checkForUpdates(options = {}) {
1838
1816
  const results = [];
1839
- const masterLatest = await fetchLatestVersion2(PACKAGE_NAME);
1817
+ const masterLatest = await fetchLatestVersion(PACKAGE_NAME);
1840
1818
  if (!masterLatest) {
1841
1819
  return results;
1842
1820
  }
@@ -1849,7 +1827,7 @@ async function checkForUpdates(options = {}) {
1849
1827
  if (!current) {
1850
1828
  return null;
1851
1829
  }
1852
- const hasUpdate = !!(masterLatest && current && semver2.gt(masterLatest, current));
1830
+ const hasUpdate = !!(masterLatest && current && semver.gt(masterLatest, current));
1853
1831
  return { name, current, latest: masterLatest, hasUpdate };
1854
1832
  });
1855
1833
  const checkResults = await Promise.all(checks);
@@ -1875,7 +1853,7 @@ function createSpinner2(text) {
1875
1853
  let currentText = text;
1876
1854
  const render = () => {
1877
1855
  const frame = SPINNER_FRAMES2[frameIndex];
1878
- process.stdout.write(`\r${chalk3.cyan(frame)} ${currentText}`);
1856
+ process.stdout.write(`\r${chalk2.cyan(frame)} ${currentText}`);
1879
1857
  frameIndex = (frameIndex + 1) % SPINNER_FRAMES2.length;
1880
1858
  };
1881
1859
  return {
@@ -1895,20 +1873,20 @@ function createSpinner2(text) {
1895
1873
  succeed(text2) {
1896
1874
  if (interval) clearInterval(interval);
1897
1875
  if (process.stdout.isTTY) {
1898
- process.stdout.write(`\r${chalk3.green("\u2713")} ${text2 || currentText}
1876
+ process.stdout.write(`\r${chalk2.green("\u2713")} ${text2 || currentText}
1899
1877
  `);
1900
1878
  } else {
1901
- console.log(` ${chalk3.green("\u2713")} ${text2 || currentText}`);
1879
+ console.log(` ${chalk2.green("\u2713")} ${text2 || currentText}`);
1902
1880
  }
1903
1881
  return this;
1904
1882
  },
1905
1883
  fail(text2) {
1906
1884
  if (interval) clearInterval(interval);
1907
1885
  if (process.stdout.isTTY) {
1908
- process.stdout.write(`\r${chalk3.red("\u2717")} ${text2 || currentText}
1886
+ process.stdout.write(`\r${chalk2.red("\u2717")} ${text2 || currentText}
1909
1887
  `);
1910
1888
  } else {
1911
- console.log(` ${chalk3.red("\u2717")} ${text2 || currentText}`);
1889
+ console.log(` ${chalk2.red("\u2717")} ${text2 || currentText}`);
1912
1890
  }
1913
1891
  return this;
1914
1892
  },
@@ -1939,9 +1917,9 @@ async function askConfirmation2(question) {
1939
1917
  }
1940
1918
  async function updateSinglePackage(pkg, pm, index, total) {
1941
1919
  const progress = `[${index + 1}/${total}]`;
1942
- const versionInfo = `${chalk3.red(pkg.current)} \u2192 ${chalk3.green(pkg.latest)}`;
1920
+ const versionInfo = `${chalk2.red(pkg.current)} \u2192 ${chalk2.green(pkg.latest)}`;
1943
1921
  const spinner = createSpinner2(
1944
- `${chalk3.dim(progress)} Updating ${chalk3.cyan(pkg.name)} ${versionInfo}`
1922
+ `${chalk2.dim(progress)} Updating ${chalk2.cyan(pkg.name)} ${versionInfo}`
1945
1923
  );
1946
1924
  spinner.start();
1947
1925
  const command = pm === "pnpm" ? `pnpm add ${pkg.name}@latest` : pm === "yarn" ? `yarn add ${pkg.name}@latest` : `npm install ${pkg.name}@latest`;
@@ -1954,18 +1932,18 @@ async function updateSinglePackage(pkg, pm, index, total) {
1954
1932
  proc.on("close", (code) => {
1955
1933
  if (code === 0) {
1956
1934
  spinner.succeed(
1957
- `${chalk3.dim(progress)} ${chalk3.cyan(pkg.name)} ${chalk3.green(pkg.latest)}`
1935
+ `${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.green(pkg.latest)}`
1958
1936
  );
1959
1937
  resolve(true);
1960
1938
  } else {
1961
1939
  spinner.fail(
1962
- `${chalk3.dim(progress)} ${chalk3.cyan(pkg.name)} ${chalk3.red("failed")}`
1940
+ `${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.red("failed")}`
1963
1941
  );
1964
1942
  resolve(false);
1965
1943
  }
1966
1944
  });
1967
1945
  proc.on("error", () => {
1968
- spinner.fail(`${chalk3.dim(progress)} ${chalk3.cyan(pkg.name)} ${chalk3.red("failed")}`);
1946
+ spinner.fail(`${chalk2.dim(progress)} ${chalk2.cyan(pkg.name)} ${chalk2.red("failed")}`);
1969
1947
  resolve(false);
1970
1948
  });
1971
1949
  });
@@ -1975,7 +1953,7 @@ async function updatePackagesWithProgress(packages) {
1975
1953
  const pm = detectPackageManager();
1976
1954
  const total = packages.length;
1977
1955
  console.log("");
1978
- console.log(chalk3.bold(` Updating ${total} package${total > 1 ? "s" : ""}...`));
1956
+ console.log(chalk2.bold(` Updating ${total} package${total > 1 ? "s" : ""}...`));
1979
1957
  console.log("");
1980
1958
  let successCount = 0;
1981
1959
  const failedPackages = [];
@@ -2011,9 +1989,9 @@ async function checkAndUpdatePackages(options = {}) {
2011
1989
  forceCheckWorkspace: options.forceCheckWorkspace
2012
1990
  });
2013
1991
  spinner.stop();
2014
- console.log(chalk3.dim(` Found ${outdated.length} outdated package(s)`));
1992
+ console.log(chalk2.dim(` Found ${outdated.length} outdated package(s)`));
2015
1993
  if (outdated.length === 0) {
2016
- console.log(chalk3.green(" \u2713 All packages are up to date"));
1994
+ console.log(chalk2.green(" \u2713 All packages are up to date"));
2017
1995
  return true;
2018
1996
  }
2019
1997
  if (options.autoUpdate || updaterCache.get("autoUpdate")) {
@@ -2024,18 +2002,18 @@ async function checkAndUpdatePackages(options = {}) {
2024
2002
  console.log("");
2025
2003
  for (const pkg of outdated) {
2026
2004
  console.log(
2027
- ` ${chalk3.yellow("\u2022")} ${chalk3.bold(pkg.name)} ${chalk3.red(pkg.current)} \u2192 ${chalk3.green(pkg.latest)}`
2005
+ ` ${chalk2.yellow("\u2022")} ${chalk2.bold(pkg.name)} ${chalk2.red(pkg.current)} \u2192 ${chalk2.green(pkg.latest)}`
2028
2006
  );
2029
2007
  }
2030
2008
  console.log("");
2031
2009
  const shouldUpdate = await askConfirmation2(
2032
- `${chalk3.green("?")} Update these packages now? ${chalk3.dim("[Y/n]")} `
2010
+ `${chalk2.green("?")} Update these packages now? ${chalk2.dim("[Y/n]")} `
2033
2011
  );
2034
2012
  if (shouldUpdate) {
2035
2013
  const success = await updatePackagesWithProgress(outdated);
2036
2014
  if (success) {
2037
2015
  const enableAuto = await askConfirmation2(
2038
- `${chalk3.green("?")} Enable auto-update for future? ${chalk3.dim("[y/N]")} `
2016
+ `${chalk2.green("?")} Enable auto-update for future? ${chalk2.dim("[y/N]")} `
2039
2017
  );
2040
2018
  if (enableAuto) {
2041
2019
  updaterCache.set("autoUpdate", true);
@@ -2045,7 +2023,7 @@ async function checkAndUpdatePackages(options = {}) {
2045
2023
  return success;
2046
2024
  }
2047
2025
  const skipVersions = await askConfirmation2(
2048
- `${chalk3.green("?")} Skip these versions in future? ${chalk3.dim("[y/N]")} `
2026
+ `${chalk2.green("?")} Skip these versions in future? ${chalk2.dim("[y/N]")} `
2049
2027
  );
2050
2028
  if (skipVersions) {
2051
2029
  const skipped = updaterCache.get("skippedVersions") || {};
@@ -2064,6 +2042,88 @@ function resetUpdaterPreferences() {
2064
2042
  consola3.success("Updater preferences reset");
2065
2043
  }
2066
2044
 
2045
+ // src/config/utils/version.ts
2046
+ import chalk3 from "chalk";
2047
+ import Conf3 from "conf";
2048
+ import consola4 from "consola";
2049
+ import semver2 from "semver";
2050
+ var versionCache = new Conf3({
2051
+ projectName: "djangocfg-nextjs",
2052
+ projectVersion: "1.0.0"
2053
+ });
2054
+ function getCurrentVersion() {
2055
+ try {
2056
+ const packageJson = require_package();
2057
+ return packageJson.version || null;
2058
+ } catch {
2059
+ return null;
2060
+ }
2061
+ }
2062
+ async function fetchLatestVersion2() {
2063
+ const lastCheck = versionCache.get("lastCheck") || 0;
2064
+ const cachedVersion = versionCache.get("latestVersion");
2065
+ if (cachedVersion && Date.now() - lastCheck < VERSION_CACHE_TTL_MS) {
2066
+ return cachedVersion;
2067
+ }
2068
+ try {
2069
+ const https = await import("https");
2070
+ return new Promise((resolve) => {
2071
+ const req = https.get(
2072
+ `https://registry.npmjs.org/${PACKAGE_NAME}/latest`,
2073
+ { timeout: 5e3 },
2074
+ (res) => {
2075
+ let data = "";
2076
+ res.on("data", (chunk) => {
2077
+ data += chunk;
2078
+ });
2079
+ res.on("end", () => {
2080
+ try {
2081
+ const json = JSON.parse(data);
2082
+ const version = json.version || null;
2083
+ if (version) {
2084
+ versionCache.set("latestVersion", version);
2085
+ versionCache.set("lastCheck", Date.now());
2086
+ }
2087
+ resolve(version);
2088
+ } catch {
2089
+ resolve(cachedVersion || null);
2090
+ }
2091
+ });
2092
+ }
2093
+ );
2094
+ req.on("error", () => resolve(cachedVersion || null));
2095
+ req.on("timeout", () => {
2096
+ req.destroy();
2097
+ resolve(cachedVersion || null);
2098
+ });
2099
+ });
2100
+ } catch {
2101
+ return cachedVersion || null;
2102
+ }
2103
+ }
2104
+ async function checkForUpdate() {
2105
+ const currentVersion = getCurrentVersion();
2106
+ if (!currentVersion) {
2107
+ return { hasUpdate: false, currentVersion: null, latestVersion: null };
2108
+ }
2109
+ const latestVersion = await fetchLatestVersion2();
2110
+ const hasUpdate = !!(latestVersion && semver2.gt(latestVersion, currentVersion));
2111
+ return { hasUpdate, currentVersion, latestVersion };
2112
+ }
2113
+ function getUpdateCommand() {
2114
+ return `pnpm add ${DJANGOCFG_PACKAGES.map((p) => `${p}@latest`).join(" ")}`;
2115
+ }
2116
+ async function printVersionInfo() {
2117
+ const { hasUpdate, currentVersion, latestVersion } = await checkForUpdate();
2118
+ if (!currentVersion) return;
2119
+ consola4.box(`\u{1F4E6} @djangocfg/nextjs v${currentVersion}`);
2120
+ if (hasUpdate && latestVersion) {
2121
+ consola4.warn(`Update Available! ${chalk3.red(currentVersion)} \u2192 ${chalk3.green(latestVersion)}`);
2122
+ consola4.info(`Run: ${chalk3.cyan(getUpdateCommand())}`);
2123
+ console.log("");
2124
+ }
2125
+ }
2126
+
2067
2127
  // src/config/plugins/devStartup.ts
2068
2128
  var startupDone = false;
2069
2129
  var DevStartupPlugin = class {
@@ -2134,87 +2194,25 @@ function resetDevStartupState() {
2134
2194
  startupDone = false;
2135
2195
  }
2136
2196
 
2137
- // src/config/plugins/compression.ts
2138
- var DEFAULT_OPTIONS = {
2139
- gzip: true,
2140
- brotli: true,
2141
- threshold: 8192,
2142
- minRatio: 0.8,
2143
- brotliLevel: 8
2144
- };
2145
- function addCompressionPlugins(config, options = {}) {
2146
- if (!isPackageInstalled("compression-webpack-plugin")) {
2147
- return false;
2148
- }
2149
- const opts = { ...DEFAULT_OPTIONS, ...options };
2150
- try {
2151
- const CompressionPlugin = __require("compression-webpack-plugin");
2152
- if (!config.plugins) {
2153
- config.plugins = [];
2154
- }
2155
- if (opts.gzip) {
2156
- config.plugins.push(
2157
- new CompressionPlugin({
2158
- filename: "[path][base].gz",
2159
- algorithm: "gzip",
2160
- test: /\.(js|css|html|svg|json)$/,
2161
- threshold: opts.threshold,
2162
- minRatio: opts.minRatio
2163
- })
2164
- );
2165
- }
2166
- if (opts.brotli) {
2167
- config.plugins.push(
2168
- new CompressionPlugin({
2169
- filename: "[path][base].br",
2170
- algorithm: "brotliCompress",
2171
- test: /\.(js|css|html|svg|json)$/,
2172
- threshold: opts.threshold,
2173
- minRatio: opts.minRatio,
2174
- compressionOptions: {
2175
- level: opts.brotliLevel
2176
- }
2177
- })
2178
- );
2197
+ // src/config/utils/deepMerge.ts
2198
+ function deepMerge(target, source) {
2199
+ const output = { ...target };
2200
+ for (const key in source) {
2201
+ if (source[key] === void 0) continue;
2202
+ if (Array.isArray(source[key])) {
2203
+ output[key] = source[key];
2204
+ } else if (source[key] && typeof source[key] === "object" && !Array.isArray(source[key])) {
2205
+ const targetValue = output[key];
2206
+ if (targetValue && typeof targetValue === "object" && !Array.isArray(targetValue)) {
2207
+ output[key] = deepMerge(targetValue, source[key]);
2208
+ } else {
2209
+ output[key] = source[key];
2210
+ }
2211
+ } else {
2212
+ output[key] = source[key];
2179
2213
  }
2180
- return true;
2181
- } catch (error) {
2182
- return false;
2183
- }
2184
- }
2185
- function isCompressionAvailable() {
2186
- return isPackageInstalled("compression-webpack-plugin");
2187
- }
2188
-
2189
- // src/pwa/plugin.ts
2190
- import { consola as consola4 } from "consola";
2191
- function withPWA(nextConfig, options = {}) {
2192
- const isDev2 = process.env.NODE_ENV === "development";
2193
- const isStaticBuild2 = process.env.NEXT_PUBLIC_STATIC_BUILD === "true";
2194
- const shouldDisable = options.disable !== void 0 ? options.disable : isDev2 || isStaticBuild2;
2195
- const defaultOptions = {
2196
- swSrc: "app/sw.ts",
2197
- swDest: "public/sw.js",
2198
- disable: shouldDisable,
2199
- cacheOnNavigation: true,
2200
- reloadOnOnline: true,
2201
- ...options
2202
- };
2203
- try {
2204
- const withSerwistInit = __require("@serwist/next").default;
2205
- const withSerwist = withSerwistInit({
2206
- swSrc: defaultOptions.swSrc,
2207
- swDest: defaultOptions.swDest,
2208
- disable: defaultOptions.disable,
2209
- cacheOnNavigation: defaultOptions.cacheOnNavigation,
2210
- reloadOnOnline: defaultOptions.reloadOnOnline,
2211
- ...defaultOptions.serwistOptions
2212
- });
2213
- return withSerwist(nextConfig);
2214
- } catch (error) {
2215
- consola4.error("Failed to configure Serwist:", error);
2216
- return nextConfig;
2217
2214
  }
2215
+ return output;
2218
2216
  }
2219
2217
 
2220
2218
  // src/config/createNextConfig.ts
@@ -2501,7 +2499,7 @@ export {
2501
2499
  defineRoute,
2502
2500
  detectPackageManager,
2503
2501
  encodeBase64,
2504
- fetchLatestVersion,
2502
+ fetchLatestVersion2 as fetchLatestVersion,
2505
2503
  findRoute,
2506
2504
  findRouteByPattern,
2507
2505
  generateOgImageMetadata,