From d9ffcb52be7fcf2c0aa13c23d1340ece0caf1401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joaqu=C3=ADn=20S=C3=A1nchez?= Date: Sat, 17 Feb 2024 14:32:19 +0100 Subject: [PATCH] feat!: add experimental PWA assets generation and injection (#621) * feat: pwa assets generation and injection * chore: update logic for assets 0.2.1 * chore: load assets generator when assets configured * chore: refactor `ResolvedIconAsset` * chore: cleanup assets entry from jsdocs * chore: remove cache control cache * chore: refactor assets loader logic * chore: include pwa assets reload support * chore: include test with png image * chore: early return if url is not an image * chore: use test in early return if url is not an image * chore: use any for PWA assets generator (+ jsdocs) * chore: refactor html injection * chore: use any for `lookupPWAAssetsInstructions` * chore: generate assets only when pwa enabled * chore: refactor helper functions * chore: return if missing icon asset * chore: refactor assets generator * chore: vite base can be empty * chore: change logic for overrideManifestIcons * chore: update logic for overrideManifestIcons * chore: update hint for overrideManifestIcons * chore: update icon last modified entry with Date.now() when created * chore: update `overrideManifestIcons` hint * chore: change `handleHotUpdate` logic * chore: find existing links in html injection * chore: add pwa assets in vue router examples via env var * chore: update lockfile * chore: fix lint * chore: move pwa assets generator to optional dependency * chore: add integration options * chore: add integration option to resolved options * chore: add public and output integration options * chore: update transform index html logic * chore: update ypes and docs --- README.md | 1 + examples/assets-generator/index.html | 17 + examples/assets-generator/package.json | 24 + examples/assets-generator/public/favicon.svg | 130 ++++ .../assets-generator/public/source-test.png | Bin 0 -> 16976 bytes .../assets-generator/pwa-assets.config.ts | 26 + examples/assets-generator/src/main.ts | 17 + examples/assets-generator/src/pwa.ts | 15 + examples/assets-generator/src/vite-env.ts | 5 + examples/assets-generator/tsconfig.json | 24 + examples/assets-generator/vite.config.ts | 42 ++ examples/preact-router/package.json | 4 +- examples/react-router/package.json | 4 +- examples/solid-router/package.json | 4 +- examples/svelte-routify/package.json | 4 +- examples/vanilla-ts-dev-options/package.json | 4 +- examples/vanilla-ts-no-ip/package.json | 4 +- examples/vue-basic-cdn/package.json | 4 +- examples/vue-router/package.json | 5 +- examples/vue-router/vite.config.ts | 9 + package.json | 24 +- pnpm-lock.yaml | 686 ++++++++++++++---- pwa-assets.d.ts | 40 + src/api.ts | 18 +- src/constants.ts | 5 + src/context.ts | 6 + src/html.ts | 30 + src/index.ts | 2 + src/options.ts | 10 +- src/plugins/build.ts | 15 +- src/plugins/dev.ts | 16 +- src/plugins/main.ts | 17 +- src/plugins/pwa-assets.ts | 129 ++++ src/pwa-assets/build.ts | 10 + src/pwa-assets/config.ts | 151 ++++ src/pwa-assets/dev.ts | 48 ++ src/pwa-assets/generator.ts | 25 + src/pwa-assets/html.ts | 56 ++ src/pwa-assets/manifest.ts | 19 + src/pwa-assets/options.ts | 34 + src/pwa-assets/types.ts | 72 ++ src/pwa-assets/utils.ts | 68 ++ src/types.ts | 122 +++- 43 files changed, 1758 insertions(+), 188 deletions(-) create mode 100644 examples/assets-generator/index.html create mode 100644 examples/assets-generator/package.json create mode 100644 examples/assets-generator/public/favicon.svg create mode 100644 examples/assets-generator/public/source-test.png create mode 100644 examples/assets-generator/pwa-assets.config.ts create mode 100644 examples/assets-generator/src/main.ts create mode 100644 examples/assets-generator/src/pwa.ts create mode 100644 examples/assets-generator/src/vite-env.ts create mode 100644 examples/assets-generator/tsconfig.json create mode 100644 examples/assets-generator/vite.config.ts create mode 100644 pwa-assets.d.ts create mode 100644 src/plugins/pwa-assets.ts create mode 100644 src/pwa-assets/build.ts create mode 100644 src/pwa-assets/config.ts create mode 100644 src/pwa-assets/dev.ts create mode 100644 src/pwa-assets/generator.ts create mode 100644 src/pwa-assets/html.ts create mode 100644 src/pwa-assets/manifest.ts create mode 100644 src/pwa-assets/options.ts create mode 100644 src/pwa-assets/types.ts create mode 100644 src/pwa-assets/utils.ts diff --git a/README.md b/README.md index 251caf44..d66e0ea5 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Zero-config PWA Framework-agnostic Plugin for Vite - ๐Ÿž **Development Support**: debug your custom service worker logic as you develop your application - ๐Ÿ› ๏ธ **Versatile**: integration with meta frameworks: [รฎles](https://github.com/ElMassimo/iles), [SvelteKit](https://github.com/sveltejs/kit), [VitePress](https://github.com/vuejs/vitepress), [Astro](https://github.com/withastro/astro), and [Nuxt 3](https://github.com/nuxt/nuxt) - ๐Ÿ’ฅ **PWA Assets Generator**: generate all the PWA assets from a single command and a single source image +- ๐Ÿš€ **PWA Assets Integration**: serving, generating and injecting PWA Assets on the fly in your application ## ๐Ÿ“ฆ Install diff --git a/examples/assets-generator/index.html b/examples/assets-generator/index.html new file mode 100644 index 00000000..410307fb --- /dev/null +++ b/examples/assets-generator/index.html @@ -0,0 +1,17 @@ + + + + + + PWA Assets Generator + + + +
+ + + diff --git a/examples/assets-generator/package.json b/examples/assets-generator/package.json new file mode 100644 index 00000000..6d649d33 --- /dev/null +++ b/examples/assets-generator/package.json @@ -0,0 +1,24 @@ +{ + "name": "assets-generator", + "type": "module", + "version": "0.0.0", + "private": true, + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "dev:png": "PNG=true vite", + "build:png": "PNG=true vite build", + "preview:png": "PNG=true vite preview" + }, + "devDependencies": { + "rimraf": "^5.0.5", + "sharp": "^0.32.6", + "sharp-ico": "^0.1.5", + "typescript": "^5.3.3", + "vite": "^5.0.10", + "vite-plugin-pwa": "workspace:*", + "@vite-pwa/assets-generator": "^0.2.4", + "workbox-window": "^7.0.0" + } +} diff --git a/examples/assets-generator/public/favicon.svg b/examples/assets-generator/public/favicon.svg new file mode 100644 index 00000000..733f4fb4 --- /dev/null +++ b/examples/assets-generator/public/favicon.svg @@ -0,0 +1,130 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/assets-generator/public/source-test.png b/examples/assets-generator/public/source-test.png new file mode 100644 index 0000000000000000000000000000000000000000..aeff825645e27cd16ee725e0411834009dc14e83 GIT binary patch literal 16976 zcmaI8c|27A7e9XQEXF>PELlb&NoA{SF{6!A*?LEb(Oae7DrDd0UL@L3DlM2P6-6PG zvdl=K5K5V>V~NQ+7>rr&{rY@=kKdoa-#i}kxOZOXo^#LZdCu$H*Lj`SovW^g9TjBP z$^rnOu-|EqI{;u-PBDNqcI8n2T)%1M5bJvI$linJLLO2Pt0Ue+6-Q&Cg~uoPTa&ZT zN2S@@+uPaMc^9K7$KCSEy_Lq57P>cbHvmDq&0ics&>zNVtNzUp1pTOiHj>cytCC}p zbGc}xEpjOn{Wl*y_6ChhLD3Rv7uJf9J?OAk^PR*OX?0$~)$nolp1Ayq{cjm7Y8ZvN zANBxl{RVE-P6BT?N` zJ~FXG9~3Xh$>&UMz__rvuyuXd-yVH2_8J-yBJDEh-X}g%5Y&kYtiu#x7;^}Il z3~a8Jhy@VOk!wncYdNzYYgHGcjdiOpxLlWX*eBtlj!u$Y(uXaa;Qad9#9D!B|EI>l zDX)ZLj>(o&Z~#lEA#M=+Gm8TdZ`x_jvp;$Z;aA$REqZc$IsPY!AgYJ2dE?duq$f)9 zKh{1Gk+)7>cif1Xss5D2=qb%@6(Q9pv1)h4?61w9$0#|#1t{mUmiK9;UNJz4q&#SZzXER z3qxN#q1K}s`mEM}(Q_Cy|7c5KH5nYI>)n^Ww4&LoyGwK_p=?<3{l>NF)eL=8*_Adw zbpP>pYbR~Yig%v~sg+0mdN%=ex zWzp~`oB{f7eVa3onb_~vslkRGK0!RLJnDeNWc6#Tt%Cs@cEEp8f#tMW0X^bo;~jLp z@#Xa;f#QUwdS2H=FZ6vIa<2NVwEgd0Qe4v|I;YXt8Zj%zOAJ?q(sj=D4-gWuVNSsD zZZza1dQS1e**(yQy?p^WY~o(OuEqRc$G@d2{yjw@Cu;>?NnT&Fd;aGleM1p_Tc5=% z$@mkEjfxPgM0Ojf%RuXfznD)(yY=2wa+DZWXS>o@fE>|HM}t zcUzr;uUoP5PwyQ&&Qfc0#YLRAbIcjo(!`CO{Sb9lt#U@b9i0t%Ln71oL2U5#D!#g8 z)(LdU8Ct7oI?1e6{Ju@QdPmYLG+~m9f0xx}Z_+xcCp)jcUQvS)bwaRZVkwk+S7B`> zE1mf5Vv9n9+M#i&xnbFGiGl@XX6U5LRE3ZDu3E3t;YyXC9^A&e&Nm#D;*vm`uij+B zXGi6;Bvf;Kk{pA)K?6F7Tr~^9BqR816r;)Q;;~Bjb7`t}n>`XnV@ zPb(13Hc5M4XVM-pOtqlI36D|?zg|*=DQQAx-*4i@@taL#Auetz zv#!l1ns$CP`do(Lx>i1@#PjE37c5vZqR$@z$Stv08u*IhJw$3Qc<4A8FBY5~!gy!M zy@jP^Exq14Ns+a=&OX(p$5^Fd1np+vA5G zob$AXcWx3mZ#a8Xo_5^!-6gd)^RHRPRo_!oY7_aM{id(C%pDSVXo;_PK0%#Zz{O{T zPXXJK+U`MXX7pA8gI)Hn84k?kaMV2+LS|tW+fKRn^FtGtIYi?z0$S+!`esNnW~wv&ZIH^PTiWx)9!#^Mv|)bhEjs<+g@61(S`nr4PCXvm@n= za@@qOl66E4?`xDBlC6+AC;!B9z;#4@6uc{O`85-!mHLy^ELlTL<>qCZ7BPvter)ro zZ+?&?a%{lGtX+P%C?nb}#ktc@ycsi_v5RW$aBV;9`_d~F04Aff(F0Cc4e5@or~yA% zd@M`e>1?{=_7741z5{!v%rRf*9X3T_F(FF$ZxXi zWv_EhSC;}Vx?YwXPALAD{yE1V4l4~-q^%L?O9Dw&OiiD>d1kUU<)MVUc|Wkno(B&d z6S6w=&DGz?>z<7XK3;!*AnpEJMWH0>JmrEpApR$PS8*Bgx)Z#i`4kZ1kDxC&II|Oy zb$CAuOo21Fb4jGcIwQACtpXx2Y4TT6!G^fip0d#x(^m1zIXzyF2BnH}^l^Iq03A#f zzNo!fAoXg&5u zW3LI(RvuBj6L$@Bs$F3r=#fZ$&c%Yl{G7Rt=EM3R@5dvu|A2u&yw^Hf1i)z zqo{pz1m8qK-`1r9;s_L-2-R_z^EYT75|hoJ$@{1t6g^B-^lux7f!mJ<2rtC;r+Aj$ zuFK~}Jq7dfa4%=9se*2?_Q&Fs^c$P~$gtUu&SWFnsRohs2DuBzbR>JkQ(?TB&4WRc z@tZ%5(x(wON!AWSz!-o2!B$gm;e|i@fS-~KaECiDsd3a)S$1bRy>5H(`>?i;J8!dd zhiQ6P*I6dd3AK`APoP$7dZ0sV7~X`rI${}9PaM7qE@W=G3n?Mv-bhOmhN>~Iw}E?% zb8J@pV5#$3}(?@PIe@#{hD;|C5sz_~6u%CqX3 zn^{yMj^@W}&T$a?OVM?HOdg+?WIH1>Y<99xr_rzR>&-ufHmFFO$A#xeV1?u~M)1+}eUT zZda~io-PMn&EV6>quYPmKE{lvT!&I=-Z+*k>)v@}{WpSerd|hONc>&lI}%Xb{3EOX zepslZI5*7zxo|Z;?5(F((`3*XSMYsu##h8>&lDEhVRUVRoi{+<=AsT^kayuyzJ_0* zGoUMWvFGjg-1hCqq~4jgKW-?g(lm6}DAL%L=+DXYG_;gh9wG04b^}U`Ah39t$FoTz zY!MwDxtezoSeEqZQ4m8245;CSO0IBdNPbm(sCdO*A_j zs!-UZSG0d8$-N4I?y?VWm}im+Sl=412cnXSLki?HSY^xf?kki_%BdZr%-?8W7I4H! zT84FBoRmZ&T@nstd?o!v7x~O>gJc_^>}GNvZE{L=$_99~9QiuOL~YWKpMN+$VTkFB z*%-$8#YRpo(a61@>DI#4dDJy13<8L=&5(xN#9E&{@3&w#xAUPfby2CXZHLgm0lEW7 znY`-0=MGyhqro3w*X0YAnuSPD!AS8>XnBbBPsGLefs94NA^P~OEhn5wMh}*sm<+w3 zZbE+Ce~cV;rtAX6b;NDUYS-YKooGh|y+v|GXd>emsxDWrouIIK`( zGz9eUkkA*DE?@1{3 z&HGF`#}A6275ycv3TyuwNb8#5_s@9RFP?jZv^UT%EaWBXyaqO}!=G22mWdD8;Wq7O zN@)w6HTx&QOVhpW+A za{|YOxssC22)71`ne6f(sxPN`O$^0sIE*~bBd67&X9AC)zrN7diV}DOenj@E95w#7 zQA1U->%H!7q&J!T-%R9SH=3Y9KCQ{pUPW;LQ0p%0IGS8)@XCSI}sCN()dhFSmi2y>NUpS9_>`?L4=` z+v_Ogff|!}+_v9Bqk8gm8jz;qca2QUe2e@Rk_sR%N$Ko>GWOt0nquSZHew}duT;sT z#j0Y^qpt6iiT1%wYc18PH`3G= zGwC6lCneMZ!sU&?g4n*d#pPCH1#s^<;{EGiz0~o`Pnid z1}+Eh%nc4~2eq6Xj)>wbi$%Z9FOZub5JTrf%TCO7Krz2=L_eye-;gKNs*9s7{gjZe(yk~#XB&mHe0}Tcq=vL4(|_3SQR*Iy1oFwle`K|2nv-h4g&{! zA2}4C?2e=QP<)15@Nd>LKZmw~KB zp8X3n7u++N*y*1O1SQalYVV-I={_R8kEqkKy6B^#7-LmE=X^sVz!)&L;+M4mN60&U z-u~&*^>hjQC91bLk&Q85;=H}}QFHg@{q2vSEbsJZwAA?Y`dUHc`#|!)nV|eE)tnOd zqV2qR@IB&x1o-un{6S!_8vcrT;5wSq^T|R_=czn4W*6|M8813XHdtI;RmTr{!}P)F zpeIs+!!{+qN=Z&4@8|sCc-BEoAn#cef3sa}cUW;pR~`9^V7;U6cNg@2hfAzgciqkS zKY*DL;@>&HP99CQw_Cp{!0YRgabuMQw=cb{P;>T}?1KrZ&Pd*p>9hE$B42rENk6-U2T7y%n@l}UjVOtl8 zaGq$leWoNentT62MmYO4a(lZMz}!g|Q^-0Pj1_ z)g7>0=sT_$$9^4uY^#qvV8Qwj45XjyyMJzAJ>fAPt=!Hz*QqIQ`a`~5Z@jHvd|hQh zjeH^-*oHq}IXch~Kh}8rJgsSt^aoK!hOV2wD*H9BTs^#_zMmn|h5olkdVQCk?{i51Y{%uD ztX7zu-{3bHI&PA zz}~@eGM8@h(w`KrV%@^Dh-h|O#UtP1f0tPPrdj|~J%={j)<1i9=I?~YX<)go@>7vo zY%-*h$tKqgNZgdv@aI3d2v6-Gvyx2|rMwD3(@)d{=#9?L$cC3^s&;E0{gz4V-;)}G zxY-kFA4q{LOYkjHD|@F%TRYae_ir`V(O zG2vpDXAA|zKuwZsOpOu*no}Ot#NGorO@{+w4S%=sEj6)sB7(Q0d0xQ@!=X{}gpEhw zaHP!>y;nmmLj5{T9$5k2KU>esn-*qGY`0@4>Ug`1Akv5956v-GVXW>ZzOK^Ya#QXC zfuW+vLq}M`6H@m(7B{aRy#pRho+;#cv9~YYmAk{V_WBN~%-g#Tk}GAz={CW`m2;4P zjt)cW?{@B?{MiS-LH>noT=XU_Z20i+^H+l^}cBY&JdU8gTd-L-dVk#_KvL zQ=kTQnd7x84Gwlzoi6ZQhVO7cAO3d!N)stS_&_0g`CSb=dOTeYO~hPzHw;MOOCo8h zU9?xfD@eyA#S7b_cAWeqxuMxQel(3L`ljB^?e5na-9WKrvuiQX}67gJSL-Seg!HJrmXi1_7?=o`b~>7 zUdQ1ck*q*UU)vAJOd;1njipR!4}W{De;On8yUa9p*NiK$jUTcQ>2IL>1Q;FGDe|n{ zn*6=(Gir_JZ{WjyxPU&_CE-EpX%+=aSw9npYuoj@RZ1 z;3X3(ruC<&geaSu!BV;sKS4kyM&$zQ2Z4>5NYHISR@UnhX|aAB-CnbB(_3=Pna{*d z0P?@-xBetE=-JLQ0jmJJ`TD1*V8a^S&G`5w`?^C-~#d4KaIKCMzr-=Q<)kb z-Ii|?s94GjgwgDOise7BC6B0by4k{nY-af<^mW|fxO)~G!f<*YXVwk&jKD1wGdJIm zolr|>;H64fuJG88@AMYvUZAb`nOvvw-`;WB$F8|87R*cl23#4dr7GRT#|i&d5AuV$Kxw?!^h#{eV5lN*cb0ghi<=X0Wm~|OqMEAxk=%Ml z3R(X0AF>DLD6cV+0_3~9j!6`t$?G49FUhf^`4@xl?+=)&z8xiZmG)okS_dN3batLz zjC5qh>cV-7{0U@^&n)kPHX`e=?M-ykL7zs;;~}!fSo!P}#6L|OIHcz``h&`BZ0IH`T=Z3S+fdl^$rQP9b(fiTujQ2pp z=h~ytGr3ckqUTR$T>H%2wwklbONL#r^PR*V$w_t2FB!^HV6Z(uXtwx0sxC?*!=zO#9rxSsX=;5iu_yIXg@Q*sTquUiwq4iGCtnQ)yrQCH{Lj zZ7d@|!_Ve3drYt!?{}3Jp}<*`VK9Kk#v1h$rnWpIp}1BXHcgcAd;j(@8hK*QMB1+_q{UkU-kn=V5{HiG zgW{sL`*sUza`vXxngsRl=`qh+siMcleQUR)rt_<%xJ3-Q?1i|ioT~(i9YAx(QJ$lh z2BCBuu+eXe&r(g;B<;;ObBh$uhw%&*w8%Q}p|nPhLmsn&W>Hkp|-Gm73r3?wySFfHAh*tG!2~Uunt1M7D`5 zNTCbNW}yIF@Dm_Zd^3NZU{m>eS+l^Xt}4+tNpJkQgpG z0oHhF(!%gK5}HY30k$o`+s)}$N-txSuwFJxm!|@%KV%uP^npe58uB%ayE(a_^o^68~%&e1WWR3hnwm!^|oPf*7nGWcY%|} zt}MlQ<{3bJz8f!J7x1R0?6JSp;*GDiE}ZS)p3*R0{S$Qh4lw7Q(X)J_`x=^KjW+(I zUxIUQHRoI06J8%UIHAfv?-F#TE9x-DkIys^W{yvA{@72YtOc#h$kW0{dE`tmX012x z>r>MsfW~zDHjBc&{rYJSigABzpUToZVu@W1>yR+>6qZH zl1muQMH!Bl?8kn(<7}H7a~IvJPQINvml!H1)F@s$p6F`~r)pr1UtSj4#hd3Q0i4+}5FUtJ~}byAi4LSzcUINdb@$8h+yFnAMdAG_a>8?aA< z{3rtZ9#b2oDyuu^E1~S-{i$uG^=tl;>>JA>)Ru>B3az=Z^ZVk|SoDpZV(aVc^Q1~H zLwhleV-q>H6zT}7{Z8z76gp*S#lB?c(Vp4WhexVE(iF$8zIpin?gcRN0~#gvvW!cK zbx9#7x-`I%YlNXf z;+gW9<~BHN$VDe*#a-Idg{^;?p9$u#6M8;=8tuJLpI}>-ePqQpncnpLv|yBal}hK767BS2eFSL%NF zz^5d3TSzpq!%)%8^N5+LCGEmE)%K&m65tHF0@HC{$V7DS>`il6Q+&+CR_o1<&vv|P z(RZ<?!t95_3L>A>0ABf*pfn@?(8+ub_kvZ9C} z&$oOq(H^u{^oM>8xLw!Woae?;l$`WLyKEn=z9Y*Mv>ImwtQBJqABYESJ^pU-d$#efy7guGY9}8bAF*?oA0mIRxW*bTJfdW zX>uaq?}i6?3)qrId7cx_mCNdjY4u$kJOfQh-6gWMfkdX))A7JG=%Gw*T%qYjrDf<$A^Xx2} zZIXDceqGxK;;xZO2&_c<9;rn~?tE5pdNOoOc6xIX*$~_uwyM&qB5})c(t{_EF}7v@ zYx?jI>FKriN^_z2SA`LEBk1DGVyfL0;wWIKUFrW?{Lho1EiK4PURPVMf~uY7gx<(@ z{^zpBU^IKjoKm&v&)s2Tm_^~O=*hU35~u(m-2|?=2M73yrHOIxV<;IQOlYyK*!hQ=9$%(WS?S=WTC>C&nT7+X&NG&Ne>D6-;ywCd`NyxX6osG9TXi4RgJI_IxT! z_|F_+En^RKOXvP``?Gz+JH8#+)#J2yLfmHIDZmaAXQ6F)uX~AMgV4>xaYfqW)M09T zsD=a63HVz#InrW;Z8;=}uD%&`AC%GwK-Hz9oG?w{3@>p{Cs_uO73C-_&s}}b}$=iluK?fYMLaS2Yquh4;l zrTi0|1-Ds9W4e6EdnWrYouRO-16e$!9(c)26o=YoB-Cu>E>EUqCs178*oR$<{*6uT zYe{F35rfimvuH#_ICF{+SxfY7Cq2YKPW##!1>Us5>V zQNr>eB(B#@7Sr7otPG8{)T090)m{cER?z2C5(58pHAz0xk=?ee=Iy}FCZW~;}|D&2k{&aCDscS zzAJi#7a0jZXkfmSl;iHV-HcLGt~oK}&`KQgt=S>1TldcX7A^z8^W+7d&lvH1$2{s$ z(5OqC)C!$_@GSSyE?mCTZ;du1IPO}X!$z>FgVZEBfZs^~Rh}_WE-@nh#51zT(tbt1 z#Y+$F2Mp5NR`vKRZ#*asy#|WDqL~W0STq|mnYR)&t)AEJn@JB()cMgktfKQPS~^-@ z9Cla^ya(L>P&^c$ffKq60ntWWM=*6MG8aSH0EZoRj0*h<+~MYjZWtY;9zG<+@njw| zgx9djlqlQR@HHe;s&9W2rO`RIS|)0(kh)!TX*rMRUz+j!!TRyPOk8*a zQ57~{JV{6LzlrH9)xIgNDcvwO349*fzxw%3(CYvskCttu901>T41D{&c)F`rHAWC< z1FR4F3Os$7^*A?13GNq`Z9_Nl^YXdi7Zu$b$cex7tw_%k^0)1}k7G~#Iux=!s6=uE zr*kj4x8KAVH5Sm*fwX%c9HFC9P6^W%K7Q*eS=l9aqay1UqjtM#UzI8UekGUj3dfoG ze?ggNoLyST@5Ol4NuFVa5-UO4ep0TyXelE$dlr{*{}Jid8Fb7YW~da|Ku?7!9`u|O zi+^oNs=6~KIDR_S{NS($_QEIZTbRBUtGfr_JvTWsWovHa$2%{ehjB12aC{2#5Nvq{ zJ&=NNjJ|B6uJ$F}SQ1955Hcl19l!uK?Ua@60ApBwCB0P8=s@yRW}QX$Z>P_8o2Z>C z9}eUrtEStWfxSjex#BlwWFHi`PBswA{U!`qpTkIIR3zD_q z+$-R4NAWh@|0Z{QSzHftG|`dK^tXedHWVlzdydZ*pL`vc@djFjge*K6+f(f@xf_!~ zM7S70$jVe+G4*$(?c&J=Flur2e`II55?;bCOl5t|Eh2*-bPn;CRo`ih>@_-j7VZ03 zAxQbj+`If)HtrAL;nr=bu#yzDmr~1?lNOnqCdjX_*Su%<7MRX- zH|3Ce#|f>7%OSu~)|3mq3-(!1DtTxHiy!_h9&ghFa>X~loBVH~buD|Q`kVN# z2lL)y&`-Sm5NTA)C~0$eqdxO|#!^LPyg+XSE73hb|k-YiuGmm}pWm)Dl8;aFoza)j3f0wONB zGvV7KU-{q6lI`(+Vl2kW5j)*M(w>ZMSZzN1)i7e-;tq_#vm==ALkGO1OV%*HBJb5c z9ZJ*zYQ|`NX zT{LqUKJ-VsaBfV1z0gg%fou~RVENf*#ow2GnflBQ2WDe5 z+#@RKq&+5_8mBnV2DM03zjaXMnWHXd+~sz9DD;l7A3OlZtA43jNewYzrL#lj(iW#C`+A~wJ!+8GvAze6hBWycoP)r;C#r%c7KfTh)f0yhqG@^dL&fg?El|>kL<$~ z+G!IYk35OLhE0v=!S`J`-!fykzRX7m~3Y(r4WzF*r>Zu!&69;sPnJ3x-DH%BEO#0 zcxx%)@Hf|(`FS)&e<%Z!*D_pnHTQJogX~QheIUfcJ zM5N_%I1!@~?)NoU9IApEZ4t@KHjV06S!}71#C>}cKl>6#E4E|s5;r?k(0^RQNE!0GlRD2Q_r$#|fK>{FDI#`*nBcoF>@{b(jAd&zXi9(XzJ^;!D> zZ$3Rrt3`(05IBO3g%GO2HDH&_StEQ-1vzwFEep+7<8{~WB1@5Y58Uns2w1g4QU?H4 zHLp6g$GCDg%6R0sTr6gd#EgzvESUFHf=<*?X_`t8@@Ea#W+=m_mmXzMbb&x4uGQRw zhx^IN*U2~bQgBD3nUSgOhNAIw0sdB72L&IG7=$*`)*!}ru^5mY&hQs%W_pu*JE(4O znj~A`&rg*nz^OAb*dqfsYl32By^@U>E=EobG`abYZR|Pe5rhzyw5z|@xmE%|v*t~e6diPZErCs*~X*2-4;*(j4akHe* zpUh3D_9jX+MnQDnW>VbE-gbGEl5}PBRct7z_iD4>t_Ff5`ggu z3i1KfIu|mPxe8t73SJfur~U*rP68Mkzr+@7+#%%85_}=YJ!2m16{TzI0V6VdkQX+l z4T?ZQV-B?i=UYgEfn7xI3E5OPiOX^L?GW_~l!OdBnHPW#m2K;=N|;owPNr-iu!T#R zZh_X?hB9AB9t#6@f>|+Fh-X7dVy^_x!glOSAKCA_(UBHri)58DEfw61CLkjZ ztep;c3T?K5@exFf7pUl!a9{-xg)qi@;qcF8e|6ScBpJu)pbtM}1&m|MATO*{vC6iO zq#HDM`uKn=dQU#%&RW-9bS28j4=hjvQ-BI1-7|;d^QXU3_XB1E0~063SaRqB&C^Dv zKwe47Za3k!#Xtm4uP5&S`j%I$4{(G+1He7Oc#9Mk%=VPM7C3M&N05?3cEjoaqscvi zampC2S2n!^kGTVDCC9Hr5u?`~YfGi$pLA11^9O*PLTA6_cPqf%+=q#pHK}lnzbhxe z`Bi-C0^{B@;I51(_S5=F46iEFY>N9h2o%t&{G z51su4crT^oE`H00x~E##DzUDehQG@tV$QqD4s}4AmXKCeivCvGDz39KH|G^_8_X^-xER(WKgL3(o6jl~j&FGB* zM;`(0?3De;V?t-5B3~D%1ybu4Q+mO}cP#X4_Ia!z@grABnqiG+cS5Jm)BgKRa$Mv! z(&sgD@&OJf%YVf-H;q_%f7{le_vWe34Yf!~F*u4Qvj`#E?~-BfGU9GUPR|B7YRB1T z|G-k-q|Ya;Xkvo*`At_tr@xUWamx$fR1ej7D;6jIz<`_H@Ym$ckr!RjKZDFE3*QrgolTyqimPSBdDx!u7^>J zf$t}EP`RK_B4+&t{+H==J7o1P;DO~21(u{rj|{{OS0q~Is5=n1j>td6AO0Bays5k#n%hQ?EmyR zW6wnK4Ed6BS!rDRKSt^@*U5|1q=(3!UP=G48aw!Ir^t9RdI_$zEPa=!@amav4X^bD z^0ES2vpn0?)y4cVPe&r+W)~(-?Z8lOl20yX#Tki~4!yDLuOfW{`_aJjGmb9m#}7D6 ze|Kq?y03$d4Aj!RH_uOiPFT**fdQQcTb9Vw3RuK^lkt5l%_@XSPmf{$L!lk#X~)*E zWOGHMolFVYR}xe*)6)Y5)qw?O_NJ!)G1&oQE)%uvv@|Ec*a4@zFtZmJ5OgjNEOCG$ zqWUwx%R=Pvv|%gV#MZ{HM}^fPa5+k~S7doeX3+^#D>y|?{zei>#}EbNtek}Or@)Cv z(EHWdE7ZE#K{~0!JHKT`HF+_5;;8tx?o+AQ79o9gGTsF{#=$lPfplJnot zYR|!*C93baWs97YVJwp4jyz=Jw%G!H2z}cvsxZG@LD2eG^nY{!8Budbla0&uLDD)x*fcP%a9a&JH|-KP z20T@2sT4FWK+VcL@Hm)b3p|vas|$LLK0Peux}KGfv`q~xEAtL5t|+uv8vGa=GEB8v z$b{w_nJwV4k2<1%IE7tqfh)|XIHG6f@K*fl6OuA(-50mOms%OYH6+2CH^qzkxK7 ztW^(q*q&E&RBEGh-Q`$@zN;-Z`x5*NsZZm*`$r~f$(nH$tL4L~*(cThj1e+QYM`A& z$E_(Q{+47vY>A#s)XXdRj3TRWz4Lkb%Lq9vp&&xaN;NS?_PieaG=7Dw(%uP9>i8+0 zBVS{`EmlOkeHgoN?XRG3c(Dwe1)J3FSvsQVCo(Y&YJn#tFQ%zsXQTuY+v8@#qI<@*{v*X5Gu-lSlSc_lvLHUdaQ$Fur-e;wiv| z4{`0quOhCvOaTj@W{tH04PMt;+$}BO15@T1dPSKhVWK*wgz`b4KIWuZ!G~Io+}mOc zEsh*3S80kKW(>}JSkrz5D~+!Dd+6_vU(lW!&JB6jKk(&ru?yZqAC;G8~W!jainn^3^kVDSO6 zvI}@cH8aFch5`9XRrVaE1gvjgrIe(9u0m>KD4a^$EyJw?A`gH**08b86?cqPp+bS2 z!|#Vq6p})4zIll;A*27MB?B8Rim&~0ol%S9#d^h#M6a0fwM~M%{)@;cc8t`8kR(B%jF7|i^Ok5E;0(``SujN_plxeB0Hxxx>msrfB z(j2o;3YHL67<*jU6(ol*+W8+071lE?Wb2q0oLG(*@Y!QPV{GE)cQ|Vc;3?d-2^-Z3 zKz6KyHn&$6bU9PAS{&PorTNS4miK~ED0uO_71o!E)1Pvp^x(nB&Da6knzgQ9fyNlfHH%{~hrwQ42yhO$Hp=D>4!N4?G8G(hL|in^cWVOels zEz7VJedP!+|EuvQ-oy5rc;IaOXI>q?Fy>=gz7@1vVJx$uw61s)$2(^_Ey#lBP0-+U zTw;l~uOw{qDGOJsbFDd^6UyzDggD5ZQ1A%stU`|leH_lhepm++0`b+LwRp5Xc~^Iqci-ut^w)KPo*Jx~ zLz?z^*lI7uWN#ymci$nGbS+bH-&I^(`O3wA{s{Q&!!%&R&xD*nuG zR&%0vvry+fu-~TWDyaqRPd7~N?=K1)li6!Xuy4Bq&-k4AR22$8K1;jy!t4Ol#+)DA ziBXSud6mS=r4+^o-f&L}q<^~u=lu61AQYx*`-r|@!B&TFy3xP#-fb4x{RQmX&#JnW zuu=ea)L`7z;=TGIA55}lgc7)$u;sU~AMU_Q>#{_FGLR!R7}1K{qnQ5vid;5m(*oRll;Gpc5@jT4+fq_A7$J(>7lJ{wBD2IHh+R8`ad2ZN!u|IaV3FQz|Pe)1P+(+ad|ag>#LI+rN#6nTX! zJ83r(PVB<;C;g8q%sB&ZXk}4N)V=`k=-7)@vVwp{ro)P`#m_Guujxu6XdJ^hLjj%v+3Ba24E2RfAfo=oHYpwmsp?mIaAH7NBuIB zRoa~YdAk)ctY7A_W*gXN%PMhrvDodVc=r0;foZB##0)St!5Y?F32smK%CK9FI##Yy z3x-c7xwjqy(brBu?df{ndu`4M*`~YQj3g~yVa>Z4B$Q>K#W|>be|0!>r77ZX+1;78 zmD?-a>1If@+BfJ8#4A>&Vzck!4m{C$>nlwQoR`E_MQTK85Y%^Mj2Btd3t zu-Uso+5CHV+r$>1q_=zfIaZ4 z{}1D@@5w8bkV&}Fu#(+~@ke(~JzxB}Z$48F6$N?U+z~JfX=d#Wzp$Pz2T}Pk* literal 0 HcmV?d00001 diff --git a/examples/assets-generator/pwa-assets.config.ts b/examples/assets-generator/pwa-assets.config.ts new file mode 100644 index 00000000..98d243af --- /dev/null +++ b/examples/assets-generator/pwa-assets.config.ts @@ -0,0 +1,26 @@ +import { + createAppleSplashScreens, + defineConfig, + minimal2023Preset, +} from '@vite-pwa/assets-generator/config' + +export default defineConfig({ + headLinkOptions: { + preset: '2023', + }, + preset: { + ...minimal2023Preset, + appleSplashScreens: createAppleSplashScreens({ + padding: 0.3, + resizeOptions: { fit: 'contain', background: 'white' }, + darkResizeOptions: { fit: 'contain', background: 'black' }, + linkMediaOptions: { + log: true, + addMediaScreen: true, + basePath: '/', + xhtml: true, + }, + }, ['iPad Air 9.7"']), + }, + images: process.env.PNG ? 'public/source-test.png' : 'public/favicon.svg', +}) diff --git a/examples/assets-generator/src/main.ts b/examples/assets-generator/src/main.ts new file mode 100644 index 00000000..fbff1d52 --- /dev/null +++ b/examples/assets-generator/src/main.ts @@ -0,0 +1,17 @@ +const date = __DATE__ + +const app = document.querySelector('#app')! + +app.innerHTML = ` +
+ PWA Logo +

PWA Assets Generator

+
+

${date}

+
+
+` + +window.addEventListener('load', () => { + import('./pwa.ts') +}) diff --git a/examples/assets-generator/src/pwa.ts b/examples/assets-generator/src/pwa.ts new file mode 100644 index 00000000..1afc1ec5 --- /dev/null +++ b/examples/assets-generator/src/pwa.ts @@ -0,0 +1,15 @@ +import { pwaInfo } from 'virtual:pwa-info' +import { pwaAssetsHead } from 'virtual:pwa-assets/head' +import { pwaAssetsIcons } from 'virtual:pwa-assets/icons' +import { registerSW } from 'virtual:pwa-register' + +console.log(pwaInfo) +console.log(pwaAssetsHead) +console.log(pwaAssetsIcons) + +registerSW({ + immediate: true, + onNeedRefresh() { + console.log('onNeedRefresh message should not appear') + }, +}) diff --git a/examples/assets-generator/src/vite-env.ts b/examples/assets-generator/src/vite-env.ts new file mode 100644 index 00000000..6b7c24fe --- /dev/null +++ b/examples/assets-generator/src/vite-env.ts @@ -0,0 +1,5 @@ +/// +/// +/// + +declare const __DATE__: string diff --git a/examples/assets-generator/tsconfig.json b/examples/assets-generator/tsconfig.json new file mode 100644 index 00000000..8ac85597 --- /dev/null +++ b/examples/assets-generator/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["ES2020", "DOM", "DOM.Iterable", "WebWorker"], + "useDefineForClassFields": true, + "module": "ESNext", + + /* Bundler mode */ + "moduleResolution": "bundler", + "resolveJsonModule": true, + "types": ["vite/client", "vite-plugin-pwa/vanillajs", "vite-plugin-pwa/info", "vite-plugin-pwa/pwa-assets"], + "allowImportingTsExtensions": true, + + /* Linting */ + "strict": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noEmit": true, + "isolatedModules": true, + "skipLibCheck": true + }, + "include": ["src"] +} diff --git a/examples/assets-generator/vite.config.ts b/examples/assets-generator/vite.config.ts new file mode 100644 index 00000000..67ab148c --- /dev/null +++ b/examples/assets-generator/vite.config.ts @@ -0,0 +1,42 @@ +import { defineConfig } from 'vite' +import { VitePWA } from 'vite-plugin-pwa' + +export default defineConfig({ + logLevel: 'info', + define: { + __DATE__: `'${new Date().toISOString()}'`, + }, + build: { + sourcemap: true, + }, + plugins: [ + VitePWA({ + mode: 'development', + base: '/', + /* buildBase: '/test-build-base/', */ + strategies: 'generateSW', + registerType: 'autoUpdate', + includeAssets: ['favicon.svg'], + manifest: { + name: 'Vite PWA', + short_name: 'Vite PWA', + theme_color: '#ffffff', + }, + pwaAssets: { + config: true, + overrideManifestIcons: true, + }, + workbox: { + globPatterns: ['**/*.{js,css,html,png,svg,ico}'], + cleanupOutdatedCaches: true, + clientsClaim: true, + skipWaiting: true, + }, + devOptions: { + enabled: true, + suppressWarnings: true, + type: 'module', + }, + }), + ], +}) diff --git a/examples/preact-router/package.json b/examples/preact-router/package.json index 58686711..bb749c79 100644 --- a/examples/preact-router/package.json +++ b/examples/preact-router/package.json @@ -56,8 +56,8 @@ "@rollup/plugin-replace": "^5.0.5", "https-localhost": "^4.7.1", "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "workbox-core": "^7.0.0", "workbox-precaching": "^7.0.0", diff --git a/examples/react-router/package.json b/examples/react-router/package.json index 9bb2135a..2641a7bf 100644 --- a/examples/react-router/package.json +++ b/examples/react-router/package.json @@ -63,8 +63,8 @@ "@vitejs/plugin-react": "^4.2.0", "https-localhost": "^4.7.1", "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "workbox-core": "^7.0.0", "workbox-precaching": "^7.0.0", diff --git a/examples/solid-router/package.json b/examples/solid-router/package.json index 56ffdf2c..5af06ca7 100644 --- a/examples/solid-router/package.json +++ b/examples/solid-router/package.json @@ -55,8 +55,8 @@ "@rollup/plugin-replace": "^5.0.5", "https-localhost": "^4.7.1", "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "vite-plugin-solid": "^2.7.2", "workbox-core": "^7.0.0", diff --git a/examples/svelte-routify/package.json b/examples/svelte-routify/package.json index ec6ade3c..047eae40 100644 --- a/examples/svelte-routify/package.json +++ b/examples/svelte-routify/package.json @@ -59,8 +59,8 @@ "svelte": "^4.2.5", "svelte-check": "^3.6.0", "svelte-preprocess": "^5.1.0", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "workbox-core": "^7.0.0", "workbox-precaching": "^7.0.0", diff --git a/examples/vanilla-ts-dev-options/package.json b/examples/vanilla-ts-dev-options/package.json index 85b72619..ec71cbe6 100644 --- a/examples/vanilla-ts-dev-options/package.json +++ b/examples/vanilla-ts-dev-options/package.json @@ -21,8 +21,8 @@ }, "devDependencies": { "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*" } } diff --git a/examples/vanilla-ts-no-ip/package.json b/examples/vanilla-ts-no-ip/package.json index bb9a2d62..9d0a1d37 100644 --- a/examples/vanilla-ts-no-ip/package.json +++ b/examples/vanilla-ts-no-ip/package.json @@ -18,8 +18,8 @@ "devDependencies": { "lodash-es": "^4.17.21", "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "workbox-cacheable-response": "^7.0.0", "workbox-core": "^7.0.0", diff --git a/examples/vue-basic-cdn/package.json b/examples/vue-basic-cdn/package.json index 346bd730..07a2fd17 100644 --- a/examples/vue-basic-cdn/package.json +++ b/examples/vue-basic-cdn/package.json @@ -18,8 +18,8 @@ "@vitejs/plugin-vue": "^4.3.4", "@vueuse/core": "^10.6.1", "https-localhost": "^4.7.1", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*" } } diff --git a/examples/vue-router/package.json b/examples/vue-router/package.json index fee4b772..5ca41356 100644 --- a/examples/vue-router/package.json +++ b/examples/vue-router/package.json @@ -4,6 +4,7 @@ "version": "0.0.0", "private": true, "scripts": { + "dev-assets": "rimraf dev-dist && DEBUG=vite-plugin-pwa PWA_ASSETS=true SW_DEV=true vite --force", "dev": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true vite --force", "dev-claims": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DEV=true CLAIMS=true SW=true vite --force", "dev-destroy": "rimraf dev-dist && DEBUG=vite-plugin-pwa SW_DESTROY=true SW_DEV=true vite --force", @@ -57,8 +58,8 @@ "@vueuse/core": "^10.6.1", "https-localhost": "^4.7.1", "rimraf": "^5.0.5", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.10", "vite-plugin-pwa": "workspace:*", "workbox-core": "^7.0.0", "workbox-precaching": "^7.0.0", diff --git a/examples/vue-router/vite.config.ts b/examples/vue-router/vite.config.ts index d8fc1b7a..00719547 100644 --- a/examples/vue-router/vite.config.ts +++ b/examples/vue-router/vite.config.ts @@ -6,6 +6,8 @@ import type { ManifestOptions, VitePWAOptions } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa' import replace from '@rollup/plugin-replace' +const pwaAssets = process.env.PWA_ASSETS === 'true' + const pwaOptions: Partial = { mode: 'development', base: '/', @@ -42,6 +44,13 @@ const pwaOptions: Partial = { }, } +if (pwaAssets) { + pwaOptions.pwaAssets = { + preset: 'minimal-2023', + overrideManifestIcons: true, + } +} + const claims = process.env.CLAIMS === 'true' const selfDestroying = process.env.SW_DESTROY === 'true' diff --git a/package.json b/package.json index a471e21d..eaaee594 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,9 @@ "./info": { "types": "./info.d.ts" }, + "./pwa-assets": { + "types": "./pwa-assets.d.ts" + }, "./*": "./*" }, "main": "dist/index.cjs", @@ -105,11 +108,6 @@ "test": "nr test-vue && nr test-react && nr test-preact && nr test-solid && nr test-svelte && nr test-typescript", "test:vite-ecosystem-ci": "nr test-typescript" }, - "peerDependencies": { - "vite": "^3.1.0 || ^4.0.0 || ^5.0.0", - "workbox-build": "^7.0.0", - "workbox-window": "^7.0.0" - }, "dependencies": { "debug": "^4.3.4", "fast-glob": "^3.3.2", @@ -126,6 +124,7 @@ "@types/prompts": "^2.4.8", "@types/react": "^18.2.21", "@typescript-eslint/eslint-plugin": "^6.11.0", + "@vite-pwa/assets-generator": "^0.2.4", "bumpp": "^9.2.0", "eslint": "^8.54.0", "esno": "0.17.0", @@ -138,9 +137,20 @@ "solid-js": "^1.8.5", "svelte": "^4.2.5", "tsup": "^7.3.0", - "typescript": "^5.2.2", - "vite": "^5.0.0", + "typescript": "^5.3.3", + "vite": "^5.0.12", "vitest": "1.0.0-beta.4", "vue": "^3.3.8" + }, + "peerDependencies": { + "@vite-pwa/assets-generator": "^0.2.4", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0", + "workbox-build": "^7.0.0", + "workbox-window": "^7.0.0" + }, + "peerDependenciesMeta": { + "@vite-pwa/assets-generator": { + "optional": true + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3dfa617d..c2efc79c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,7 +26,7 @@ importers: devDependencies: '@antfu/eslint-config': specifier: ^2.0.0 - version: 2.0.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.2.2)(vitest@1.0.0-beta.4) + version: 2.0.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.3.3)(vitest@1.0.0-beta.4) '@antfu/ni': specifier: ^0.21.9 version: 0.21.9 @@ -47,7 +47,10 @@ importers: version: 18.2.21 '@typescript-eslint/eslint-plugin': specifier: ^6.11.0 - version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2) + version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.3.3) + '@vite-pwa/assets-generator': + specifier: ^0.2.4 + version: 0.2.4 bumpp: specifier: ^9.2.0 version: 9.2.0 @@ -83,19 +86,19 @@ importers: version: 4.2.5 tsup: specifier: ^7.3.0 - version: 7.3.0(typescript@5.2.2) + version: 7.3.0(typescript@5.3.3) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.12 + version: 5.0.12(@types/node@18.17.14) vitest: specifier: 1.0.0-beta.4 version: 1.0.0-beta.4(@types/node@18.17.14) vue: specifier: ^3.3.8 - version: 3.3.8(typescript@5.2.2) + version: 3.3.8(typescript@5.3.3) docs: dependencies: @@ -152,6 +155,33 @@ importers: specifier: ^6.5.4 version: 6.5.4 + examples/assets-generator: + devDependencies: + '@vite-pwa/assets-generator': + specifier: ^0.2.4 + version: 0.2.4 + rimraf: + specifier: ^5.0.5 + version: 5.0.5 + sharp: + specifier: ^0.32.6 + version: 0.32.6 + sharp-ico: + specifier: ^0.1.5 + version: 0.1.5 + typescript: + specifier: ^5.3.3 + version: 5.3.3 + vite: + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) + vite-plugin-pwa: + specifier: workspace:* + version: link:../.. + workbox-window: + specifier: ^7.0.0 + version: 7.0.0 + examples/preact-router: dependencies: preact: @@ -163,7 +193,7 @@ importers: devDependencies: '@preact/preset-vite': specifier: ^2.7.0 - version: 2.7.0(@babel/core@7.23.3)(preact@10.17.1)(vite@5.0.0) + version: 2.7.0(@babel/core@7.23.3)(preact@10.17.1)(vite@5.0.10) '@rollup/plugin-replace': specifier: ^5.0.5 version: 5.0.5(rollup@4.4.1) @@ -174,11 +204,11 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -230,7 +260,7 @@ importers: version: 5.3.3 '@vitejs/plugin-react': specifier: ^4.2.0 - version: 4.2.0(vite@5.0.0) + version: 4.2.0(vite@5.0.10) https-localhost: specifier: ^4.7.1 version: 4.7.1 @@ -238,11 +268,11 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -278,17 +308,17 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. vite-plugin-solid: specifier: ^2.7.2 - version: 2.7.2(solid-js@1.8.5)(vite@5.0.0) + version: 2.7.2(solid-js@1.8.5)(vite@5.0.10) workbox-core: specifier: ^7.0.0 version: 7.0.0 @@ -312,7 +342,7 @@ importers: version: 2.18.12 '@sveltejs/vite-plugin-svelte': specifier: ^3.0.0 - version: 3.0.0(svelte@4.2.5)(vite@5.0.0) + version: 3.0.0(svelte@4.2.5)(vite@5.0.10) '@tsconfig/svelte': specifier: ^5.0.2 version: 5.0.2 @@ -336,13 +366,13 @@ importers: version: 3.6.0(@babel/core@7.21.8)(svelte@4.2.5) svelte-preprocess: specifier: ^5.1.0 - version: 5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.2.2) + version: 5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.3.3) typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -452,11 +482,11 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -470,11 +500,11 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -501,14 +531,14 @@ importers: dependencies: vue: specifier: ^3.3.8 - version: 3.3.8(typescript@5.2.2) + version: 3.3.8(typescript@5.3.3) devDependencies: '@rollup/plugin-replace': specifier: ^5.0.5 version: 5.0.5(rollup@4.4.1) '@vitejs/plugin-vue': specifier: ^4.3.4 - version: 4.3.4(vite@5.0.0)(vue@3.3.8) + version: 4.3.4(vite@5.0.10)(vue@3.3.8) '@vueuse/core': specifier: ^10.6.1 version: 10.6.1(vue@3.3.8) @@ -516,11 +546,11 @@ importers: specifier: ^4.7.1 version: 4.7.1 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -529,7 +559,7 @@ importers: dependencies: vue: specifier: ^3.3.8 - version: 3.3.8(typescript@5.2.2) + version: 3.3.8(typescript@5.3.3) vue-router: specifier: ^4.2.5 version: 4.2.5(vue@3.3.8) @@ -539,7 +569,7 @@ importers: version: 5.0.5(rollup@4.4.1) '@vitejs/plugin-vue': specifier: ^4.5.0 - version: 4.5.0(vite@5.0.0)(vue@3.3.8) + version: 4.5.0(vite@5.0.10)(vue@3.3.8) '@vueuse/core': specifier: ^10.6.1 version: 10.6.1(vue@3.3.8) @@ -550,11 +580,11 @@ importers: specifier: ^5.0.5 version: 5.0.5 typescript: - specifier: ^5.2.2 - version: 5.2.2 + specifier: ^5.3.3 + version: 5.3.3 vite: - specifier: ^5.0.0 - version: 5.0.0(@types/node@18.17.14) + specifier: ^5.0.10 + version: 5.0.10(@types/node@18.17.14) vite-plugin-pwa: specifier: workspace:* version: link:../.. @@ -704,7 +734,7 @@ packages: '@jridgewell/gen-mapping': 0.3.2 '@jridgewell/trace-mapping': 0.3.18 - /@antfu/eslint-config@2.0.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.2.2)(vitest@1.0.0-beta.4): + /@antfu/eslint-config@2.0.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.3.3)(vitest@1.0.0-beta.4): resolution: {integrity: sha512-kAhbg7loDbT7g3rkLkgZ1R7C5v43wzAOjLMAcdT1xFMGEhAtG8MhBMUXrRCwdaV8ebvLYjO+mqUVCdgrHaFPOA==} hasBin: true peerDependencies: @@ -714,9 +744,9 @@ packages: '@eslint-types/jsdoc': 46.8.2-1 '@eslint-types/typescript-eslint': 6.11.0 '@eslint-types/unicorn': 49.0.0 - '@stylistic/eslint-plugin': 1.4.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@stylistic/eslint-plugin': 1.4.0(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 eslint-config-flat-gitignore: 0.1.1 eslint-plugin-antfu: 1.0.10(eslint@8.54.0) @@ -727,10 +757,10 @@ packages: eslint-plugin-markdown: 3.0.1(eslint@8.54.0) eslint-plugin-n: 16.3.1(eslint@8.54.0) eslint-plugin-no-only-tests: 3.1.0 - eslint-plugin-perfectionist: 2.4.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.2.2)(vue-eslint-parser@9.3.2) + eslint-plugin-perfectionist: 2.4.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.3.3)(vue-eslint-parser@9.3.2) eslint-plugin-unicorn: 49.0.0(eslint@8.54.0) eslint-plugin-unused-imports: 3.0.0(@typescript-eslint/eslint-plugin@6.11.0)(eslint@8.54.0) - eslint-plugin-vitest: 0.3.10(@typescript-eslint/eslint-plugin@6.11.0)(eslint@8.54.0)(typescript@5.2.2)(vitest@1.0.0-beta.4) + eslint-plugin-vitest: 0.3.10(@typescript-eslint/eslint-plugin@6.11.0)(eslint@8.54.0)(typescript@5.3.3)(vitest@1.0.0-beta.4) eslint-plugin-vue: 9.18.1(eslint@8.54.0) eslint-plugin-yml: 1.10.0(eslint@8.54.0) execa: 8.0.1 @@ -775,6 +805,10 @@ packages: resolution: {integrity: sha512-CQkeV+oJxUazwjlHD0/3ZD08QWKuGQkhnrKo3e6ly5pd48VUpXbb77q0xMU4+vc2CkJnDS02Eq/M9ugyX20XZA==} dev: true + /@antfu/utils@0.7.6: + resolution: {integrity: sha512-pvFiLP2BeOKA/ZOS6jxx4XhKzdVLHDhGlFEaZ2flWWYf2xOqVniqpk38I04DFRyz+L0ASggl7SkItTc+ZLju4w==} + dev: true + /@apideck/better-ajv-errors@0.3.6(ajv@8.11.0): resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} engines: {node: '>=10'} @@ -2441,6 +2475,10 @@ packages: to-fast-properties: 2.0.0 dev: true + /@canvas/image-data@1.0.0: + resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==} + dev: true + /@docsearch/css@3.2.1: resolution: {integrity: sha512-gaP6TxxwQC+K8D6TRx5WULUWKrcbzECOPA2KCVMuI+6C7dNiGUk5yXXzVhc5sld79XKYLnO9DRTI4mjXDYkh+g==} dev: true @@ -3118,7 +3156,7 @@ packages: resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /@preact/preset-vite@2.7.0(@babel/core@7.23.3)(preact@10.17.1)(vite@5.0.0): + /@preact/preset-vite@2.7.0(@babel/core@7.23.3)(preact@10.17.1)(vite@5.0.10): resolution: {integrity: sha512-m5N0FVtxbCCDxNk55NGhsRpKJChYcupcuQHzMJc/Bll07IKZKn8amwYciyKFS9haU6AgzDAJ/ewvApr6Qg1DHw==} peerDependencies: '@babel/core': 7.x @@ -3127,13 +3165,13 @@ packages: '@babel/core': 7.23.3 '@babel/plugin-transform-react-jsx': 7.22.15(@babel/core@7.23.3) '@babel/plugin-transform-react-jsx-development': 7.22.5(@babel/core@7.23.3) - '@prefresh/vite': 2.4.1(preact@10.17.1)(vite@5.0.0) + '@prefresh/vite': 2.4.1(preact@10.17.1)(vite@5.0.10) '@rollup/pluginutils': 4.2.1 babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.23.3) debug: 4.3.4 kolorist: 1.8.0 resolve: 1.22.8 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) transitivePeerDependencies: - preact - supports-color @@ -3155,7 +3193,7 @@ packages: resolution: {integrity: sha512-KtC/fZw+oqtwOLUFM9UtiitB0JsVX0zLKNyRTA332sqREqSALIIQQxdUCS1P3xR/jT1e2e8/5rwH6gdcMLEmsQ==} dev: true - /@prefresh/vite@2.4.1(preact@10.17.1)(vite@5.0.0): + /@prefresh/vite@2.4.1(preact@10.17.1)(vite@5.0.10): resolution: {integrity: sha512-vthWmEqu8TZFeyrBNc9YE5SiC3DVSzPgsOCp/WQ7FqdHpOIJi7Z8XvCK06rBPOtG4914S52MjG9Ls22eVAiuqQ==} peerDependencies: preact: ^10.4.0 @@ -3167,7 +3205,7 @@ packages: '@prefresh/utils': 1.2.0 '@rollup/pluginutils': 4.2.1 preact: 10.17.1 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) transitivePeerDependencies: - supports-color dev: true @@ -3436,13 +3474,13 @@ packages: estraverse: 5.3.0 dev: true - /@stylistic/eslint-plugin-ts@1.4.0(eslint@8.54.0)(typescript@5.2.2): + /@stylistic/eslint-plugin-ts@1.4.0(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-eNEC0MufXfe2v9fW+g5yDzMMcws80cn1gKIt9CaLVjUuWnwCdY4SG1hUtDfEpBCTNBZgG/LKKls15dSa1x++0g==} peerDependencies: eslint: '*' dependencies: '@stylistic/eslint-plugin-js': 1.4.0 - '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 graphemer: 1.4.0 transitivePeerDependencies: @@ -3450,14 +3488,14 @@ packages: - typescript dev: true - /@stylistic/eslint-plugin@1.4.0(eslint@8.54.0)(typescript@5.2.2): + /@stylistic/eslint-plugin@1.4.0(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-DtPiS4jr7m+A2nlcn8Ls4LEsOj1KC8x+KvAmoUI+nTcnin4Hkb8/I9Vteuu2CFLyVmlnKIQhrL5JC/xUEMyE9w==} peerDependencies: eslint: '*' dependencies: '@stylistic/eslint-plugin-js': 1.4.0 '@stylistic/eslint-plugin-jsx': 1.4.0 - '@stylistic/eslint-plugin-ts': 1.4.0(eslint@8.54.0)(typescript@5.2.2) + '@stylistic/eslint-plugin-ts': 1.4.0(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 transitivePeerDependencies: - supports-color @@ -3525,7 +3563,7 @@ packages: - supports-color dev: true - /@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.0.0)(svelte@4.2.5)(vite@5.0.0): + /@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.0.0)(svelte@4.2.5)(vite@5.0.10): resolution: {integrity: sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==} engines: {node: ^18.0.0 || >=20} peerDependencies: @@ -3533,10 +3571,10 @@ packages: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 dependencies: - '@sveltejs/vite-plugin-svelte': 3.0.0(svelte@4.2.5)(vite@5.0.0) + '@sveltejs/vite-plugin-svelte': 3.0.0(svelte@4.2.5)(vite@5.0.10) debug: 4.3.4 svelte: 4.2.5 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) transitivePeerDependencies: - supports-color dev: true @@ -3561,22 +3599,22 @@ packages: - supports-color dev: true - /@sveltejs/vite-plugin-svelte@3.0.0(svelte@4.2.5)(vite@5.0.0): + /@sveltejs/vite-plugin-svelte@3.0.0(svelte@4.2.5)(vite@5.0.10): resolution: {integrity: sha512-Th0nupxk8hl5Rcg9jm+1xWylwco4bSUAvutWxM4W4bjOAollpXLmrYqSSnYo9pPbZOO6ZGRm6sSqYa/v1d/Saw==} engines: {node: ^18.0.0 || >=20} peerDependencies: svelte: ^4.0.0 || ^5.0.0-next.0 vite: ^5.0.0 dependencies: - '@sveltejs/vite-plugin-svelte-inspector': 2.0.0(@sveltejs/vite-plugin-svelte@3.0.0)(svelte@4.2.5)(vite@5.0.0) + '@sveltejs/vite-plugin-svelte-inspector': 2.0.0(@sveltejs/vite-plugin-svelte@3.0.0)(svelte@4.2.5)(vite@5.0.10) debug: 4.3.4 deepmerge: 4.3.1 kleur: 4.1.5 magic-string: 0.30.5 svelte: 4.2.5 svelte-hmr: 0.15.3(svelte@4.2.5) - vite: 5.0.0(@types/node@18.17.14) - vitefu: 0.2.5(vite@5.0.0) + vite: 5.0.10(@types/node@18.17.14) + vitefu: 0.2.5(vite@5.0.10) transitivePeerDependencies: - supports-color dev: true @@ -3815,7 +3853,7 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -3827,10 +3865,10 @@ packages: optional: true dependencies: '@eslint-community/regexpp': 4.8.0 - '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.3.3) '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/type-utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/type-utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 debug: 4.3.4 eslint: 8.54.0 @@ -3838,8 +3876,8 @@ packages: ignore: 5.2.4 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -3864,7 +3902,7 @@ packages: - supports-color dev: true - /@typescript-eslint/parser@6.11.0(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/parser@6.11.0(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -3876,11 +3914,11 @@ packages: dependencies: '@typescript-eslint/scope-manager': 6.11.0 '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 debug: 4.3.4 eslint: 8.54.0 - typescript: 5.2.2 + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -3921,7 +3959,7 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils@6.11.0(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/type-utils@6.11.0(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -3931,12 +3969,12 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) + '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) debug: 4.3.4 eslint: 8.54.0 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -3972,7 +4010,7 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2): + /@typescript-eslint/typescript-estree@6.11.0(typescript@5.3.3): resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -3987,8 +4025,8 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.3(typescript@5.2.2) - typescript: 5.2.2 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - supports-color dev: true @@ -4011,7 +4049,7 @@ packages: - typescript dev: true - /@typescript-eslint/utils@6.11.0(eslint@8.54.0)(typescript@5.2.2): + /@typescript-eslint/utils@6.11.0(eslint@8.54.0)(typescript@5.3.3): resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==} engines: {node: ^16.0.0 || >=18.0.0} peerDependencies: @@ -4022,7 +4060,7 @@ packages: '@types/semver': 7.5.1 '@typescript-eslint/scope-manager': 6.11.0 '@typescript-eslint/types': 6.11.0 - '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2) + '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) eslint: 8.54.0 semver: 7.5.4 transitivePeerDependencies: @@ -4082,7 +4120,7 @@ packages: engines: {node: '>=14'} dependencies: '@unocss/core': 0.45.18 - unconfig: 0.3.6 + unconfig: 0.3.11 dev: true /@unocss/core@0.45.18: @@ -4201,7 +4239,20 @@ packages: vite: 3.1.0 dev: true - /@vitejs/plugin-react@4.2.0(vite@5.0.0): + /@vite-pwa/assets-generator@0.2.4: + resolution: {integrity: sha512-DXyPLPR/IpbZPSpo1amZEPghY/ziIwpTUKNaz0v1xG+ELzCXmrVQhVzEMqr2JLSqRxjc+UzKfGJA/YdUuaao3w==} + engines: {node: '>=16.14.0'} + hasBin: true + dependencies: + cac: 6.7.14 + colorette: 2.0.20 + consola: 3.2.3 + sharp: 0.32.6 + sharp-ico: 0.1.5 + unconfig: 0.3.11 + dev: true + + /@vitejs/plugin-react@4.2.0(vite@5.0.10): resolution: {integrity: sha512-+MHTH/e6H12kRp5HUkzOGqPMksezRMmW+TNzlh/QXfI8rRf6l2Z2yH/v12no1UvTwhZgEDMuQ7g7rrfMseU6FQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -4212,7 +4263,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.3) '@types/babel__core': 7.20.4 react-refresh: 0.14.0 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) transitivePeerDependencies: - supports-color dev: true @@ -4239,26 +4290,26 @@ packages: vue: 3.2.45 dev: true - /@vitejs/plugin-vue@4.3.4(vite@5.0.0)(vue@3.3.8): + /@vitejs/plugin-vue@4.3.4(vite@5.0.10)(vue@3.3.8): resolution: {integrity: sha512-ciXNIHKPriERBisHFBvnTbfKa6r9SAesOYXeGDzgegcvy9Q4xdScSHAmKbNT0M3O0S9LKhIf5/G+UYG4NnnzYw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.0.0 vue: ^3.2.25 dependencies: - vite: 5.0.0(@types/node@18.17.14) - vue: 3.3.8(typescript@5.2.2) + vite: 5.0.10(@types/node@18.17.14) + vue: 3.3.8(typescript@5.3.3) dev: true - /@vitejs/plugin-vue@4.5.0(vite@5.0.0)(vue@3.3.8): + /@vitejs/plugin-vue@4.5.0(vite@5.0.10)(vue@3.3.8): resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: vite: ^4.0.0 || ^5.0.0 vue: ^3.2.25 dependencies: - vite: 5.0.0(@types/node@18.17.14) - vue: 3.3.8(typescript@5.2.2) + vite: 5.0.10(@types/node@18.17.14) + vue: 3.3.8(typescript@5.3.3) dev: true /@vitest/expect@1.0.0-beta.4: @@ -4368,7 +4419,7 @@ packages: '@vue/shared': 3.2.45 estree-walker: 2.0.2 magic-string: 0.25.9 - postcss: 8.4.20 + postcss: 8.4.31 source-map: 0.6.1 dev: true @@ -4524,7 +4575,7 @@ packages: dependencies: '@vue/compiler-ssr': 3.3.8 '@vue/shared': 3.3.8 - vue: 3.3.8(typescript@5.2.2) + vue: 3.3.8(typescript@5.3.3) /@vue/shared@3.2.38: resolution: {integrity: sha512-dTyhTIRmGXBjxJE+skC8tTWCGLCVc4wQgRRLt8+O9p5ewBAjoBwtCAkLPrtToSr1xltoe3st21Pv953aOZ7alg==} @@ -4823,6 +4874,10 @@ packages: dequal: 2.0.3 dev: true + /b4a@1.6.4: + resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} + dev: true + /babel-plugin-dynamic-import-node@2.3.3: resolution: {integrity: sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==} dependencies: @@ -4898,11 +4953,23 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: true + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: true + /bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + /body-parser@1.20.0: resolution: {integrity: sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -4980,6 +5047,13 @@ packages: /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + /buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: true + /bufferutil@4.0.6: resolution: {integrity: sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==} engines: {node: '>=6.14.2'} @@ -5151,6 +5225,10 @@ packages: fsevents: 2.3.3 dev: true + /chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + dev: true + /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -5204,10 +5282,29 @@ packages: /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: true + + /color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + dependencies: + color-convert: 2.0.1 + color-string: 1.9.1 + dev: true + /colorette@2.0.19: resolution: {integrity: sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==} dev: true + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -5274,6 +5371,11 @@ packages: resolution: {integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==} dev: true + /consola@3.2.3: + resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==} + engines: {node: ^14.18.0 || >=16.10.0} + dev: true + /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -5438,6 +5540,30 @@ packages: resolution: {integrity: sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==} dev: true + /decode-bmp@0.2.1: + resolution: {integrity: sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==} + engines: {node: '>=8.6.0'} + dependencies: + '@canvas/image-data': 1.0.0 + to-data-view: 1.1.0 + dev: true + + /decode-ico@0.4.1: + resolution: {integrity: sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==} + engines: {node: '>=8.6'} + dependencies: + '@canvas/image-data': 1.0.0 + decode-bmp: 0.2.1 + to-data-view: 1.1.0 + dev: true + + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: true + /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} engines: {node: '>=6'} @@ -5445,6 +5571,11 @@ packages: type-detect: 4.0.8 dev: true + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -5461,10 +5592,6 @@ packages: object-keys: 1.1.1 dev: false - /defu@6.1.0: - resolution: {integrity: sha512-pOFYRTIhoKujrmbTRhcW5lYQLBXw/dlTwfI8IguF1QCDJOcJzNH1w+YFjxqy6BAuJrClTy6MUE8q+oKJ2FLsIw==} - dev: true - /defu@6.1.2: resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==} dev: true @@ -5502,6 +5629,11 @@ packages: engines: {node: '>=8'} dev: true + /detect-libc@2.0.2: + resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} + engines: {node: '>=8'} + dev: true + /detect-node@2.1.0: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} dev: true @@ -5593,6 +5725,12 @@ packages: engines: {node: '>= 0.8'} dev: true + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: true + /error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} dependencies: @@ -6043,7 +6181,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.3.3) debug: 3.2.7 eslint: 8.54.0 eslint-import-resolver-node: 0.3.9 @@ -6173,7 +6311,7 @@ packages: engines: {node: '>=5.0.0'} dev: true - /eslint-plugin-perfectionist@2.4.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.2.2)(vue-eslint-parser@9.3.2): + /eslint-plugin-perfectionist@2.4.0(eslint@8.54.0)(svelte@4.2.5)(typescript@5.3.3)(vue-eslint-parser@9.3.2): resolution: {integrity: sha512-til+vyf56wAUgFv5guBA1Zo5lTw9xj2kCeK/g+9NBtsRy1rkGrlqnvxYNuFExcK3VsPhUUtx5UdScEDz9ahQ5Q==} peerDependencies: astro-eslint-parser: ^0.16.0 @@ -6191,7 +6329,7 @@ packages: vue-eslint-parser: optional: true dependencies: - '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 minimatch: 9.0.3 natural-compare-lite: 1.4.0 @@ -6255,12 +6393,12 @@ packages: '@typescript-eslint/eslint-plugin': optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 eslint-rule-composer: 0.3.0 dev: true - /eslint-plugin-vitest@0.3.10(@typescript-eslint/eslint-plugin@6.11.0)(eslint@8.54.0)(typescript@5.2.2)(vitest@1.0.0-beta.4): + /eslint-plugin-vitest@0.3.10(@typescript-eslint/eslint-plugin@6.11.0)(eslint@8.54.0)(typescript@5.3.3)(vitest@1.0.0-beta.4): resolution: {integrity: sha512-08lj4rdhZHYyHk+Py2nJ7SlE6arP8GNfGXl9jVqhe9s5JoZIGiBpIkLGX+VNBiB6vXTn56H6Ant7Koc6XzRjtQ==} engines: {node: 14.x || >= 16} peerDependencies: @@ -6273,8 +6411,8 @@ packages: vitest: optional: true dependencies: - '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2) - '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2) + '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.3.3) eslint: 8.54.0 vitest: 1.0.0-beta.4(@types/node@18.17.14) transitivePeerDependencies: @@ -6519,6 +6657,11 @@ packages: strip-final-newline: 3.0.0 dev: true + /expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + dev: true + /express@4.18.1: resolution: {integrity: sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==} engines: {node: '>= 0.10.0'} @@ -6561,6 +6704,10 @@ packages: /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + /fast-fifo@1.3.2: + resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} + dev: true + /fast-glob@3.2.11: resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} engines: {node: '>=8.6.0'} @@ -6694,6 +6841,10 @@ packages: engines: {node: '>= 0.6'} dev: true + /fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + dev: true + /fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} @@ -6819,7 +6970,7 @@ packages: resolution: {integrity: sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==} hasBin: true dependencies: - colorette: 2.0.19 + colorette: 2.0.20 defu: 6.1.2 https-proxy-agent: 5.0.1 mri: 1.2.0 @@ -6830,6 +6981,10 @@ packages: - supports-color dev: true + /github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + dev: true + /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -7073,6 +7228,10 @@ packages: engines: {node: '>=16.17.0'} dev: true + /ico-endec@0.1.6: + resolution: {integrity: sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==} + dev: true + /iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -7083,6 +7242,10 @@ packages: /idb@7.0.2: resolution: {integrity: sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==} + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: true + /ignore-walk@5.0.1: resolution: {integrity: sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -7127,6 +7290,10 @@ packages: /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + /internal-slot@1.0.5: resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} engines: {node: '>= 0.4'} @@ -7164,6 +7331,10 @@ packages: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} dev: true + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: true + /is-bigint@1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: @@ -7384,13 +7555,13 @@ packages: supports-color: 7.2.0 dev: false - /jiti@1.15.0: - resolution: {integrity: sha512-cClBkETOCVIpPMjX3ULlivuBvmt8l2Xtz+SHrULO06OqdtV0QFR2cuhc4FJnXByjUUX4CY0pl1nph0aFh9D3yA==} + /jiti@1.18.2: + resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==} hasBin: true dev: true - /jiti@1.18.2: - resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==} + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} hasBin: true dev: true @@ -7808,6 +7979,11 @@ packages: engines: {node: '>=12'} dev: true + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true + /min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -7859,6 +8035,10 @@ packages: yallist: 4.0.0 dev: true + /mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + dev: true + /mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true @@ -7875,7 +8055,7 @@ packages: /mlly@1.4.2: resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} dependencies: - acorn: 8.10.0 + acorn: 8.11.2 pathe: 1.1.1 pkg-types: 1.0.3 ufo: 1.3.0 @@ -7920,6 +8100,16 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /napi-build-utils@1.0.2: + resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} + dev: true + /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} dev: true @@ -7933,6 +8123,17 @@ packages: engines: {node: '>= 0.6'} dev: true + /node-abi@3.52.0: + resolution: {integrity: sha512-JJ98b02z16ILv7859irtXn4oUaFWADtvkzy2c0IAatNVX2Mc9Yoh8z6hZInn3QwvMEYhHuQloYi+TTQy67SIdQ==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /node-addon-api@6.1.0: + resolution: {integrity: sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==} + dev: true + /node-fetch-native@0.1.4: resolution: {integrity: sha512-10EKpOCQPXwZVFh3U1ptOMWBgKTbsN7Vvo6WVKt5pw4hp8zbv6ZVBZPlXw+5M6Tyi1oc1iD4/sNPd71KYA16tQ==} dev: true @@ -8355,6 +8556,15 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 + /postcss@8.4.32: + resolution: {integrity: sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + /preact-router@4.1.2(preact@10.17.1): resolution: {integrity: sha512-uICUaUFYh+XQ+6vZtQn1q+X6rSqwq+zorWOCLWPF5FAsQh3EJ+RsDQ9Ee+fjk545YWQHfUxhrBAaemfxEnMOUg==} peerDependencies: @@ -8370,6 +8580,25 @@ packages: resolution: {integrity: sha512-UA9DX/OJwv6YwP9Vn7Ti/vF80XL+YA5H2l7BpCtUr3ya8LWHFzpiO5R+N7dN16ujpIxhekRFuOOF82bXX7K/lg==} dev: true + /prebuild-install@7.1.1: + resolution: {integrity: sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==} + engines: {node: '>=10'} + hasBin: true + dependencies: + detect-libc: 2.0.2 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.6 + mkdirp-classic: 0.5.3 + napi-build-utils: 1.0.2 + node-abi: 3.52.0 + pump: 3.0.0 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.1 + tunnel-agent: 0.6.0 + dev: true + /prelude-ls@1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -8433,6 +8662,13 @@ packages: sade: 1.8.1 dev: true + /pump@3.0.0: + resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: true + /punycode@2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} @@ -8451,6 +8687,10 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + /queue-tick@1.0.1: + resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} + dev: true + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: @@ -8480,6 +8720,16 @@ packages: flat: 5.0.2 dev: true + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.6 + strip-json-comments: 2.0.1 + dev: true + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -8934,6 +9184,29 @@ packages: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} dev: true + /sharp-ico@0.1.5: + resolution: {integrity: sha512-a3jODQl82NPp1d5OYb0wY+oFaPk7AvyxipIowCHk7pBsZCWgbe0yAkU2OOXdoH0ENyANhyOQbs9xkAiRHcF02Q==} + dependencies: + decode-ico: 0.4.1 + ico-endec: 0.1.6 + sharp: 0.32.6 + dev: true + + /sharp@0.32.6: + resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} + engines: {node: '>=14.15.0'} + requiresBuild: true + dependencies: + color: 4.2.3 + detect-libc: 2.0.2 + node-addon-api: 6.1.0 + prebuild-install: 7.1.1 + semver: 7.5.4 + simple-get: 4.0.1 + tar-fs: 3.0.4 + tunnel-agent: 0.6.0 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -8974,6 +9247,24 @@ packages: engines: {node: '>=14'} dev: true + /simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + dev: true + + /simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + dev: true + + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: true + /sirv@2.0.2: resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} engines: {node: '>= 10'} @@ -9119,6 +9410,13 @@ packages: engines: {node: '>=10.0.0'} dev: true + /streamx@2.15.6: + resolution: {integrity: sha512-q+vQL4AAz+FdfT137VF69Cc/APqUbxy+MDOImRrMvchJpigHj9GksgDU2LYbO9rx7RX6osWgxJB2WxhYv4SZAw==} + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + dev: true + /string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -9253,6 +9551,11 @@ packages: min-indent: 1.0.1 dev: true + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -9334,8 +9637,8 @@ packages: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.5 - svelte-preprocess: 5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.2.2) - typescript: 5.2.2 + svelte-preprocess: 5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.3.3) + typescript: 5.3.3 transitivePeerDependencies: - '@babel/core' - coffeescript @@ -9470,7 +9773,7 @@ packages: typescript: 4.9.4 dev: true - /svelte-preprocess@5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.2.2): + /svelte-preprocess@5.1.0(@babel/core@7.21.8)(svelte@4.2.5)(typescript@5.3.3): resolution: {integrity: sha512-EkErPiDzHAc0k2MF5m6vBNmRUh338h2myhinUw/xaqsLs7/ZvsgREiLGj03VrSzbY/TB5ZXgBOsKraFee5yceA==} engines: {node: '>= 14.10.0'} requiresBuild: true @@ -9515,7 +9818,7 @@ packages: sorcery: 0.11.0 strip-indent: 3.0.0 svelte: 4.2.5 - typescript: 5.2.2 + typescript: 5.3.3 dev: true /svelte@3.50.0: @@ -9546,6 +9849,42 @@ packages: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true + /tar-fs@2.1.1: + resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 2.2.0 + dev: true + + /tar-fs@3.0.4: + resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} + dependencies: + mkdirp-classic: 0.5.3 + pump: 3.0.0 + tar-stream: 3.1.6 + dev: true + + /tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.0 + dev: true + + /tar-stream@3.1.6: + resolution: {integrity: sha512-B/UyjYwPpMBv+PaFSWAmtYjwdrlEaZQEhMIBFNC5oEG8lpiW8XjcSdmEaClj28ArfKScKHs2nshz3k2le6crsg==} + dependencies: + b4a: 1.6.4 + fast-fifo: 1.3.2 + streamx: 2.15.6 + dev: true + /tar@6.1.15: resolution: {integrity: sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==} engines: {node: '>=10'} @@ -9622,6 +9961,10 @@ packages: engines: {node: '>=14.0.0'} dev: true + /to-data-view@1.1.0: + resolution: {integrity: sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==} + dev: true + /to-fast-properties@2.0.0: resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} engines: {node: '>=4'} @@ -9673,13 +10016,13 @@ packages: hasBin: true dev: true - /ts-api-utils@1.0.3(typescript@5.2.2): + /ts-api-utils@1.0.3(typescript@5.3.3): resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' dependencies: - typescript: 5.2.2 + typescript: 5.3.3 dev: true /ts-interface-checker@0.1.13: @@ -9694,7 +10037,7 @@ packages: resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} dev: true - /tsup@7.3.0(typescript@5.2.2): + /tsup@7.3.0(typescript@5.3.3): resolution: {integrity: sha512-Ja1eaSRrE+QarmATlNO5fse2aOACYMBX+IZRKy1T+gpyH+jXgRrl5l4nHIQJQ1DoDgEjHDTw8cpE085UdBZuWQ==} engines: {node: '>=18'} hasBin: true @@ -9724,7 +10067,7 @@ packages: source-map: 0.8.0-beta.0 sucrase: 3.25.0 tree-kill: 1.2.2 - typescript: 5.2.2 + typescript: 5.3.3 transitivePeerDependencies: - supports-color - ts-node @@ -9751,6 +10094,12 @@ packages: fsevents: 2.3.3 dev: true + /tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + dependencies: + safe-buffer: 5.2.1 + dev: true + /type-check@0.3.2: resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} engines: {node: '>= 0.8.0'} @@ -9818,8 +10167,8 @@ packages: hasBin: true dev: true - /typescript@5.2.2: - resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} engines: {node: '>=14.17'} hasBin: true @@ -9846,12 +10195,13 @@ packages: which-boxed-primitive: 1.0.2 dev: false - /unconfig@0.3.6: - resolution: {integrity: sha512-JWefWyjLrDAbzs30sFkzcE9YpvAhN9+UPMZBwnNUmaY9X7QhI+wCGP4hoEWfZDzvkP+WIaZDPcMUJjarpxFvKg==} + /unconfig@0.3.11: + resolution: {integrity: sha512-bV/nqePAKv71v3HdVUn6UefbsDKQWRX+bJIkiSm0+twIds6WiD2bJLWWT3i214+J/B4edufZpG2w7Y63Vbwxow==} dependencies: - '@antfu/utils': 0.5.2 - defu: 6.1.0 - jiti: 1.15.0 + '@antfu/utils': 0.7.6 + defu: 6.1.2 + jiti: 1.21.0 + mlly: 1.4.2 dev: true /undici@5.14.0: @@ -10078,7 +10428,7 @@ packages: mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.12(@types/node@18.17.14) transitivePeerDependencies: - '@types/node' - less @@ -10090,7 +10440,7 @@ packages: - terser dev: true - /vite-plugin-solid@2.7.2(solid-js@1.8.5)(vite@5.0.0): + /vite-plugin-solid@2.7.2(solid-js@1.8.5)(vite@5.0.10): resolution: {integrity: sha512-GV2SMLAibOoXe76i02AsjAg7sbm/0lngBlERvJKVN67HOrJsHcWgkt0R6sfGLDJuFkv2aBe14Zm4vJcNME+7zw==} peerDependencies: solid-js: ^1.7.2 @@ -10103,8 +10453,8 @@ packages: merge-anything: 5.1.7 solid-js: 1.8.5 solid-refresh: 0.5.3(solid-js@1.8.5) - vite: 5.0.0(@types/node@18.17.14) - vitefu: 0.2.4(vite@5.0.0) + vite: 5.0.10(@types/node@18.17.14) + vitefu: 0.2.4(vite@5.0.10) transitivePeerDependencies: - supports-color dev: true @@ -10166,14 +10516,14 @@ packages: dependencies: '@types/node': 18.17.14 esbuild: 0.18.20 - postcss: 8.4.31 + postcss: 8.4.32 rollup: 3.29.0 optionalDependencies: fsevents: 2.3.3 dev: true - /vite@5.0.0(@types/node@18.17.14): - resolution: {integrity: sha512-ESJVM59mdyGpsiNAeHQOR/0fqNoOyWPYesFto8FFZugfmhdHx8Fzd8sF3Q/xkVhZsyOxHfdM7ieiVAorI9RjFw==} + /vite@5.0.10(@types/node@18.17.14): + resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -10202,7 +10552,43 @@ packages: dependencies: '@types/node': 18.17.14 esbuild: 0.19.5 - postcss: 8.4.31 + postcss: 8.4.32 + rollup: 4.4.1 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vite@5.0.12(@types/node@18.17.14): + resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.17.14 + esbuild: 0.19.5 + postcss: 8.4.32 rollup: 4.4.1 optionalDependencies: fsevents: 2.3.3 @@ -10219,7 +10605,7 @@ packages: vite: 4.5.0(@types/node@18.17.14) dev: true - /vitefu@0.2.4(vite@5.0.0): + /vitefu@0.2.4(vite@5.0.10): resolution: {integrity: sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==} peerDependencies: vite: ^3.0.0 || ^4.0.0 @@ -10227,10 +10613,10 @@ packages: vite: optional: true dependencies: - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) dev: true - /vitefu@0.2.5(vite@5.0.0): + /vitefu@0.2.5(vite@5.0.10): resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} peerDependencies: vite: ^3.0.0 || ^4.0.0 || ^5.0.0 @@ -10238,7 +10624,7 @@ packages: vite: optional: true dependencies: - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.10(@types/node@18.17.14) dev: true /vitepress@1.0.0-alpha.13(@algolia/client-search@4.14.2)(@types/react@18.2.21)(react@18.2.0): @@ -10310,7 +10696,7 @@ packages: strip-literal: 1.0.1 tinybench: 2.5.0 tinypool: 0.8.1 - vite: 5.0.0(@types/node@18.17.14) + vite: 5.0.12(@types/node@18.17.14) vite-node: 1.0.0-beta.4(@types/node@18.17.14) why-is-node-running: 2.2.2 transitivePeerDependencies: @@ -10373,7 +10759,7 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.3.8(typescript@5.2.2) + vue: 3.3.8(typescript@5.3.3) dev: true /vue-eslint-parser@9.3.2(eslint@8.54.0): @@ -10400,7 +10786,7 @@ packages: vue: ^3.2.0 dependencies: '@vue/devtools-api': 6.5.0 - vue: 3.3.8(typescript@5.2.2) + vue: 3.3.8(typescript@5.3.3) dev: false /vue@3.2.38: @@ -10422,7 +10808,7 @@ packages: '@vue/shared': 3.2.45 dev: true - /vue@3.3.8(typescript@5.2.2): + /vue@3.3.8(typescript@5.3.3): resolution: {integrity: sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==} peerDependencies: typescript: '*' @@ -10435,7 +10821,7 @@ packages: '@vue/runtime-dom': 3.3.8 '@vue/server-renderer': 3.3.8(vue@3.3.8) '@vue/shared': 3.3.8 - typescript: 5.2.2 + typescript: 5.3.3 /w3c-hr-time@1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} diff --git a/pwa-assets.d.ts b/pwa-assets.d.ts new file mode 100644 index 00000000..81d19e90 --- /dev/null +++ b/pwa-assets.d.ts @@ -0,0 +1,40 @@ +/* WARNING: these virtual modules are meant to be used by integrations and not being consumed directly from applications */ + +declare module 'virtual:pwa-assets/head' { + export interface PWAAssetHeadLink { + id?: string + rel: 'apple-touch-startup-image' | 'apple-touch-icon' | 'icon' + href: string + media?: string + sizes?: string + type?: string + } + + export interface ColorSchemeMeta { + name: string + content: string + } + + export interface PWAAssetsHead { + links: PWAAssetHeadLink[] + themeColor?: ColorSchemeMeta + } + + export const pwaAssetsHead: PWAAssetsHead +} + +declare module 'virtual:pwa-assets/icons' { + import type { AppleSplashScreenLink, FaviconLink, HtmlLink, IconAsset } from '@vite-pwa/assets-generator/api' + + export type PWAAssetIcon = Omit, 'buffer'> + + export interface PWAAssetsIcons { + favicon: Record> + transparent: Record> + maskable: Record> + apple: Record> + appleSplashScreen: Record> + } + + export const pwaAssetsIcons: PWAAssetsIcons +} diff --git a/src/api.ts b/src/api.ts index 4ecaac86..724eb121 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,6 +1,7 @@ import { resolve } from 'node:path' import { existsSync } from 'node:fs' import type { OutputBundle } from 'rollup' +import { cyan, yellow } from 'kolorist' import { generateInjectManifest, generateServiceWorker } from './modules' import { generateWebManifestFile } from './assets' import { DEV_SW_NAME, FILE_SW_REGISTER } from './constants' @@ -23,11 +24,19 @@ export async function _generateSW({ options, viteConfig }: PWAPluginContext) { await generateServiceWorker(options, viteConfig) } -export function _generateBundle({ options, viteConfig, useImportRegister }: PWAPluginContext, bundle?: OutputBundle) { +export function _generateBundle(ctx: PWAPluginContext, bundle?: OutputBundle) { + const { options, viteConfig, useImportRegister } = ctx if (options.disable || !bundle) return if (options.manifest) { + if (!options.manifest.theme_color) { + console.warn([ + '', + `${cyan(`PWA v${ctx.version}`)}`, + `${yellow('WARNING: "theme_color" is missing from the web manifest, your application will not be able to be installed')}`, + ].join('\n')) + } bundle[options.manifestFilename] = { // @ts-expect-error: for Vite 3 support, Vite 4 has removed `isAsset` property isAsset: true, @@ -55,7 +64,7 @@ export function _generateBundle({ options, viteConfig, useImportRegister }: PWAP return bundle } -export function createAPI(ctx: PWAPluginContext): VitePluginPWAAPI { +export function createAPI(ctx: PWAPluginContext) { return { get disabled() { return ctx?.options?.disable @@ -144,5 +153,8 @@ export function createAPI(ctx: PWAPluginContext): VitePluginPWAAPI { if (result != null) options[configField].additionalManifestEntries = result }, - } + pwaAssetsGenerator() { + return ctx.pwaAssetsGenerator + }, + } satisfies VitePluginPWAAPI } diff --git a/src/constants.ts b/src/constants.ts index 4bc3748a..469efbc2 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -25,9 +25,14 @@ export const defaultInjectManifestVitePlugins = [ export const PWA_INFO_VIRTUAL = 'virtual:pwa-info' export const RESOLVED_PWA_INFO_VIRTUAL = `\0${PWA_INFO_VIRTUAL}` +export const PWA_ASSETS_HEAD_VIRTUAL = 'virtual:pwa-assets/head' +export const RESOLVED_PWA_ASSETS_HEAD_VIRTUAL = `\0${PWA_ASSETS_HEAD_VIRTUAL}` +export const PWA_ASSETS_ICONS_VIRTUAL = 'virtual:pwa-assets/icons' +export const RESOLVED_PWA_ASSETS_ICONS_VIRTUAL = `\0${PWA_ASSETS_ICONS_VIRTUAL}` export const DEV_SW_NAME = 'dev-sw.js?dev-sw' export const DEV_SW_VIRTUAL = `${VIRTUAL_MODULES_RESOLVE_PREFIX}pwa-entry-point-loaded` export const RESOLVED_DEV_SW_VIRTUAL = `\0${DEV_SW_VIRTUAL}` export const DEV_READY_NAME = 'vite-pwa-plugin:dev-ready' export const DEV_REGISTER_SW_NAME = 'vite-plugin-pwa:register-sw' +export const DEV_PWA_ASSETS_NAME = 'vite-plugin-pwa:pwa-assets' diff --git a/src/context.ts b/src/context.ts index 2b014c5b..1c7cbab6 100644 --- a/src/context.ts +++ b/src/context.ts @@ -1,20 +1,26 @@ import type { ResolvedConfig } from 'vite' +import { version } from '../package.json' import type { ResolvedVitePWAOptions, VitePWAOptions } from './types' +import type { PWAAssetsGenerator } from './pwa-assets/types' export interface PWAPluginContext { + version: string viteConfig: ResolvedConfig userOptions: Partial options: ResolvedVitePWAOptions useImportRegister: boolean devEnvironment: boolean + pwaAssetsGenerator: Promise } export function createContext(userOptions: Partial): PWAPluginContext { return { + version, userOptions, options: undefined!, viteConfig: undefined!, useImportRegister: false, devEnvironment: false, + pwaAssetsGenerator: Promise.resolve(undefined), } } diff --git a/src/html.ts b/src/html.ts index 2144f294..6c5f044e 100644 --- a/src/html.ts +++ b/src/html.ts @@ -1,4 +1,5 @@ import { + DEV_PWA_ASSETS_NAME, DEV_READY_NAME, DEV_REGISTER_SW_NAME, DEV_SW_NAME, @@ -91,6 +92,35 @@ import.meta.hot.on('${DEV_REGISTER_SW_NAME}', ({ mode, inlinePath, registerPath, document.head.appendChild(registerSW); } }); +import.meta.hot.on('${DEV_PWA_ASSETS_NAME}', ({ themeColor, links }) => { + if (themeColor) { + const metaThemeColor = document.querySelector('meta[name="theme-color"]'); + if (metaThemeColor) { + metaThemeColor.content = themeColor.content; + } else { + const meta = document.createElement('meta'); + meta.setAttribute('name', 'theme-color'); + meta.setAttribute('content', themeColor.content); + document.head.appendChild(meta); + } + } + if (links) { + links.map((l) => { + const link = document.querySelector(\`link[href="\${l.href}"]\`) ?? document.createElement('link'); + if (l.id) link.setAttribute('id', l.id); + else link.removeAttribute('id'); + link.setAttribute('rel', l.rel); + link.setAttribute('href', l.href); + if (l.media) link.setAttribute('media', l.media); + else link.removeAttribute('media'); + if (l.sizes) link.setAttribute('sizes', l.sizes); + else link.removeAttribute('sizes'); + if (l.type) link.setAttribute('type', l.type); + else link.removeAttribute('type'); + if (!link.parentNode) document.head.appendChild(link); + }); + } +}); function registerDevSW() { try { import.meta.hot.send('${DEV_READY_NAME}'); diff --git a/src/index.ts b/src/index.ts index 2c1a66ca..fa98b2a2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import type { Plugin } from 'vite' import { createContext } from './context' import type { VitePWAOptions } from './types' +import { AssetsPlugin } from './plugins/pwa-assets' import { BuildPlugin } from './plugins/build' import { DevPlugin } from './plugins/dev' import { MainPlugin } from './plugins/main' @@ -15,6 +16,7 @@ export function VitePWA(userOptions: Partial = {}): Plugin[] { InfoPlugin(ctx, api), BuildPlugin(ctx), DevPlugin(ctx), + AssetsPlugin(ctx), ] } diff --git a/src/options.ts b/src/options.ts index 3ebe6fcd..23b61617 100644 --- a/src/options.ts +++ b/src/options.ts @@ -1,12 +1,13 @@ import fs from 'node:fs' import { extname, resolve } from 'node:path' import process from 'node:process' -import type { ResolvedConfig } from 'vite' import type { GenerateSWOptions, InjectManifestOptions } from 'workbox-build' -import type { ManifestOptions, ResolvedVitePWAOptions, VitePWAOptions } from './types' +import type { ManifestOptions, ResolvedVitePWAOptions } from './types' import { configureStaticAssets } from './assets' import { resolveBasePath, slash } from './utils' import { defaultInjectManifestVitePlugins } from './constants' +import type { PWAPluginContext } from './context' +import { resolvePWAAssetsOptions } from './pwa-assets/options' function resolveSwPaths(injectManifest: boolean, root: string, srcDir: string, outDir: string, filename: string): { swSrc: string @@ -32,7 +33,8 @@ function resolveSwPaths(injectManifest: boolean, root: string, srcDir: string, o } } -export async function resolveOptions(options: Partial, viteConfig: ResolvedConfig): Promise { +export async function resolveOptions(ctx: PWAPluginContext): Promise { + const { userOptions: options, viteConfig } = ctx const root = viteConfig.root const pkg = fs.existsSync('package.json') ? JSON.parse(fs.readFileSync('package.json', 'utf-8')) @@ -59,6 +61,7 @@ export async function resolveOptions(options: Partial, viteConfi selfDestroying = false, integration = {}, buildBase, + pwaAssets, } = options const basePath = resolveBasePath(base) @@ -210,6 +213,7 @@ export async function resolveOptions(options: Partial, viteConfi sourcemap, enableWorkboxModulesLogs, }, + pwaAssets: resolvePWAAssetsOptions(pwaAssets), } // calculate hash only when required diff --git a/src/plugins/build.ts b/src/plugins/build.ts index 79dd6e83..73fb583e 100644 --- a/src/plugins/build.ts +++ b/src/plugins/build.ts @@ -26,19 +26,28 @@ export function BuildPlugin(ctx: PWAPluginContext) { return transformIndexHtmlHandler(html) }, enforce: 'post', // deprecated since Vite 4 - async transform(html) { // deprecated since Vite 4 + transform(html) { // deprecated since Vite 4 return transformIndexHtmlHandler(html) }, }, - generateBundle(_, bundle) { + async generateBundle(_, bundle) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (pwaAssetsGenerator) + pwaAssetsGenerator.injectManifestIcons() + return _generateBundle(ctx, bundle) }, closeBundle: { sequential: true, order: ctx.userOptions?.integration?.closeBundleOrder, async handler() { - if (!ctx.viteConfig.build.ssr && !ctx.options.disable) + if (!ctx.viteConfig.build.ssr && !ctx.options.disable) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (pwaAssetsGenerator) + await pwaAssetsGenerator.generate() + await _generateSW(ctx) + } }, }, async buildEnd(error) { diff --git a/src/plugins/dev.ts b/src/plugins/dev.ts index 1a5bd348..ad024a15 100644 --- a/src/plugins/dev.ts +++ b/src/plugins/dev.ts @@ -1,6 +1,7 @@ import { basename, resolve } from 'node:path' import { existsSync, promises as fs, mkdirSync } from 'node:fs' import type { Plugin, ResolvedConfig, ViteDevServer } from 'vite' +import { cyan, yellow } from 'kolorist' import { generateRegisterDevSW, generateSWHMR, @@ -60,10 +61,19 @@ export function DevPlugin(ctx: PWAPluginContext) { ctx.devEnvironment = true const { options } = ctx if (!options.disable && options.manifest && options.devOptions.enabled) { - server.ws.on(DEV_READY_NAME, createSWResponseHandler(server, ctx)) + server.ws.on(DEV_READY_NAME, createWSResponseHandler(server, ctx)) const name = options.devOptions.webManifestUrl ?? `${options.base}${options.manifestFilename}` - server.middlewares.use((req, res, next) => { + server.middlewares.use(async (req, res, next) => { if (req.url === name) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + pwaAssetsGenerator?.injectManifestIcons() + if (ctx.options.manifest && !ctx.options.manifest.theme_color) { + console.warn([ + '', + `${cyan(`PWA v${ctx.version}`)}`, + `${yellow('WARNING: "theme_color" is missing from the web manifest, your application will not be able to be installed')}`, + ].join('\n')) + } res.statusCode = 200 res.setHeader('Content-Type', 'application/manifest+json') res.write(generateWebManifestFile(options), 'utf-8') @@ -228,7 +238,7 @@ async function createDevRegisterSW(options: ResolvedVitePWAOptions, viteConfig: } } -function createSWResponseHandler(server: ViteDevServer, ctx: PWAPluginContext): () => Promise { +function createWSResponseHandler(server: ViteDevServer, ctx: PWAPluginContext): () => Promise { return async () => { const { options, useImportRegister } = ctx const { injectRegister, scope, base } = options diff --git a/src/plugins/main.ts b/src/plugins/main.ts index 9d9f6914..c7f0953c 100644 --- a/src/plugins/main.ts +++ b/src/plugins/main.ts @@ -1,4 +1,5 @@ import type { Plugin, UserConfig } from 'vite' +import { cyan, yellow } from 'kolorist' import { VIRTUAL_MODULES, VIRTUAL_MODULES_MAP, @@ -26,7 +27,21 @@ export function MainPlugin(ctx: PWAPluginContext, api: VitePluginPWAAPI) { ctx.useImportRegister = false ctx.viteConfig = config ctx.userOptions?.integration?.configureOptions?.(config, ctx.userOptions) - ctx.options = await resolveOptions(ctx.userOptions, config) + ctx.options = await resolveOptions(ctx) + if (ctx.options.pwaAssets && !ctx.options.pwaAssets.disabled) { + ctx.pwaAssetsGenerator = import('../pwa-assets/generator').then(({ loadInstructions }) => loadInstructions(ctx)) + .catch((e) => { + console.error([ + '', + cyan(`PWA v${ctx.version}`), + yellow('WARNING: you must install the following dev dependencies to use the PWA assets generator:'), + yellow('- "@vite-pwa/assets-generator"'), + yellow('- "sharp" (should be installed when installing @vite-pwa/assets-generator)'), + yellow('- "sharp-ico" (should be installed when installing @vite-pwa/assets-generator)'), + ].join('\n'), e) + return Promise.resolve(undefined) + }) + } }, resolveId(id) { return VIRTUAL_MODULES.includes(id) ? VIRTUAL_MODULES_RESOLVE_PREFIX + id : undefined diff --git a/src/plugins/pwa-assets.ts b/src/plugins/pwa-assets.ts new file mode 100644 index 00000000..fd45ce6b --- /dev/null +++ b/src/plugins/pwa-assets.ts @@ -0,0 +1,129 @@ +import type { ModuleNode, Plugin, ViteDevServer } from 'vite' +import type { PWAPluginContext } from '../context' +import { + DEV_PWA_ASSETS_NAME, + DEV_READY_NAME, + PWA_ASSETS_HEAD_VIRTUAL, + PWA_ASSETS_ICONS_VIRTUAL, + RESOLVED_PWA_ASSETS_HEAD_VIRTUAL, + RESOLVED_PWA_ASSETS_ICONS_VIRTUAL, +} from '../constants' +import { extractIcons } from '../pwa-assets/utils' + +export function AssetsPlugin(ctx: PWAPluginContext) { + return { + name: 'vite-plugin-pwa:pwa-assets', + enforce: 'post', + transformIndexHtml: { + order: 'post', + async handler(html) { + return await transformIndexHtmlHandler(html, ctx) + }, + enforce: 'post', // deprecated since Vite 4 + async transform(html) { // deprecated since Vite 4 + return await transformIndexHtmlHandler(html, ctx) + }, + }, + resolveId(id) { + switch (true) { + case id === PWA_ASSETS_HEAD_VIRTUAL: + return RESOLVED_PWA_ASSETS_HEAD_VIRTUAL + case id === PWA_ASSETS_ICONS_VIRTUAL: + return RESOLVED_PWA_ASSETS_ICONS_VIRTUAL + default: + return undefined + } + }, + async load(id) { + if (id === RESOLVED_PWA_ASSETS_HEAD_VIRTUAL) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + const head = pwaAssetsGenerator?.resolveHtmlAssets() ?? { links: [], themeColor: undefined } + return `export const pwaAssetsHead = ${JSON.stringify(head)}` + } + + if (id === RESOLVED_PWA_ASSETS_ICONS_VIRTUAL) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + const icons = extractIcons(pwaAssetsGenerator?.instructions()) + return `export const pwaAssetsIcons = ${JSON.stringify(icons)}` + } + }, + async handleHotUpdate({ file, server }) { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (await pwaAssetsGenerator?.checkHotUpdate(file)) { + const modules: ModuleNode[] = [] + const head = server.moduleGraph.getModuleById(RESOLVED_PWA_ASSETS_HEAD_VIRTUAL) + head && modules.push(head) + const icons = server.moduleGraph.getModuleById(RESOLVED_PWA_ASSETS_ICONS_VIRTUAL) + icons && modules.push(icons) + if (modules) + return modules + + server.ws.send({ type: 'full-reload' }) + return [] + } + }, + configureServer(server) { + server.ws.on(DEV_READY_NAME, createWSResponseHandler(ctx, server)) + server.middlewares.use(async (req, res, next) => { + const url = req.url + if (!url) + return next() + + if (!/\.(ico|png|svg|webp)$/.test(url)) + return next() + + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (!pwaAssetsGenerator) + return next() + + const icon = await pwaAssetsGenerator.findIconAsset(url) + if (!icon) + return next() + + if (icon.age > 0) { + const ifModifiedSince = req.headers['if-modified-since'] ?? req.headers['If-Modified-Since'] + const useIfModifiedSince = ifModifiedSince ? Array.isArray(ifModifiedSince) ? ifModifiedSince[0] : ifModifiedSince : undefined + if (useIfModifiedSince && new Date(icon.lastModified).getTime() / 1000 >= new Date(useIfModifiedSince).getTime() / 1000) { + res.statusCode = 304 + res.end() + return + } + } + + const buffer = await icon.buffer + res.setHeader('Age', icon.age / 1000) + res.setHeader('Content-Type', icon.mimeType) + res.setHeader('Content-Length', buffer.length) + res.setHeader('Last-Modified', new Date(icon.lastModified).toUTCString()) + res.statusCode = 200 + res.end(buffer) + }) + }, + } +} + +async function transformIndexHtmlHandler(html: string, ctx: PWAPluginContext) { + // dev: color-theme and icon links injected using createWSResponseHandler + if (ctx.devEnvironment && ctx.options.devOptions.enabled) + return html + + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (!pwaAssetsGenerator) + return html + + return pwaAssetsGenerator.transformIndexHtml(html) +} + +function createWSResponseHandler(ctx: PWAPluginContext, server: ViteDevServer): () => Promise { + return async () => { + const pwaAssetsGenerator = await ctx.pwaAssetsGenerator + if (pwaAssetsGenerator) { + const data = pwaAssetsGenerator.resolveHtmlAssets() + server.ws.send({ + type: 'custom', + event: DEV_PWA_ASSETS_NAME, + data, + }) + } + } +} diff --git a/src/pwa-assets/build.ts b/src/pwa-assets/build.ts new file mode 100644 index 00000000..c8591264 --- /dev/null +++ b/src/pwa-assets/build.ts @@ -0,0 +1,10 @@ +import { mkdir } from 'node:fs/promises' +import { generateAssets } from '@vite-pwa/assets-generator/api/generate-assets' +import type { AssetsGeneratorContext } from './types' + +export async function generate( + assetsGeneratorContext: AssetsGeneratorContext, +) { + await mkdir(assetsGeneratorContext.imageOutDir, { recursive: true }) + await generateAssets(assetsGeneratorContext.assetsInstructions, true, assetsGeneratorContext.imageOutDir) +} diff --git a/src/pwa-assets/config.ts b/src/pwa-assets/config.ts new file mode 100644 index 00000000..53238684 --- /dev/null +++ b/src/pwa-assets/config.ts @@ -0,0 +1,151 @@ +import { basename, dirname, relative, resolve } from 'node:path' +import { readFile } from 'node:fs/promises' +import type { UserConfig } from '@vite-pwa/assets-generator/config' +import { loadConfig } from '@vite-pwa/assets-generator/config' +import { cyan, red } from 'kolorist' +import { instructions } from '@vite-pwa/assets-generator/api/instructions' +import type { PWAPluginContext } from '../context' +import type { ResolvedPWAAssetsOptions } from '../types' +import type { AssetsGeneratorContext, ResolvedIconAsset } from './types' + +export async function loadAssetsGeneratorContext( + ctx: PWAPluginContext, + assetsGeneratorContext?: AssetsGeneratorContext, +) { + const root = ctx.viteConfig.root ?? process.cwd() + const { config, sources } = await loadConfiguration(root, ctx) + if (!config.preset) { + console.error([ + '', + cyan(`PWA v${ctx.version}`), + red('ERROR: No preset for assets generator found'), + ].join('\n')) + return + } + + const { + preset, + images, + headLinkOptions: userHeadLinkOptions, + } = config + + if (!images) { + console.error([ + '', + cyan(`PWA v${ctx.version}`), + red('ERROR: No image provided for assets generator'), + ].join('\n')) + return + } + + if (Array.isArray(images)) { + if (!images.length) { + console.error([ + '', + cyan(`PWA v${ctx.version}`), + red('ERROR: No image provided for assets generator'), + ].join('\n')) + return + } + if (images.length > 1) { + console.error([ + '', + cyan(`PWA v${ctx.version}`), + red('ERROR: Only one image is supported for assets generator'), + ].join('\n')) + return + } + } + + const pwaAssets = ctx.options.pwaAssets as ResolvedPWAAssetsOptions + + const useImage = Array.isArray(images) ? images[0] : images + // the image must be relative to the root directory + const imageFile = resolve(root, useImage) + const publicDir = pwaAssets.integration?.publicDir ?? resolve(root, ctx.viteConfig.publicDir || 'public') + const outDir = pwaAssets.integration?.outDir ?? resolve(root, ctx.viteConfig.build?.outDir || 'dist') + // image can be inside public subdirectory: public/pwa/icon.svg => pwa/icon.svg + const imageName = relative(publicDir, imageFile) + // resolve the output folder for the image: /pwa/icon.svg + const imageOutDir = dirname(resolve(outDir, imageName)) + + const xhtml = userHeadLinkOptions?.xhtml === true + const includeId = userHeadLinkOptions?.includeId === true + const assetsInstructions = await instructions({ + imageResolver: () => readFile(imageFile), + imageName, + preset, + faviconPreset: userHeadLinkOptions?.preset, + htmlLinks: { xhtml, includeId }, + basePath: pwaAssets.integration?.baseUrl || ctx.viteConfig.base || '/', + resolveSvgName: userHeadLinkOptions?.resolveSvgName ?? (name => basename(name)), + }) + const { + includeHtmlHeadLinks = true, + overrideManifestIcons: useOverrideManifestIcons, + injectThemeColor = false, + } = pwaAssets + + // override manifest icons when: + // - manifest is defined and + // - missing manifest.icons entry or manifest.icons present and overrideManifestIcons is enabled + const overrideManifestIcons = ctx.options.manifest === false || !ctx.options.manifest + ? false + : 'icons' in ctx.options.manifest + ? useOverrideManifestIcons // explicit override + : true + + if (assetsGeneratorContext === undefined) { + return { + lastModified: Date.now(), + assetsInstructions, + cache: new Map(), + useImage, + imageFile, + publicDir, + outDir, + imageName, + imageOutDir, + xhtml, + includeId, + // normalize sources + sources: sources.map(source => source.replace(/\\/g, '/')), + injectThemeColor, + includeHtmlHeadLinks, + overrideManifestIcons, + } satisfies AssetsGeneratorContext + } + + assetsGeneratorContext.lastModified = Date.now() + assetsGeneratorContext.assetsInstructions = assetsInstructions + assetsGeneratorContext.useImage = useImage + assetsGeneratorContext.imageFile = imageFile + assetsGeneratorContext.outDir = outDir + assetsGeneratorContext.imageName = imageName + assetsGeneratorContext.imageOutDir = imageOutDir + assetsGeneratorContext.xhtml = xhtml + assetsGeneratorContext.includeId = includeId + assetsGeneratorContext.injectThemeColor = injectThemeColor + assetsGeneratorContext.includeHtmlHeadLinks = includeHtmlHeadLinks + assetsGeneratorContext.overrideManifestIcons = overrideManifestIcons + assetsGeneratorContext.cache.clear() +} + +async function loadConfiguration(root: string, ctx: PWAPluginContext) { + const pwaAssets = ctx.options.pwaAssets as ResolvedPWAAssetsOptions + if (pwaAssets.config === false) { + return await loadConfig(root, { + config: false, + preset: pwaAssets.preset as UserConfig['preset'], + images: pwaAssets.images, + logLevel: 'silent', + }) + } + + return await loadConfig( + root, + typeof pwaAssets.config === 'boolean' + ? root + : { config: pwaAssets.config }, + ) +} diff --git a/src/pwa-assets/dev.ts b/src/pwa-assets/dev.ts new file mode 100644 index 00000000..898016b0 --- /dev/null +++ b/src/pwa-assets/dev.ts @@ -0,0 +1,48 @@ +import type { PWAPluginContext } from '../context' +import type { AssetsGeneratorContext, ResolvedIconAsset } from './types' +import { loadAssetsGeneratorContext } from './config' + +export async function findIconAsset( + path: string, + { assetsInstructions, cache, lastModified }: AssetsGeneratorContext, +) { + let resolved = cache.get(path) + if (resolved) { + resolved.age = Date.now() - lastModified + return resolved + } + + const iconAsset = assetsInstructions.transparent[path] + ?? assetsInstructions.maskable[path] + ?? assetsInstructions.apple[path] + ?? assetsInstructions.favicon[path] + ?? assetsInstructions.appleSplashScreen[path] + + if (!iconAsset) + return + + if (iconAsset) { + resolved = { + path, + mimeType: iconAsset.mimeType, + buffer: iconAsset.buffer(), + lastModified: Date.now(), + age: 0, + } satisfies ResolvedIconAsset + cache.set(path, resolved) + return resolved + } +} + +export async function checkHotUpdate( + file: string, + ctx: PWAPluginContext, + assetsGeneratorContext: AssetsGeneratorContext, +) { + // watch pwa assets configuration file + const result = assetsGeneratorContext.sources.includes(file) + if (result) + await loadAssetsGeneratorContext(ctx, assetsGeneratorContext) + + return result +} diff --git a/src/pwa-assets/generator.ts b/src/pwa-assets/generator.ts new file mode 100644 index 00000000..4bafd58b --- /dev/null +++ b/src/pwa-assets/generator.ts @@ -0,0 +1,25 @@ +import type { PWAPluginContext } from '../context' +import type { PWAAssetsGenerator } from './types' +import { loadAssetsGeneratorContext } from './config' +import { generate } from './build' +import { checkHotUpdate, findIconAsset } from './dev' +import { resolveHtmlAssets, transformIndexHtml } from './html' +import { injectManifestIcons } from './manifest' +import { extractIcons } from './utils' + +export async function loadInstructions(ctx: PWAPluginContext) { + const assetsGeneratorContext = await loadAssetsGeneratorContext(ctx) + if (!assetsGeneratorContext) + return + + return { + generate: () => generate(assetsGeneratorContext), + findIconAsset: (path: string) => findIconAsset(path, assetsGeneratorContext), + resolveHtmlAssets: () => resolveHtmlAssets(ctx, assetsGeneratorContext), + transformIndexHtml: (html: string) => transformIndexHtml(html, ctx, assetsGeneratorContext), + injectManifestIcons: () => injectManifestIcons(ctx, assetsGeneratorContext), + instructions: () => assetsGeneratorContext.assetsInstructions, + icons: () => extractIcons(assetsGeneratorContext.assetsInstructions), + checkHotUpdate: file => checkHotUpdate(file, ctx, assetsGeneratorContext), + } satisfies PWAAssetsGenerator +} diff --git a/src/pwa-assets/html.ts b/src/pwa-assets/html.ts new file mode 100644 index 00000000..b4251b0d --- /dev/null +++ b/src/pwa-assets/html.ts @@ -0,0 +1,56 @@ +import { generateHtmlMarkup } from '@vite-pwa/assets-generator/api/generate-html-markup' +import type { PWAPluginContext } from '../context' +import type { AssetsGeneratorContext, PWAHtmlAssets } from './types' +import { mapLink } from './utils' + +export function transformIndexHtml( + html: string, + ctx: PWAPluginContext, + assetsGeneratorContext: AssetsGeneratorContext, +) { + if (assetsGeneratorContext.injectThemeColor) { + const manifest = ctx.options.manifest + if (manifest && 'theme_color' in manifest && manifest.theme_color) { + html = html.replace( + '', + `\n`, + ) + } + } + + if (assetsGeneratorContext.includeHtmlHeadLinks) { + const link = generateHtmlMarkup(assetsGeneratorContext.assetsInstructions) + if (link.length) + html = html.replace('', `\n${link.join('\n')}`) + } + + return html +} + +export function resolveHtmlAssets( + ctx: PWAPluginContext, + assetsGeneratorContext: AssetsGeneratorContext, +) { + const header: PWAHtmlAssets = { + links: [], + themeColor: undefined, + } + if (assetsGeneratorContext.injectThemeColor) { + const manifest = ctx.options.manifest + if (manifest && 'theme_color' in manifest && manifest.theme_color) + header.themeColor = { name: 'theme-color', content: manifest.theme_color } + } + + if (assetsGeneratorContext.includeHtmlHeadLinks) { + const includeId = assetsGeneratorContext.includeId + const instruction = assetsGeneratorContext.assetsInstructions + const favicon = Array.from(Object.values(instruction.favicon)) + const apple = Array.from(Object.values(instruction.apple)) + const appleSplashScreen = Array.from(Object.values(instruction.appleSplashScreen)) + favicon.forEach(icon => icon.linkObject && header.links.push(mapLink(includeId, icon.linkObject))) + apple.forEach(icon => icon.linkObject && header.links.push(mapLink(includeId, icon.linkObject))) + appleSplashScreen.forEach(icon => icon.linkObject && header.links.push(mapLink(includeId, icon.linkObject))) + } + + return header +} diff --git a/src/pwa-assets/manifest.ts b/src/pwa-assets/manifest.ts new file mode 100644 index 00000000..9ea5004e --- /dev/null +++ b/src/pwa-assets/manifest.ts @@ -0,0 +1,19 @@ +import { generateManifestIconsEntry } from '@vite-pwa/assets-generator/api/generate-manifest-icons-entry' +import type { PWAPluginContext } from '../context' +import type { AssetsGeneratorContext } from './types' + +export function injectManifestIcons( + ctx: PWAPluginContext, + assetsGeneratorContext: AssetsGeneratorContext, +) { + if (!assetsGeneratorContext.overrideManifestIcons) + return + + const manifest = ctx.options.manifest + if (manifest) { + manifest.icons = generateManifestIconsEntry( + 'object', + assetsGeneratorContext.assetsInstructions, + ).icons + } +} diff --git a/src/pwa-assets/options.ts b/src/pwa-assets/options.ts new file mode 100644 index 00000000..4b9a2959 --- /dev/null +++ b/src/pwa-assets/options.ts @@ -0,0 +1,34 @@ +import type { PWAAssetsOptions, ResolvedPWAAssetsOptions } from '../types' + +export function resolvePWAAssetsOptions( + options?: PWAAssetsOptions, +) { + if (!options) + return false + + const { + disabled: useDisabled, + config, + preset, + image = 'public/favicon.svg', + htmlPreset = '2023', + overrideManifestIcons = false, + includeHtmlHeadLinks = true, + injectThemeColor = true, + integration, + } = options ?? {} + + const disabled = useDisabled || (!config && !preset) + + return { + disabled, + config: disabled || !config ? false : config, + preset: disabled || config ? false : preset ?? 'minimal-2023', + images: [image], + htmlPreset, + overrideManifestIcons, + includeHtmlHeadLinks, + injectThemeColor, + integration, + } satisfies ResolvedPWAAssetsOptions +} diff --git a/src/pwa-assets/types.ts b/src/pwa-assets/types.ts new file mode 100644 index 00000000..f1e9367d --- /dev/null +++ b/src/pwa-assets/types.ts @@ -0,0 +1,72 @@ +import type { + AppleSplashScreenLink, + FaviconLink, + HtmlLink, + IconAsset, + ImageAssetsInstructions, +} from '@vite-pwa/assets-generator/api' + +export interface PWAHtmlLink { + id?: string + rel: 'apple-touch-startup-image' | 'apple-touch-icon' | 'icon' + href: string + media?: string + sizes?: string + type?: string +} + +export interface ColorSchemeMeta { + name: string + content: string +} + +export interface ResolvedIconAsset { + path: string + mimeType: string + // eslint-disable-next-line node/prefer-global/buffer + buffer: Promise + age: number + lastModified: number +} + +export interface PWAHtmlAssets { + links: PWAHtmlLink[] + themeColor?: ColorSchemeMeta +} + +export interface AssetsGeneratorContext { + lastModified: number + assetsInstructions: ImageAssetsInstructions + cache: Map + useImage: string + imageFile: string + publicDir: string + outDir: string + imageName: string + imageOutDir: string + xhtml: boolean + includeId: boolean + sources: string[] + injectThemeColor: boolean + includeHtmlHeadLinks: boolean + overrideManifestIcons: boolean +} + +export interface PWAAssetsIcons { + favicon: Record, 'buffer'>> + transparent: Record, 'buffer'>> + maskable: Record, 'buffer'>> + apple: Record, 'buffer'>> + appleSplashScreen: Record, 'buffer'>> +} + +export interface PWAAssetsGenerator { + generate: () => Promise + findIconAsset: (path: string) => Promise + resolveHtmlAssets: () => PWAHtmlAssets + transformIndexHtml: (html: string) => string + injectManifestIcons: () => void + instructions: () => ImageAssetsInstructions + icons: () => PWAAssetsIcons + checkHotUpdate: (path: string) => Promise +} diff --git a/src/pwa-assets/utils.ts b/src/pwa-assets/utils.ts new file mode 100644 index 00000000..28b7d108 --- /dev/null +++ b/src/pwa-assets/utils.ts @@ -0,0 +1,68 @@ +import type { + AppleSplashScreenLink, + FaviconLink, + HtmlLink, + ImageAssetsInstructions, +} from '@vite-pwa/assets-generator/api' +import type { PWAAssetsIcons, PWAHtmlLink } from './types' + +export function mapLink( + includeId: boolean, + link: HtmlLink | FaviconLink | AppleSplashScreenLink, +) { + const linkObject: PWAHtmlLink = { + href: link.href, + rel: link.rel, + } + + if (includeId && link.id) + linkObject.id = link.id + + if ('media' in link && link.media) + linkObject.media = link.media + + linkObject.href = link.href + + if ('sizes' in link && link.sizes) + linkObject.sizes = link.sizes + + if ('type' in link && link.type) + linkObject.type = link.type + + return linkObject +} + +export function extractIcons(instructions?: ImageAssetsInstructions) { + const icons: PWAAssetsIcons = { + favicon: {}, + transparent: {}, + maskable: {}, + apple: {}, + appleSplashScreen: {}, + } + + if (instructions) { + Array.from(Object.values(instructions.favicon)).forEach(({ buffer: _buffer, ...rest }) => { + if (rest.url) + icons.favicon[rest.url] = { ...rest } + }) + Array.from(Object.values(instructions.transparent)).forEach(({ buffer: _buffer, ...rest }) => { + if (rest.url) + icons.transparent[rest.url] = { ...rest } + }) + Array.from(Object.values(instructions.maskable)).forEach(({ buffer: _buffer, ...rest }) => { + if (rest.url) + icons.maskable[rest.url] = { ...rest } + }) + Array.from(Object.values(instructions.apple)).forEach(({ buffer: _buffer, ...rest }) => { + if (rest.url) + icons.apple[rest.url] = { ...rest } + }) + Array.from(Object.values(instructions.appleSplashScreen)).forEach(({ buffer: _buffer, ...rest }) => { + if (rest.url) + icons.appleSplashScreen[rest.url] = { ...rest } + }) + } + + return icons +} diff --git a/src/types.ts b/src/types.ts index 79dfccb0..52e7375d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,6 +1,9 @@ import type { BuildOptions, Plugin, ResolvedConfig, UserConfig } from 'vite' import type { GenerateSWOptions, InjectManifestOptions, ManifestEntry } from 'workbox-build' import type { OutputBundle, RollupOptions } from 'rollup' +import type { BuiltInPreset, Preset } from '@vite-pwa/assets-generator/config' +import type { HtmlLinkPreset } from '@vite-pwa/assets-generator/api' +import type { PWAAssetsGenerator } from './pwa-assets/types' export type InjectManifestVitePlugins = string[] | ((vitePluginIds: string[]) => string[]) export type CustomInjectManifestOptions = InjectManifestOptions & { @@ -93,6 +96,112 @@ export interface PWAIntegration { ) => void | Promise } +/** + * PWA assets generation and injection options. + */ +export interface PWAAssetsOptions { + disabled?: boolean + /** + * PWA assets generation and injection. + * + * By default, the plugin will search for the pwa assets generator configuration file in the root directory of your project: + * - pwa-assets.config.js + * - pwa-assets.config.mjs + * - pwa-assets.config.cjs + * - pwa-assets.config.ts + * - pwa-assets.config.cts + * - pwa-assets.config.mts + * + * If using a string path, it should be relative to the root directory of your project. + * + * Setting to `false` will disable config resolving. + * + * **WARNING**: You can use only one image in the configuration file. + * + * @default false + * @see https://vite-pwa-org.netlify.app/assets-generator/cli.html#configurations + */ + config?: string | boolean + /** + * Preset to use. + * + * If the `config` option is enabled, this option will be ignored. + * + * Setting this option `false` will disable PWA assets generation (if the `config` option is also disabled). + * + * @default 'minimal-2023' + */ + preset?: false | BuiltInPreset | Preset + /** + * Path relative to `root` folder where to find the image to use for generating PWA assets. + * + * If the `config` option is enabled, this option will be ignored. + * + * @default `public/favicon.svg` + */ + image?: string + /** + * The preset to use for head links (favicon links). + * + * If the `config` option is enabled, this option will be ignored. + * + * @see https://vite-pwa-org.netlify.app/assets-generator/#preset-minimal-2023 + * @see https://vite-pwa-org.netlify.app/assets-generator/#preset-minimal + * @default '2023' + */ + htmlPreset?: HtmlLinkPreset + /** + * Should the plugin include html head links? + * + * @default true + */ + includeHtmlHeadLinks?: boolean + /** + * Should the plugin override the PWA web manifest icons' entry? + * + * The plugin will auto-detect the icons from the manifest, if missing, then the plugin will ignore this option and will include the icons. + * + * @default false + */ + overrideManifestIcons?: boolean + /** + * Should the PWA web manifest `theme_color` be injected in the html head? + * + * @default true + */ + injectThemeColor?: boolean + /** + * PWA Assets integration support. + * + * This option should be only used by integrations, it is not meant to be used by end users. + */ + integration?: { + /** + * The base url for the PWA assets. + * + * @default `vite.base` + */ + baseUrl?: string + /** + * The public directory to resolve the image: should be an absolute path. + * + * @default `vite.root/vite.publicDir` + */ + publicDir?: string + /** + * The output directory: should be an absolute path. + * + * @default `vite.root/vite.build.outDir` + */ + outDir?: string + } +} + +export interface ResolvedPWAAssetsOptions extends Required> { + integration?: PWAAssetsOptions['integration'] + images: string[] +} + /** * Plugin options. */ @@ -246,9 +355,16 @@ export interface VitePWAOptions { * * For example, if your base path is `/`, then, in your Laravel PWA configuration use `buildPath: '/build/'`. * - * By default: `vite.base`. + * @default `vite.base`. */ buildBase?: string + + /** + * PWA assets generation and injection. + * + * @experimental + */ + pwaAssets?: PWAAssetsOptions } export interface ResolvedServiceWorkerOptions { @@ -257,7 +373,7 @@ export interface ResolvedServiceWorkerOptions { rollupOptions: RollupOptions } -export interface ResolvedVitePWAOptions extends Required { +export interface ResolvedVitePWAOptions extends Required> { swSrc: string swDest: string workbox: GenerateSWOptions @@ -272,6 +388,7 @@ export interface ResolvedVitePWAOptions extends Required { sourcemap?: BuildOptions['sourcemap'] enableWorkboxModulesLogs?: true } + pwaAssets: false | ResolvedPWAAssetsOptions } export interface ShareTargetFiles { @@ -552,6 +669,7 @@ export interface VitePluginPWAAPI { * Explicitly generate the PWA services worker. */ generateSW(): Promise + pwaAssetsGenerator(): Promise } export type ExtendManifestEntriesHook = (manifestEntries: (string | ManifestEntry)[]) => (string | ManifestEntry)[] | undefined