@julien-lin/universal-pwa-templates 1.3.7 → 1.3.8

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.cjs CHANGED
@@ -21,13 +21,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
23
  determineTemplateType: () => determineTemplateType,
24
+ djangoApiServiceWorkerTemplate: () => djangoApiServiceWorkerTemplate,
25
+ djangoSpaServiceWorkerTemplate: () => djangoSpaServiceWorkerTemplate,
26
+ flaskApiServiceWorkerTemplate: () => flaskApiServiceWorkerTemplate,
27
+ flaskSpaServiceWorkerTemplate: () => flaskSpaServiceWorkerTemplate,
24
28
  getAvailableTemplateTypes: () => getAvailableTemplateTypes,
25
29
  getServiceWorkerTemplate: () => getServiceWorkerTemplate,
30
+ laravelApiServiceWorkerTemplate: () => laravelApiServiceWorkerTemplate,
31
+ laravelSpaServiceWorkerTemplate: () => laravelSpaServiceWorkerTemplate,
32
+ laravelSsrServiceWorkerTemplate: () => laravelSsrServiceWorkerTemplate,
26
33
  phpServiceWorkerTemplate: () => phpServiceWorkerTemplate,
27
34
  placeholder: () => placeholder,
28
35
  spaServiceWorkerTemplate: () => spaServiceWorkerTemplate,
29
36
  ssrServiceWorkerTemplate: () => ssrServiceWorkerTemplate,
30
37
  staticServiceWorkerTemplate: () => staticServiceWorkerTemplate,
38
+ symfonyApiServiceWorkerTemplate: () => symfonyApiServiceWorkerTemplate,
39
+ symfonySpaServiceWorkerTemplate: () => symfonySpaServiceWorkerTemplate,
31
40
  wordpressServiceWorkerTemplate: () => wordpressServiceWorkerTemplate
32
41
  });
33
42
  module.exports = __toCommonJS(index_exports);
@@ -537,6 +546,1007 @@ if (typeof workbox !== 'undefined') {
537
546
  }
