diff --git a/package.json b/package.json index 2faa6fdf..250ef4d9 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@testing-library/jest-dom": "^6.8.0", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.6.1", - "@vitejs/plugin-react": "^6.0.2", + "@vitejs/plugin-react": "^5.2.0", "@vitest/ui": "^4.1.8", "chai": "^6.0.1", "eslint": "^9.39.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 29e603e2..6ea5bdc7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,7 +27,7 @@ importers: version: https://codeload.github.com/profullstack/autoblog/tar.gz/75e54af77cbcf61dbd90fb3ed529c1b2dad1ed6f '@profullstack/stack': specifier: ^0.1.3 - version: 0.1.3(@supabase/ssr@0.7.0(@supabase/supabase-js@2.74.0))(next@15.5.19(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) + version: 0.1.3(@supabase/ssr@0.7.0(@supabase/supabase-js@2.74.0))(next@15.5.19(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) '@profullstack/text-type-detection': specifier: ^1.0.0 version: 1.0.0 @@ -57,7 +57,7 @@ importers: version: 2.5.0 next: specifier: ^15.0.0 - version: 15.5.19(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + version: 15.5.19(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) openpgp: specifier: ^6.2.0 version: 6.2.2 @@ -93,8 +93,8 @@ importers: specifier: ^14.6.1 version: 14.6.1(@testing-library/dom@10.4.1) '@vitejs/plugin-react': - specifier: ^6.0.2 - version: 6.0.2(vite@7.3.1(@types/node@24.7.0)(terser@5.46.0)) + specifier: ^5.2.0 + version: 5.2.0(vite@7.3.1(@types/node@24.7.0)(terser@5.46.0)) '@vitest/ui': specifier: ^4.1.8 version: 4.1.8(vitest@4.1.8) @@ -153,14 +153,97 @@ packages: resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.7': + resolution: {integrity: sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.7': + resolution: {integrity: sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.7': + resolution: {integrity: sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.8': + resolution: {integrity: sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.29.7': + resolution: {integrity: sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.29.7': + resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.29.7': + resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.29.7': + resolution: {integrity: sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.29.7': + resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.29.7': + resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.29.7': + resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.29.7': + resolution: {integrity: sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.7': + resolution: {integrity: sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.8': + resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-transform-react-jsx-self@7.29.7': + resolution: {integrity: sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.29.7': + resolution: {integrity: sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.6': resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} + '@babel/template@7.29.7': + resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.8': + resolution: {integrity: sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.8': + resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==} + engines: {node: '>=6.9.0'} + '@bundled-es-modules/cookie@2.0.1': resolution: {integrity: sha512-8o+5fRPLNbjbdGRRmJj3h6Hh1AQJf2dk3qQ/5ZFb+PXkRNiSoMGGUKlsgLfrxneb72axVJyIYji64E2+nNfYyw==} @@ -613,6 +696,9 @@ packages: '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -894,8 +980,8 @@ packages: resolution: {integrity: sha512-3tG0Icz2gwLfwbOwdYxgCTTcjCyAAhEnU82ReIrbOQiN8f3R84WrPLWfE4Pqg/ce57VFVPpNkSmd5doaXKV+dw==} engines: {node: '>=20.0.0'} - '@rolldown/pluginutils@1.0.1': - resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} '@rollup/rollup-android-arm-eabi@4.52.4': resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==} @@ -1101,6 +1187,18 @@ packages: '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.27.0': + resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -1313,18 +1411,11 @@ packages: cpu: [x64] os: [win32] - '@vitejs/plugin-react@6.0.2': - resolution: {integrity: sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg==} + '@vitejs/plugin-react@5.2.0': + resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 - babel-plugin-react-compiler: ^1.0.0 - vite: ^8.0.0 - peerDependenciesMeta: - '@rolldown/plugin-babel': - optional: true - babel-plugin-react-compiler: - optional: true + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 '@vitest/expect@4.1.8': resolution: {integrity: sha512-h3nDO677RDLEGlBxyQ5CW8RlMThSKSRLUePLOx09gNIWRL40edgA1GCZSZgf1W55MFAG6/Sw14KeaAnqv0NKdQ==} @@ -1470,6 +1561,11 @@ packages: base-64@1.0.0: resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + baseline-browser-mapping@2.11.11: + resolution: {integrity: sha512-/yImnXwyTvgMkhgekLHok/Rx5vO6E0BmStWlSqKWMVm2a2ITuZ1Tn+9bgLS+gZRdZmWtd8nxuhHpdmCUOWsTQQ==} + engines: {node: '>=6.0.0'} + hasBin: true + blessed@0.1.81: resolution: {integrity: sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==} engines: {node: '>= 0.8.0'} @@ -1492,6 +1588,11 @@ packages: browser-stdout@1.3.1: resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + browserslist@4.28.7: + resolution: {integrity: sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -1525,6 +1626,9 @@ packages: caniuse-lite@1.0.30001767: resolution: {integrity: sha512-34+zUAMhSH+r+9eKmYG+k2Rpt8XttfE4yXAjoZvkAPs15xcYQhyBYdalJ65BzivAvGRMViEjy6oKr/S91loekQ==} + caniuse-lite@1.0.30001806: + resolution: {integrity: sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==} + chai@6.2.0: resolution: {integrity: sha512-aUTnJc/JipRzJrNADXVvpVqi6CO0dn3nx4EVPxijri+fj3LUUDyZQOgVeW54Ob3Y1Xh9Iz8f+CgaCl8v0mn9bA==} engines: {node: '>=18'} @@ -1690,6 +1794,9 @@ packages: ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + electron-to-chromium@1.5.399: + resolution: {integrity: sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1972,6 +2079,10 @@ packages: resolution: {integrity: sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==} engines: {node: '>= 0.4'} + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + get-caller-file@2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} @@ -2260,6 +2371,11 @@ packages: canvas: optional: true + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} @@ -2273,6 +2389,11 @@ packages: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + jsonwebtoken@9.0.2: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} @@ -2344,6 +2465,9 @@ packages: resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} engines: {node: 20 || >=22} + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + lz-string@1.5.0: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true @@ -2469,6 +2593,10 @@ packages: resolution: {integrity: sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==} engines: {node: '>= 0.4'} + node-releases@2.0.51: + resolution: {integrity: sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==} + engines: {node: '>=18'} + nwsapi@2.2.22: resolution: {integrity: sha512-ujSMe1OWVn55euT1ihwCI1ZcAaAU3nxUiDwfDQldc51ZXaB9m2AyOn6/jh1BLe2t/G8xd6uKG1UBF2aZJeg2SQ==} @@ -2644,6 +2772,10 @@ packages: react-is@17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + react@19.2.7: resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} engines: {node: '>=0.10.0'} @@ -3027,6 +3159,12 @@ packages: until-async@3.0.2: resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} @@ -3219,6 +3357,9 @@ packages: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + yargs-parser@21.1.1: resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} engines: {node: '>=12'} @@ -3275,10 +3416,122 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.7': + dependencies: + '@babel/helper-validator-identifier': 7.29.7 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.7': {} + + '@babel/core@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-compilation-targets': 7.29.7 + '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7) + '@babel/helpers': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3(supports-color@8.1.1) + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.29.8': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.29.7': + dependencies: + '@babel/compat-data': 7.29.7 + '@babel/helper-validator-option': 7.29.7 + browserslist: 4.28.7 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.29.7': {} + + '@babel/helper-module-imports@7.29.7': + dependencies: + '@babel/traverse': 7.29.8 + '@babel/types': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-module-imports': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@babel/traverse': 7.29.8 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.29.7': {} + + '@babel/helper-string-parser@7.29.7': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-identifier@7.29.7': {} + + '@babel/helper-validator-option@7.29.7': {} + + '@babel/helpers@7.29.7': + dependencies: + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + + '@babel/parser@7.29.8': + dependencies: + '@babel/types': 7.29.8 + + '@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + + '@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)': + dependencies: + '@babel/core': 7.29.7 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/runtime@7.28.6': {} + '@babel/template@7.29.7': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@babel/traverse@7.29.8': + dependencies: + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.8 + '@babel/helper-globals': 7.29.7 + '@babel/parser': 7.29.8 + '@babel/template': 7.29.7 + '@babel/types': 7.29.8 + debug: 4.4.3(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.8': + dependencies: + '@babel/helper-string-parser': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 + '@bundled-es-modules/cookie@2.0.1': dependencies: cookie: 1.1.1 @@ -3596,10 +3849,13 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 '@jridgewell/trace-mapping': 0.3.31 - optional: true - '@jridgewell/resolve-uri@3.1.2': - optional: true + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/source-map@0.3.11': dependencies: @@ -3613,7 +3869,6 @@ snapshots: dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 - optional: true '@mswjs/interceptors@0.39.7': dependencies: @@ -3761,18 +4016,18 @@ snapshots: optionalDependencies: react: 19.2.7 - '@profullstack/stack@0.1.3(@supabase/ssr@0.7.0(@supabase/supabase-js@2.74.0))(next@15.5.19(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)': + '@profullstack/stack@0.1.3(@supabase/ssr@0.7.0(@supabase/supabase-js@2.74.0))(next@15.5.19(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)': dependencies: '@profullstack/emailer': 1.0.1 '@profullstack/referrals': 0.1.0(react@19.2.7) optionalDependencies: '@supabase/ssr': 0.7.0(@supabase/supabase-js@2.74.0) - next: 15.5.19(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + next: 15.5.19(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 '@profullstack/text-type-detection@1.0.0': {} - '@rolldown/pluginutils@1.0.1': {} + '@rolldown/pluginutils@1.0.0-rc.3': {} '@rollup/rollup-android-arm-eabi@4.52.4': optional: true @@ -3948,6 +4203,27 @@ snapshots: '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + '@types/babel__generator': 7.27.0 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.28.0 + + '@types/babel__generator@7.27.0': + dependencies: + '@babel/types': 7.29.8 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.8 + '@babel/types': 7.29.8 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.8 + '@types/chai@5.2.2': dependencies: '@types/deep-eql': 4.0.2 @@ -4138,10 +4414,17 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.12.2': optional: true - '@vitejs/plugin-react@6.0.2(vite@7.3.1(@types/node@24.7.0)(terser@5.46.0))': + '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@24.7.0)(terser@5.46.0))': dependencies: - '@rolldown/pluginutils': 1.0.1 + '@babel/core': 7.29.7 + '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7) + '@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 vite: 7.3.1(@types/node@24.7.0)(terser@5.46.0) + transitivePeerDependencies: + - supports-color '@vitest/expect@4.1.8': dependencies: @@ -4328,6 +4611,8 @@ snapshots: base-64@1.0.0: {} + baseline-browser-mapping@2.11.11: {} + blessed@0.1.81: {} brace-expansion@1.1.12: @@ -4349,6 +4634,14 @@ snapshots: browser-stdout@1.3.1: {} + browserslist@4.28.7: + dependencies: + baseline-browser-mapping: 2.11.11 + caniuse-lite: 1.0.30001806 + electron-to-chromium: 1.5.399 + node-releases: 2.0.51 + update-browserslist-db: 1.2.3(browserslist@4.28.7) + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: @@ -4384,6 +4677,8 @@ snapshots: caniuse-lite@1.0.30001767: {} + caniuse-lite@1.0.30001806: {} + chai@6.2.0: {} chai@6.2.2: {} @@ -4530,6 +4825,8 @@ snapshots: dependencies: safe-buffer: 5.2.1 + electron-to-chromium@1.5.399: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -4738,7 +5035,7 @@ snapshots: eslint: 9.39.2 eslint-import-resolver-node: 0.3.10 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2))(eslint@9.39.2) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.2) eslint-plugin-react: 7.37.5(eslint@9.39.2) eslint-plugin-react-hooks: 5.2.0(eslint@9.39.2) @@ -4768,7 +5065,7 @@ snapshots: tinyglobby: 0.2.15 unrs-resolver: 1.12.2 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2))(eslint@9.39.2) transitivePeerDependencies: - supports-color @@ -4783,7 +5080,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.2): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.60.1(eslint@9.39.2)(typescript@5.9.3))(eslint@9.39.2))(eslint@9.39.2))(eslint@9.39.2): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -5013,6 +5310,8 @@ snapshots: generator-function@2.0.1: {} + gensync@1.0.0-beta.2: {} + get-caller-file@2.0.5: {} get-intrinsic@1.3.0: @@ -5173,7 +5472,7 @@ snapshots: is-bun-module@2.0.0: dependencies: - semver: 7.7.2 + semver: 7.8.1 is-callable@1.2.7: {} @@ -5322,6 +5621,8 @@ snapshots: - supports-color - utf-8-validate + jsesc@3.1.0: {} + json-buffer@3.0.1: {} json-schema-traverse@0.4.1: {} @@ -5332,6 +5633,8 @@ snapshots: dependencies: minimist: 1.2.8 + json5@2.2.3: {} + jsonwebtoken@9.0.2: dependencies: jws: 4.0.1 @@ -5343,7 +5646,7 @@ snapshots: lodash.isstring: 4.0.1 lodash.once: 4.1.1 ms: 2.1.3 - semver: 7.7.2 + semver: 7.8.1 jsx-ast-utils@3.3.5: dependencies: @@ -5411,6 +5714,10 @@ snapshots: lru-cache@11.2.5: {} + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + lz-string@1.5.0: {} magic-string@0.30.21: @@ -5526,7 +5833,7 @@ snapshots: natural-compare@1.4.0: {} - next@15.5.19(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + next@15.5.19(@babel/core@7.29.7)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: '@next/env': 15.5.19 '@swc/helpers': 0.5.15 @@ -5534,7 +5841,7 @@ snapshots: postcss: 8.4.31 react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - styled-jsx: 5.1.6(react@19.2.7) + styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.7) optionalDependencies: '@next/swc-darwin-arm64': 15.5.19 '@next/swc-darwin-x64': 15.5.19 @@ -5556,6 +5863,8 @@ snapshots: object.entries: 1.1.9 semver: 6.3.1 + node-releases@2.0.51: {} + nwsapi@2.2.22: {} object-assign@4.1.1: {} @@ -5744,6 +6053,8 @@ snapshots: react-is@17.0.2: {} + react-refresh@0.18.0: {} + react@19.2.7: {} readdirp@4.1.2: {} @@ -6064,10 +6375,12 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(react@19.2.7): + styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.7): dependencies: client-only: 0.0.1 react: 19.2.7 + optionalDependencies: + '@babel/core': 7.29.7 supports-color@7.2.0: dependencies: @@ -6241,6 +6554,12 @@ snapshots: until-async@3.0.2: {} + update-browserslist-db@1.2.3(browserslist@4.28.7): + dependencies: + browserslist: 4.28.7 + escalade: 3.2.0 + picocolors: 1.1.1 + uri-js@4.4.1: dependencies: punycode: 2.3.1 @@ -6397,6 +6716,8 @@ snapshots: y18n@5.0.8: {} + yallist@3.1.1: {} + yargs-parser@21.1.1: {} yargs-unparser@2.0.0: diff --git a/public/manifest.json b/public/manifest.json index 940d51a3..d2cf57a9 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,13 +1,18 @@ { + "id": "/?source=pwa", "name": "QryptChat - Quantum-Resistant Messaging", "short_name": "QryptChat", "description": "Secure, quantum-resistant end-to-end encrypted messaging", - "version": "1.0", + "lang": "en", + "dir": "ltr", "start_url": "/?source=pwa", + "scope": "/", "display": "standalone", + "display_override": ["standalone", "minimal-ui", "browser"], "orientation": "portrait", "theme_color": "#6366f1", "background_color": "#ffffff", + "categories": ["social", "communication", "productivity"], "icons": [ { "src": "/icons/android-chrome-36x36.png", @@ -59,8 +64,14 @@ { "src": "/icons/android-chrome-512x512.png", "sizes": "512x512", - "type": "image/png" + "type": "image/png", + "purpose": "any" + }, + { + "src": "/icons/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } - ], - "splash_pages": null -} \ No newline at end of file + ] +} diff --git a/public/sw.js b/public/sw.js index 38231997..caf7428b 100644 --- a/public/sw.js +++ b/public/sw.js @@ -3,15 +3,36 @@ * Basic offline functionality without ES module imports */ -const CACHE_NAME = 'qryptchat-v1'; +// Bumped to v1 -> v2 so clients running the old cache-first worker drop the +// stale app shell they precached on install. +const CACHE_NAME = 'qryptchat-v2'; +const OFFLINE_SHELL = '/'; const STATIC_CACHE_URLS = [ - '/', + OFFLINE_SHELL, '/manifest.json', '/icons/icon-192x192.png', '/icons/icon-512x512.png', '/favicon.svg' ]; +/** + * Content-addressed or rarely-changing assets that are safe to serve from cache. + * Everything else (API routes, SSE streams, auth) must always hit the network — + * encrypted message payloads must never come back from a cache. + * @param {URL} url + * @returns {boolean} + */ +function isCacheableAsset(url) { + if (url.pathname.startsWith('/api/')) return false; + return ( + url.pathname.startsWith('/_next/static/') || + url.pathname.startsWith('/icons/') || + url.pathname.startsWith('/fonts/') || + url.pathname === '/manifest.json' || + /\.(?:png|jpe?g|svg|webp|ico|woff2?|css)$/.test(url.pathname) + ); +} + // Install event - cache static resources self.addEventListener('install', (event) => { console.log('Service Worker installing...'); @@ -48,14 +69,48 @@ self.addEventListener('activate', (event) => { ); }); -// Fetch event - serve from cache, fallback to network +// Fetch event self.addEventListener('fetch', (event) => { + const { request } = event; + + // Never intercept uploads/mutations or third-party origins (Supabase, analytics). + if (request.method !== 'GET') return; + + let url; + try { + url = new URL(request.url); + } catch { + return; + } + if (url.origin !== self.location.origin) return; + + // Page loads are network-first with the cached shell as an offline fallback. + // Cache-first here pinned the installed app to the HTML captured at install + // time, whose hashed Next.js chunks stop existing after the next deploy. + if (request.mode === 'navigate') { + event.respondWith( + fetch(request) + .then((response) => { + if (response.ok && url.pathname === OFFLINE_SHELL) { + const copy = response.clone(); + event.waitUntil( + caches.open(CACHE_NAME).then((cache) => cache.put(OFFLINE_SHELL, copy)) + ); + } + return response; + }) + .catch(async () => { + const cached = await caches.match(OFFLINE_SHELL); + return cached || Response.error(); + }) + ); + return; + } + + if (!isCacheableAsset(url)) return; + event.respondWith( - caches.match(event.request) - .then((response) => { - // Return cached version or fetch from network - return response || fetch(event.request); - }) + caches.match(request).then((cached) => cached || fetch(request)) ); }); diff --git a/src/app/layout.jsx b/src/app/layout.jsx index 039939ef..20b32d01 100644 --- a/src/app/layout.jsx +++ b/src/app/layout.jsx @@ -13,6 +13,47 @@ export const metadata = { }, description: 'End-to-end encrypted messaging with post-quantum cryptography (ML-KEM-1024 / CRYSTALS-Kyber and CRYSTALS-Dilithium). Open source, self-hostable, and accessible over Tor.', applicationName: 'QryptChat', + // Chromium refuses to offer "Install app" without a linked manifest, and iOS + // needs the apple-* tags below for "Add to Home Screen" to open standalone. + // Both were lost when src/app.html went away in the Next.js migration. + manifest: '/manifest.json', + appleWebApp: { + capable: true, + statusBarStyle: 'default', + title: 'QryptChat', + }, + icons: { + icon: [ + { url: '/favicon.svg', type: 'image/svg+xml' }, + { url: '/icons/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, + { url: '/icons/favicon-16x16.png', sizes: '16x16', type: 'image/png' }, + // Desktop environments (KDE/Plasma, GNOME) pick the largest declared icon + // for the installed app's launcher entry. + { url: '/icons/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' }, + { url: '/icons/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' }, + ], + shortcut: ['/favicon.ico'], + apple: [ + { url: '/icons/apple-touch-icon-180x180.png', sizes: '180x180', type: 'image/png' }, + { url: '/icons/apple-touch-icon-152x152.png', sizes: '152x152', type: 'image/png' }, + { url: '/icons/apple-touch-icon-144x144.png', sizes: '144x144', type: 'image/png' }, + { url: '/icons/apple-touch-icon-120x120.png', sizes: '120x120', type: 'image/png' }, + { url: '/icons/apple-touch-icon-114x114.png', sizes: '114x114', type: 'image/png' }, + { url: '/icons/apple-touch-icon-76x76.png', sizes: '76x76', type: 'image/png' }, + { url: '/icons/apple-touch-icon-72x72.png', sizes: '72x72', type: 'image/png' }, + { url: '/icons/apple-touch-icon-60x60.png', sizes: '60x60', type: 'image/png' }, + { url: '/icons/apple-touch-icon-57x57.png', sizes: '57x57', type: 'image/png' }, + ], + }, + other: { + // `appleWebApp.capable` above emits the modern `mobile-web-app-capable`. + // iOS before 15.4 ignores the manifest's `display` and only goes standalone + // on the apple-prefixed tag, which Next no longer emits — declare it here. + 'apple-mobile-web-app-capable': 'yes', + 'msapplication-TileColor': '#6366f1', + 'msapplication-TileImage': '/icons/mstile-144x144.png', + 'msapplication-config': '/icons/browserconfig.xml', + }, keywords: [ 'quantum-resistant messaging', 'post-quantum cryptography', @@ -47,6 +88,13 @@ export const metadata = { }, }; +export const viewport = { + themeColor: '#ffffff', + width: 'device-width', + initialScale: 1, + viewportFit: 'cover', +}; + const organizationJsonLd = { '@context': 'https://schema.org', '@type': 'Organization', @@ -82,11 +130,9 @@ export default function RootLayout({ children }) { return (
- - - - - + {/* Icons, viewport, theme-color and the apple-mobile-web-app-* tags are + emitted from the `metadata` / `viewport` exports above — declaring + them here too produced duplicate tags. */}