538
547
  `;
539
548
 
549
+ // src/service-worker/laravel-spa.ts
550
+ var laravelSpaServiceWorkerTemplate = `
551
+ // Load Workbox from CDN
552
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
553
+
554
+ // Ensure Workbox is loaded
555
+ if (typeof workbox !== 'undefined') {
556
+ // Precache des assets statiques
557
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
558
+
559
+ // Navigation route pour SPA
560
+ const navigationHandler = workbox.precaching.createHandlerBoundToURL('/index.html')
561
+ const navigationRoute = new workbox.routing.NavigationRoute(navigationHandler, {
562
+ allowlist: [/^\\//],
563
+ denylist: [/^\\/api/, /^\\/livewire/, /^\\/_/],
564
+ })
565
+ workbox.routing.registerRoute(navigationRoute)
566
+
567
+ // CacheFirst pour images
568
+ workbox.routing.registerRoute(
569
+ ({ request }) => request.destination === 'image',
570
+ new workbox.strategies.CacheFirst({
571
+ cacheName: 'laravel-images-cache',
572
+ plugins: [
573
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
574
+ new workbox.expiration.ExpirationPlugin({
575
+ maxEntries: 60,
576
+ maxAgeSeconds: 30 * 24 * 60 * 60,
577
+ }),
578
+ ],
579
+ })
580
+ )
581
+
582
+ // CacheFirst pour fonts
583
+ workbox.routing.registerRoute(
584
+ ({ request }) => request.destination === 'font',
585
+ new workbox.strategies.CacheFirst({
586
+ cacheName: 'laravel-fonts-cache',
587
+ plugins: [
588
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
589
+ new workbox.expiration.ExpirationPlugin({
590
+ maxEntries: 30,
591
+ maxAgeSeconds: 365 * 24 * 60 * 60,
592
+ }),
593
+ ],
594
+ })
595
+ )
596
+
597
+ // StaleWhileRevalidate pour CSS/JS
598
+ workbox.routing.registerRoute(
599
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
600
+ new workbox.strategies.StaleWhileRevalidate({
601
+ cacheName: 'laravel-assets-cache',
602
+ plugins: [
603
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
604
+ new workbox.expiration.ExpirationPlugin({
605
+ maxEntries: 50,
606
+ maxAgeSeconds: 7 * 24 * 60 * 60,
607
+ }),
608
+ ],
609
+ })
610
+ )
611
+
612
+ // NetworkFirst pour API (CSRF-friendly)
613
+ workbox.routing.registerRoute(
614
+ ({ url, request }) =>
615
+ request.method === 'GET' &&
616
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/graphql')),
617
+ new workbox.strategies.NetworkFirst({
618
+ cacheName: 'laravel-api-cache',
619
+ fetchOptions: {
620
+ credentials: 'same-origin',
621
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
622
+ },
623
+ plugins: [
624
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
625
+ new workbox.expiration.ExpirationPlugin({
626
+ maxEntries: 50,
627
+ maxAgeSeconds: 5 * 60,
628
+ }),
629
+ ],
630
+ networkTimeoutSeconds: 3,
631
+ })
632
+ )
633
+
634
+ // Livewire endpoints
635
+ workbox.routing.registerRoute(
636
+ ({ url, request }) =>
637
+ request.method === 'GET' && url.pathname.startsWith('/livewire/'),
638
+ new workbox.strategies.NetworkFirst({
639
+ cacheName: 'laravel-livewire-cache',
640
+ fetchOptions: {
641
+ credentials: 'same-origin',
642
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
643
+ },
644
+ plugins: [
645
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
646
+ new workbox.expiration.ExpirationPlugin({
647
+ maxEntries: 30,
648
+ maxAgeSeconds: 2 * 60,
649
+ }),
650
+ ],
651
+ networkTimeoutSeconds: 3,
652
+ })
653
+ )
654
+ } else {
655
+ console.error('Workbox could not be loaded.')
656
+ }
657
+ `;
658
+
659
+ // src/service-worker/laravel-ssr.ts
660
+ var laravelSsrServiceWorkerTemplate = `
661
+ // Load Workbox from CDN
662
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
663
+
664
+ // Ensure Workbox is loaded
665
+ if (typeof workbox !== 'undefined') {
666
+ // Precache des assets statiques critiques
667
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
668
+
669
+ // NetworkFirst pour les pages HTML
670
+ workbox.routing.registerRoute(
671
+ ({ request }) => request.mode === 'navigate',
672
+ new workbox.strategies.NetworkFirst({
673
+ cacheName: 'laravel-pages-cache',
674
+ plugins: [
675
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
676
+ new workbox.expiration.ExpirationPlugin({
677
+ maxEntries: 50,
678
+ maxAgeSeconds: 24 * 60 * 60,
679
+ }),
680
+ ],
681
+ networkTimeoutSeconds: 3,
682
+ })
683
+ )
684
+
685
+ // CacheFirst pour images
686
+ workbox.routing.registerRoute(
687
+ ({ request }) => request.destination === 'image',
688
+ new workbox.strategies.CacheFirst({
689
+ cacheName: 'laravel-images-cache',
690
+ plugins: [
691
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
692
+ new workbox.expiration.ExpirationPlugin({
693
+ maxEntries: 60,
694
+ maxAgeSeconds: 30 * 24 * 60 * 60,
695
+ }),
696
+ ],
697
+ })
698
+ )
699
+
700
+ // CacheFirst pour fonts
701
+ workbox.routing.registerRoute(
702
+ ({ request }) => request.destination === 'font',
703
+ new workbox.strategies.CacheFirst({
704
+ cacheName: 'laravel-fonts-cache',
705
+ plugins: [
706
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
707
+ new workbox.expiration.ExpirationPlugin({
708
+ maxEntries: 30,
709
+ maxAgeSeconds: 365 * 24 * 60 * 60,
710
+ }),
711
+ ],
712
+ })
713
+ )
714
+
715
+ // StaleWhileRevalidate pour CSS/JS
716
+ workbox.routing.registerRoute(
717
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
718
+ new workbox.strategies.StaleWhileRevalidate({
719
+ cacheName: 'laravel-assets-cache',
720
+ plugins: [
721
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
722
+ new workbox.expiration.ExpirationPlugin({
723
+ maxEntries: 50,
724
+ maxAgeSeconds: 7 * 24 * 60 * 60,
725
+ }),
726
+ ],
727
+ })
728
+ )
729
+
730
+ // NetworkFirst pour API (CSRF-friendly)
731
+ workbox.routing.registerRoute(
732
+ ({ url, request }) =>
733
+ request.method === 'GET' &&
734
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/graphql')),
735
+ new workbox.strategies.NetworkFirst({
736
+ cacheName: 'laravel-api-cache',
737
+ fetchOptions: {
738
+ credentials: 'same-origin',
739
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
740
+ },
741
+ plugins: [
742
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
743
+ new workbox.expiration.ExpirationPlugin({
744
+ maxEntries: 50,
745
+ maxAgeSeconds: 5 * 60,
746
+ }),
747
+ ],
748
+ networkTimeoutSeconds: 3,
749
+ })
750
+ )
751
+ } else {
752
+ console.error('Workbox could not be loaded.')
753
+ }
754
+ `;
755
+
756
+ // src/service-worker/laravel-api.ts
757
+ var laravelApiServiceWorkerTemplate = `
758
+ // Load Workbox from CDN
759
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
760
+
761
+ // Ensure Workbox is loaded
762
+ if (typeof workbox !== 'undefined') {
763
+ // Precache des assets statiques
764
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
765
+
766
+ // CacheFirst pour assets publics
767
+ workbox.routing.registerRoute(
768
+ ({ url }) => url.pathname.startsWith('/build/') || url.pathname.startsWith('/public/') || url.pathname.startsWith('/storage/'),
769
+ new workbox.strategies.CacheFirst({
770
+ cacheName: 'laravel-public-assets-cache',
771
+ plugins: [
772
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
773
+ new workbox.expiration.ExpirationPlugin({
774
+ maxEntries: 100,
775
+ maxAgeSeconds: 30 * 24 * 60 * 60,
776
+ }),
777
+ ],
778
+ })
779
+ )
780
+
781
+ // CacheFirst pour images
782
+ workbox.routing.registerRoute(
783
+ ({ request }) => request.destination === 'image',
784
+ new workbox.strategies.CacheFirst({
785
+ cacheName: 'laravel-images-cache',
786
+ plugins: [
787
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
788
+ new workbox.expiration.ExpirationPlugin({
789
+ maxEntries: 60,
790
+ maxAgeSeconds: 30 * 24 * 60 * 60,
791
+ }),
792
+ ],
793
+ })
794
+ )
795
+
796
+ // StaleWhileRevalidate pour CSS/JS
797
+ workbox.routing.registerRoute(
798
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
799
+ new workbox.strategies.StaleWhileRevalidate({
800
+ cacheName: 'laravel-assets-cache',
801
+ plugins: [
802
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
803
+ new workbox.expiration.ExpirationPlugin({
804
+ maxEntries: 50,
805
+ maxAgeSeconds: 7 * 24 * 60 * 60,
806
+ }),
807
+ ],
808
+ })
809
+ )
810
+
811
+ // NetworkFirst pour API (CSRF-friendly)
812
+ workbox.routing.registerRoute(
813
+ ({ url, request }) =>
814
+ request.method === 'GET' &&
815
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/graphql')),
816
+ new workbox.strategies.NetworkFirst({
817
+ cacheName: 'laravel-api-cache',
818
+ fetchOptions: {
819
+ credentials: 'same-origin',
820
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
821
+ },
822
+ plugins: [
823
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
824
+ new workbox.expiration.ExpirationPlugin({
825
+ maxEntries: 50,
826
+ maxAgeSeconds: 5 * 60,
827
+ }),
828
+ ],
829
+ networkTimeoutSeconds: 3,
830
+ })
831
+ )
832
+ } else {
833
+ console.error('Workbox could not be loaded.')
834
+ }
835
+ `;
836
+
837
+ // src/service-worker/symfony-spa.ts
838
+ var symfonySpaServiceWorkerTemplate = `
839
+ // Load Workbox from CDN
840
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
841
+
842
+ // Ensure Workbox is loaded
843
+ if (typeof workbox !== 'undefined') {
844
+ // Precache des assets statiques
845
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
846
+
847
+ // Navigation route pour SPA Symfony
848
+ const navigationHandler = workbox.precaching.createHandlerBoundToURL('/index.html')
849
+ const navigationRoute = new workbox.routing.NavigationRoute(navigationHandler, {
850
+ allowlist: [/^\\//],
851
+ denylist: [/^\\/api/, /^\\/graphql/, /^\\/_profiler/, /^\\/_wdt/, /^\\/_fragment/, /^\\/login/, /^\\/logout/],
852
+ })
853
+ workbox.routing.registerRoute(navigationRoute)
854
+
855
+ // Routes sensibles (auth/CSRF) en r\xE9seau uniquement
856
+ workbox.routing.registerRoute(
857
+ ({ url, request }) =>
858
+ request.method === 'GET' &&
859
+ (url.pathname.startsWith('/login') ||
860
+ url.pathname.startsWith('/logout') ||
861
+ url.pathname.startsWith('/auth') ||
862
+ url.pathname.startsWith('/_csrf')),
863
+ new workbox.strategies.NetworkOnly({
864
+ fetchOptions: {
865
+ credentials: 'same-origin',
866
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
867
+ },
868
+ })
869
+ )
870
+
871
+ // CacheFirst pour assets versionn\xE9s (Webpack Encore + bundles)
872
+ workbox.routing.registerRoute(
873
+ ({ url }) => url.pathname.startsWith('/build/') || url.pathname.startsWith('/bundles/'),
874
+ new workbox.strategies.CacheFirst({
875
+ cacheName: 'symfony-assets-cache',
876
+ plugins: [
877
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
878
+ new workbox.expiration.ExpirationPlugin({
879
+ maxEntries: 100,
880
+ maxAgeSeconds: 30 * 24 * 60 * 60,
881
+ }),
882
+ ],
883
+ })
884
+ )
885
+
886
+ // CacheFirst pour images
887
+ workbox.routing.registerRoute(
888
+ ({ request }) => request.destination === 'image',
889
+ new workbox.strategies.CacheFirst({
890
+ cacheName: 'symfony-images-cache',
891
+ plugins: [
892
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
893
+ new workbox.expiration.ExpirationPlugin({
894
+ maxEntries: 60,
895
+ maxAgeSeconds: 30 * 24 * 60 * 60,
896
+ }),
897
+ ],
898
+ })
899
+ )
900
+
901
+ // CacheFirst pour fonts
902
+ workbox.routing.registerRoute(
903
+ ({ request }) => request.destination === 'font',
904
+ new workbox.strategies.CacheFirst({
905
+ cacheName: 'symfony-fonts-cache',
906
+ plugins: [
907
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
908
+ new workbox.expiration.ExpirationPlugin({
909
+ maxEntries: 30,
910
+ maxAgeSeconds: 365 * 24 * 60 * 60,
911
+ }),
912
+ ],
913
+ })
914
+ )
915
+
916
+ // StaleWhileRevalidate pour CSS/JS
917
+ workbox.routing.registerRoute(
918
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
919
+ new workbox.strategies.StaleWhileRevalidate({
920
+ cacheName: 'symfony-static-assets-cache',
921
+ plugins: [
922
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
923
+ new workbox.expiration.ExpirationPlugin({
924
+ maxEntries: 50,
925
+ maxAgeSeconds: 7 * 24 * 60 * 60,
926
+ }),
927
+ ],
928
+ })
929
+ )
930
+
931
+ // NetworkFirst pour API (CSRF-friendly)
932
+ workbox.routing.registerRoute(
933
+ ({ url, request }) =>
934
+ request.method === 'GET' &&
935
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/graphql')),
936
+ new workbox.strategies.NetworkFirst({
937
+ cacheName: 'symfony-api-cache',
938
+ fetchOptions: {
939
+ credentials: 'same-origin',
940
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
941
+ },
942
+ plugins: [
943
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
944
+ new workbox.expiration.ExpirationPlugin({
945
+ maxEntries: 50,
946
+ maxAgeSeconds: 5 * 60,
947
+ }),
948
+ ],
949
+ networkTimeoutSeconds: 3,
950
+ })
951
+ )
952
+ } else {
953
+ console.error('Workbox could not be loaded.')
954
+ }
955
+ `;
956
+
957
+ // src/service-worker/symfony-api.ts
958
+ var symfonyApiServiceWorkerTemplate = `
959
+ // Load Workbox from CDN
960
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
961
+
962
+ // Ensure Workbox is loaded
963
+ if (typeof workbox !== 'undefined') {
964
+ // Precache des assets statiques
965
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
966
+
967
+ // Routes sensibles (auth/CSRF) en r\xE9seau uniquement
968
+ workbox.routing.registerRoute(
969
+ ({ url, request }) =>
970
+ request.method === 'GET' &&
971
+ (url.pathname.startsWith('/login') ||
972
+ url.pathname.startsWith('/logout') ||
973
+ url.pathname.startsWith('/auth') ||
974
+ url.pathname.startsWith('/_csrf')),
975
+ new workbox.strategies.NetworkOnly({
976
+ fetchOptions: {
977
+ credentials: 'same-origin',
978
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
979
+ },
980
+ })
981
+ )
982
+
983
+ // CacheFirst pour assets versionn\xE9s (Webpack Encore + bundles)
984
+ workbox.routing.registerRoute(
985
+ ({ url }) => url.pathname.startsWith('/build/') || url.pathname.startsWith('/bundles/'),
986
+ new workbox.strategies.CacheFirst({
987
+ cacheName: 'symfony-assets-cache',
988
+ plugins: [
989
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
990
+ new workbox.expiration.ExpirationPlugin({
991
+ maxEntries: 100,
992
+ maxAgeSeconds: 30 * 24 * 60 * 60,
993
+ }),
994
+ ],
995
+ })
996
+ )
997
+
998
+ // CacheFirst pour images
999
+ workbox.routing.registerRoute(
1000
+ ({ request }) => request.destination === 'image',
1001
+ new workbox.strategies.CacheFirst({
1002
+ cacheName: 'symfony-images-cache',
1003
+ plugins: [
1004
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1005
+ new workbox.expiration.ExpirationPlugin({
1006
+ maxEntries: 60,
1007
+ maxAgeSeconds: 30 * 24 * 60 * 60,
1008
+ }),
1009
+ ],
1010
+ })
1011
+ )
1012
+
1013
+ // StaleWhileRevalidate pour CSS/JS
1014
+ workbox.routing.registerRoute(
1015
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
1016
+ new workbox.strategies.StaleWhileRevalidate({
1017
+ cacheName: 'symfony-static-assets-cache',
1018
+ plugins: [
1019
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1020
+ new workbox.expiration.ExpirationPlugin({
1021
+ maxEntries: 50,
1022
+ maxAgeSeconds: 7 * 24 * 60 * 60,
1023
+ }),
1024
+ ],
1025
+ })
1026
+ )
1027
+
1028
+ // NetworkFirst pour API (CSRF-friendly)
1029
+ workbox.routing.registerRoute(
1030
+ ({ url, request }) =>
1031
+ request.method === 'GET' &&
1032
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/graphql')),
1033
+ new workbox.strategies.NetworkFirst({
1034
+ cacheName: 'symfony-api-cache',
1035
+ fetchOptions: {
1036
+ credentials: 'same-origin',
1037
+ headers: { 'X-Requested-With': 'XMLHttpRequest' },
1038
+ },
1039
+ plugins: [
1040
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1041
+ new workbox.expiration.ExpirationPlugin({
1042
+ maxEntries: 50,
1043
+ maxAgeSeconds: 5 * 60,
1044
+ }),
1045
+ ],
1046
+ networkTimeoutSeconds: 3,
1047
+ })
1048
+ )
1049
+ } else {
1050
+ console.error('Workbox could not be loaded.')
1051
+ }
1052
+ `;
1053
+
1054
+ // src/service-worker/django-spa.ts
1055
+ var djangoSpaServiceWorkerTemplate = `
1056
+ // Load Workbox from CDN
1057
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
1058
+
1059
+ // Ensure Workbox is loaded
1060
+ if (typeof workbox !== 'undefined') {
1061
+ // Precache des assets statiques
1062
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
1063
+
1064
+ // Navigation route pour SPA
1065
+ const navigationHandler = workbox.precaching.createHandlerBoundToURL('/index.html')
1066
+ const navigationRoute = new workbox.routing.NavigationRoute(navigationHandler, {
1067
+ allowlist: [/^\\//],
1068
+ denylist: [/^\\/api/, /^\\/admin/, /^\\/_/],
1069
+ })
1070
+ workbox.routing.registerRoute(navigationRoute)
1071
+
1072
+ // CacheFirst pour fichiers statiques Django (/static/)
1073
+ workbox.routing.registerRoute(
1074
+ ({ url }) => url.pathname.startsWith('/static/'),
1075
+ new workbox.strategies.CacheFirst({
1076
+ cacheName: 'django-static-cache',
1077
+ plugins: [
1078
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1079
+ new workbox.expiration.ExpirationPlugin({
1080
+ maxEntries: 100,
1081
+ maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
1082
+ }),
1083
+ ],
1084
+ })
1085
+ )
1086
+
1087
+ // CacheFirst pour fichiers m\xE9dia Django (/media/)
1088
+ workbox.routing.registerRoute(
1089
+ ({ url }) => url.pathname.startsWith('/media/'),
1090
+ new workbox.strategies.CacheFirst({
1091
+ cacheName: 'django-media-cache',
1092
+ plugins: [
1093
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1094
+ new workbox.expiration.ExpirationPlugin({
1095
+ maxEntries: 50,
1096
+ maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days
1097
+ }),
1098
+ ],
1099
+ })
1100
+ )
1101
+
1102
+ // CacheFirst pour images
1103
+ workbox.routing.registerRoute(
1104
+ ({ request }) => request.destination === 'image',
1105
+ new workbox.strategies.CacheFirst({
1106
+ cacheName: 'django-images-cache',
1107
+ plugins: [
1108
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1109
+ new workbox.expiration.ExpirationPlugin({
1110
+ maxEntries: 60,
1111
+ maxAgeSeconds: 30 * 24 * 60 * 60,
1112
+ }),
1113
+ ],
1114
+ })
1115
+ )
1116
+
1117
+ // CacheFirst pour fonts
1118
+ workbox.routing.registerRoute(
1119
+ ({ request }) => request.destination === 'font',
1120
+ new workbox.strategies.CacheFirst({
1121
+ cacheName: 'django-fonts-cache',
1122
+ plugins: [
1123
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1124
+ new workbox.expiration.ExpirationPlugin({
1125
+ maxEntries: 30,
1126
+ maxAgeSeconds: 365 * 24 * 60 * 60,
1127
+ }),
1128
+ ],
1129
+ })
1130
+ )
1131
+
1132
+ // StaleWhileRevalidate pour CSS/JS
1133
+ workbox.routing.registerRoute(
1134
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
1135
+ new workbox.strategies.StaleWhileRevalidate({
1136
+ cacheName: 'django-assets-cache',
1137
+ plugins: [
1138
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1139
+ new workbox.expiration.ExpirationPlugin({
1140
+ maxEntries: 50,
1141
+ maxAgeSeconds: 7 * 24 * 60 * 60,
1142
+ }),
1143
+ ],
1144
+ })
1145
+ )
1146
+
1147
+ // NetworkFirst pour API (CSRF-friendly avec credentials)
1148
+ workbox.routing.registerRoute(
1149
+ ({ url, request }) =>
1150
+ request.method === 'GET' &&
1151
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/api/v1/') || url.pathname.startsWith('/api/v2/')),
1152
+ new workbox.strategies.NetworkFirst({
1153
+ cacheName: 'django-api-cache',
1154
+ fetchOptions: {
1155
+ credentials: 'same-origin',
1156
+ headers: {
1157
+ 'X-Requested-With': 'XMLHttpRequest',
1158
+ },
1159
+ },
1160
+ plugins: [
1161
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1162
+ new workbox.expiration.ExpirationPlugin({
1163
+ maxEntries: 50,
1164
+ maxAgeSeconds: 5 * 60, // 5 minutes
1165
+ }),
1166
+ ],
1167
+ networkTimeoutSeconds: 3,
1168
+ })
1169
+ )
1170
+
1171
+ // NetworkOnly pour admin (toujours frais, pas de cache)
1172
+ workbox.routing.registerRoute(
1173
+ ({ url }) => url.pathname.startsWith('/admin/'),
1174
+ new workbox.strategies.NetworkOnly({
1175
+ cacheName: 'django-admin-cache',
1176
+ fetchOptions: {
1177
+ credentials: 'same-origin',
1178
+ },
1179
+ })
1180
+ )
1181
+
1182
+ // NetworkOnly pour CSRF token endpoint
1183
+ workbox.routing.registerRoute(
1184
+ ({ url }) => url.pathname.includes('/csrf-token/') || url.pathname.includes('/csrf/'),
1185
+ new workbox.strategies.NetworkOnly({
1186
+ cacheName: 'django-csrf-cache',
1187
+ fetchOptions: {
1188
+ credentials: 'same-origin',
1189
+ },
1190
+ })
1191
+ )
1192
+ } else {
1193
+ console.error('Workbox could not be loaded.')
1194
+ }
1195
+ `;
1196
+
1197
+ // src/service-worker/django-api.ts
1198
+ var djangoApiServiceWorkerTemplate = `
1199
+ // Load Workbox from CDN
1200
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
1201
+
1202
+ // Ensure Workbox is loaded
1203
+ if (typeof workbox !== 'undefined') {
1204
+ // Precache des assets statiques
1205
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
1206
+
1207
+ // CacheFirst pour fichiers statiques Django (/static/)
1208
+ workbox.routing.registerRoute(
1209
+ ({ url }) => url.pathname.startsWith('/static/'),
1210
+ new workbox.strategies.CacheFirst({
1211
+ cacheName: 'django-static-cache',
1212
+ plugins: [
1213
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1214
+ new workbox.expiration.ExpirationPlugin({
1215
+ maxEntries: 100,
1216
+ maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
1217
+ }),
1218
+ ],
1219
+ })
1220
+ )
1221
+
1222
+ // CacheFirst pour fichiers m\xE9dia Django (/media/)
1223
+ workbox.routing.registerRoute(
1224
+ ({ url }) => url.pathname.startsWith('/media/'),
1225
+ new workbox.strategies.CacheFirst({
1226
+ cacheName: 'django-media-cache',
1227
+ plugins: [
1228
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1229
+ new workbox.expiration.ExpirationPlugin({
1230
+ maxEntries: 50,
1231
+ maxAgeSeconds: 7 * 24 * 60 * 60, // 7 days
1232
+ }),
1233
+ ],
1234
+ })
1235
+ )
1236
+
1237
+ // CacheFirst pour images
1238
+ workbox.routing.registerRoute(
1239
+ ({ request }) => request.destination === 'image',
1240
+ new workbox.strategies.CacheFirst({
1241
+ cacheName: 'django-images-cache',
1242
+ plugins: [
1243
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1244
+ new workbox.expiration.ExpirationPlugin({
1245
+ maxEntries: 60,
1246
+ maxAgeSeconds: 30 * 24 * 60 * 60,
1247
+ }),
1248
+ ],
1249
+ })
1250
+ )
1251
+
1252
+ // StaleWhileRevalidate pour CSS/JS
1253
+ workbox.routing.registerRoute(
1254
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
1255
+ new workbox.strategies.StaleWhileRevalidate({
1256
+ cacheName: 'django-assets-cache',
1257
+ plugins: [
1258
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1259
+ new workbox.expiration.ExpirationPlugin({
1260
+ maxEntries: 50,
1261
+ maxAgeSeconds: 7 * 24 * 60 * 60,
1262
+ }),
1263
+ ],
1264
+ })
1265
+ )
1266
+
1267
+ // NetworkFirst pour API (CSRF-friendly avec credentials)
1268
+ workbox.routing.registerRoute(
1269
+ ({ url, request }) =>
1270
+ request.method === 'GET' &&
1271
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/api/v1/') || url.pathname.startsWith('/api/v2/')),
1272
+ new workbox.strategies.NetworkFirst({
1273
+ cacheName: 'django-api-cache',
1274
+ fetchOptions: {
1275
+ credentials: 'same-origin',
1276
+ headers: {
1277
+ 'X-Requested-With': 'XMLHttpRequest',
1278
+ },
1279
+ },
1280
+ plugins: [
1281
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1282
+ new workbox.expiration.ExpirationPlugin({
1283
+ maxEntries: 50,
1284
+ maxAgeSeconds: 5 * 60, // 5 minutes
1285
+ }),
1286
+ ],
1287
+ networkTimeoutSeconds: 3,
1288
+ })
1289
+ )
1290
+
1291
+ // NetworkOnly pour admin (toujours frais, pas de cache)
1292
+ workbox.routing.registerRoute(
1293
+ ({ url }) => url.pathname.startsWith('/admin/'),
1294
+ new workbox.strategies.NetworkOnly({
1295
+ cacheName: 'django-admin-cache',
1296
+ fetchOptions: {
1297
+ credentials: 'same-origin',
1298
+ },
1299
+ })
1300
+ )
1301
+
1302
+ // NetworkOnly pour CSRF token endpoint
1303
+ workbox.routing.registerRoute(
1304
+ ({ url }) => url.pathname.includes('/csrf-token/') || url.pathname.includes('/csrf/'),
1305
+ new workbox.strategies.NetworkOnly({
1306
+ cacheName: 'django-csrf-cache',
1307
+ fetchOptions: {
1308
+ credentials: 'same-origin',
1309
+ },
1310
+ })
1311
+ )
1312
+ } else {
1313
+ console.error('Workbox could not be loaded.')
1314
+ }
1315
+ `;
1316
+
1317
+ // src/service-worker/flask-spa.ts
1318
+ var flaskSpaServiceWorkerTemplate = `
1319
+ // Load Workbox from CDN
1320
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
1321
+
1322
+ // Ensure Workbox is loaded
1323
+ if (typeof workbox !== 'undefined') {
1324
+ // Precache des assets statiques
1325
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
1326
+
1327
+ // Navigation route pour SPA
1328
+ const navigationHandler = workbox.precaching.createHandlerBoundToURL('/index.html')
1329
+ const navigationRoute = new workbox.routing.NavigationRoute(navigationHandler, {
1330
+ allowlist: [/^\\//],
1331
+ denylist: [/^\\/api/, /^\\/admin/, /^\\/_/],
1332
+ })
1333
+ workbox.routing.registerRoute(navigationRoute)
1334
+
1335
+ // CacheFirst pour fichiers statiques Flask (/static/)
1336
+ workbox.routing.registerRoute(
1337
+ ({ url }) => url.pathname.startsWith('/static/'),
1338
+ new workbox.strategies.CacheFirst({
1339
+ cacheName: 'flask-static-cache',
1340
+ plugins: [
1341
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1342
+ new workbox.expiration.ExpirationPlugin({
1343
+ maxEntries: 100,
1344
+ maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
1345
+ }),
1346
+ ],
1347
+ })
1348
+ )
1349
+
1350
+ // CacheFirst pour images
1351
+ workbox.routing.registerRoute(
1352
+ ({ request }) => request.destination === 'image',
1353
+ new workbox.strategies.CacheFirst({
1354
+ cacheName: 'flask-images-cache',
1355
+ plugins: [
1356
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1357
+ new workbox.expiration.ExpirationPlugin({
1358
+ maxEntries: 60,
1359
+ maxAgeSeconds: 30 * 24 * 60 * 60,
1360
+ }),
1361
+ ],
1362
+ })
1363
+ )
1364
+
1365
+ // CacheFirst pour fonts
1366
+ workbox.routing.registerRoute(
1367
+ ({ request }) => request.destination === 'font',
1368
+ new workbox.strategies.CacheFirst({
1369
+ cacheName: 'flask-fonts-cache',
1370
+ plugins: [
1371
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1372
+ new workbox.expiration.ExpirationPlugin({
1373
+ maxEntries: 30,
1374
+ maxAgeSeconds: 365 * 24 * 60 * 60,
1375
+ }),
1376
+ ],
1377
+ })
1378
+ )
1379
+
1380
+ // StaleWhileRevalidate pour CSS/JS
1381
+ workbox.routing.registerRoute(
1382
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
1383
+ new workbox.strategies.StaleWhileRevalidate({
1384
+ cacheName: 'flask-assets-cache',
1385
+ plugins: [
1386
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1387
+ new workbox.expiration.ExpirationPlugin({
1388
+ maxEntries: 50,
1389
+ maxAgeSeconds: 7 * 24 * 60 * 60,
1390
+ }),
1391
+ ],
1392
+ })
1393
+ )
1394
+
1395
+ // NetworkFirst pour API (CSRF-friendly avec credentials)
1396
+ workbox.routing.registerRoute(
1397
+ ({ url, request }) =>
1398
+ request.method === 'GET' &&
1399
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/api/v1/') || url.pathname.startsWith('/api/v2/')),
1400
+ new workbox.strategies.NetworkFirst({
1401
+ cacheName: 'flask-api-cache',
1402
+ fetchOptions: {
1403
+ credentials: 'same-origin',
1404
+ headers: {
1405
+ 'X-Requested-With': 'XMLHttpRequest',
1406
+ },
1407
+ },
1408
+ plugins: [
1409
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1410
+ new workbox.expiration.ExpirationPlugin({
1411
+ maxEntries: 50,
1412
+ maxAgeSeconds: 5 * 60, // 5 minutes
1413
+ }),
1414
+ ],
1415
+ networkTimeoutSeconds: 3,
1416
+ })
1417
+ )
1418
+
1419
+ // NetworkOnly pour admin (toujours frais, pas de cache)
1420
+ workbox.routing.registerRoute(
1421
+ ({ url }) => url.pathname.startsWith('/admin/'),
1422
+ new workbox.strategies.NetworkOnly({
1423
+ cacheName: 'flask-admin-cache',
1424
+ fetchOptions: {
1425
+ credentials: 'same-origin',
1426
+ },
1427
+ })
1428
+ )
1429
+
1430
+ // NetworkOnly pour CSRF token endpoint (Flask-WTF)
1431
+ workbox.routing.registerRoute(
1432
+ ({ url }) => url.pathname.includes('/csrf-token/') || url.pathname.includes('/csrf/'),
1433
+ new workbox.strategies.NetworkOnly({
1434
+ cacheName: 'flask-csrf-cache',
1435
+ fetchOptions: {
1436
+ credentials: 'same-origin',
1437
+ },
1438
+ })
1439
+ )
1440
+ } else {
1441
+ console.error('Workbox could not be loaded.')
1442
+ }
1443
+ `;
1444
+
1445
+ // src/service-worker/flask-api.ts
1446
+ var flaskApiServiceWorkerTemplate = `
1447
+ // Load Workbox from CDN
1448
+ importScripts('https://storage.googleapis.com/workbox-cdn/releases/7.4.0/workbox-sw.js')
1449
+
1450
+ // Ensure Workbox is loaded
1451
+ if (typeof workbox !== 'undefined') {
1452
+ // Precache des assets statiques
1453
+ workbox.precaching.precacheAndRoute(self.__WB_MANIFEST)
1454
+
1455
+ // CacheFirst pour fichiers statiques Flask (/static/)
1456
+ workbox.routing.registerRoute(
1457
+ ({ url }) => url.pathname.startsWith('/static/'),
1458
+ new workbox.strategies.CacheFirst({
1459
+ cacheName: 'flask-static-cache',
1460
+ plugins: [
1461
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1462
+ new workbox.expiration.ExpirationPlugin({
1463
+ maxEntries: 100,
1464
+ maxAgeSeconds: 30 * 24 * 60 * 60, // 30 days
1465
+ }),
1466
+ ],
1467
+ })
1468
+ )
1469
+
1470
+ // CacheFirst pour images
1471
+ workbox.routing.registerRoute(
1472
+ ({ request }) => request.destination === 'image',
1473
+ new workbox.strategies.CacheFirst({
1474
+ cacheName: 'flask-images-cache',
1475
+ plugins: [
1476
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1477
+ new workbox.expiration.ExpirationPlugin({
1478
+ maxEntries: 60,
1479
+ maxAgeSeconds: 30 * 24 * 60 * 60,
1480
+ }),
1481
+ ],
1482
+ })
1483
+ )
1484
+
1485
+ // StaleWhileRevalidate pour CSS/JS
1486
+ workbox.routing.registerRoute(
1487
+ ({ request }) => request.destination === 'style' || request.destination === 'script',
1488
+ new workbox.strategies.StaleWhileRevalidate({
1489
+ cacheName: 'flask-assets-cache',
1490
+ plugins: [
1491
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1492
+ new workbox.expiration.ExpirationPlugin({
1493
+ maxEntries: 50,
1494
+ maxAgeSeconds: 7 * 24 * 60 * 60,
1495
+ }),
1496
+ ],
1497
+ })
1498
+ )
1499
+
1500
+ // NetworkFirst pour API (CSRF-friendly avec credentials)
1501
+ workbox.routing.registerRoute(
1502
+ ({ url, request }) =>
1503
+ request.method === 'GET' &&
1504
+ (url.pathname.startsWith('/api/') || url.pathname.startsWith('/api/v1/') || url.pathname.startsWith('/api/v2/')),
1505
+ new workbox.strategies.NetworkFirst({
1506
+ cacheName: 'flask-api-cache',
1507
+ fetchOptions: {
1508
+ credentials: 'same-origin',
1509
+ headers: {
1510
+ 'X-Requested-With': 'XMLHttpRequest',
1511
+ },
1512
+ },
1513
+ plugins: [
1514
+ new workbox.cacheableResponse.CacheableResponsePlugin({ statuses: [0, 200] }),
1515
+ new workbox.expiration.ExpirationPlugin({
1516
+ maxEntries: 50,
1517
+ maxAgeSeconds: 5 * 60, // 5 minutes
1518
+ }),
1519
+ ],
1520
+ networkTimeoutSeconds: 3,
1521
+ })
1522
+ )
1523
+
1524
+ // NetworkOnly pour admin (toujours frais, pas de cache)
1525
+ workbox.routing.registerRoute(
1526
+ ({ url }) => url.pathname.startsWith('/admin/'),
1527
+ new workbox.strategies.NetworkOnly({
1528
+ cacheName: 'flask-admin-cache',
1529
+ fetchOptions: {
1530
+ credentials: 'same-origin',
1531
+ },
1532
+ })
1533
+ )
1534
+
1535
+ // NetworkOnly pour CSRF token endpoint (Flask-WTF)
1536
+ workbox.routing.registerRoute(
1537
+ ({ url }) => url.pathname.includes('/csrf-token/') || url.pathname.includes('/csrf/'),
1538
+ new workbox.strategies.NetworkOnly({
1539
+ cacheName: 'flask-csrf-cache',
1540
+ fetchOptions: {
1541
+ credentials: 'same-origin',
1542
+ },
1543
+ })
1544
+ )
1545
+ } else {
1546
+ console.error('Workbox could not be loaded.')
1547
+ }
1548
+ `;
1549
+
540
1550
  // src/service-worker/index.ts
541
1551
  function getServiceWorkerTemplate(type) {
542
1552
  const templates = {
@@ -544,7 +1554,16 @@ function getServiceWorkerTemplate(type) {
544
1554
  spa: spaServiceWorkerTemplate,
545
1555
  ssr: ssrServiceWorkerTemplate,
546
1556
  wordpress: wordpressServiceWorkerTemplate,
547
- php: phpServiceWorkerTemplate
1557
+ php: phpServiceWorkerTemplate,
1558
+ "laravel-spa": laravelSpaServiceWorkerTemplate,
1559
+ "laravel-ssr": laravelSsrServiceWorkerTemplate,
1560
+ "laravel-api": laravelApiServiceWorkerTemplate,
1561
+ "symfony-spa": symfonySpaServiceWorkerTemplate,
1562
+ "symfony-api": symfonyApiServiceWorkerTemplate,
1563
+ "django-spa": djangoSpaServiceWorkerTemplate,
1564
+ "django-api": djangoApiServiceWorkerTemplate,
1565
+ "flask-spa": flaskSpaServiceWorkerTemplate,
1566
+ "flask-api": flaskApiServiceWorkerTemplate
548
1567
  };
549
1568
  const content = templates[type];
550
1569
  if (!content) {
@@ -556,7 +1575,22 @@ function getServiceWorkerTemplate(type) {
556
1575
  };
557
1576
  }
558
1577
  function getAvailableTemplateTypes() {
559
- return ["static", "spa", "ssr", "wordpress", "php"];
1578
+ return [
1579
+ "static",
1580
+ "spa",
1581
+ "ssr",
1582
+ "wordpress",
1583
+ "php",
1584
+ "laravel-spa",
1585
+ "laravel-ssr",
1586
+ "laravel-api",
1587
+ "symfony-spa",
1588
+ "symfony-api",
1589
+ "django-spa",
1590
+ "django-api",
1591
+ "flask-spa",
1592
+ "flask-api"
1593
+ ];
560
1594
  }
561
1595
  function determineTemplateType(architecture, framework) {
562
1596
  if (framework === "WordPress" || framework === "WooCommerce") {
@@ -565,9 +1599,27 @@ function determineTemplateType(architecture, framework) {
565
1599
  if (framework === "Drupal" || framework === "Joomla" || framework === "Magento" || framework === "Shopify" || framework === "PrestaShop") {
566
1600
  return "php";
567
1601
  }
568
- if (framework === "Symfony" || framework === "Laravel" || framework === "CodeIgniter" || framework === "CakePHP" || framework === "Yii" || framework === "Laminas") {
1602
+ if (framework === "Symfony") {
1603
+ return architecture === "spa" ? "symfony-spa" : "symfony-api";
1604
+ }
1605
+ if (framework === "CodeIgniter" || framework === "CakePHP" || framework === "Yii" || framework === "Laminas") {
569
1606
  return "php";
570
1607
  }
1608
+ if (framework === "Laravel") {
1609
+ if (architecture === "spa") {
1610
+ return "laravel-spa";
1611
+ }
1612
+ if (architecture === "ssr") {
1613
+ return "laravel-ssr";
1614
+ }
1615
+ return "laravel-api";
1616
+ }
1617
+ if (framework === "Django") {
1618
+ return architecture === "spa" ? "django-spa" : "django-api";
1619
+ }
1620
+ if (framework === "Flask") {
1621
+ return architecture === "spa" ? "flask-spa" : "flask-api";
1622
+ }
571
1623
  if (architecture === "spa") {
572
1624
  return "spa";
573
1625
  }
@@ -582,12 +1634,21 @@ var placeholder = true;
582
1634
  // Annotate the CommonJS export names for ESM import in node:
583
1635
  0 && (module.exports = {
584
1636
  determineTemplateType,
1637
+ djangoApiServiceWorkerTemplate,
1638
+ djangoSpaServiceWorkerTemplate,
1639
+ flaskApiServiceWorkerTemplate,
1640
+ flaskSpaServiceWorkerTemplate,
585
1641
  getAvailableTemplateTypes,
586
1642
  getServiceWorkerTemplate,
1643
+ laravelApiServiceWorkerTemplate,
1644
+ laravelSpaServiceWorkerTemplate,
1645
+ laravelSsrServiceWorkerTemplate,
587
1646
  phpServiceWorkerTemplate,
588
1647
  placeholder,
589
1648
  spaServiceWorkerTemplate,
590
1649
  ssrServiceWorkerTemplate,
591
1650
  staticServiceWorkerTemplate,
1651
+ symfonyApiServiceWorkerTemplate,
1652
+ symfonySpaServiceWorkerTemplate,
592
1653
  wordpressServiceWorkerTemplate
593
1654
  });