From 83be49cdec3a37781816d008a85ad4a6cd221ff4 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Wed, 24 Sep 2025 11:40:45 +0000 Subject: [PATCH 01/89] add dependency --- package.json | 2 +- yarn.lock | 352 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 339 insertions(+), 15 deletions(-) diff --git a/package.json b/package.json index c51e093..0a66281 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "connect-pg-simple": "^9.0.1", "cors": "^2.8.5", "es-toolkit": "^1.39.10", - "express": "^4.19.2", + "express": "^5", "express-session": "^1.18.0", "global": "^4.4.0", "morgan": "^1.10.0", diff --git a/yarn.lock b/yarn.lock index 5e5892a..7626882 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1738,6 +1738,14 @@ abort-controller@^3.0.0: dependencies: event-target-shim "^5.0.0" +accepts@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895" + integrity sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng== + dependencies: + mime-types "^3.0.0" + negotiator "^1.0.0" + accepts@~1.3.4, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -1998,6 +2006,21 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" +body-parser@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" + integrity sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg== + dependencies: + bytes "^3.1.2" + content-type "^1.0.5" + debug "^4.4.0" + http-errors "^2.0.0" + iconv-lite "^0.6.3" + on-finished "^2.4.1" + qs "^6.14.0" + raw-body "^3.0.0" + type-is "^2.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2056,7 +2079,7 @@ bunyan@^1.8.14: mv "~2" safe-json-stringify "~1" -bytes@3.1.2: +bytes@3.1.2, bytes@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== @@ -2088,6 +2111,14 @@ cache-manager@^3.6.1: lodash.clonedeep "^4.5.0" lru-cache "6.0.0" +call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -2099,6 +2130,14 @@ call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" +call-bound@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" + integrity sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg== + dependencies: + call-bind-apply-helpers "^1.0.2" + get-intrinsic "^1.3.0" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -2369,7 +2408,14 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@~1.0.4, content-type@~1.0.5: +content-disposition@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-1.0.0.tgz#844426cb398f934caefcbb172200126bc7ceace2" + integrity sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg== + dependencies: + safe-buffer "5.2.1" + +content-type@^1.0.5, content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -2384,12 +2430,17 @@ cookie-signature@1.0.7: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== +cookie-signature@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" + integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== + cookie@0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -cookie@~0.7.2: +cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -2898,7 +2949,7 @@ delaunator@5: dependencies: robust-predicates "^3.0.2" -depd@2.0.0, depd@~2.0.0: +depd@2.0.0, depd@^2.0.0, depd@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== @@ -3014,6 +3065,15 @@ dtrace-provider@~0.8: dependencies: nan "^2.14.0" +dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -3064,6 +3124,11 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== +encodeurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -3120,11 +3185,23 @@ es-define-property@^1.0.0: dependencies: get-intrinsic "^1.2.4" +es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== + es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== + dependencies: + es-errors "^1.3.0" + es-toolkit@^1.39.10: version "1.39.10" resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.39.10.tgz#513407af73e79f9940e7ec7650f2e6dceeaf1d81" @@ -3140,7 +3217,7 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== -escape-html@~1.0.3: +escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== @@ -3160,7 +3237,7 @@ estree-walker@^2.0.2: resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== -etag@~1.8.1: +etag@^1.8.1, etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== @@ -3204,7 +3281,7 @@ express-session@^1.18.0: safe-buffer "5.2.1" uid-safe "~2.1.5" -express@^4.18.2, express@^4.19.2: +express@^4.18.2: version "4.19.2" resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== @@ -3241,6 +3318,39 @@ express@^4.18.2, express@^4.19.2: utils-merge "1.0.1" vary "~1.1.2" +express@^5: + version "5.1.0" + resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" + integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== + dependencies: + accepts "^2.0.0" + body-parser "^2.2.0" + content-disposition "^1.0.0" + content-type "^1.0.5" + cookie "^0.7.1" + cookie-signature "^1.2.1" + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + finalhandler "^2.1.0" + fresh "^2.0.0" + http-errors "^2.0.0" + merge-descriptors "^2.0.0" + mime-types "^3.0.0" + on-finished "^2.4.1" + once "^1.4.0" + parseurl "^1.3.3" + proxy-addr "^2.0.7" + qs "^6.14.0" + range-parser "^1.2.1" + router "^2.2.0" + send "^1.1.0" + serve-static "^2.2.0" + statuses "^2.0.1" + type-is "^2.0.1" + vary "^1.1.2" + exsolve@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.4.tgz#7de5c75af82ecd15998328fbf5f2295883be3a39" @@ -3345,6 +3455,18 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +finalhandler@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" + integrity sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q== + dependencies: + debug "^4.4.0" + encodeurl "^2.0.0" + escape-html "^1.0.3" + on-finished "^2.4.1" + parseurl "^1.3.3" + statuses "^2.0.1" + find-cache-dir@3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" @@ -3403,6 +3525,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-2.0.0.tgz#8dd7df6a1b3a1b3a5cf186c05a5dd267622635a4" + integrity sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A== + fs-constants@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" @@ -3455,6 +3582,30 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: has-symbols "^1.0.3" hasown "^2.0.0" +get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== + dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.1.1" + function-bind "^1.1.2" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" + +get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -3578,6 +3729,11 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" +gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== + graceful-fs@^4.1.15, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" @@ -3620,6 +3776,11 @@ has-symbols@^1.0.3: resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== + hasha@5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" @@ -3657,7 +3818,7 @@ html-to-image@^1.11.3: resolved "https://registry.yarnpkg.com/html-to-image/-/html-to-image-1.11.13.tgz#adbc989c993b7aaf90b629c0cacf833db84d5f43" integrity sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg== -http-errors@2.0.0: +http-errors@2.0.0, http-errors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== @@ -3704,13 +3865,20 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@0.6: +iconv-lite@0.6, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== dependencies: safer-buffer ">= 2.1.2 < 3.0.0" +iconv-lite@0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.7.0.tgz#c50cd80e6746ca8115eb98743afa81aa0e147a3e" + integrity sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -3882,6 +4050,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== +is-promise@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" + integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ== + is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" @@ -4177,6 +4350,11 @@ marked@^4.0.10: resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + mdast-util-from-markdown@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" @@ -4207,6 +4385,11 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== +media-typer@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-1.1.0.tgz#6ab74b8f2d3320f2064b2a87a38e7931ff3a5561" + integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw== + meow@9: version "9.0.0" resolved "https://registry.yarnpkg.com/meow/-/meow-9.0.0.tgz#cd9510bc5cac9dee7d03c73ee1f9ad959f4ea364" @@ -4230,6 +4413,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" + integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g== + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" @@ -4512,6 +4700,18 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== +mime-db@^1.54.0: + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-types@^3.0.0, mime-types@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-3.0.1.tgz#b1d94d6997a9b32fd69ebaed0db73de8acb519ce" + integrity sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA== + dependencies: + mime-db "^1.54.0" + mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" @@ -4687,6 +4887,11 @@ negotiator@0.6.3: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== +negotiator@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-1.0.0.tgz#b6c91bb47172d69f93cfd7c357bbb529019b5f6a" + integrity sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg== + new-github-issue-url@0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/new-github-issue-url/-/new-github-issue-url-0.2.1.tgz#e17be1f665a92de465926603e44b9f8685630c1d" @@ -4851,6 +5056,11 @@ object-inspect@^1.13.1: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== + obuf@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -4866,7 +5076,7 @@ on-exit-leak-free@^2.1.0: resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== -on-finished@2.4.1: +on-finished@2.4.1, on-finished@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== @@ -5008,7 +5218,7 @@ parse-json@^5.0.0: json-parse-even-better-errors "^2.3.0" lines-and-columns "^1.1.6" -parseurl@~1.3.3: +parseurl@^1.3.3, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== @@ -5091,6 +5301,11 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +path-to-regexp@^8.0.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" + integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -5515,7 +5730,7 @@ prompts@2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -proxy-addr@~2.0.7: +proxy-addr@^2.0.7, proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -5582,6 +5797,13 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +qs@^6.14.0: + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== + dependencies: + side-channel "^1.1.0" + quansync@^0.2.7, quansync@^0.2.8: version "0.2.10" resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" @@ -5612,7 +5834,7 @@ random-bytes@~1.0.0: resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== -range-parser@~1.2.1: +range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== @@ -5627,6 +5849,16 @@ raw-body@2.5.2: iconv-lite "0.4.24" unpipe "1.0.0" +raw-body@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-3.0.1.tgz#ced5cd79a77bbb0496d707f2a0f9e1ae3aecdcb1" + integrity sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.7.0" + unpipe "1.0.0" + rc9@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/rc9/-/rc9-2.1.2.tgz#6282ff638a50caa0a91a31d76af4a0b9cbd1080d" @@ -5816,6 +6048,17 @@ roughjs@^4.6.6: points-on-curve "^0.2.0" points-on-path "^0.2.1" +router@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/router/-/router-2.2.0.tgz#019be620b711c87641167cc79b99090f00b146ef" + integrity sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ== + dependencies: + debug "^4.4.0" + depd "^2.0.0" + is-promise "^4.0.0" + parseurl "^1.3.3" + path-to-regexp "^8.0.0" + run-parallel@^1.1.9: version "1.2.0" resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" @@ -5899,6 +6142,23 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" +send@^1.1.0, send@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" + integrity sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw== + dependencies: + debug "^4.3.5" + encodeurl "^2.0.0" + escape-html "^1.0.3" + etag "^1.8.1" + fresh "^2.0.0" + http-errors "^2.0.0" + mime-types "^3.0.1" + ms "^2.1.3" + on-finished "^2.4.1" + range-parser "^1.2.1" + statuses "^2.0.1" + serve-static@1.15.0: version "1.15.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" @@ -5909,6 +6169,16 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +serve-static@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" + integrity sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ== + dependencies: + encodeurl "^2.0.0" + escape-html "^1.0.3" + parseurl "^1.3.3" + send "^1.2.0" + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -5943,6 +6213,35 @@ shimmer@^1.2.1: resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + side-channel@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -5953,6 +6252,17 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" + signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -6078,6 +6388,11 @@ statuses@2.0.1: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== +statuses@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.2.tgz#8f75eecef765b5e1cfcdc080da59409ed424e382" + integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw== + "string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" @@ -6440,6 +6755,15 @@ type-fest@^0.8.0, type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== +type-is@^2.0.0, type-is@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-2.0.1.tgz#64f6cf03f92fce4015c2b224793f6bdd4b068c97" + integrity sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw== + dependencies: + content-type "^1.0.5" + media-typer "^1.1.0" + mime-types "^3.0.0" + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -6565,7 +6889,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vary@^1, vary@~1.1.2: +vary@^1, vary@^1.1.2, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== From 895150b529163361f95232bb48862135d889fb54 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Wed, 24 Sep 2025 12:08:34 +0000 Subject: [PATCH 02/89] remove legacy try-catch route handlers --- src/app.ts | 10 +- src/controllers/admins.ts | 78 +++--- src/controllers/cmsSettings.ts | 84 +++--- src/controllers/documentRoots.ts | 200 ++++++-------- src/controllers/documents.ts | 335 +++++++++++------------- src/controllers/rootGroupPermissions.ts | 74 +++--- src/controllers/rootUserPermissions.ts | 86 +++--- src/controllers/studentGroups.ts | 210 +++++++-------- src/controllers/users.ts | 24 +- 9 files changed, 465 insertions(+), 636 deletions(-) diff --git a/src/app.ts b/src/app.ts index 1cf6e28..3cceff9 100644 --- a/src/app.ts +++ b/src/app.ts @@ -118,14 +118,10 @@ const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) = }; const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - try { - if (req.user) { - return res.status(200).send('OK'); - } - throw new HTTP401Error(); - } catch (error) { - next(error); + if (req.user) { + return res.status(200).send('OK'); } + throw new HTTP401Error(); }; app.get(`${API_URL}/checklogin`, SessionOauthStrategy, checkLogin); diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index 49c0012..2e92bf3 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -10,56 +10,44 @@ export const createAllowedAction: RequestHandler { - try { - const { action, documentType } = req.body; - const record = await prisma.allowedAction.create({ - data: { - action: action, - documentType: documentType - } - }); - res.notifications = [ - { - event: IoEvent.NEW_RECORD, - message: { type: RecordType.AllowedAction, record: record }, - to: IoRoom.ADMIN - } - ]; - res.status(200).json(record); - } catch (error) { - next(error); - } + const { action, documentType } = req.body; + const record = await prisma.allowedAction.create({ + data: { + action: action, + documentType: documentType + } + }); + res.notifications = [ + { + event: IoEvent.NEW_RECORD, + message: { type: RecordType.AllowedAction, record: record }, + to: IoRoom.ADMIN + } + ]; + res.status(200).json(record); }; export const allowedActions: RequestHandler = async (req, res, next) => { - try { - const actions = await prisma.allowedAction.findMany({}); - res.json(actions); - } catch (error) { - next(error); - } + const actions = await prisma.allowedAction.findMany({}); + res.json(actions); }; export const destroyAllowedAction: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const { id } = req.params; - if (!id) { - throw new HTTP403Error('unknown id'); - } - const action = await prisma.allowedAction.delete({ - where: { - id: req.params.id - } - }); - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { type: RecordType.Document, id: action.id }, - to: IoRoom.ADMIN - } - ]; - res.status(204).send(); - } catch (error) { - next(error); + const { id } = req.params; + if (!id) { + throw new HTTP403Error('unknown id'); } + const action = await prisma.allowedAction.delete({ + where: { + id: req.params.id + } + }); + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { type: RecordType.Document, id: action.id }, + to: IoRoom.ADMIN + } + ]; + res.status(204).send(); }; diff --git a/src/controllers/cmsSettings.ts b/src/controllers/cmsSettings.ts index 21c20e3..9342ad9 100644 --- a/src/controllers/cmsSettings.ts +++ b/src/controllers/cmsSettings.ts @@ -4,66 +4,50 @@ import { ChangedRecord, IoEvent, RecordType } from '../routes/socketEventTypes'; import { CmsSettings as DbCmsSettings } from '@prisma/client'; export const find: RequestHandler = async (req, res, next) => { - try { - const settings = await CmsSettings.findModel(req.user!); - res.json(settings); - } catch (error) { - next(error); - } + const settings = await CmsSettings.findModel(req.user!); + res.json(settings); }; export const update: RequestHandler> = async (req, res, next) => { - try { - await CmsSettings.updateModel(req.user!, req.body); - res.status(204).send(); - } catch (error) { - next(error); - } + await CmsSettings.updateModel(req.user!, req.body); + res.status(204).send(); }; export const logout: RequestHandler> = async (req, res, next) => { - try { - const model = await CmsSettings.logout(req.user!); - if (!model) { - res.status(204).send(); - return; - } - const change: ChangedRecord = { - type: RecordType.CmsSettings, - record: model - }; - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: change, - to: [req.user!.id] - } - ]; - + const model = await CmsSettings.logout(req.user!); + if (!model) { res.status(204).send(); - } catch (error) { - next(error); + return; } + const change: ChangedRecord = { + type: RecordType.CmsSettings, + record: model + }; + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: change, + to: [req.user!.id] + } + ]; + + res.status(204).send(); }; export const githubToken: RequestHandler = async (req, res, next) => { - try { - const { code } = req.query; - const model = await CmsSettings.fetchToken(req.user!.id, code); + const { code } = req.query; + const model = await CmsSettings.fetchToken(req.user!.id, code); - const change: ChangedRecord = { - type: RecordType.CmsSettings, - record: model - }; - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: change, - to: [req.user!.id] - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + const change: ChangedRecord = { + type: RecordType.CmsSettings, + record: model + }; + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: change, + to: [req.user!.id] + } + ]; + res.status(200).json(model); }; diff --git a/src/controllers/documentRoots.ts b/src/controllers/documentRoots.ts index 57f4a28..bf58e1b 100644 --- a/src/controllers/documentRoots.ts +++ b/src/controllers/documentRoots.ts @@ -8,25 +8,17 @@ import { NoneAccess, RO_RW_DocumentRootAccess } from '../helpers/accessPolicy'; import { hasElevatedAccess } from '../models/User'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const document = await DocumentRoot.findModel(req.user!, req.params.id); - res.json(document); - } catch (error) { - next(error); - } + const document = await DocumentRoot.findModel(req.user!, req.params.id); + res.json(document); }; export const findMany: RequestHandler = async (req, res, next) => { - try { - const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids]; - if (ids.length === 0) { - return res.json([]); - } - const documents = await DocumentRoot.findManyModels(req.user!.id, ids); - res.json(documents); - } catch (error) { - next(error); + const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids]; + if (ids.length === 0) { + return res.json([]); } + const documents = await DocumentRoot.findManyModels(req.user!.id, ids); + res.json(documents); }; export const findManyFor: RequestHandler< @@ -35,43 +27,31 @@ export const findManyFor: RequestHandler< any, { ignoreMissingRoots?: boolean; ids: string[] } > = async (req, res, next) => { - try { - if (!req.params.id) { - throw new HTTP400Error('Missing user id'); - } - const canLoad = req.user!.id === req.params.id || hasElevatedAccess(req.user?.role); - if (!canLoad) { - throw new HTTP403Error('Not Authorized'); - } - const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids]; - if (ids.length === 0) { - return res.json([]); - } - const documents = await DocumentRoot.findManyModels( - req.params.id, - ids, - !!req.query.ignoreMissingRoots - ); - res.json(documents); - } catch (error) { - next(error); + if (!req.params.id) { + throw new HTTP400Error('Missing user id'); } + const canLoad = req.user!.id === req.params.id || hasElevatedAccess(req.user?.role); + if (!canLoad) { + throw new HTTP403Error('Not Authorized'); + } + const ids = Array.isArray(req.query.ids) ? req.query.ids : [req.query.ids]; + if (ids.length === 0) { + return res.json([]); + } + const documents = await DocumentRoot.findManyModels(req.params.id, ids, !!req.query.ignoreMissingRoots); + res.json(documents); }; export const allDocuments: RequestHandler = async (req, res, next) => { - try { - if (!hasElevatedAccess(req.user!.role)) { - throw new HTTP403Error('Not Authorized'); - } - const ids = Array.isArray(req.query.rids) ? req.query.rids : [req.query.rids]; - if (ids.length === 0) { - return res.json([]); - } - const documents = await Document.allOfDocumentRoots(req.user!, ids); - res.json(documents); - } catch (error) { - next(error); + if (!hasElevatedAccess(req.user!.role)) { + throw new HTTP403Error('Not Authorized'); } + const ids = Array.isArray(req.query.rids) ? req.query.rids : [req.query.rids]; + if (ids.length === 0) { + return res.json([]); + } + const documents = await Document.allOfDocumentRoots(req.user!, ids); + res.json(documents); }; export const create: RequestHandler<{ id: string }, any, CreateConfig | undefined> = async ( @@ -79,88 +59,70 @@ export const create: RequestHandler<{ id: string }, any, CreateConfig | undefine res, next ) => { - try { - const documentRoot = await DocumentRoot.createModel(req.params.id, req.body); - /** - * Notifications to - * - the user who created the document - * - users with ro/rw access to the document root - * - student groups with ro/rw access to the document root - */ - const groupIds = documentRoot.groupPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.groupId); - const userIds = documentRoot.userPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.userId); - const sharedAccess = RO_RW_DocumentRootAccess.has(documentRoot.sharedAccess) - ? IoRoom.ALL - : IoRoom.ADMIN; - res.notifications = [ - { - event: IoEvent.NEW_RECORD, - message: { type: RecordType.DocumentRoot, record: documentRoot }, - to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.json(documentRoot); - } catch (error) { - next(error); - } + const documentRoot = await DocumentRoot.createModel(req.params.id, req.body); + /** + * Notifications to + * - the user who created the document + * - users with ro/rw access to the document root + * - student groups with ro/rw access to the document root + */ + const groupIds = documentRoot.groupPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.groupId); + const userIds = documentRoot.userPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.userId); + const sharedAccess = RO_RW_DocumentRootAccess.has(documentRoot.sharedAccess) ? IoRoom.ALL : IoRoom.ADMIN; + res.notifications = [ + { + event: IoEvent.NEW_RECORD, + message: { type: RecordType.DocumentRoot, record: documentRoot }, + to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.json(documentRoot); }; export const update: RequestHandler<{ id: string }, any, UpdateConfig> = async (req, res, next) => { - try { - const model = await DocumentRoot.updateModel(req.params.id, req.body); + const model = await DocumentRoot.updateModel(req.params.id, req.body); - /** - * Notifications to All users since the document root is a global entity. - * --> even with restricted access, the document root can be seen by all users. - */ - const change: ChangedRecord = { - type: RecordType.DocumentRoot, - record: model - }; - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: change, - to: [IoRoom.ALL] - } - ]; + /** + * Notifications to All users since the document root is a global entity. + * --> even with restricted access, the document root can be seen by all users. + */ + const change: ChangedRecord = { + type: RecordType.DocumentRoot, + record: model + }; + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: change, + to: [IoRoom.ALL] + } + ]; - res.status(204).send(); - } catch (error) { - next(error); - } + res.status(204).send(); }; export const permissions: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const permissions = await DocumentRoot.getPermissions(req.user!, req.params.id); - res.json(permissions); - } catch (error) { - next(error); - } + const permissions = await DocumentRoot.getPermissions(req.user!, req.params.id); + res.json(permissions); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const model = await DocumentRoot.deleteModel(req.user!, req.params.id); + const model = await DocumentRoot.deleteModel(req.user!, req.params.id); - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { type: RecordType.DocumentRoot, id: model.id }, - to: [ - ...model.rootGroupPermissions.map((p) => p.studentGroupId), - ...model.rootUserPermissions.map((u) => u.userId), - RO_RW_DocumentRootAccess.has(model.sharedAccess) ? IoRoom.ALL : IoRoom.ADMIN - ] - } - ]; - res.json(model); - } catch (error) { - next(error); - } + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { type: RecordType.DocumentRoot, id: model.id }, + to: [ + ...model.rootGroupPermissions.map((p) => p.studentGroupId), + ...model.rootUserPermissions.map((u) => u.userId), + RO_RW_DocumentRootAccess.has(model.sharedAccess) ? IoRoom.ALL : IoRoom.ADMIN + ] + } + ]; + res.json(model); }; diff --git a/src/controllers/documents.ts b/src/controllers/documents.ts index af504c0..37605e5 100644 --- a/src/controllers/documents.ts +++ b/src/controllers/documents.ts @@ -9,12 +9,8 @@ import prisma from '../prisma'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const document = await Document.findModel(req.user!, req.params.id); - res.json(document); - } catch (error) { - next(error); - } + const document = await Document.findModel(req.user!, req.params.id); + res.json(document); }; export const create: RequestHandler< @@ -23,41 +19,35 @@ export const create: RequestHandler< DbDocument, { onBehalfOf?: 'true'; uniqueMain?: 'true' } > = async (req, res, next) => { - try { - const { type, documentRootId, data, parentId } = req.body; - const { onBehalfOf, uniqueMain } = req.query; - const onBehalfUserId = onBehalfOf === 'true' ? req.body.authorId : undefined; - const { model, permissions } = await Document.createModel( - req.user!, - type, - documentRootId, - data, - !parentId ? undefined : parentId, - uniqueMain === 'true', - onBehalfUserId - ); - /** - * Notifications to - * - the user who created the document - * - users with ro/rw access to the document root - * - student groups with ro/rw access to the document root - */ - const groupIds = permissions.group.filter((p) => !NoneAccess.has(p.access)).map((p) => p.groupId); - const userIds = permissions.user.filter((p) => !NoneAccess.has(p.access)).map((p) => p.userId); - const sharedAccess = RO_RW_DocumentRootAccess.has(permissions.sharedAccess) - ? IoRoom.ALL - : IoRoom.ADMIN; - res.notifications = [ - { - event: IoEvent.NEW_RECORD, - message: { type: RecordType.Document, record: model }, - to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving, - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + const { type, documentRootId, data, parentId } = req.body; + const { onBehalfOf, uniqueMain } = req.query; + const onBehalfUserId = onBehalfOf === 'true' ? req.body.authorId : undefined; + const { model, permissions } = await Document.createModel( + req.user!, + type, + documentRootId, + data, + !parentId ? undefined : parentId, + uniqueMain === 'true', + onBehalfUserId + ); + /** + * Notifications to + * - the user who created the document + * - users with ro/rw access to the document root + * - student groups with ro/rw access to the document root + */ + const groupIds = permissions.group.filter((p) => !NoneAccess.has(p.access)).map((p) => p.groupId); + const userIds = permissions.user.filter((p) => !NoneAccess.has(p.access)).map((p) => p.userId); + const sharedAccess = RO_RW_DocumentRootAccess.has(permissions.sharedAccess) ? IoRoom.ALL : IoRoom.ADMIN; + res.notifications = [ + { + event: IoEvent.NEW_RECORD, + message: { type: RecordType.Document, record: model }, + to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving, + } + ]; + res.status(200).json(model); }; export const update: RequestHandler< @@ -66,47 +56,36 @@ export const update: RequestHandler< { data: JsonObject }, { onBehalfOf?: 'true' } > = async (req, res, next) => { - try { - const { onBehalfOf } = req.query; - const model = await Document.updateModel( - req.user!, - req.params.id, - req.body.data, - onBehalfOf === 'true' - ); - /** - * Notifications to - * - the user who updated the document - * - users with ro/rw access to the document root - * - student groups with ro/rw access to the document root - */ - const change: ChangedDocument = { - id: model.id, - data: model.data, - updatedAt: model.updatedAt - }; - const groupIds = model.documentRoot.rootGroupPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.studentGroupId); - const userIds = model.documentRoot.rootUserPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.userId); - const sharedAccess = RO_RW_DocumentRootAccess.has(model.documentRoot.sharedAccess) - ? [IoRoom.ALL] - : []; + const { onBehalfOf } = req.query; + const model = await Document.updateModel(req.user!, req.params.id, req.body.data, onBehalfOf === 'true'); + /** + * Notifications to + * - the user who updated the document + * - users with ro/rw access to the document root + * - student groups with ro/rw access to the document root + */ + const change: ChangedDocument = { + id: model.id, + data: model.data, + updatedAt: model.updatedAt + }; + const groupIds = model.documentRoot.rootGroupPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.studentGroupId); + const userIds = model.documentRoot.rootUserPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.userId); + const sharedAccess = RO_RW_DocumentRootAccess.has(model.documentRoot.sharedAccess) ? [IoRoom.ALL] : []; - res.notifications = [ - { - event: IoEvent.CHANGED_DOCUMENT, - message: change, - to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; + res.notifications = [ + { + event: IoEvent.CHANGED_DOCUMENT, + message: change, + to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; - res.status(204).send(); - } catch (error) { - next(error); - } + res.status(204).send(); }; const childrenSql = (parentId: string) => { @@ -129,121 +108,109 @@ const childrenSql = (parentId: string) => { }; export const linkTo: RequestHandler<{ id: string; parentId: string }, any, any> = async (req, res, next) => { - try { - if (req.params.id === req.params.parentId) { - throw new HTTP403Error('Not allowed to link to self'); - } - const current = await Document.findModel(req.user!, req.params.id); - if (!current || !RWAccess.has(current.highestPermission)) { - throw new HTTP404Error('Model not found'); - } - const children = await prisma.$queryRaw(childrenSql(current.document.id)); - if (children.some((c) => c.id === req.params.parentId)) { - throw new HTTP403Error( - "No circular links allowed (trying to link a document to one of it's children)" - ); - } - const linkTo = await Document.findModel(req.user!, req.params.parentId); - if (!linkTo || NoneAccess.has(linkTo.highestPermission)) { - throw new HTTP404Error('Model linking to not found'); - } - if (linkTo.document.authorId !== current.document.authorId) { - throw new HTTP403Error('Not allowed to relink a model to anothers document'); + if (req.params.id === req.params.parentId) { + throw new HTTP403Error('Not allowed to link to self'); + } + const current = await Document.findModel(req.user!, req.params.id); + if (!current || !RWAccess.has(current.highestPermission)) { + throw new HTTP404Error('Model not found'); + } + const children = await prisma.$queryRaw(childrenSql(current.document.id)); + if (children.some((c) => c.id === req.params.parentId)) { + throw new HTTP403Error( + "No circular links allowed (trying to link a document to one of it's children)" + ); + } + const linkTo = await Document.findModel(req.user!, req.params.parentId); + if (!linkTo || NoneAccess.has(linkTo.highestPermission)) { + throw new HTTP404Error('Model linking to not found'); + } + if (linkTo.document.authorId !== current.document.authorId) { + throw new HTTP403Error('Not allowed to relink a model to anothers document'); + } + const allowedAction = await prisma.allowedAction.findFirst({ + where: { + action: 'update@parent_id', + documentType: current?.document.type } - const allowedAction = await prisma.allowedAction.findFirst({ - where: { - action: 'update@parent_id', - documentType: current?.document.type + }); + if (!allowedAction) { + throw new HTTP403Error('Not allowed to relink this model'); + } + const updated = await prisma.document.update({ + where: { + id: current.document.id + }, + data: { + parent: { + connect: { id: linkTo.document.id } } - }); - if (!allowedAction) { - throw new HTTP403Error('Not allowed to relink this model'); - } - const updated = await prisma.document.update({ - where: { - id: current.document.id - }, - data: { - parent: { - connect: { id: linkTo.document.id } - } - }, - include: { - documentRoot: { - include: { - rootGroupPermissions: { - select: { - access: true, - studentGroupId: true - } - }, - rootUserPermissions: { - select: { - access: true, - userId: true - } + }, + include: { + documentRoot: { + include: { + rootGroupPermissions: { + select: { + access: true, + studentGroupId: true + } + }, + rootUserPermissions: { + select: { + access: true, + userId: true } } } } - }); - /** - * Notifications to - * - the user who updated the document - * - users with ro/rw access to the document root - * - student groups with ro/rw access to the document root - */ + } + }); + /** + * Notifications to + * - the user who updated the document + * - users with ro/rw access to the document root + * - student groups with ro/rw access to the document root + */ - const groupIds = updated.documentRoot.rootGroupPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.studentGroupId); - const userIds = updated.documentRoot.rootUserPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.userId); - const sharedAccess = RO_RW_DocumentRootAccess.has(updated.documentRoot.sharedAccess) - ? [IoRoom.ALL] - : []; + const groupIds = updated.documentRoot.rootGroupPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.studentGroupId); + const userIds = updated.documentRoot.rootUserPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.userId); + const sharedAccess = RO_RW_DocumentRootAccess.has(updated.documentRoot.sharedAccess) ? [IoRoom.ALL] : []; - delete (updated as any).documentRoot; - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { - type: RecordType.Document, - record: updated - }, - to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; + delete (updated as any).documentRoot; + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.Document, + record: updated + }, + to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; - res.status(200).json(updated); - } catch (error) { - next(error); - } + res.status(200).json(updated); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const model = await Document.deleteModel(req.user!, req.params.id); + const model = await Document.deleteModel(req.user!, req.params.id); - const groupIds = model.documentRoot.rootGroupPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.studentGroupId); - const userIds = model.documentRoot.rootUserPermissions - .filter((p) => !NoneAccess.has(p.access)) - .map((p) => p.userId); - const sharedAccess = RO_RW_DocumentRootAccess.has(model.documentRoot.sharedAccess) - ? [IoRoom.ALL] - : []; - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { type: RecordType.Document, id: model.id }, - to: [...groupIds, ...userIds, ...sharedAccess, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.status(204).send(); - } catch (error) { - next(error); - } + const groupIds = model.documentRoot.rootGroupPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.studentGroupId); + const userIds = model.documentRoot.rootUserPermissions + .filter((p) => !NoneAccess.has(p.access)) + .map((p) => p.userId); + const sharedAccess = RO_RW_DocumentRootAccess.has(model.documentRoot.sharedAccess) ? [IoRoom.ALL] : []; + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { type: RecordType.Document, id: model.id }, + to: [...groupIds, ...userIds, ...sharedAccess, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.status(204).send(); }; diff --git a/src/controllers/rootGroupPermissions.ts b/src/controllers/rootGroupPermissions.ts index f32c1e4..995f078 100644 --- a/src/controllers/rootGroupPermissions.ts +++ b/src/controllers/rootGroupPermissions.ts @@ -9,58 +9,46 @@ export const create: RequestHandler< any, { documentRootId: string; groupId: string; access: Access } > = async (req, res, next) => { - try { - const { documentRootId, groupId, access } = req.body; + const { documentRootId, groupId, access } = req.body; - if (!(documentRootId && groupId && access)) { - throw new HTTP400Error('Missing documentRootId, groupId or access'); - } + if (!(documentRootId && groupId && access)) { + throw new HTTP400Error('Missing documentRootId, groupId or access'); + } - const model = await RootGroupPermission.createModel(req.user!, documentRootId, groupId, access); + const model = await RootGroupPermission.createModel(req.user!, documentRootId, groupId, access); - res.notifications = [ - { - event: IoEvent.NEW_RECORD, - message: { type: RecordType.GroupPermission, record: model }, - to: model.groupId - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + res.notifications = [ + { + event: IoEvent.NEW_RECORD, + message: { type: RecordType.GroupPermission, record: model }, + to: model.groupId + } + ]; + res.status(200).json(model); }; export const update: RequestHandler<{ id: string }, any, { access: Access }> = async (req, res, next) => { - try { - const model = await RootGroupPermission.updateModel(req.user!, req.params.id, req.body.access); + const model = await RootGroupPermission.updateModel(req.user!, req.params.id, req.body.access); - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { type: RecordType.GroupPermission, record: model }, - to: model.groupId - } - ]; - res.status(200).send(model); - } catch (error) { - next(error); - } + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { type: RecordType.GroupPermission, record: model }, + to: model.groupId + } + ]; + res.status(200).send(model); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const model = await RootGroupPermission.deleteModel(req.user!, req.params.id); + const model = await RootGroupPermission.deleteModel(req.user!, req.params.id); - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { type: RecordType.GroupPermission, id: model.id }, - to: model.groupId - } - ]; - res.json(model); - } catch (error) { - next(error); - } + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { type: RecordType.GroupPermission, id: model.id }, + to: model.groupId + } + ]; + res.json(model); }; diff --git a/src/controllers/rootUserPermissions.ts b/src/controllers/rootUserPermissions.ts index e09f98e..c60270a 100644 --- a/src/controllers/rootUserPermissions.ts +++ b/src/controllers/rootUserPermissions.ts @@ -10,64 +10,52 @@ export const create: RequestHandler< any, { documentRootId: string; userId: string; access: Access } > = async (req, res, next) => { - try { - const { documentRootId, userId, access } = req.body; + const { documentRootId, userId, access } = req.body; - if (!(documentRootId && userId && access)) { - throw new HTTP400Error('Missing documentRootId, userId or access'); - } + if (!(documentRootId && userId && access)) { + throw new HTTP400Error('Missing documentRootId, userId or access'); + } - const model = await RootUserPermission.createModel(req.user!, documentRootId, userId, access); + const model = await RootUserPermission.createModel(req.user!, documentRootId, userId, access); - res.notifications = [ - { - event: IoEvent.NEW_RECORD, - message: { type: RecordType.UserPermission, record: model }, - to: [model.userId, IoRoom.ADMIN] - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + res.notifications = [ + { + event: IoEvent.NEW_RECORD, + message: { type: RecordType.UserPermission, record: model }, + to: [model.userId, IoRoom.ADMIN] + } + ]; + res.status(200).json(model); }; export const update: RequestHandler<{ id: string }, any, { access: Access }> = async (req, res, next) => { - try { - if (!req.params.id) { - throw new HTTP400Error('Missing id'); - } - const model = await RootUserPermission.updateModel(req.user!, req.params.id, req.body.access); - - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { type: RecordType.UserPermission, record: model }, - to: [model.userId, IoRoom.ADMIN] - } - ]; - res.status(200).send(model); - } catch (error) { - next(error); + if (!req.params.id) { + throw new HTTP400Error('Missing id'); } -}; + const model = await RootUserPermission.updateModel(req.user!, req.params.id, req.body.access); -export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - if (!req.params.id) { - throw new HTTP400Error('Missing id'); + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { type: RecordType.UserPermission, record: model }, + to: [model.userId, IoRoom.ADMIN] } - const model = await RootUserPermission.deleteModel(req.user!, req.params.id); + ]; + res.status(200).send(model); +}; - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { type: RecordType.UserPermission, id: model.id }, - to: [model.userId, IoRoom.ADMIN] - } - ]; - res.json(model); - } catch (error) { - next(error); +export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { + if (!req.params.id) { + throw new HTTP400Error('Missing id'); } + const model = await RootUserPermission.deleteModel(req.user!, req.params.id); + + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { type: RecordType.UserPermission, id: model.id }, + to: [model.userId, IoRoom.ADMIN] + } + ]; + res.json(model); }; diff --git a/src/controllers/studentGroups.ts b/src/controllers/studentGroups.ts index 8948f5a..bce1dba 100644 --- a/src/controllers/studentGroups.ts +++ b/src/controllers/studentGroups.ts @@ -4,22 +4,14 @@ import StudentGroup from '../models/StudentGroup'; import { IoEvent, RecordType } from '../routes/socketEventTypes'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const group = await StudentGroup.findModel(req.user!, req.params.id); - res.json(group); - } catch (error) { - next(error); - } + const group = await StudentGroup.findModel(req.user!, req.params.id); + res.json(group); }; export const create: RequestHandler = async (req, res, next) => { - try { - const { name, description, parentId } = req.body; - const model = await StudentGroup.createModel(req.user!, name, description, parentId); - res.status(200).json(model); - } catch (error) { - next(error); - } + const { name, description, parentId } = req.body; + const model = await StudentGroup.createModel(req.user!, name, description, parentId); + res.status(200).json(model); }; export const update: RequestHandler<{ id: string }, any, { data: DbStudentGroup }> = async ( @@ -27,26 +19,22 @@ export const update: RequestHandler<{ id: string }, any, { data: DbStudentGroup res, next ) => { - try { - const model = await StudentGroup.updateModel(req.user!, req.params.id, req.body.data); - if (!model) { - return res.status(404).json({ message: 'Student group not found' }); - } - - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { - type: RecordType.StudentGroup, - record: model - }, - to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); + const model = await StudentGroup.updateModel(req.user!, req.params.id, req.body.data); + if (!model) { + return res.status(404).json({ message: 'Student group not found' }); } + + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.StudentGroup, + record: model + }, + to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.status(200).json(model); }; export const setAdminRole: RequestHandler<{ id: string; userId: string }, any, { isAdmin: boolean }> = async ( @@ -54,54 +42,46 @@ export const setAdminRole: RequestHandler<{ id: string; userId: string }, any, { res, next ) => { - try { - const model = await StudentGroup.setAdminRole( - req.user!, - req.params.id, - req.params.userId, - req.body.isAdmin - ); - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { - type: RecordType.StudentGroup, - record: model - }, - to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + const model = await StudentGroup.setAdminRole( + req.user!, + req.params.id, + req.params.userId, + req.body.isAdmin + ); + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.StudentGroup, + record: model + }, + to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.status(200).json(model); }; export const addUser: RequestHandler<{ id: string; userId: string }, any, any> = async (req, res, next) => { - try { - const model = await StudentGroup.addUser(req.user!, req.params.id, req.params.userId); - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { - type: RecordType.StudentGroup, - record: model - }, - to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + const model = await StudentGroup.addUser(req.user!, req.params.id, req.params.userId); + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.StudentGroup, + record: model }, - { - event: IoEvent.NEW_RECORD, - message: { - type: RecordType.StudentGroup, - record: model - }, - to: [req.params.userId] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + to: [model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + }, + { + event: IoEvent.NEW_RECORD, + message: { + type: RecordType.StudentGroup, + record: model + }, + to: [req.params.userId] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.status(200).json(model); }; export const removeUser: RequestHandler<{ id: string; userId: string }, any, any> = async ( @@ -109,56 +89,44 @@ export const removeUser: RequestHandler<{ id: string; userId: string }, any, any res, next ) => { - try { - const model = await StudentGroup.removeUser(req.user!, req.params.id, req.params.userId); - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { - type: RecordType.StudentGroup, - record: model - }, - to: [req.params.userId, model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + const model = await StudentGroup.removeUser(req.user!, req.params.id, req.params.userId); + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.StudentGroup, + record: model }, - { - event: IoEvent.DELETED_RECORD, - message: { - type: RecordType.StudentGroup, - id: model.id - }, - to: [req.params.userId] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.status(200).json(model); - } catch (error) { - next(error); - } + to: [req.params.userId, model.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + }, + { + event: IoEvent.DELETED_RECORD, + message: { + type: RecordType.StudentGroup, + id: model.id + }, + to: [req.params.userId] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.status(200).json(model); }; export const all: RequestHandler = async (req, res, next) => { - try { - const users = await StudentGroup.all(req.user!); - res.json(users); - } catch (error) { - next(error); - } + const users = await StudentGroup.all(req.user!); + res.json(users); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const group = await StudentGroup.deleteModel(req.user!, req.params.id); - res.notifications = [ - { - event: IoEvent.DELETED_RECORD, - message: { - type: RecordType.StudentGroup, - id: group.id - }, - to: [group.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving - } - ]; - res.json(group); - } catch (error) { - next(error); - } + const group = await StudentGroup.deleteModel(req.user!, req.params.id); + res.notifications = [ + { + event: IoEvent.DELETED_RECORD, + message: { + type: RecordType.StudentGroup, + id: group.id + }, + to: [group.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + } + ]; + res.json(group); }; diff --git a/src/controllers/users.ts b/src/controllers/users.ts index 0ee89f5..f9fa897 100644 --- a/src/controllers/users.ts +++ b/src/controllers/users.ts @@ -8,28 +8,16 @@ export const user: RequestHandler = async (req, res) => { }; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - try { - const user = await User.findModel(req.params.id); - res.json(user); - } catch (error) { - next(error); - } + const user = await User.findModel(req.params.id); + res.json(user); }; export const update: RequestHandler<{ id: string }, any, { data: DbUser }> = async (req, res, next) => { - try { - const model = await User.updateModel(req.user!, req.params.id, req.body.data); - res.status(200).json(model); - } catch (error) { - next(error); - } + const model = await User.updateModel(req.user!, req.params.id, req.body.data); + res.status(200).json(model); }; export const all: RequestHandler = async (req, res, next) => { - try { - const users = await User.all(req.user!); - res.json(users); - } catch (error) { - next(error); - } + const users = await User.all(req.user!); + res.json(users); }; From ab1d2d296246e96e2dfe52a68d3271c8fcbec891 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Thu, 25 Sep 2025 09:50:49 +0200 Subject: [PATCH 03/89] update types --- package.json | 4 ++-- yarn.lock | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 0a66281..7b6ed15 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "connect-pg-simple": "^9.0.1", "cors": "^2.8.5", "es-toolkit": "^1.39.10", - "express": "^5", + "express": "^5.1.0", "express-session": "^1.18.0", "global": "^4.4.0", "morgan": "^1.10.0", @@ -45,7 +45,7 @@ "@mermaid-js/mermaid-cli": "^10.9.1", "@types/connect-pg-simple": "^7.0.3", "@types/cors": "^2.8.17", - "@types/express": "^4.17.21", + "@types/express": "^5.0.3", "@types/morgan": "^1.9.9", "@types/node": "^20.14.6", "@types/passport-azure-ad": "^4.3.6", diff --git a/yarn.lock b/yarn.lock index 7626882..838ebac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1408,6 +1408,16 @@ "@types/range-parser" "*" "@types/send" "*" +"@types/express-serve-static-core@^5.0.0": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" + integrity sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + "@types/send" "*" + "@types/express-session@*": version "1.18.0" resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.18.0.tgz#7c6f25c3604b28d6bc08a2e3929997bbc7672fa2" @@ -1415,7 +1425,7 @@ dependencies: "@types/express" "*" -"@types/express@*", "@types/express@^4.17.21": +"@types/express@*": version "4.17.21" resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== @@ -1425,6 +1435,15 @@ "@types/qs" "*" "@types/serve-static" "*" +"@types/express@^5.0.3": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.3.tgz#6c4bc6acddc2e2a587142e1d8be0bce20757e956" + integrity sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^5.0.0" + "@types/serve-static" "*" + "@types/geojson@*": version "7946.0.16" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" @@ -3318,7 +3337,7 @@ express@^4.18.2: utils-merge "1.0.1" vary "~1.1.2" -express@^5: +express@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" integrity sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA== From 47fff51013e918a6449f87eaba1b4332b39840a8 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Thu, 25 Sep 2025 09:51:16 +0200 Subject: [PATCH 04/89] update error handling and comment out login-strategy --- src/app.ts | 28 ++++++++++++++++++++++++---- src/utils/errors/BaseError.ts | 1 + 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/app.ts b/src/app.ts index 3cceff9..87014dd 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,7 +10,7 @@ import router from './routes/router'; import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRules } from './auth/guard'; import authConfig from './routes/authConfig'; import { type User } from '@prisma/client'; -import { HttpStatusCode } from './utils/errors/BaseError'; +import BaseError, { HttpStatusCode } from './utils/errors/BaseError'; import { HTTP401Error } from './utils/errors/Errors'; import connectPgSimple from 'connect-pg-simple'; import Logger from './utils/logger'; @@ -80,14 +80,14 @@ export const sessionMiddleware = session({ } }); -app.use(sessionMiddleware); +// app.use(sessionMiddleware); -app.use(passport.initialize()); +// app.use(passport.initialize()); /** alias for passport.authenticate('session'); e.g. to use the session... */ app.use(passport.session()); -passport.use(strategyForEnvironment()); +// passport.use(strategyForEnvironment()); passport.serializeUser((user, done) => { done(null, user.id); @@ -141,6 +141,25 @@ const logout = async (req: Request, res: Response, next: NextFunction) => { app.post(`${API_URL}/logout`, logout); +const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { + if ((err as BaseError).isHttpError) { + const httpErr = err as BaseError; + res.status(httpErr.statusCode).send({ + errors: [ + { + name: httpErr.name, + message: httpErr.message, + status: httpErr.statusCode, + isOperational: httpErr.isOperational + } + ] + }); + } else { + res.status(500).send({ errors: [{ name: err.name, message: err.message }] }); + } + Logger.error(err); +}; + export const configure = (_app: typeof app) => { /** * Notification Middleware @@ -213,6 +232,7 @@ export const configure = (_app: typeof app) => { routeGuard(AccessRules), // route guard middleware router // the router with all the routes ); + _app.use(errorHandler); }; if (process.env.NODE_ENV === 'test') { diff --git a/src/utils/errors/BaseError.ts b/src/utils/errors/BaseError.ts index 2cad3dd..35049f9 100644 --- a/src/utils/errors/BaseError.ts +++ b/src/utils/errors/BaseError.ts @@ -8,6 +8,7 @@ export enum HttpStatusCode { } export default class BaseError extends Error { + public readonly isHttpError = true; public readonly name: string; public readonly statusCode: HttpStatusCode; public readonly isOperational: boolean; From 339dbee2ddbda19b4fa030e407912c5e6d5bd7b8 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Thu, 25 Sep 2025 10:36:30 +0200 Subject: [PATCH 05/89] try ts confgi --- package.json | 5 +++-- src/app.ts | 1 - tsconfig.json | 14 ++++++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 7b6ed15..0985068 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "name": "teaching-website-backend", "version": "1.0.0", - "main": "index.js", + "type": "module", + "main": "dist/src/server.js", "repository": "https://github.com/GBSL-Informatik/teaching-website-backend.git", "author": "GBSL Informatik", "license": "CC-BY-SA", @@ -62,4 +63,4 @@ "engines": { "node": "^22.11.0" } -} +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 87014dd..b16289a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -47,7 +47,6 @@ app.use( // received packages should be presented in the JSON format app.use(express.json({ limit: '5mb' })); - app.use(morganMiddleware); const store = new (connectPgSimple(session))({ diff --git a/tsconfig.json b/tsconfig.json index c9000a3..ffe2dc6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -29,11 +29,11 @@ // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ /* Modules */ - "module": "commonjs", + "module": "nodenext", /* Specify what module code is generated. */ // "rootDir": "./", /* Specify the root folder within your source files. */ - // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + "moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */ // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ @@ -41,7 +41,7 @@ // "types": [], /* Specify type package names to be included without being referenced in a source file. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ @@ -142,5 +142,11 @@ // from generated source code references. // This improves issue grouping in Sentry. "sourceRoot": "/" - } + }, + "exclude": [ "node_modules" ], + "include": [ + "src/**/*.ts", + "bin/*.ts", + "prisma/**/*.ts" + ] } From f010b650297a1375286e8795fdfafb59174c4211 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 26 Sep 2025 15:59:38 +0000 Subject: [PATCH 06/89] make it running --- .eslintrc.json | 28 +++ .prettierrc => .prettierrc,json | 0 package.json | 32 +-- prisma/seed.ts | 8 +- process.env.d.ts | 10 + src/app.ts | 338 +++++++++++++++++--------------- src/instrumentation.ts | 3 +- src/models/User.ts | 227 +++++++++++---------- src/server.ts | 95 +++++---- src/utils/errors/BaseError.ts | 44 +++-- tsconfig.json | 163 +++------------ yarn.lock | 314 +++++++++++++++++++++++++++-- 12 files changed, 766 insertions(+), 496 deletions(-) create mode 100644 .eslintrc.json rename .prettierrc => .prettierrc,json (100%) create mode 100644 process.env.d.ts diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..4e9a7b4 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,28 @@ +{ + "env": { + "es2021": true, + "node": true + }, + "extends": ["prettier"], + "plugins": ["prettier", "@typescript-eslint"], + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "rules": { + "prettier/prettier": [ + "error", + { + "arrowParens": "always", + "bracketSpacing": true, + "bracketSameLine": false, + "printWidth": 110, + "proseWrap": "never", + "singleQuote": true, + "trailingComma": "none", + "tabWidth": 4 + } + ] + }, + "parser": "@typescript-eslint/parser" +} diff --git a/.prettierrc b/.prettierrc,json similarity index 100% rename from .prettierrc rename to .prettierrc,json diff --git a/package.json b/package.json index 0985068..87a08f2 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,22 @@ { "name": "teaching-website-backend", "version": "1.0.0", - "type": "module", - "main": "dist/src/server.js", + "main": "server.js", "repository": "https://github.com/GBSL-Informatik/teaching-website-backend.git", "author": "GBSL Informatik", "license": "CC-BY-SA", "scripts": { - "build": "yarn run prisma generate && tsc --build ./tsconfig.build.json && (yarn sentry:sourcemaps || true)", - "start": "node -r dotenv/config ./dist/src/server.js", - "dev": "dotenv -- nodemon src/server.ts", - "dummy:run": "ts-node -r dotenv/config ./bin/dummy.ts", + "dev": "cross-env NODE_ENV=development nodemon -r tsconfig-paths/register --exec ts-node ./src/server.ts --files", + "build": "tsc && tsc-alias", + "start": "cross-env NODE_ENV=production node ./build/src/server.js", + "lint": "eslint ./src/**/*.ts --fix", + "format": "prettier --write ./**/*.{ts,json}", + "format:check": "prettier --check .", "db:migrate": "yarn prisma migrate deploy", "db:migrate:dev": "yarn prisma migrate dev", "db:seed": "yarn prisma db seed", "db:reset": "dotenv -- ts-node prisma/reset.ts", "db:recreate": "yarn run db:reset && yarn run db:migrate && yarn run db:seed", - "format": "prettier --write .", - "format:check": "prettier --check .", "sentry:sourcemaps": "sentry-cli sourcemaps inject --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist && sentry-cli sourcemaps upload --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist" }, "dependencies": { @@ -27,9 +26,11 @@ "@sentry/node": "^10.8.0", "connect-pg-simple": "^9.0.1", "cors": "^2.8.5", + "cross-env": "^10.0.0", + "dotenv": "^17.2.2", "es-toolkit": "^1.39.10", "express": "^5.1.0", - "express-session": "^1.18.0", + "express-session": "^1.18.2", "global": "^4.4.0", "morgan": "^1.10.0", "passport": "^0.7.0", @@ -50,15 +51,22 @@ "@types/morgan": "^1.9.9", "@types/node": "^20.14.6", "@types/passport-azure-ad": "^4.3.6", + "@typescript-eslint/eslint-plugin": "^8.44.1", + "@typescript-eslint/parser": "^8.44.1", "dotenv-cli": "^7.4.2", - "nodemon": "^3.1.3", - "prettier": "^3.3.2", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "nodemon": "^3.1.10", + "prettier": "^3.6.2", "prisma": "^6.15.0", "prisma-dbml-generator": "^0.12.0", "prisma-docs-generator": "^0.8.0", "prisma-erd-generator": "^2.0.4", "ts-node": "^10.9.2", - "typescript": "^5.5.4" + "tsc-alias": "^1.8.16", + "tsconfig-paths": "^4.2.0", + "typescript": "^5.5.4", + "typescript-transform-paths": "^3.5.5" }, "engines": { "node": "^22.11.0" diff --git a/prisma/seed.ts b/prisma/seed.ts index 6e00bb4..61abc18 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,23 +1,23 @@ import { Access, PrismaClient, User } from '@prisma/client'; import { FOO_BAR_ID, TEST_USER_ID, users as seedUsers } from './seed-files/users'; -import { documents as seedDocuments } from './seed-files/documents'; +import { documents as seedDocuments } from '@/prisma/seed-files/documents'; import { ALL_USERS_GROUP_ID, CLASS_GROUP_ID, PROJECT_GROUP_ID, studentGroups as seedStudentGroups -} from './seed-files/student-groups'; +} from '@/prisma/seed-files/student-groups'; import { documentRoots as seedDocumentRoots, NONE_EXAM_DOCUMENT_ID, RW_EXERCISE_IMPSUM_DOCUMENT_ROOT_ID, RO_VISIBILITY_WRAPPER_DOCUMENT_ROOT_ID, RW_EXERCISE_LOREM_DOCUMENT_ROOT_ID -} from './seed-files/document-roots'; +} from '@/prisma/seed-files/document-roots'; import { rootUserPermissions as seedRootUserPermissions, rootGroupPermissions as seedRootGroupPermissions -} from './seed-files/document-root-permissions'; +} from '@/prisma/seed-files/document-root-permissions'; const prisma = new PrismaClient(); diff --git a/process.env.d.ts b/process.env.d.ts new file mode 100644 index 0000000..c887da4 --- /dev/null +++ b/process.env.d.ts @@ -0,0 +1,10 @@ +declare global { + namespace NodeJS { + interface ProcessEnv { + [key: string]: string | undefined; + PORT: string; + } + } +} + +export {}; diff --git a/src/app.ts b/src/app.ts index b16289a..62ce8bd 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,22 +1,28 @@ -import { strategyForEnvironment } from './auth/index'; -import express, { NextFunction, Request, Response } from 'express'; -import session from 'express-session'; -import prisma from './prisma'; -import path from 'path'; -import cors from 'cors'; -import morganMiddleware from './middleware/morgan.middleware'; -import passport from 'passport'; -import router from './routes/router'; -import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRules } from './auth/guard'; -import authConfig from './routes/authConfig'; -import { type User } from '@prisma/client'; -import BaseError, { HttpStatusCode } from './utils/errors/BaseError'; -import { HTTP401Error } from './utils/errors/Errors'; -import connectPgSimple from 'connect-pg-simple'; -import Logger from './utils/logger'; -import type { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; -import type { Server } from 'socket.io'; -import { CORS_ORIGIN, SAME_SITE } from './utils/originConfig'; +import express, { NextFunction, Request, Response } from "express"; +import session from "express-session"; +import prisma from "@/prisma"; +import path from "path"; +import cors from "cors"; +import morganMiddleware from "./middleware/morgan.middleware"; +import passport from "passport"; +import router from "./routes/router"; +import routeGuard, { + PUBLIC_GET_ACCESS, + PUBLIC_GET_ACCESS_REGEX, + createAccessRules, +} from "./auth/guard"; +import authConfig from "./routes/authConfig"; +import { type User } from "@prisma/client"; +import BaseError, { HttpStatusCode } from "./utils/errors/BaseError"; +import { HTTP401Error } from "./utils/errors/Errors"; +import connectPgSimple from "connect-pg-simple"; +import Logger from "./utils/logger"; +import type { + ClientToServerEvents, + ServerToClientEvents, +} from "./routes/socketEventTypes"; +import type { Server } from "socket.io"; +import { CORS_ORIGIN, SAME_SITE } from "./utils/originConfig"; const AccessRules = createAccessRules(authConfig.accessMatrix); @@ -27,7 +33,7 @@ const AccessRules = createAccessRules(authConfig.accessMatrix); */ const app = express(); -export const API_VERSION = 'v1'; +export const API_VERSION = "v1"; export const API_URL = `/api/${API_VERSION}`; /** @@ -38,20 +44,20 @@ export const API_URL = `/api/${API_VERSION}`; // ensure the server can call other domains: enable cross origin resource sharing (cors) app.use( - cors({ - credentials: true, - origin: CORS_ORIGIN, - methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'] - }) + cors({ + credentials: true, + origin: CORS_ORIGIN, + methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"], + }) ); // received packages should be presented in the JSON format -app.use(express.json({ limit: '5mb' })); +app.use(express.json({ limit: "5mb" })); app.use(morganMiddleware); const store = new (connectPgSimple(session))({ - conString: process.env.DATABASE_URL, - tableName: 'sessions' + conString: process.env.DATABASE_URL, + tableName: "sessions", }); const SESSION_MAX_AGE = 2592000000 as const; // 1000 * 60 * 60 * 24 * 30 = 2592000000 = 30 days @@ -59,24 +65,24 @@ const SESSION_MAX_AGE = 2592000000 as const; // 1000 * 60 * 60 * 24 * 30 = 25920 /** make sure to have 1 (reverse) proxy in front of the application * as is the case with dokku (nginx) */ -app.set('trust proxy', 1); +app.set("trust proxy", 1); -const SESSION_KEY = `${process.env.APP_NAME || 'twa'}ApiKey`; +const SESSION_KEY = `${process.env.APP_NAME || "twa"}ApiKey`; /** https://medium.com/developer-rants/how-to-handle-sessions-properly-in-express-js-with-heroku-c35ea8c0e500 */ export const sessionMiddleware = session({ - name: SESSION_KEY /** twa stands for "TeachingWebsiteApi" */, - store: store, - secret: process.env.SESSION_SECRET || 'secret', - saveUninitialized: false, - resave: false, - proxy: process.env.NODE_ENV === 'production', - cookie: { - secure: process.env.NODE_ENV === 'production', - httpOnly: true, - sameSite: SAME_SITE, - maxAge: SESSION_MAX_AGE // 30 days - } + name: SESSION_KEY /** twa stands for "TeachingWebsiteApi" */, + store: store, + secret: process.env.SESSION_SECRET || "secret", + saveUninitialized: false, + resave: false, + proxy: process.env.NODE_ENV === "production", + cookie: { + secure: process.env.NODE_ENV === "production", + httpOnly: true, + sameSite: SAME_SITE, + maxAge: SESSION_MAX_AGE, // 30 days + }, }); // app.use(sessionMiddleware); @@ -89,153 +95,175 @@ app.use(passport.session()); // passport.use(strategyForEnvironment()); passport.serializeUser((user, done) => { - done(null, user.id); + done(null, user.id); }); -const deserializeUser = async (id: string, done: (err: any, user?: User | null) => void) => { - const user = await prisma.user.findUnique({ where: { id: id } }); - done(null, user); +const deserializeUser = async ( + id: string, + done: (err: any, user?: User | null) => void +) => { + const user = await prisma.user.findUnique({ where: { id: id } }); + done(null, user); }; passport.deserializeUser(deserializeUser); // Serve the static files to be accessed by the docs app -app.use(express.static(path.join(__dirname, '..', 'docs'))); +app.use(express.static(path.join(__dirname, "..", "docs"))); const welcomeApi = (req: Request, res: Response) => { - return res.status(200).send('Welcome to the TEACHING-WEBSITE-API V1.0'); + return res.status(200).send("Welcome to the TEACHING-WEBSITE-API V1.0"); }; // Public Endpoints app.get(`${API_URL}`, welcomeApi); -const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate('oauth-bearer', { session: true })(req, res, next); +const SessionOauthStrategy = ( + req: Request, + res: Response, + next: NextFunction +) => { + if (req.isAuthenticated()) { + return next(); + } + passport.authenticate("oauth-bearer", { session: true })(req, res, next); }; const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - if (req.user) { - return res.status(200).send('OK'); - } - throw new HTTP401Error(); + if (req.user) { + return res.status(200).send("OK"); + } + throw new HTTP401Error(); }; app.get(`${API_URL}/checklogin`, SessionOauthStrategy, checkLogin); const logout = async (req: Request, res: Response, next: NextFunction) => { - req.logout({ keepSessionInfo: false }, (err) => { - if (err) { - Logger.error(err); - return next(err); - } - }); - Logger.info(req.user); - Logger.info(req.session); - // await prisma.sessions.delete({ where: { sid: req.session.id } }); - res.clearCookie(SESSION_KEY).send(); + req.logout({ keepSessionInfo: false }, (err) => { + if (err) { + Logger.error(err); + return next(err); + } + }); + Logger.info(req.user); + Logger.info(req.session); + // await prisma.sessions.delete({ where: { sid: req.session.id } }); + res.clearCookie(SESSION_KEY).send(); }; app.post(`${API_URL}/logout`, logout); -const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { - if ((err as BaseError).isHttpError) { - const httpErr = err as BaseError; - res.status(httpErr.statusCode).send({ - errors: [ - { - name: httpErr.name, - message: httpErr.message, - status: httpErr.statusCode, - isOperational: httpErr.isOperational - } - ] - }); - } else { - res.status(500).send({ errors: [{ name: err.name, message: err.message }] }); - } - Logger.error(err); +const errorHandler = ( + err: Error, + req: Request, + res: Response, + next: NextFunction +) => { + if ((err as BaseError).isHttpError) { + const httpErr = err as BaseError; + res.status(httpErr.statusCode).send({ + errors: [ + { + name: httpErr.name, + message: httpErr.message, + status: httpErr.statusCode, + isOperational: httpErr.isOperational, + }, + ], + }); + } else { + res + .status(500) + .send({ errors: [{ name: err.name, message: err.message }] }); + } + Logger.error(err); }; export const configure = (_app: typeof app) => { - /** - * Notification Middleware - * when the response `res` contains a `notifications` property, the middleware will - * send the notification over SocketIO to the specififed rooms. - */ - _app.use((req: Request, res, next) => { - res.on('finish', async () => { - if (res.statusCode >= 400) { - return; - } - const io = req.io as Server; - - if (res.notifications && io) { - res.notifications.forEach((notification) => { - const except: string[] = []; - /** ignore this socket */ - if (!notification.toSelf) { - const socketID = req.headers['x-metadata-socketid'] as string; - if (socketID) { - except.push(socketID); - } - } - io.except(except) - .to(notification.to) - .emit(notification.event, notification.message as any); - }); + /** + * Notification Middleware + * when the response `res` contains a `notifications` property, the middleware will + * send the notification over SocketIO to the specififed rooms. + */ + _app.use((req: Request, res, next) => { + res.on("finish", async () => { + if (res.statusCode >= 400) { + return; + } + const io = req.io as Server; + + if (res.notifications && io) { + res.notifications.forEach((notification) => { + const except: string[] = []; + /** ignore this socket */ + if (!notification.toSelf) { + const socketID = req.headers["x-metadata-socketid"] as string; + if (socketID) { + except.push(socketID); } + } + io.except(except) + .to(notification.to) + .emit(notification.event, notification.message as any); }); - next(); + } }); - /** - * API Route Guard - * This middleware will check if the user is authenticated and has the required - * permissions to access the requested route. - */ - _app.use( - `${API_URL}`, - (req, res, next) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate('oauth-bearer', { session: true }, (err: Error, user: User, info: any) => { - if (err) { - /** - * An error occurred during authorization. Send a Not Autohrized - * status code. - */ - return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: err.message }); - } - - if ( - !user && - !( - PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || - PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) - ) - ) { - // If no user object found, send a 401 response. - return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: 'Unauthorized' }); - } - req.user = user; - if (info) { - // access token payload will be available in req.authInfo downstream - req.authInfo = info; - return next(); - } - })(req, res, next); - }, - routeGuard(AccessRules), // route guard middleware - router // the router with all the routes - ); - _app.use(errorHandler); + next(); + }); + /** + * API Route Guard + * This middleware will check if the user is authenticated and has the required + * permissions to access the requested route. + */ + _app.use( + `${API_URL}`, + (req, res, next) => { + if (req.isAuthenticated()) { + return next(); + } + passport.authenticate( + "oauth-bearer", + { session: true }, + (err: Error, user: User, info: any) => { + if (err) { + /** + * An error occurred during authorization. Send a Not Autohrized + * status code. + */ + return res + .status(HttpStatusCode.UNAUTHORIZED) + .json({ error: err.message }); + } + + if ( + !user && + !( + PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || + PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) + ) + ) { + // If no user object found, send a 401 response. + return res + .status(HttpStatusCode.UNAUTHORIZED) + .json({ error: "Unauthorized" }); + } + req.user = user; + if (info) { + // access token payload will be available in req.authInfo downstream + req.authInfo = info; + return next(); + } + } + )(req, res, next); + }, + routeGuard(AccessRules), // route guard middleware + router // the router with all the routes + ); + _app.use(errorHandler); }; -if (process.env.NODE_ENV === 'test') { - configure(app); +if (process.env.NODE_ENV === "test") { + configure(app); } export default app; diff --git a/src/instrumentation.ts b/src/instrumentation.ts index 5ce1684..78a42f5 100644 --- a/src/instrumentation.ts +++ b/src/instrumentation.ts @@ -1,6 +1,7 @@ import * as Sentry from '@sentry/node'; import Logger from './utils/logger'; - +import dotenv from 'dotenv'; +dotenv.config(); if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) { Logger.info('Initializing Sentry'); let samplingRate = 0.1; diff --git a/src/models/User.ts b/src/models/User.ts index c7c42ec..1c3edac 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -1,128 +1,141 @@ -import { Prisma, PrismaClient, User as DbUser, Role, User } from '@prisma/client'; -import prisma from '../prisma'; -import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; -import { createDataExtractor } from '../helpers/dataExtractor'; -import _ from 'es-toolkit/compat'; -const getData = createDataExtractor(['firstName', 'lastName']); +import { Prisma, PrismaClient, User as DbUser, Role } from "@prisma/client"; +import prisma from "../prisma"; +import { HTTP403Error, HTTP404Error } from "../utils/errors/Errors"; +import { createDataExtractor } from "../helpers/dataExtractor"; +import _ from "es-toolkit/compat"; +const getData = createDataExtractor([ + "firstName", + "lastName", +]); const RoleAccessLevel: { [key in Role]: number } = { - [Role.STUDENT]: 0, - [Role.TEACHER]: 1, - [Role.ADMIN]: 2 + [Role.STUDENT]: 0, + [Role.TEACHER]: 1, + [Role.ADMIN]: 2, }; export const getAccessLevel = (role?: Role | null) => { - if (!role) { - return 0; - } - return RoleAccessLevel[role] || 0; + if (!role) { + return 0; + } + return RoleAccessLevel[role] || 0; }; export const hasElevatedAccess = (role?: Role | null) => { - if (!role) { - return false; - } - return RoleAccessLevel[role] > 0; + if (!role) { + return false; + } + return RoleAccessLevel[role] > 0; }; export const whereStudentGroupAccess = (userId: string, isAdmin?: boolean) => ({ - studentGroups: { - some: { - studentGroup: { - users: { - some: - isAdmin === undefined - ? { userId } - : { - userId, - isAdmin - } - } - } - } - } + studentGroups: { + some: { + studentGroup: { + users: { + some: + isAdmin === undefined + ? { userId } + : { + userId, + isAdmin, + }, + }, + }, + }, + }, }); -function User(db: PrismaClient['user']) { - return Object.assign(db, { - async findModel(id: string): Promise { - return db.findUnique({ where: { id } }); - }, +function User(db: PrismaClient["user"]) { + return Object.assign(db, { + async findModel(id: string): Promise { + return db.findUnique({ where: { id } }); + }, - async updateModel(actor: DbUser, id: string, data: Partial): Promise { - const record = await db.findUnique({ where: { id: id } }); - if (!record) { - throw new HTTP404Error('User not found'); - } - const elevatedAccess = hasElevatedAccess(actor.role); - if (!(record.id === actor.id || elevatedAccess)) { - throw new HTTP403Error('Not authorized'); - } - if (data.role && data.role !== record.role) { - await this.setRole(actor, id, data.role as Role); - } - /** remove fields not updatable*/ - const sanitized = getData(data, false, record.id === actor.id ? false : elevatedAccess); - return db.update({ - where: { - id: id - }, - data: sanitized - }); + async updateModel( + actor: DbUser, + id: string, + data: Partial + ): Promise { + const record = await db.findUnique({ where: { id: id } }); + if (!record) { + throw new HTTP404Error("User not found"); + } + const elevatedAccess = hasElevatedAccess(actor.role); + if (!(record.id === actor.id || elevatedAccess)) { + throw new HTTP403Error("Not authorized"); + } + if (data.role && data.role !== record.role) { + await this.setRole(actor, id, data.role as Role); + } + /** remove fields not updatable*/ + const sanitized = getData( + data, + false, + record.id === actor.id ? false : elevatedAccess + ); + return db.update({ + where: { + id: id, }, + data: sanitized, + }); + }, - async all(actor: DbUser): Promise { - if (hasElevatedAccess(actor.role)) { - /** - * Admins and teachers can see all users. - * Reason: teachers need to add new users to their student groups - */ - return db.findMany({}); - } - const users = await db.findMany({ - where: { - OR: [ - { - id: actor.id - }, - whereStudentGroupAccess(actor.id) - ] - }, - distinct: ['id'] - }); - return users; + async all(actor: DbUser): Promise { + if (hasElevatedAccess(actor.role)) { + /** + * Admins and teachers can see all users. + * Reason: teachers need to add new users to their student groups + */ + return db.findMany({}); + } + const users = await db.findMany({ + where: { + OR: [ + { + id: actor.id, + }, + whereStudentGroupAccess(actor.id), + ], }, + distinct: ["id"], + }); + return users; + }, - async setRole(actor: DbUser, userId: string, role: Role): Promise { - if (!hasElevatedAccess(actor.role)) { - throw new HTTP403Error('Not authorized'); - } - const actorLevel = RoleAccessLevel[actor.role]; - const roleLevel = RoleAccessLevel[role]; - if (roleLevel > actorLevel) { - throw new HTTP403Error('Not allowed to set a higher role'); - } - if (actor.id === userId && roleLevel < actorLevel) { - throw new HTTP403Error('Not allowed to lower own role'); - } - const record = await this.findModel(userId); - if (!record) { - throw new HTTP404Error('User not found'); - } - const recordLevel = RoleAccessLevel[record.role]; - if (actorLevel < recordLevel) { - throw new HTTP403Error('Not allowed to change the role of user with a higher role'); - } - return db.update({ - where: { - id: userId - }, - data: { - role: role - } - }); - } - }); + async setRole(actor: DbUser, userId: string, role: Role): Promise { + if (!hasElevatedAccess(actor.role)) { + throw new HTTP403Error("Not authorized"); + } + const actorLevel = RoleAccessLevel[actor.role]; + const roleLevel = RoleAccessLevel[role]; + if (roleLevel > actorLevel) { + throw new HTTP403Error("Not allowed to set a higher role"); + } + if (actor.id === userId && roleLevel < actorLevel) { + throw new HTTP403Error("Not allowed to lower own role"); + } + const record = await this.findModel(userId); + if (!record) { + throw new HTTP404Error("User not found"); + } + const recordLevel = RoleAccessLevel[record.role]; + if (actorLevel < recordLevel) { + throw new HTTP403Error( + "Not allowed to change the role of user with a higher role" + ); + } + return db.update({ + where: { + id: userId, + }, + data: { + role: role, + }, + }); + }, + }); } export default User(prisma.user); diff --git a/src/server.ts b/src/server.ts index a069504..1012aaa 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,66 +1,81 @@ -import './instrumentation'; -import app, { configure, sessionMiddleware } from './app'; -import http from 'http'; -import Logger from './utils/logger'; -import { Server } from 'socket.io'; -import { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; -import passport from 'passport'; -import EventRouter from './routes/socketEvents'; -import { NextFunction, Request, Response } from 'express'; -import { HTTP403Error } from './utils/errors/Errors'; -import { CORS_ORIGIN } from './utils/originConfig'; -import * as Sentry from '@sentry/node'; +import "./instrumentation"; +import app, { configure, sessionMiddleware } from "./app"; +import http from "http"; +import Logger from "@/utils/logger"; +import { Server } from "socket.io"; +import { + ClientToServerEvents, + ServerToClientEvents, +} from "./routes/socketEventTypes"; +import passport from "passport"; +import EventRouter from "./routes/socketEvents"; +import type { NextFunction, Request, Response } from "express"; +import { HTTP403Error } from "./utils/errors/Errors"; +import { CORS_ORIGIN } from "./utils/originConfig"; +import * as Sentry from "@sentry/node"; const PORT = process.env.PORT || 3002; const server = http.createServer(app); const io = new Server(server, { - cors: { - origin: CORS_ORIGIN, - credentials: true, - methods: ['GET', 'POST', 'PUT', 'DELETE'] - }, - pingInterval: 15_000, - pingTimeout: 20_000, - transports: ['websocket', 'webtransport' /* , 'polling' */] + cors: { + origin: CORS_ORIGIN, + credentials: true, + methods: ["GET", "POST", "PUT", "DELETE"], + }, + pingInterval: 15_000, + pingTimeout: 20_000, + transports: ["websocket", "webtransport" /* , 'polling' */], }); // convert a connect middleware to a Socket.IO middleware -io.use((socket, next) => { - sessionMiddleware(socket.request as Request, {} as Response, next as NextFunction); -}); -io.use((socket, next) => { - passport.initialize()(socket.request as Request, {} as Response, next as NextFunction); -}); -io.use((socket, next) => { - passport.session()(socket.request as Request, {} as Response, next as NextFunction); -}); +// io.use((socket, next) => { +// sessionMiddleware( +// socket.request as Request, +// {} as Response, +// next as NextFunction +// ); +// }); +// io.use((socket, next) => { +// passport.initialize()( +// socket.request as Request, +// {} as Response, +// next as NextFunction +// ); +// }); +// io.use((socket, next) => { +// passport.session()( +// socket.request as Request, +// {} as Response, +// next as NextFunction +// ); +// }); EventRouter(io); // only allow authenticated users in socketio io.use((socket, next) => { - if ((socket.request as any).user) { - next(); - } else { - next(new HTTP403Error('unauthorized')); - } + if ((socket.request as any).user) { + next(); + } else { + next(new HTTP403Error("unauthorized")); + } }); // Make io accessible to our router app.use((req: Request, res, next) => { - req.io = io; - next(); + req.io = io; + next(); }); configure(app); -if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) { - Sentry.setupExpressErrorHandler(app); +if (process.env.NODE_ENV === "production" && process.env.SENTRY_DSN) { + Sentry.setupExpressErrorHandler(app); } server.listen(PORT || 3002, () => { - Logger.info(`application is running at: http://localhost:${PORT}`); - Logger.info('Press Ctrl+C to quit.'); + Logger.info(`application is running at: http://localhost:${PORT}`); + Logger.info("Press Ctrl+C to quit."); }); diff --git a/src/utils/errors/BaseError.ts b/src/utils/errors/BaseError.ts index 35049f9..9b7890c 100644 --- a/src/utils/errors/BaseError.ts +++ b/src/utils/errors/BaseError.ts @@ -1,26 +1,32 @@ export enum HttpStatusCode { - OK = 200, - BAD_REQUEST = 400, - UNAUTHORIZED = 401, - FORBIDDEN = 403, - NOT_FOUND = 404, - INTERNAL_SERVER = 500 + OK = 200, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + FORBIDDEN = 403, + NOT_FOUND = 404, + INTERNAL_SERVER = 500, } export default class BaseError extends Error { - public readonly isHttpError = true; - public readonly name: string; - public readonly statusCode: HttpStatusCode; - public readonly isOperational: boolean; + public readonly isHttpError = true; + public readonly name: string; + public readonly statusCode: HttpStatusCode; + public readonly isOperational: boolean; + public readonly cause: string; - constructor(name: string, httpCode: HttpStatusCode, description: string, isOperational: boolean) { - super(`[${httpCode}] ${description}`); - Object.setPrototypeOf(this, new.target.prototype); - this.cause = description; - this.name = name; - this.statusCode = httpCode; - this.isOperational = isOperational; + constructor( + name: string, + httpCode: HttpStatusCode, + description: string, + isOperational: boolean + ) { + super(`[${httpCode}] ${description}`); + Object.setPrototypeOf(this, new.target.prototype); + this.cause = description; + this.name = name; + this.statusCode = httpCode; + this.isOperational = isOperational; - Error.captureStackTrace(this); - } + Error.captureStackTrace(this); + } } diff --git a/tsconfig.json b/tsconfig.json index ffe2dc6..c84cb80 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,152 +1,35 @@ { "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "ES2022", - - /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - "lib": ["esnext", "dom"], - - /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "nodenext", - - /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "nodenext", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ - // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ - // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ - // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + "target": "es6", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "resolveJsonModule": true, + "baseUrl": ".", + "outDir": "build", "sourceMap": true, - - /* Create source map files for emitted JavaScript files. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - "outDir": "dist", - - /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, - - /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, - - /* Ensure that casing is correct in imports. */ - - /* Type Checking */ "strict": true, - - /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true, - - /* Skip type checking all .d.ts files. */ - "resolveJsonModule": true, - + "isolatedModules": true, + "esModuleInterop": true, + "types": ["node", "express"], "typeRoots": [ "./src/types", "./node_modules/@types/", "./src/@types/" ], - - "types": [ - "node", - "express" + "plugins": [ + { + "transform": "typescript-transform-paths" + }, + { + "transform": "typescript-transform-paths", + "afterDeclarations": true + } ], - - "inlineSources": true, - - // Set `sourceRoot` to "/" to strip the build path prefix - // from generated source code references. - // This improves issue grouping in Sentry. - "sourceRoot": "/" + "paths": { + "@/prisma/*": ["prisma/*"], + "@/*": ["src/*"] + } }, - "exclude": [ "node_modules" ], - "include": [ - "src/**/*.ts", - "bin/*.ts", - "prisma/**/*.ts" - ] + "include": ["process.env.d.ts", "./**/*.ts"], + "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index 838ebac..d92144c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -136,6 +136,23 @@ enabled "2.0.x" kuler "^2.0.0" +"@epic-web/invariant@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@epic-web/invariant/-/invariant-1.0.0.tgz#1073e5dee6dd540410784990eb73e4acd25c9813" + integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== + +"@eslint-community/eslint-utils@^4.7.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" + integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== + dependencies: + eslint-visitor-keys "^3.4.3" + +"@eslint-community/regexpp@^4.10.0": + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + "@floating-ui/core@^1.5.3", "@floating-ui/core@^1.6.0": version "1.6.9" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" @@ -609,6 +626,11 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@pkgr/core@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" + integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== + "@prisma/adapter-pg@^6.15.0": version "6.15.0" resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-6.15.0.tgz#4602a8cbb70214e9b771cf13c0737744ba328f3f" @@ -1629,6 +1651,104 @@ dependencies: "@types/node" "*" +"@typescript-eslint/eslint-plugin@^8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz#011a2b5913d297b3d9d77f64fb78575bab01a1b3" + integrity sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "8.44.1" + "@typescript-eslint/type-utils" "8.44.1" + "@typescript-eslint/utils" "8.44.1" + "@typescript-eslint/visitor-keys" "8.44.1" + graphemer "^1.4.0" + ignore "^7.0.0" + natural-compare "^1.4.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/parser@^8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.44.1.tgz#d4c85791389462823596ad46e2b90d34845e05eb" + integrity sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw== + dependencies: + "@typescript-eslint/scope-manager" "8.44.1" + "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/typescript-estree" "8.44.1" + "@typescript-eslint/visitor-keys" "8.44.1" + debug "^4.3.4" + +"@typescript-eslint/project-service@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.44.1.tgz#1bccd9796d25032b190f355f55c5fde061158abb" + integrity sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA== + dependencies: + "@typescript-eslint/tsconfig-utils" "^8.44.1" + "@typescript-eslint/types" "^8.44.1" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz#31c27f92e4aed8d0f4d6fe2b9e5187d1d8797bd7" + integrity sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg== + dependencies: + "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/visitor-keys" "8.44.1" + +"@typescript-eslint/tsconfig-utils@8.44.1", "@typescript-eslint/tsconfig-utils@^8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz#e1d9d047078fac37d3e638484ab3b56215963342" + integrity sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ== + +"@typescript-eslint/type-utils@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz#be9d31e0f911d17ee8ac99921bb74cf1f9df3906" + integrity sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g== + dependencies: + "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/typescript-estree" "8.44.1" + "@typescript-eslint/utils" "8.44.1" + debug "^4.3.4" + ts-api-utils "^2.1.0" + +"@typescript-eslint/types@8.44.1", "@typescript-eslint/types@^8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.44.1.tgz#85d1cad1290a003ff60420388797e85d1c3f76ff" + integrity sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ== + +"@typescript-eslint/typescript-estree@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz#4f17650e5adabecfcc13cd8c517937a4ef5cd424" + integrity sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A== + dependencies: + "@typescript-eslint/project-service" "8.44.1" + "@typescript-eslint/tsconfig-utils" "8.44.1" + "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/visitor-keys" "8.44.1" + debug "^4.3.4" + fast-glob "^3.3.2" + is-glob "^4.0.3" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^2.1.0" + +"@typescript-eslint/utils@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.44.1.tgz#f23d48eb90791a821dc17d4f67bb96faeb75d63d" + integrity sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg== + dependencies: + "@eslint-community/eslint-utils" "^4.7.0" + "@typescript-eslint/scope-manager" "8.44.1" + "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/typescript-estree" "8.44.1" + +"@typescript-eslint/visitor-keys@8.44.1": + version "8.44.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz#1d96197a7fcceaba647b3bd6a8594df8dc4deb5a" + integrity sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw== + dependencies: + "@typescript-eslint/types" "8.44.1" + eslint-visitor-keys "^4.2.1" + "@vue/compat@^3.2.45": version "3.5.13" resolved "https://registry.yarnpkg.com/@vue/compat/-/compat-3.5.13.tgz#b8f715dc4ff0b4964165d51e0023bd2631de5ae5" @@ -2232,7 +2352,7 @@ chevrotain@~11.0.3: "@chevrotain/utils" "11.0.3" lodash-es "4.17.21" -chokidar@^3.5.2, chokidar@^3.6.0: +chokidar@^3.5.2, chokidar@^3.5.3, chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -2378,6 +2498,11 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +commander@^9.0.0: + version "9.5.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-9.5.0.tgz#bc08d1eb5cedf7ccb797a96199d41c7bc3e60d30" + integrity sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2459,7 +2584,7 @@ cookie@0.6.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -cookie@^0.7.1, cookie@~0.7.2: +cookie@0.7.2, cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -2519,6 +2644,14 @@ create-require@^1.1.0: resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== +cross-env@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-10.0.0.tgz#ba25823cfa1ed6af293dcded8796fa16cd162456" + integrity sha512-aU8qlEK/nHYtVuN4p7UQgAwVljzMg8hB4YK5ThRqD2l/ziSnryncPNn7bMLt5cFYsKVKBh8HqLqyCoTupEUu7Q== + dependencies: + "@epic-web/invariant" "^1.0.0" + cross-spawn "^7.0.6" + cross-fetch@3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -3077,6 +3210,11 @@ dotenv@^16.6.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== +dotenv@^17.2.2: + version "17.2.2" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.2.tgz#4010cfe1c2be4fc0f46fd3d951afb424bc067ac6" + integrity sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q== + dtrace-provider@~0.8: version "0.8.8" resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" @@ -3251,6 +3389,29 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +eslint-config-prettier@^10.1.8: + version "10.1.8" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#15734ce4af8c2778cc32f0b01b37b0b5cd1ecb97" + integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w== + +eslint-plugin-prettier@^5.5.4: + version "5.5.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz#9d61c4ea11de5af704d4edf108c82ccfa7f2e61c" + integrity sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg== + dependencies: + prettier-linter-helpers "^1.0.0" + synckit "^0.11.7" + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" + integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== + estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" @@ -3286,16 +3447,16 @@ execa@5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -express-session@^1.18.0: - version "1.18.0" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3" - integrity sha512-m93QLWr0ju+rOwApSsyso838LQwgfs44QtOP/WBiwtAgPIo/SAh1a5c6nn2BR6mFNZehTpqKDESzP+fRHVbxwQ== +express-session@^1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.2.tgz#34db6252611b57055e877036eea09b4453dec5d8" + integrity sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A== dependencies: - cookie "0.6.0" + cookie "0.7.2" cookie-signature "1.0.7" debug "2.6.9" depd "~2.0.0" - on-headers "~1.0.2" + on-headers "~1.1.0" parseurl "~1.3.3" safe-buffer "5.2.1" uid-safe "~2.1.5" @@ -3398,6 +3559,11 @@ fast-check@^3.23.1: dependencies: pure-rand "^6.1.0" +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + fast-glob@^3.2.9: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" @@ -3637,6 +3803,13 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== +get-tsconfig@^4.10.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.1.tgz#d34c1c01f47d65a606c37aa7a177bc3e56ab4b2e" + integrity sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ== + dependencies: + resolve-pkg-maps "^1.0.0" + giget@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/giget/-/giget-2.0.0.tgz#395fc934a43f9a7a29a29d55b99f23e30c14f195" @@ -3729,7 +3902,7 @@ globals@^15.14.0: resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== -globby@11.1.0, globby@^11.0.1: +globby@11.1.0, globby@^11.0.1, globby@^11.0.4: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -3758,6 +3931,11 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + hachure-fill@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" @@ -3920,6 +4098,11 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== +ignore@^7.0.0: + version "7.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" + integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -4137,6 +4320,11 @@ json-parse-even-better-errors@^2.3.0: resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json5@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + jsonfile@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" @@ -4774,7 +4962,7 @@ minimatch@^5.0.1, minimatch@^5.1.0: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.4: +minimatch@^9.0.0, minimatch@^9.0.4, minimatch@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== @@ -4877,6 +5065,11 @@ mv@~2: ncp "~2.0.0" rimraf "~2.4.0" +mylas@^2.1.9: + version "2.1.13" + resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" + integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg== + mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" @@ -4896,6 +5089,11 @@ nanoid@^3.3.8: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + ncp@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" @@ -4969,10 +5167,10 @@ node-jose@^2.2.0: process "^0.11.10" uuid "^9.0.0" -nodemon@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.3.tgz#dcce9ee0aa7d19cd4dcd576ae9a0456d9078b286" - integrity sha512-m4Vqs+APdKzDFpuaL9F9EVOF85+h070FnkHVEoU4+rmT6Vw0bmNl7s61VEkY/cJkL7RCv1p4urnUDUMrS5rk2w== +nodemon@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1" + integrity sha512-WDjw3pJ0/0jMFmyNDp3gvY2YizjLmmOUQo6DEBY+JgdvW/yQ9mEeSw6H5ythl5Ny2ytb7f9C2nIbjSxMNzbJXw== dependencies: chokidar "^3.5.2" debug "^4" @@ -5114,6 +5312,11 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== +on-headers@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" + integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== + once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -5546,6 +5749,13 @@ pkg-types@^2.2.0: exsolve "^1.0.7" pathe "^2.0.3" +plimit-lit@^1.2.6: + version "1.6.1" + resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.6.1.tgz#a34594671b31ee8e93c72d505dfb6852eb72374a" + integrity sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA== + dependencies: + queue-lit "^1.5.1" + pluralize@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" @@ -5671,10 +5881,17 @@ postgres-range@^1.1.1: resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== -prettier@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.3.2.tgz#03ff86dc7c835f2d2559ee76876a3914cec4a90a" - integrity sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA== +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^3.6.2: + version "3.6.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.6.2.tgz#ccda02a1003ebbb2bfda6f83a074978f608b9393" + integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ== prisma-dbml-generator@^0.12.0: version "0.12.0" @@ -5828,6 +6045,11 @@ quansync@^0.2.7, quansync@^0.2.8: resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== +queue-lit@^1.5.1: + version "1.5.2" + resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.5.2.tgz#83c24d4f4764802377b05a6e5c73017caf3f8747" + integrity sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw== + queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -6001,6 +6223,11 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + resolve@1.22.2: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" @@ -6142,6 +6369,11 @@ semver@^7.5.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== +semver@^7.6.0: + version "7.7.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" + integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== + send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -6474,6 +6706,11 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" @@ -6536,6 +6773,13 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +synckit@^0.11.7: + version "0.11.11" + resolved "https://registry.yarnpkg.com/synckit/-/synckit-0.11.11.tgz#c0b619cf258a97faa209155d9cd1699b5c998cb0" + integrity sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw== + dependencies: + "@pkgr/core" "^0.2.9" + tailwindcss@^3.4.17: version "3.4.17" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" @@ -6705,6 +6949,11 @@ triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.4.1.tgz#6fde70271dc6e5d73ca0c3b24e2d92afb7441984" integrity sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg== +ts-api-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-2.1.0.tgz#595f7094e46eed364c13fd23e75f9513d29baf91" + integrity sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ== + ts-dedent@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" @@ -6749,6 +6998,28 @@ ts-toolbelt@^9.6.0: resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5" integrity sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w== +tsc-alias@^1.8.16: + version "1.8.16" + resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.8.16.tgz#dbc74e797071801c7284f1a478259de920f852d4" + integrity sha512-QjCyu55NFyRSBAl6+MTFwplpFcnm2Pq01rR/uxfqJoLMm6X3O14KEGtaSDZpJYaE1bJBGDjD0eSuiIWPe2T58g== + dependencies: + chokidar "^3.5.3" + commander "^9.0.0" + get-tsconfig "^4.10.0" + globby "^11.0.4" + mylas "^2.1.9" + normalize-path "^3.0.0" + plimit-lit "^1.2.6" + +tsconfig-paths@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz#ef78e19039133446d244beac0fd6a1632e2d107c" + integrity sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg== + dependencies: + json5 "^2.2.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + type-fest@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" @@ -6791,6 +7062,13 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" +typescript-transform-paths@^3.5.5: + version "3.5.5" + resolved "https://registry.yarnpkg.com/typescript-transform-paths/-/typescript-transform-paths-3.5.5.tgz#72f473017a687a08ac72177e72926349d53ff436" + integrity sha512-RMK86wKe/4+ad+3kMT9SKAs3K0tUHLe7hF+MLbD6VpC9VUmFuKorhf3pHz+qO5GdS4mUp2ncNUo14j6ws9UvBQ== + dependencies: + minimatch "^9.0.5" + typescript@^5.5.4: version "5.5.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" From c031755440e76063c331ecdae8b1d8b270038f6a Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 26 Sep 2025 16:05:52 +0000 Subject: [PATCH 07/89] add eslintconfig --- eslint.config.mjs | 54 +++++++ package.json | 3 +- yarn.lock | 349 +++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 398 insertions(+), 8 deletions(-) create mode 100644 eslint.config.mjs diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..d67c32d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,54 @@ +import { defineConfig } from 'eslint/config'; +import prettier from 'eslint-plugin-prettier'; +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all +}); + +export default defineConfig([ + { + extends: compat.extends('prettier'), + + plugins: { + prettier, + '@typescript-eslint': typescriptEslint + }, + + languageOptions: { + globals: { + ...globals.node + }, + + parser: tsParser, + ecmaVersion: 'latest', + sourceType: 'module' + }, + + rules: { + 'prettier/prettier': [ + 'error', + { + arrowParens: 'always', + bracketSpacing: true, + bracketSameLine: false, + printWidth: 110, + proseWrap: 'never', + singleQuote: true, + trailingComma: 'none', + tabWidth: 4 + } + ] + } + } +]); diff --git a/package.json b/package.json index 87a08f2..8f8d645 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dev": "cross-env NODE_ENV=development nodemon -r tsconfig-paths/register --exec ts-node ./src/server.ts --files", "build": "tsc && tsc-alias", "start": "cross-env NODE_ENV=production node ./build/src/server.js", - "lint": "eslint ./src/**/*.ts --fix", + "lint": "eslint . --ignore-pattern node_modules --fix", "format": "prettier --write ./**/*.{ts,json}", "format:check": "prettier --check .", "db:migrate": "yarn prisma migrate deploy", @@ -54,6 +54,7 @@ "@typescript-eslint/eslint-plugin": "^8.44.1", "@typescript-eslint/parser": "^8.44.1", "dotenv-cli": "^7.4.2", + "eslint": "^9.36.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.4", "nodemon": "^3.1.10", diff --git a/yarn.lock b/yarn.lock index d92144c..df9b66f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -141,18 +141,72 @@ resolved "https://registry.yarnpkg.com/@epic-web/invariant/-/invariant-1.0.0.tgz#1073e5dee6dd540410784990eb73e4acd25c9813" integrity sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA== -"@eslint-community/eslint-utils@^4.7.0": +"@eslint-community/eslint-utils@^4.7.0", "@eslint-community/eslint-utils@^4.8.0": version "4.9.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz#7308df158e064f0dd8b8fdb58aa14fa2a7f913b3" integrity sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g== dependencies: eslint-visitor-keys "^3.4.3" -"@eslint-community/regexpp@^4.10.0": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.12.1": version "4.12.1" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== +"@eslint/config-array@^0.21.0": + version "0.21.0" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.0.tgz#abdbcbd16b124c638081766392a4d6b509f72636" + integrity sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ== + dependencies: + "@eslint/object-schema" "^2.1.6" + debug "^4.3.1" + minimatch "^3.1.2" + +"@eslint/config-helpers@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.3.1.tgz#d316e47905bd0a1a931fa50e669b9af4104d1617" + integrity sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA== + +"@eslint/core@^0.15.2": + version "0.15.2" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.2.tgz#59386327d7862cc3603ebc7c78159d2dcc4a868f" + integrity sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg== + dependencies: + "@types/json-schema" "^7.0.15" + +"@eslint/eslintrc@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.3.1.tgz#e55f7f1dd400600dd066dbba349c4c0bac916964" + integrity sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.36.0": + version "9.36.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.36.0.tgz#b1a3893dd6ce2defed5fd49de805ba40368e8fef" + integrity sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw== + +"@eslint/object-schema@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" + integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== + +"@eslint/plugin-kit@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz#fd8764f0ee79c8ddab4da65460c641cefee017c5" + integrity sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w== + dependencies: + "@eslint/core" "^0.15.2" + levn "^0.4.1" + "@floating-ui/core@^1.5.3", "@floating-ui/core@^1.6.0": version "1.6.9" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" @@ -203,6 +257,29 @@ dependencies: "@tanstack/vue-virtual" "^3.0.0-beta.60" +"@humanfs/core@^0.19.1": + version "0.19.1" + resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" + integrity sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA== + +"@humanfs/node@^0.16.6": + version "0.16.7" + resolved "https://registry.yarnpkg.com/@humanfs/node/-/node-0.16.7.tgz#822cb7b3a12c5a240a24f621b5a2413e27a45f26" + integrity sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ== + dependencies: + "@humanfs/core" "^0.19.1" + "@humanwhocodes/retry" "^0.4.0" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/retry@^0.4.0", "@humanwhocodes/retry@^0.4.2": + version "0.4.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/retry/-/retry-0.4.3.tgz#c2b9d2e374ee62c586d3adbea87199b1d7a7a6ba" + integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== + "@iconify/types@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" @@ -1420,6 +1497,11 @@ dependencies: "@types/ms" "*" +"@types/estree@^1.0.6": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + "@types/express-serve-static-core@^4.17.33": version "4.19.5" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" @@ -1476,6 +1558,11 @@ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== +"@types/json-schema@^7.0.15": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + "@types/mdast@^3.0.0": version "3.0.15" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" @@ -1898,6 +1985,11 @@ acorn-import-attributes@^1.9.5: resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + acorn-walk@^8.1.1: version "8.3.3" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" @@ -1915,6 +2007,11 @@ acorn@^8.14.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -1937,6 +2034,16 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-escapes@^4.2.1: version "4.3.2" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" @@ -1961,7 +2068,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -2310,6 +2417,14 @@ chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@^5.0.1: version "5.3.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" @@ -3034,6 +3149,13 @@ debug@4.3.4: dependencies: ms "2.1.2" +debug@^4.3.1, debug@^4.3.2: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + debug@^4.3.5, debug@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" @@ -3061,6 +3183,11 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge-ts@7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz#ff818564007f5c150808d2b7b732cac83aa415ab" @@ -3379,7 +3506,7 @@ escape-html@^1.0.3, escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-string-regexp@4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -3402,6 +3529,14 @@ eslint-plugin-prettier@^5.5.4: prettier-linter-helpers "^1.0.0" synckit "^0.11.7" +eslint-scope@^8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.4.0.tgz#88e646a207fad61436ffa39eb505147200655c82" + integrity sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" @@ -3412,11 +3547,85 @@ eslint-visitor-keys@^4.2.1: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz#4cfea60fe7dd0ad8e816e1ed026c1d5251b512c1" integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== +eslint@^9.36.0: + version "9.36.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.36.0.tgz#9cc5cbbfb9c01070425d9bfed81b4e79a1c09088" + integrity sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ== + dependencies: + "@eslint-community/eslint-utils" "^4.8.0" + "@eslint-community/regexpp" "^4.12.1" + "@eslint/config-array" "^0.21.0" + "@eslint/config-helpers" "^0.3.1" + "@eslint/core" "^0.15.2" + "@eslint/eslintrc" "^3.3.1" + "@eslint/js" "9.36.0" + "@eslint/plugin-kit" "^0.3.5" + "@humanfs/node" "^0.16.6" + "@humanwhocodes/module-importer" "^1.0.1" + "@humanwhocodes/retry" "^0.4.2" + "@types/estree" "^1.0.6" + "@types/json-schema" "^7.0.15" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.6" + debug "^4.3.2" + escape-string-regexp "^4.0.0" + eslint-scope "^8.4.0" + eslint-visitor-keys "^4.2.1" + espree "^10.4.0" + esquery "^1.5.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^8.0.0" + find-up "^5.0.0" + glob-parent "^6.0.2" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + json-stable-stringify-without-jsonify "^1.0.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + +espree@^10.0.1, espree@^10.4.0: + version "10.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.4.0.tgz#d54f4949d4629005a1fa168d937c3ff1f7e2a837" + integrity sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ== + dependencies: + acorn "^8.15.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.2.1" + +esquery@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + estree-walker@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@^1.8.1, etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" @@ -3559,6 +3768,11 @@ fast-check@^3.23.1: dependencies: pure-rand "^6.1.0" +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + fast-diff@^1.1.2: version "1.3.0" resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" @@ -3586,6 +3800,16 @@ fast-glob@^3.3.2: merge2 "^1.3.0" micromatch "^4.0.8" +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + fast-redact@^3.1.1: version "3.5.0" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" @@ -3615,6 +3839,13 @@ fecha@^4.2.0: resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd" integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== + dependencies: + flat-cache "^4.0.0" + file-saver@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" @@ -3661,7 +3892,7 @@ find-cache-dir@3.3.2: make-dir "^3.0.2" pkg-dir "^4.1.0" -find-up@5.0.0: +find-up@5.0.0, find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== @@ -3677,6 +3908,19 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +flat-cache@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== + dependencies: + flatted "^3.2.9" + keyv "^4.5.4" + +flatted@^3.2.9: + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== + fn.name@1.x.x: version "1.1.0" resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" @@ -3897,6 +4141,11 @@ global@^4.4.0: min-document "^2.19.0" process "^0.11.10" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globals@^15.14.0: version "15.15.0" resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" @@ -4136,6 +4385,11 @@ import-meta-resolve@^4.1.0: resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706" integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw== +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + indent-string@4.0.0, indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" @@ -4225,7 +4479,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4315,11 +4569,26 @@ js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + json5@^2.2.2: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -4358,6 +4627,13 @@ katex@^0.16.9: dependencies: commander "^8.3.0" +keyv@^4.5.4: + version "4.5.4" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" + integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== + dependencies: + json-buffer "3.0.1" + khroma@^2.0.0, khroma@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" @@ -4416,6 +4692,14 @@ lazystream@^1.0.0: dependencies: readable-stream "^2.0.5" +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + lilconfig@^3.0.0, lilconfig@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" @@ -4479,6 +4763,11 @@ lodash.isplainobject@^4.0.6: resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + lodash.union@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" @@ -5346,6 +5635,18 @@ open@7.4.2: is-docker "^2.0.0" is-wsl "^2.1.1" +optionator@^0.9.3: + version "0.9.4" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734" + integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.5" + p-filter@2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-2.1.0.tgz#1b1472562ae7a0f742f0f3d3d3718ea66ff9c09c" @@ -5881,6 +6182,11 @@ postgres-range@^1.1.1: resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -5992,6 +6298,11 @@ pump@^3.0.0: end-of-stream "^1.1.0" once "^1.3.1" +punycode@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" + integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== + puppeteer-core@19.11.1: version "19.11.1" resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-19.11.1.tgz#4c63d7a0a6cd268ff054ebcac315b646eee32667" @@ -6723,6 +7034,11 @@ strip-indent@3.0.0, strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + stylis@^4.1.3: version "4.3.2" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" @@ -6753,7 +7069,7 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.0.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== @@ -7020,6 +7336,13 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-fest@^0.16.0: version "0.16.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860" @@ -7128,6 +7451,13 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7300,6 +7630,11 @@ winston@^3.13.0: triple-beam "^1.3.0" winston-transport "^4.7.0" +word-wrap@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" + integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" From 973f05a02bfb2132bb4bfbcb8d47a44188053b0a Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 26 Sep 2025 16:07:01 +0000 Subject: [PATCH 08/89] update --- .prettierrc,json => .prettierrc | 2 +- prisma/seed.ts | 16 +- process.env.d.ts | 10 +- src/app.ts | 337 +++++++++++++++----------------- src/models/Document.ts | 5 +- src/models/User.ts | 227 ++++++++++----------- src/routes/socketEvents.ts | 5 +- src/server.ts | 65 +++--- src/utils/errors/BaseError.ts | 45 ++--- 9 files changed, 338 insertions(+), 374 deletions(-) rename .prettierrc,json => .prettierrc (99%) diff --git a/.prettierrc,json b/.prettierrc similarity index 99% rename from .prettierrc,json rename to .prettierrc index f2a72ff..a1312d5 100644 --- a/.prettierrc,json +++ b/.prettierrc @@ -7,4 +7,4 @@ "singleQuote": true, "trailingComma": "none", "tabWidth": 4 -} +} \ No newline at end of file diff --git a/prisma/seed.ts b/prisma/seed.ts index 61abc18..d6608bc 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -56,7 +56,9 @@ async function main() { data: { users: { connectOrCreate: allUsersGroupMembers.map((user) => ({ - where: { id: { studentGroupId: ALL_USERS_GROUP_ID, userId: user.id } }, + where: { + id: { studentGroupId: ALL_USERS_GROUP_ID, userId: user.id } + }, create: { userId: user.id } })) } @@ -68,11 +70,15 @@ async function main() { users: { connectOrCreate: [ { - where: { id: { studentGroupId: CLASS_GROUP_ID, userId: FOO_BAR_ID } }, + where: { + id: { studentGroupId: CLASS_GROUP_ID, userId: FOO_BAR_ID } + }, create: { userId: FOO_BAR_ID } }, { - where: { id: { studentGroupId: CLASS_GROUP_ID, userId: FOO_BAR_ID } }, + where: { + id: { studentGroupId: CLASS_GROUP_ID, userId: FOO_BAR_ID } + }, create: { userId: TEST_USER_ID } } ] @@ -85,7 +91,9 @@ async function main() { users: { connectOrCreate: [ { - where: { id: { studentGroupId: PROJECT_GROUP_ID, userId: FOO_BAR_ID } }, + where: { + id: { studentGroupId: PROJECT_GROUP_ID, userId: FOO_BAR_ID } + }, create: { userId: FOO_BAR_ID } } ] diff --git a/process.env.d.ts b/process.env.d.ts index c887da4..9b9e512 100644 --- a/process.env.d.ts +++ b/process.env.d.ts @@ -1,10 +1,10 @@ declare global { - namespace NodeJS { - interface ProcessEnv { - [key: string]: string | undefined; - PORT: string; + namespace NodeJS { + interface ProcessEnv { + [key: string]: string | undefined; + PORT: string; + } } - } } export {}; diff --git a/src/app.ts b/src/app.ts index 62ce8bd..19a8d88 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,28 +1,21 @@ -import express, { NextFunction, Request, Response } from "express"; -import session from "express-session"; -import prisma from "@/prisma"; -import path from "path"; -import cors from "cors"; -import morganMiddleware from "./middleware/morgan.middleware"; -import passport from "passport"; -import router from "./routes/router"; -import routeGuard, { - PUBLIC_GET_ACCESS, - PUBLIC_GET_ACCESS_REGEX, - createAccessRules, -} from "./auth/guard"; -import authConfig from "./routes/authConfig"; -import { type User } from "@prisma/client"; -import BaseError, { HttpStatusCode } from "./utils/errors/BaseError"; -import { HTTP401Error } from "./utils/errors/Errors"; -import connectPgSimple from "connect-pg-simple"; -import Logger from "./utils/logger"; -import type { - ClientToServerEvents, - ServerToClientEvents, -} from "./routes/socketEventTypes"; -import type { Server } from "socket.io"; -import { CORS_ORIGIN, SAME_SITE } from "./utils/originConfig"; +import express, { NextFunction, Request, Response } from 'express'; +import session from 'express-session'; +import prisma from '@/prisma'; +import path from 'path'; +import cors from 'cors'; +import morganMiddleware from './middleware/morgan.middleware'; +import passport from 'passport'; +import router from './routes/router'; +import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRules } from './auth/guard'; +import authConfig from './routes/authConfig'; +import { type User } from '@prisma/client'; +import BaseError, { HttpStatusCode } from './utils/errors/BaseError'; +import { HTTP401Error } from './utils/errors/Errors'; +import connectPgSimple from 'connect-pg-simple'; +import Logger from './utils/logger'; +import type { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; +import type { Server } from 'socket.io'; +import { CORS_ORIGIN, SAME_SITE } from './utils/originConfig'; const AccessRules = createAccessRules(authConfig.accessMatrix); @@ -33,7 +26,7 @@ const AccessRules = createAccessRules(authConfig.accessMatrix); */ const app = express(); -export const API_VERSION = "v1"; +export const API_VERSION = 'v1'; export const API_URL = `/api/${API_VERSION}`; /** @@ -44,20 +37,20 @@ export const API_URL = `/api/${API_VERSION}`; // ensure the server can call other domains: enable cross origin resource sharing (cors) app.use( - cors({ - credentials: true, - origin: CORS_ORIGIN, - methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"], - }) + cors({ + credentials: true, + origin: CORS_ORIGIN, + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'] + }) ); // received packages should be presented in the JSON format -app.use(express.json({ limit: "5mb" })); +app.use(express.json({ limit: '5mb' })); app.use(morganMiddleware); const store = new (connectPgSimple(session))({ - conString: process.env.DATABASE_URL, - tableName: "sessions", + conString: process.env.DATABASE_URL, + tableName: 'sessions' }); const SESSION_MAX_AGE = 2592000000 as const; // 1000 * 60 * 60 * 24 * 30 = 2592000000 = 30 days @@ -65,24 +58,24 @@ const SESSION_MAX_AGE = 2592000000 as const; // 1000 * 60 * 60 * 24 * 30 = 25920 /** make sure to have 1 (reverse) proxy in front of the application * as is the case with dokku (nginx) */ -app.set("trust proxy", 1); +app.set('trust proxy', 1); -const SESSION_KEY = `${process.env.APP_NAME || "twa"}ApiKey`; +const SESSION_KEY = `${process.env.APP_NAME || 'twa'}ApiKey`; /** https://medium.com/developer-rants/how-to-handle-sessions-properly-in-express-js-with-heroku-c35ea8c0e500 */ export const sessionMiddleware = session({ - name: SESSION_KEY /** twa stands for "TeachingWebsiteApi" */, - store: store, - secret: process.env.SESSION_SECRET || "secret", - saveUninitialized: false, - resave: false, - proxy: process.env.NODE_ENV === "production", - cookie: { - secure: process.env.NODE_ENV === "production", - httpOnly: true, - sameSite: SAME_SITE, - maxAge: SESSION_MAX_AGE, // 30 days - }, + name: SESSION_KEY /** twa stands for "TeachingWebsiteApi" */, + store: store, + secret: process.env.SESSION_SECRET || 'secret', + saveUninitialized: false, + resave: false, + proxy: process.env.NODE_ENV === 'production', + cookie: { + secure: process.env.NODE_ENV === 'production', + httpOnly: true, + sameSite: SAME_SITE, + maxAge: SESSION_MAX_AGE // 30 days + } }); // app.use(sessionMiddleware); @@ -95,175 +88,153 @@ app.use(passport.session()); // passport.use(strategyForEnvironment()); passport.serializeUser((user, done) => { - done(null, user.id); + done(null, user.id); }); -const deserializeUser = async ( - id: string, - done: (err: any, user?: User | null) => void -) => { - const user = await prisma.user.findUnique({ where: { id: id } }); - done(null, user); +const deserializeUser = async (id: string, done: (err: any, user?: User | null) => void) => { + const user = await prisma.user.findUnique({ where: { id: id } }); + done(null, user); }; passport.deserializeUser(deserializeUser); // Serve the static files to be accessed by the docs app -app.use(express.static(path.join(__dirname, "..", "docs"))); +app.use(express.static(path.join(__dirname, '..', 'docs'))); const welcomeApi = (req: Request, res: Response) => { - return res.status(200).send("Welcome to the TEACHING-WEBSITE-API V1.0"); + return res.status(200).send('Welcome to the TEACHING-WEBSITE-API V1.0'); }; // Public Endpoints app.get(`${API_URL}`, welcomeApi); -const SessionOauthStrategy = ( - req: Request, - res: Response, - next: NextFunction -) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate("oauth-bearer", { session: true })(req, res, next); +const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) => { + if (req.isAuthenticated()) { + return next(); + } + passport.authenticate('oauth-bearer', { session: true })(req, res, next); }; const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - if (req.user) { - return res.status(200).send("OK"); - } - throw new HTTP401Error(); + if (req.user) { + return res.status(200).send('OK'); + } + throw new HTTP401Error(); }; app.get(`${API_URL}/checklogin`, SessionOauthStrategy, checkLogin); const logout = async (req: Request, res: Response, next: NextFunction) => { - req.logout({ keepSessionInfo: false }, (err) => { - if (err) { - Logger.error(err); - return next(err); - } - }); - Logger.info(req.user); - Logger.info(req.session); - // await prisma.sessions.delete({ where: { sid: req.session.id } }); - res.clearCookie(SESSION_KEY).send(); + req.logout({ keepSessionInfo: false }, (err) => { + if (err) { + Logger.error(err); + return next(err); + } + }); + Logger.info(req.user); + Logger.info(req.session); + // await prisma.sessions.delete({ where: { sid: req.session.id } }); + res.clearCookie(SESSION_KEY).send(); }; app.post(`${API_URL}/logout`, logout); -const errorHandler = ( - err: Error, - req: Request, - res: Response, - next: NextFunction -) => { - if ((err as BaseError).isHttpError) { - const httpErr = err as BaseError; - res.status(httpErr.statusCode).send({ - errors: [ - { - name: httpErr.name, - message: httpErr.message, - status: httpErr.statusCode, - isOperational: httpErr.isOperational, - }, - ], - }); - } else { - res - .status(500) - .send({ errors: [{ name: err.name, message: err.message }] }); - } - Logger.error(err); +const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { + if ((err as BaseError).isHttpError) { + const httpErr = err as BaseError; + res.status(httpErr.statusCode).send({ + errors: [ + { + name: httpErr.name, + message: httpErr.message, + status: httpErr.statusCode, + isOperational: httpErr.isOperational + } + ] + }); + } else { + res.status(500).send({ errors: [{ name: err.name, message: err.message }] }); + } + Logger.error(err); }; export const configure = (_app: typeof app) => { - /** - * Notification Middleware - * when the response `res` contains a `notifications` property, the middleware will - * send the notification over SocketIO to the specififed rooms. - */ - _app.use((req: Request, res, next) => { - res.on("finish", async () => { - if (res.statusCode >= 400) { - return; - } - const io = req.io as Server; - - if (res.notifications && io) { - res.notifications.forEach((notification) => { - const except: string[] = []; - /** ignore this socket */ - if (!notification.toSelf) { - const socketID = req.headers["x-metadata-socketid"] as string; - if (socketID) { - except.push(socketID); + /** + * Notification Middleware + * when the response `res` contains a `notifications` property, the middleware will + * send the notification over SocketIO to the specififed rooms. + */ + _app.use((req: Request, res, next) => { + res.on('finish', async () => { + if (res.statusCode >= 400) { + return; + } + const io = req.io as Server; + + if (res.notifications && io) { + res.notifications.forEach((notification) => { + const except: string[] = []; + /** ignore this socket */ + if (!notification.toSelf) { + const socketID = req.headers['x-metadata-socketid'] as string; + if (socketID) { + except.push(socketID); + } + } + io.except(except) + .to(notification.to) + .emit(notification.event, notification.message as any); + }); } - } - io.except(except) - .to(notification.to) - .emit(notification.event, notification.message as any); }); - } + next(); }); - next(); - }); - /** - * API Route Guard - * This middleware will check if the user is authenticated and has the required - * permissions to access the requested route. - */ - _app.use( - `${API_URL}`, - (req, res, next) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate( - "oauth-bearer", - { session: true }, - (err: Error, user: User, info: any) => { - if (err) { - /** - * An error occurred during authorization. Send a Not Autohrized - * status code. - */ - return res - .status(HttpStatusCode.UNAUTHORIZED) - .json({ error: err.message }); - } - - if ( - !user && - !( - PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || - PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) - ) - ) { - // If no user object found, send a 401 response. - return res - .status(HttpStatusCode.UNAUTHORIZED) - .json({ error: "Unauthorized" }); - } - req.user = user; - if (info) { - // access token payload will be available in req.authInfo downstream - req.authInfo = info; - return next(); - } - } - )(req, res, next); - }, - routeGuard(AccessRules), // route guard middleware - router // the router with all the routes - ); - _app.use(errorHandler); + /** + * API Route Guard + * This middleware will check if the user is authenticated and has the required + * permissions to access the requested route. + */ + _app.use( + `${API_URL}`, + (req, res, next) => { + if (req.isAuthenticated()) { + return next(); + } + passport.authenticate('oauth-bearer', { session: true }, (err: Error, user: User, info: any) => { + if (err) { + /** + * An error occurred during authorization. Send a Not Autohrized + * status code. + */ + return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: err.message }); + } + + if ( + !user && + !( + PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || + PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) + ) + ) { + // If no user object found, send a 401 response. + return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: 'Unauthorized' }); + } + req.user = user; + if (info) { + // access token payload will be available in req.authInfo downstream + req.authInfo = info; + return next(); + } + })(req, res, next); + }, + routeGuard(AccessRules), // route guard middleware + router // the router with all the routes + ); + _app.use(errorHandler); }; -if (process.env.NODE_ENV === "test") { - configure(app); +if (process.env.NODE_ENV === 'test') { + configure(app); } export default app; diff --git a/src/models/Document.ts b/src/models/Document.ts index af1bbe4..093b38c 100644 --- a/src/models/Document.ts +++ b/src/models/Document.ts @@ -120,7 +120,10 @@ function Document(db: PrismaClient['document']) { where: actor.role === Role.ADMIN ? { id: _onBehalfOfUserId } - : { id: _onBehalfOfUserId, ...whereStudentGroupAccess(actor.id, true) } + : { + id: _onBehalfOfUserId, + ...whereStudentGroupAccess(actor.id, true) + } }); if (!onBehalfOfUser) { throw new HTTP404Error('On Behalf Of user not found or no required access'); diff --git a/src/models/User.ts b/src/models/User.ts index 1c3edac..712e76c 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -1,141 +1,128 @@ -import { Prisma, PrismaClient, User as DbUser, Role } from "@prisma/client"; -import prisma from "../prisma"; -import { HTTP403Error, HTTP404Error } from "../utils/errors/Errors"; -import { createDataExtractor } from "../helpers/dataExtractor"; -import _ from "es-toolkit/compat"; -const getData = createDataExtractor([ - "firstName", - "lastName", -]); +import { Prisma, PrismaClient, User as DbUser, Role } from '@prisma/client'; +import prisma from '../prisma'; +import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; +import { createDataExtractor } from '../helpers/dataExtractor'; +import _ from 'es-toolkit/compat'; +const getData = createDataExtractor(['firstName', 'lastName']); const RoleAccessLevel: { [key in Role]: number } = { - [Role.STUDENT]: 0, - [Role.TEACHER]: 1, - [Role.ADMIN]: 2, + [Role.STUDENT]: 0, + [Role.TEACHER]: 1, + [Role.ADMIN]: 2 }; export const getAccessLevel = (role?: Role | null) => { - if (!role) { - return 0; - } - return RoleAccessLevel[role] || 0; + if (!role) { + return 0; + } + return RoleAccessLevel[role] || 0; }; export const hasElevatedAccess = (role?: Role | null) => { - if (!role) { - return false; - } - return RoleAccessLevel[role] > 0; + if (!role) { + return false; + } + return RoleAccessLevel[role] > 0; }; export const whereStudentGroupAccess = (userId: string, isAdmin?: boolean) => ({ - studentGroups: { - some: { - studentGroup: { - users: { - some: - isAdmin === undefined - ? { userId } - : { - userId, - isAdmin, - }, - }, - }, - }, - }, + studentGroups: { + some: { + studentGroup: { + users: { + some: + isAdmin === undefined + ? { userId } + : { + userId, + isAdmin + } + } + } + } + } }); -function User(db: PrismaClient["user"]) { - return Object.assign(db, { - async findModel(id: string): Promise { - return db.findUnique({ where: { id } }); - }, - - async updateModel( - actor: DbUser, - id: string, - data: Partial - ): Promise { - const record = await db.findUnique({ where: { id: id } }); - if (!record) { - throw new HTTP404Error("User not found"); - } - const elevatedAccess = hasElevatedAccess(actor.role); - if (!(record.id === actor.id || elevatedAccess)) { - throw new HTTP403Error("Not authorized"); - } - if (data.role && data.role !== record.role) { - await this.setRole(actor, id, data.role as Role); - } - /** remove fields not updatable*/ - const sanitized = getData( - data, - false, - record.id === actor.id ? false : elevatedAccess - ); - return db.update({ - where: { - id: id, +function User(db: PrismaClient['user']) { + return Object.assign(db, { + async findModel(id: string): Promise { + return db.findUnique({ where: { id } }); }, - data: sanitized, - }); - }, - async all(actor: DbUser): Promise { - if (hasElevatedAccess(actor.role)) { - /** - * Admins and teachers can see all users. - * Reason: teachers need to add new users to their student groups - */ - return db.findMany({}); - } - const users = await db.findMany({ - where: { - OR: [ - { - id: actor.id, - }, - whereStudentGroupAccess(actor.id), - ], + async updateModel(actor: DbUser, id: string, data: Partial): Promise { + const record = await db.findUnique({ where: { id: id } }); + if (!record) { + throw new HTTP404Error('User not found'); + } + const elevatedAccess = hasElevatedAccess(actor.role); + if (!(record.id === actor.id || elevatedAccess)) { + throw new HTTP403Error('Not authorized'); + } + if (data.role && data.role !== record.role) { + await this.setRole(actor, id, data.role as Role); + } + /** remove fields not updatable*/ + const sanitized = getData(data, false, record.id === actor.id ? false : elevatedAccess); + return db.update({ + where: { + id: id + }, + data: sanitized + }); }, - distinct: ["id"], - }); - return users; - }, - async setRole(actor: DbUser, userId: string, role: Role): Promise { - if (!hasElevatedAccess(actor.role)) { - throw new HTTP403Error("Not authorized"); - } - const actorLevel = RoleAccessLevel[actor.role]; - const roleLevel = RoleAccessLevel[role]; - if (roleLevel > actorLevel) { - throw new HTTP403Error("Not allowed to set a higher role"); - } - if (actor.id === userId && roleLevel < actorLevel) { - throw new HTTP403Error("Not allowed to lower own role"); - } - const record = await this.findModel(userId); - if (!record) { - throw new HTTP404Error("User not found"); - } - const recordLevel = RoleAccessLevel[record.role]; - if (actorLevel < recordLevel) { - throw new HTTP403Error( - "Not allowed to change the role of user with a higher role" - ); - } - return db.update({ - where: { - id: userId, - }, - data: { - role: role, + async all(actor: DbUser): Promise { + if (hasElevatedAccess(actor.role)) { + /** + * Admins and teachers can see all users. + * Reason: teachers need to add new users to their student groups + */ + return db.findMany({}); + } + const users = await db.findMany({ + where: { + OR: [ + { + id: actor.id + }, + whereStudentGroupAccess(actor.id) + ] + }, + distinct: ['id'] + }); + return users; }, - }); - }, - }); + + async setRole(actor: DbUser, userId: string, role: Role): Promise { + if (!hasElevatedAccess(actor.role)) { + throw new HTTP403Error('Not authorized'); + } + const actorLevel = RoleAccessLevel[actor.role]; + const roleLevel = RoleAccessLevel[role]; + if (roleLevel > actorLevel) { + throw new HTTP403Error('Not allowed to set a higher role'); + } + if (actor.id === userId && roleLevel < actorLevel) { + throw new HTTP403Error('Not allowed to lower own role'); + } + const record = await this.findModel(userId); + if (!record) { + throw new HTTP404Error('User not found'); + } + const recordLevel = RoleAccessLevel[record.role]; + if (actorLevel < recordLevel) { + throw new HTTP403Error('Not allowed to change the role of user with a higher role'); + } + return db.update({ + where: { + id: userId + }, + data: { + role: role + } + }); + } + }); } export default User(prisma.user); diff --git a/src/routes/socketEvents.ts b/src/routes/socketEvents.ts index 6fa84ad..27fb68e 100644 --- a/src/routes/socketEvents.ts +++ b/src/routes/socketEvents.ts @@ -28,7 +28,10 @@ const EventRouter = (io: Server) => const rooms = [...io.sockets.adapter.rooms.keys()].map( (id) => [id, io.sockets.adapter.rooms.get(id)?.size || 0] as [string, number] ); - io.to(IoRoom.ADMIN).emit(IoEvent.CONNECTED_CLIENTS, { rooms: rooms, type: 'full' }); + io.to(IoRoom.ADMIN).emit(IoEvent.CONNECTED_CLIENTS, { + rooms: rooms, + type: 'full' + }); } if (hasElevatedAccess(user.role)) { socket.on(IoClientEvent.ACTION, onAction(user, socket)); diff --git a/src/server.ts b/src/server.ts index 1012aaa..1bbb6cb 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,32 +1,29 @@ -import "./instrumentation"; -import app, { configure, sessionMiddleware } from "./app"; -import http from "http"; -import Logger from "@/utils/logger"; -import { Server } from "socket.io"; -import { - ClientToServerEvents, - ServerToClientEvents, -} from "./routes/socketEventTypes"; -import passport from "passport"; -import EventRouter from "./routes/socketEvents"; -import type { NextFunction, Request, Response } from "express"; -import { HTTP403Error } from "./utils/errors/Errors"; -import { CORS_ORIGIN } from "./utils/originConfig"; -import * as Sentry from "@sentry/node"; +import './instrumentation'; +import app, { configure, sessionMiddleware } from './app'; +import http from 'http'; +import Logger from '@/utils/logger'; +import { Server } from 'socket.io'; +import { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; +import passport from 'passport'; +import EventRouter from './routes/socketEvents'; +import type { NextFunction, Request, Response } from 'express'; +import { HTTP403Error } from './utils/errors/Errors'; +import { CORS_ORIGIN } from './utils/originConfig'; +import * as Sentry from '@sentry/node'; const PORT = process.env.PORT || 3002; const server = http.createServer(app); const io = new Server(server, { - cors: { - origin: CORS_ORIGIN, - credentials: true, - methods: ["GET", "POST", "PUT", "DELETE"], - }, - pingInterval: 15_000, - pingTimeout: 20_000, - transports: ["websocket", "webtransport" /* , 'polling' */], + cors: { + origin: CORS_ORIGIN, + credentials: true, + methods: ['GET', 'POST', 'PUT', 'DELETE'] + }, + pingInterval: 15_000, + pingTimeout: 20_000, + transports: ['websocket', 'webtransport' /* , 'polling' */] }); // convert a connect middleware to a Socket.IO middleware @@ -56,26 +53,26 @@ EventRouter(io); // only allow authenticated users in socketio io.use((socket, next) => { - if ((socket.request as any).user) { - next(); - } else { - next(new HTTP403Error("unauthorized")); - } + if ((socket.request as any).user) { + next(); + } else { + next(new HTTP403Error('unauthorized')); + } }); // Make io accessible to our router app.use((req: Request, res, next) => { - req.io = io; - next(); + req.io = io; + next(); }); configure(app); -if (process.env.NODE_ENV === "production" && process.env.SENTRY_DSN) { - Sentry.setupExpressErrorHandler(app); +if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) { + Sentry.setupExpressErrorHandler(app); } server.listen(PORT || 3002, () => { - Logger.info(`application is running at: http://localhost:${PORT}`); - Logger.info("Press Ctrl+C to quit."); + Logger.info(`application is running at: http://localhost:${PORT}`); + Logger.info('Press Ctrl+C to quit.'); }); diff --git a/src/utils/errors/BaseError.ts b/src/utils/errors/BaseError.ts index 9b7890c..60b0abe 100644 --- a/src/utils/errors/BaseError.ts +++ b/src/utils/errors/BaseError.ts @@ -1,32 +1,27 @@ export enum HttpStatusCode { - OK = 200, - BAD_REQUEST = 400, - UNAUTHORIZED = 401, - FORBIDDEN = 403, - NOT_FOUND = 404, - INTERNAL_SERVER = 500, + OK = 200, + BAD_REQUEST = 400, + UNAUTHORIZED = 401, + FORBIDDEN = 403, + NOT_FOUND = 404, + INTERNAL_SERVER = 500 } export default class BaseError extends Error { - public readonly isHttpError = true; - public readonly name: string; - public readonly statusCode: HttpStatusCode; - public readonly isOperational: boolean; - public readonly cause: string; + public readonly isHttpError = true; + public readonly name: string; + public readonly statusCode: HttpStatusCode; + public readonly isOperational: boolean; + public readonly cause: string; - constructor( - name: string, - httpCode: HttpStatusCode, - description: string, - isOperational: boolean - ) { - super(`[${httpCode}] ${description}`); - Object.setPrototypeOf(this, new.target.prototype); - this.cause = description; - this.name = name; - this.statusCode = httpCode; - this.isOperational = isOperational; + constructor(name: string, httpCode: HttpStatusCode, description: string, isOperational: boolean) { + super(`[${httpCode}] ${description}`); + Object.setPrototypeOf(this, new.target.prototype); + this.cause = description; + this.name = name; + this.statusCode = httpCode; + this.isOperational = isOperational; - Error.captureStackTrace(this); - } + Error.captureStackTrace(this); + } } From 13eae8b74e6ec9c57bcd5eef2a5b81efa795b853 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 26 Sep 2025 17:48:18 +0000 Subject: [PATCH 09/89] update ts --- package.json | 4 ++-- yarn.lock | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 8f8d645..a66581e 100644 --- a/package.json +++ b/package.json @@ -66,10 +66,10 @@ "ts-node": "^10.9.2", "tsc-alias": "^1.8.16", "tsconfig-paths": "^4.2.0", - "typescript": "^5.5.4", + "typescript": "^5.9.2", "typescript-transform-paths": "^3.5.5" }, "engines": { "node": "^22.11.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index df9b66f..5c90c12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7392,10 +7392,10 @@ typescript-transform-paths@^3.5.5: dependencies: minimatch "^9.0.5" -typescript@^5.5.4: - version "5.5.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.4.tgz#d9852d6c82bad2d2eda4fd74a5762a8f5909e9ba" - integrity sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q== +typescript@^5.9.2: + version "5.9.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" + integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== ufo@^1.5.4: version "1.6.1" From c7a746606cf93ce3e3cc15ca844a1ca2ff594bcc Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 26 Sep 2025 17:57:43 +0000 Subject: [PATCH 10/89] remove passport, use any as user --- package.json | 5 +- src/app.ts | 104 +++++----- src/auth/azureAD.ts | 14 +- src/auth/guard.ts | 4 +- src/auth/mock.ts | 8 +- src/controllers/cmsSettings.ts | 12 +- src/controllers/documentRoots.ts | 16 +- src/controllers/documents.ts | 25 ++- src/controllers/rootGroupPermissions.ts | 6 +- src/controllers/rootUserPermissions.ts | 6 +- src/controllers/studentGroups.ts | 16 +- src/controllers/users.ts | 6 +- src/server.ts | 2 +- yarn.lock | 247 +----------------------- 14 files changed, 122 insertions(+), 349 deletions(-) diff --git a/package.json b/package.json index a66581e..439b945 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,6 @@ "express-session": "^1.18.2", "global": "^4.4.0", "morgan": "^1.10.0", - "passport": "^0.7.0", - "passport-azure-ad": "^4.3.5", "socket.io": "^4.8.1", "winston": "^3.13.0" }, @@ -50,7 +48,6 @@ "@types/express": "^5.0.3", "@types/morgan": "^1.9.9", "@types/node": "^20.14.6", - "@types/passport-azure-ad": "^4.3.6", "@typescript-eslint/eslint-plugin": "^8.44.1", "@typescript-eslint/parser": "^8.44.1", "dotenv-cli": "^7.4.2", @@ -72,4 +69,4 @@ "engines": { "node": "^22.11.0" } -} +} \ No newline at end of file diff --git a/src/app.ts b/src/app.ts index 19a8d88..88b95ce 100644 --- a/src/app.ts +++ b/src/app.ts @@ -4,7 +4,7 @@ import prisma from '@/prisma'; import path from 'path'; import cors from 'cors'; import morganMiddleware from './middleware/morgan.middleware'; -import passport from 'passport'; +// import passport from 'passport'; import router from './routes/router'; import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRules } from './auth/guard'; import authConfig from './routes/authConfig'; @@ -83,20 +83,20 @@ export const sessionMiddleware = session({ // app.use(passport.initialize()); /** alias for passport.authenticate('session'); e.g. to use the session... */ -app.use(passport.session()); +// app.use(passport.session()); -// passport.use(strategyForEnvironment()); +// // passport.use(strategyForEnvironment()); -passport.serializeUser((user, done) => { - done(null, user.id); -}); +// passport.serializeUser((user, done) => { +// done(null, user.id); +// }); const deserializeUser = async (id: string, done: (err: any, user?: User | null) => void) => { const user = await prisma.user.findUnique({ where: { id: id } }); done(null, user); }; -passport.deserializeUser(deserializeUser); +// passport.deserializeUser(deserializeUser); // Serve the static files to be accessed by the docs app app.use(express.static(path.join(__dirname, '..', 'docs'))); @@ -109,30 +109,30 @@ const welcomeApi = (req: Request, res: Response) => { app.get(`${API_URL}`, welcomeApi); const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate('oauth-bearer', { session: true })(req, res, next); + return next(); + // if (req.isAuthenticated()) { + // } + // passport.authenticate('oauth-bearer', { session: true })(req, res, next); }; const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - if (req.user) { - return res.status(200).send('OK'); - } - throw new HTTP401Error(); + return res.status(200).send('OK'); + // if (req.user) { + // } + // throw new HTTP401Error(); }; app.get(`${API_URL}/checklogin`, SessionOauthStrategy, checkLogin); const logout = async (req: Request, res: Response, next: NextFunction) => { - req.logout({ keepSessionInfo: false }, (err) => { - if (err) { - Logger.error(err); - return next(err); - } - }); - Logger.info(req.user); - Logger.info(req.session); + // req.logout({ keepSessionInfo: false }, (err) => { + // if (err) { + // Logger.error(err); + // return next(err); + // } + // }); + // Logger.info(req.user); + // Logger.info(req.session); // await prisma.sessions.delete({ where: { sid: req.session.id } }); res.clearCookie(SESSION_KEY).send(); }; @@ -197,35 +197,35 @@ export const configure = (_app: typeof app) => { _app.use( `${API_URL}`, (req, res, next) => { - if (req.isAuthenticated()) { - return next(); - } - passport.authenticate('oauth-bearer', { session: true }, (err: Error, user: User, info: any) => { - if (err) { - /** - * An error occurred during authorization. Send a Not Autohrized - * status code. - */ - return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: err.message }); - } - - if ( - !user && - !( - PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || - PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) - ) - ) { - // If no user object found, send a 401 response. - return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: 'Unauthorized' }); - } - req.user = user; - if (info) { - // access token payload will be available in req.authInfo downstream - req.authInfo = info; - return next(); - } - })(req, res, next); + return next(); + // if (req.isAuthenticated()) { + // } + // passport.authenticate('oauth-bearer', { session: true }, (err: Error, user: User, info: any) => { + // if (err) { + // /** + // * An error occurred during authorization. Send a Not Autohrized + // * status code. + // */ + // return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: err.message }); + // } + + // if ( + // !user && + // !( + // PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || + // PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) + // ) + // ) { + // // If no user object found, send a 401 response. + // return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: 'Unauthorized' }); + // } + // req.user = user; + // if (info) { + // // access token payload will be available in req.authInfo downstream + // req.authInfo = info; + // return next(); + // } + // })(req, res, next); }, routeGuard(AccessRules), // route guard middleware router // the router with all the routes diff --git a/src/auth/azureAD.ts b/src/auth/azureAD.ts index 1418d7c..36a7ed7 100644 --- a/src/auth/azureAD.ts +++ b/src/auth/azureAD.ts @@ -1,5 +1,5 @@ import prisma from '../prisma'; -import { BearerStrategy, IBearerStrategyOptionWithRequest, VerifyBearerFunction } from 'passport-azure-ad'; +// import { BearerStrategy, IBearerStrategyOptionWithRequest, VerifyBearerFunction } from 'passport-azure-ad'; import { getAuthInfo, userProps } from '../helpers/authInfo'; import authConfig from '../routes/authConfig'; import Logger from '../utils/logger'; @@ -17,7 +17,7 @@ const auth = { loggingLevel: authConfig.settings.loggingLevel }; -const options: IBearerStrategyOptionWithRequest = { +const options = { identityMetadata: `https://${auth.authority}/${auth.tenantID}/${auth.version}/${auth.discovery}`, issuer: `https://${auth.authority}/${auth.tenantID}/${auth.version}`, clientID: auth.clientID, @@ -29,7 +29,7 @@ const options: IBearerStrategyOptionWithRequest = { scope: auth.scope }; -const BearerVerify: VerifyBearerFunction = async (token, done) => { +const BearerVerify = async (token: any, done: any) => { const { oid } = getAuthInfo(token); // @link https://medium.com/@prashantramnyc/node-js-with-passport-authentication-simplified-76ca65ee91e5 const user = await prisma.user @@ -46,7 +46,7 @@ const BearerVerify: VerifyBearerFunction = async (token, done) => { done(null, user, token); }; -export const getStrategy = () => { - const strategy = new BearerStrategy(options, BearerVerify); - return strategy; -}; +// export const getStrategy = () => { +// const strategy = new BearerStrategy(options, BearerVerify); +// return strategy; +// }; diff --git a/src/auth/guard.ts b/src/auth/guard.ts index 76c608d..c4d51b2 100644 --- a/src/auth/guard.ts +++ b/src/auth/guard.ts @@ -77,13 +77,13 @@ const routeGuard = (accessMatrix: AccessRegexRule[]) => { const reqPath = req.path.toLowerCase(); /* istanbul ignore if */ if ( - !req.user && + !(req as any).user && !(PUBLIC_GET_ACCESS.has(reqPath) || PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(reqPath))) ) { return res.status(HttpStatusCode.FORBIDDEN).json({ error: 'No roles claim found!' }); } - if (!requestHasRequiredAttributes(accessMatrix, req.path, req.method, req.user?.role)) { + if (!requestHasRequiredAttributes(accessMatrix, req.path, req.method, (req as any).user?.role)) { return res .status(HttpStatusCode.FORBIDDEN) .json({ error: 'User does not have the role, method or path' }); diff --git a/src/auth/mock.ts b/src/auth/mock.ts index d831e51..4079548 100644 --- a/src/auth/mock.ts +++ b/src/auth/mock.ts @@ -1,17 +1,17 @@ /* istanbul ignore file */ import { Request } from 'express'; import { ParamsDictionary } from 'express-serve-static-core'; -import { Strategy, StrategyCreated, StrategyCreatedStatic } from 'passport'; +// import { Strategy, StrategyCreated, StrategyCreatedStatic } from 'passport'; import { ParsedQs } from 'qs'; import prisma from '../prisma'; import Logger from '../utils/logger'; -class MockStrat extends Strategy { +class MockStrat { name = 'oauth-bearer'; constructor() { - super(); + // super(); } async authenticate( - this: StrategyCreated, + this: any, req: Request>, options?: any ) { diff --git a/src/controllers/cmsSettings.ts b/src/controllers/cmsSettings.ts index 9342ad9..43861a6 100644 --- a/src/controllers/cmsSettings.ts +++ b/src/controllers/cmsSettings.ts @@ -4,17 +4,17 @@ import { ChangedRecord, IoEvent, RecordType } from '../routes/socketEventTypes'; import { CmsSettings as DbCmsSettings } from '@prisma/client'; export const find: RequestHandler = async (req, res, next) => { - const settings = await CmsSettings.findModel(req.user!); + const settings = await CmsSettings.findModel((req as any).user!); res.json(settings); }; export const update: RequestHandler> = async (req, res, next) => { - await CmsSettings.updateModel(req.user!, req.body); + await CmsSettings.updateModel((req as any).user!, req.body); res.status(204).send(); }; export const logout: RequestHandler> = async (req, res, next) => { - const model = await CmsSettings.logout(req.user!); + const model = await CmsSettings.logout((req as any).user!); if (!model) { res.status(204).send(); return; @@ -27,7 +27,7 @@ export const logout: RequestHandler> = async (r { event: IoEvent.CHANGED_RECORD, message: change, - to: [req.user!.id] + to: [(req as any).user!.id] } ]; @@ -36,7 +36,7 @@ export const logout: RequestHandler> = async (r export const githubToken: RequestHandler = async (req, res, next) => { const { code } = req.query; - const model = await CmsSettings.fetchToken(req.user!.id, code); + const model = await CmsSettings.fetchToken((req as any).user!.id, code); const change: ChangedRecord = { type: RecordType.CmsSettings, @@ -46,7 +46,7 @@ export const githubToken: RequestHandler = asyn { event: IoEvent.CHANGED_RECORD, message: change, - to: [req.user!.id] + to: [(req as any).user!.id] } ]; res.status(200).json(model); diff --git a/src/controllers/documentRoots.ts b/src/controllers/documentRoots.ts index bf58e1b..c6f05ac 100644 --- a/src/controllers/documentRoots.ts +++ b/src/controllers/documentRoots.ts @@ -8,7 +8,7 @@ import { NoneAccess, RO_RW_DocumentRootAccess } from '../helpers/accessPolicy'; import { hasElevatedAccess } from '../models/User'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - const document = await DocumentRoot.findModel(req.user!, req.params.id); + const document = await DocumentRoot.findModel((req as any).user!, req.params.id); res.json(document); }; @@ -17,7 +17,7 @@ export const findMany: RequestHandler = async if (ids.length === 0) { return res.json([]); } - const documents = await DocumentRoot.findManyModels(req.user!.id, ids); + const documents = await DocumentRoot.findManyModels((req as any).user!.id, ids); res.json(documents); }; @@ -30,7 +30,7 @@ export const findManyFor: RequestHandler< if (!req.params.id) { throw new HTTP400Error('Missing user id'); } - const canLoad = req.user!.id === req.params.id || hasElevatedAccess(req.user?.role); + const canLoad = (req as any).user!.id === req.params.id || hasElevatedAccess((req as any).user?.role); if (!canLoad) { throw new HTTP403Error('Not Authorized'); } @@ -43,14 +43,14 @@ export const findManyFor: RequestHandler< }; export const allDocuments: RequestHandler = async (req, res, next) => { - if (!hasElevatedAccess(req.user!.role)) { + if (!hasElevatedAccess((req as any).user!.role)) { throw new HTTP403Error('Not Authorized'); } const ids = Array.isArray(req.query.rids) ? req.query.rids : [req.query.rids]; if (ids.length === 0) { return res.json([]); } - const documents = await Document.allOfDocumentRoots(req.user!, ids); + const documents = await Document.allOfDocumentRoots((req as any).user!, ids); res.json(documents); }; @@ -77,7 +77,7 @@ export const create: RequestHandler<{ id: string }, any, CreateConfig | undefine { event: IoEvent.NEW_RECORD, message: { type: RecordType.DocumentRoot, record: documentRoot }, - to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + to: [...groupIds, ...userIds, sharedAccess, (req as any).user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving } ]; res.json(documentRoot); @@ -106,12 +106,12 @@ export const update: RequestHandler<{ id: string }, any, UpdateConfig> = async ( }; export const permissions: RequestHandler<{ id: string }> = async (req, res, next) => { - const permissions = await DocumentRoot.getPermissions(req.user!, req.params.id); + const permissions = await DocumentRoot.getPermissions((req as any).user!, req.params.id); res.json(permissions); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - const model = await DocumentRoot.deleteModel(req.user!, req.params.id); + const model = await DocumentRoot.deleteModel((req as any).user!, req.params.id); res.notifications = [ { diff --git a/src/controllers/documents.ts b/src/controllers/documents.ts index 37605e5..bbb3f0c 100644 --- a/src/controllers/documents.ts +++ b/src/controllers/documents.ts @@ -9,7 +9,7 @@ import prisma from '../prisma'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - const document = await Document.findModel(req.user!, req.params.id); + const document = await Document.findModel((req as any).user!, req.params.id); res.json(document); }; @@ -23,7 +23,7 @@ export const create: RequestHandler< const { onBehalfOf, uniqueMain } = req.query; const onBehalfUserId = onBehalfOf === 'true' ? req.body.authorId : undefined; const { model, permissions } = await Document.createModel( - req.user!, + (req as any).user!, type, documentRootId, data, @@ -44,7 +44,7 @@ export const create: RequestHandler< { event: IoEvent.NEW_RECORD, message: { type: RecordType.Document, record: model }, - to: [...groupIds, ...userIds, sharedAccess, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving, + to: [...groupIds, ...userIds, sharedAccess, (req as any).user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving, } ]; res.status(200).json(model); @@ -57,7 +57,12 @@ export const update: RequestHandler< { onBehalfOf?: 'true' } > = async (req, res, next) => { const { onBehalfOf } = req.query; - const model = await Document.updateModel(req.user!, req.params.id, req.body.data, onBehalfOf === 'true'); + const model = await Document.updateModel( + (req as any).user!, + req.params.id, + req.body.data, + onBehalfOf === 'true' + ); /** * Notifications to * - the user who updated the document @@ -81,7 +86,7 @@ export const update: RequestHandler< { event: IoEvent.CHANGED_DOCUMENT, message: change, - to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, (req as any).user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving } ]; @@ -111,7 +116,7 @@ export const linkTo: RequestHandler<{ id: string; parentId: string }, any, any> if (req.params.id === req.params.parentId) { throw new HTTP403Error('Not allowed to link to self'); } - const current = await Document.findModel(req.user!, req.params.id); + const current = await Document.findModel((req as any).user!, req.params.id); if (!current || !RWAccess.has(current.highestPermission)) { throw new HTTP404Error('Model not found'); } @@ -121,7 +126,7 @@ export const linkTo: RequestHandler<{ id: string; parentId: string }, any, any> "No circular links allowed (trying to link a document to one of it's children)" ); } - const linkTo = await Document.findModel(req.user!, req.params.parentId); + const linkTo = await Document.findModel((req as any).user!, req.params.parentId); if (!linkTo || NoneAccess.has(linkTo.highestPermission)) { throw new HTTP404Error('Model linking to not found'); } @@ -188,7 +193,7 @@ export const linkTo: RequestHandler<{ id: string; parentId: string }, any, any> type: RecordType.Document, record: updated }, - to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + to: [...groupIds, ...sharedAccess, ...userIds, IoRoom.ADMIN, (req as any).user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving } ]; @@ -196,7 +201,7 @@ export const linkTo: RequestHandler<{ id: string; parentId: string }, any, any> }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - const model = await Document.deleteModel(req.user!, req.params.id); + const model = await Document.deleteModel((req as any).user!, req.params.id); const groupIds = model.documentRoot.rootGroupPermissions .filter((p) => !NoneAccess.has(p.access)) @@ -209,7 +214,7 @@ export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { event: IoEvent.DELETED_RECORD, message: { type: RecordType.Document, id: model.id }, - to: [...groupIds, ...userIds, ...sharedAccess, IoRoom.ADMIN, req.user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving + to: [...groupIds, ...userIds, ...sharedAccess, IoRoom.ADMIN, (req as any).user!.id] // overlappings are handled by socket.io: https://socket.io/docs/v3/rooms/#joining-and-leaving } ]; res.status(204).send(); diff --git a/src/controllers/rootGroupPermissions.ts b/src/controllers/rootGroupPermissions.ts index 995f078..a9f6c17 100644 --- a/src/controllers/rootGroupPermissions.ts +++ b/src/controllers/rootGroupPermissions.ts @@ -15,7 +15,7 @@ export const create: RequestHandler< throw new HTTP400Error('Missing documentRootId, groupId or access'); } - const model = await RootGroupPermission.createModel(req.user!, documentRootId, groupId, access); + const model = await RootGroupPermission.createModel((req as any).user!, documentRootId, groupId, access); res.notifications = [ { @@ -28,7 +28,7 @@ export const create: RequestHandler< }; export const update: RequestHandler<{ id: string }, any, { access: Access }> = async (req, res, next) => { - const model = await RootGroupPermission.updateModel(req.user!, req.params.id, req.body.access); + const model = await RootGroupPermission.updateModel((req as any).user!, req.params.id, req.body.access); res.notifications = [ { @@ -41,7 +41,7 @@ export const update: RequestHandler<{ id: string }, any, { access: Access }> = a }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - const model = await RootGroupPermission.deleteModel(req.user!, req.params.id); + const model = await RootGroupPermission.deleteModel((req as any).user!, req.params.id); res.notifications = [ { diff --git a/src/controllers/rootUserPermissions.ts b/src/controllers/rootUserPermissions.ts index c60270a..04e0508 100644 --- a/src/controllers/rootUserPermissions.ts +++ b/src/controllers/rootUserPermissions.ts @@ -16,7 +16,7 @@ export const create: RequestHandler< throw new HTTP400Error('Missing documentRootId, userId or access'); } - const model = await RootUserPermission.createModel(req.user!, documentRootId, userId, access); + const model = await RootUserPermission.createModel((req as any).user!, documentRootId, userId, access); res.notifications = [ { @@ -32,7 +32,7 @@ export const update: RequestHandler<{ id: string }, any, { access: Access }> = a if (!req.params.id) { throw new HTTP400Error('Missing id'); } - const model = await RootUserPermission.updateModel(req.user!, req.params.id, req.body.access); + const model = await RootUserPermission.updateModel((req as any).user!, req.params.id, req.body.access); res.notifications = [ { @@ -48,7 +48,7 @@ export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => if (!req.params.id) { throw new HTTP400Error('Missing id'); } - const model = await RootUserPermission.deleteModel(req.user!, req.params.id); + const model = await RootUserPermission.deleteModel((req as any).user!, req.params.id); res.notifications = [ { diff --git a/src/controllers/studentGroups.ts b/src/controllers/studentGroups.ts index bce1dba..0349a03 100644 --- a/src/controllers/studentGroups.ts +++ b/src/controllers/studentGroups.ts @@ -4,13 +4,13 @@ import StudentGroup from '../models/StudentGroup'; import { IoEvent, RecordType } from '../routes/socketEventTypes'; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { - const group = await StudentGroup.findModel(req.user!, req.params.id); + const group = await StudentGroup.findModel((req as any).user!, req.params.id); res.json(group); }; export const create: RequestHandler = async (req, res, next) => { const { name, description, parentId } = req.body; - const model = await StudentGroup.createModel(req.user!, name, description, parentId); + const model = await StudentGroup.createModel((req as any).user!, name, description, parentId); res.status(200).json(model); }; @@ -19,7 +19,7 @@ export const update: RequestHandler<{ id: string }, any, { data: DbStudentGroup res, next ) => { - const model = await StudentGroup.updateModel(req.user!, req.params.id, req.body.data); + const model = await StudentGroup.updateModel((req as any).user!, req.params.id, req.body.data); if (!model) { return res.status(404).json({ message: 'Student group not found' }); } @@ -43,7 +43,7 @@ export const setAdminRole: RequestHandler<{ id: string; userId: string }, any, { next ) => { const model = await StudentGroup.setAdminRole( - req.user!, + (req as any).user!, req.params.id, req.params.userId, req.body.isAdmin @@ -62,7 +62,7 @@ export const setAdminRole: RequestHandler<{ id: string; userId: string }, any, { }; export const addUser: RequestHandler<{ id: string; userId: string }, any, any> = async (req, res, next) => { - const model = await StudentGroup.addUser(req.user!, req.params.id, req.params.userId); + const model = await StudentGroup.addUser((req as any).user!, req.params.id, req.params.userId); res.notifications = [ { event: IoEvent.CHANGED_RECORD, @@ -89,7 +89,7 @@ export const removeUser: RequestHandler<{ id: string; userId: string }, any, any res, next ) => { - const model = await StudentGroup.removeUser(req.user!, req.params.id, req.params.userId); + const model = await StudentGroup.removeUser((req as any).user!, req.params.id, req.params.userId); res.notifications = [ { event: IoEvent.CHANGED_RECORD, @@ -112,12 +112,12 @@ export const removeUser: RequestHandler<{ id: string; userId: string }, any, any }; export const all: RequestHandler = async (req, res, next) => { - const users = await StudentGroup.all(req.user!); + const users = await StudentGroup.all((req as any).user!); res.json(users); }; export const destroy: RequestHandler<{ id: string }> = async (req, res, next) => { - const group = await StudentGroup.deleteModel(req.user!, req.params.id); + const group = await StudentGroup.deleteModel((req as any).user!, req.params.id); res.notifications = [ { event: IoEvent.DELETED_RECORD, diff --git a/src/controllers/users.ts b/src/controllers/users.ts index f9fa897..5e92ce0 100644 --- a/src/controllers/users.ts +++ b/src/controllers/users.ts @@ -4,7 +4,7 @@ import User from '../models/User'; import Logger from '../utils/logger'; export const user: RequestHandler = async (req, res) => { - res.json(req.user); + res.json((req as any).user); }; export const find: RequestHandler<{ id: string }> = async (req, res, next) => { @@ -13,11 +13,11 @@ export const find: RequestHandler<{ id: string }> = async (req, res, next) => { }; export const update: RequestHandler<{ id: string }, any, { data: DbUser }> = async (req, res, next) => { - const model = await User.updateModel(req.user!, req.params.id, req.body.data); + const model = await User.updateModel((req as any).user!, req.params.id, req.body.data); res.status(200).json(model); }; export const all: RequestHandler = async (req, res, next) => { - const users = await User.all(req.user!); + const users = await User.all((req as any).user!); res.json(users); }; diff --git a/src/server.ts b/src/server.ts index 1bbb6cb..9d464e1 100644 --- a/src/server.ts +++ b/src/server.ts @@ -4,7 +4,7 @@ import http from 'http'; import Logger from '@/utils/logger'; import { Server } from 'socket.io'; import { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; -import passport from 'passport'; +// import passport from 'passport'; import EventRouter from './routes/socketEvents'; import type { NextFunction, Request, Response } from 'express'; import { HTTP403Error } from './utils/errors/Errors'; diff --git a/yarn.lock b/yarn.lock index 5c90c12..7dafb98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1625,21 +1625,6 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA== -"@types/passport-azure-ad@^4.3.6": - version "4.3.6" - resolved "https://registry.yarnpkg.com/@types/passport-azure-ad/-/passport-azure-ad-4.3.6.tgz#f0dd11cb29a41c169f94e1e7e7bc8d07d192f0b1" - integrity sha512-1/CWGFAtsG/5wPk8nGpEIPMiIz/X/IYNjLJVL4Kl5WyGFMdjml0GG1kw82SkY+8tW1RUi4b9mangemJ0qVTLNg== - dependencies: - "@types/express" "*" - "@types/passport" "*" - -"@types/passport@*": - version "1.0.16" - resolved "https://registry.yarnpkg.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf" - integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A== - dependencies: - "@types/express" "*" - "@types/pg-pool@2.0.6": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/pg-pool/-/pg-pool-2.0.6.tgz#1376d9dc5aec4bb2ec67ce28d7e9858227403c77" @@ -2178,11 +2163,6 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -async@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9" - integrity sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g== - async@^3.2.3: version "3.2.5" resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" @@ -2208,11 +2188,6 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -base64url@^3.0.0, base64url@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" - integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== - basic-auth@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" @@ -2294,11 +2269,6 @@ buffer-crc32@^0.2.1, buffer-crc32@^0.2.13, buffer-crc32@~0.2.3: resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== -buffer-equal-constant-time@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" - integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA== - buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -2315,16 +2285,6 @@ buffer@^6.0.3: base64-js "^1.3.1" ieee754 "^1.2.1" -bunyan@^1.8.14: - version "1.8.15" - resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.15.tgz#8ce34ca908a17d0776576ca1b2f6cbd916e93b46" - integrity sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig== - optionalDependencies: - dtrace-provider "~0.8" - moment "^2.19.3" - mv "~2" - safe-json-stringify "~1" - bytes@3.1.2, bytes@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -2348,15 +2308,6 @@ c12@3.1.0: pkg-types "^2.2.0" rc9 "^2.1.2" -cache-manager@^3.6.1: - version "3.6.3" - resolved "https://registry.yarnpkg.com/cache-manager/-/cache-manager-3.6.3.tgz#48052f3cf9ee4bac1cbb6adeedd69faf9da4ec04" - integrity sha512-dS4DnV6c6cQcVH5OxzIU1XZaACXwvVIiUPkFytnRmLOACuBGv3GQgRQ1RJGRRw4/9DF14ZK2RFlZu1TUgDniMg== - dependencies: - async "3.2.3" - lodash.clonedeep "^4.5.0" - lru-cache "6.0.0" - call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" @@ -3342,13 +3293,6 @@ dotenv@^17.2.2: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.2.tgz#4010cfe1c2be4fc0f46fd3d951afb424bc067ac6" integrity sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q== -dtrace-provider@~0.8: - version "0.8.8" - resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" - integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== - dependencies: - nan "^2.14.0" - dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -3363,13 +3307,6 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -ecdsa-sig-formatter@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" - integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== - dependencies: - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -3491,11 +3428,6 @@ es-toolkit@^1.39.10: resolved "https://registry.yarnpkg.com/es-toolkit/-/es-toolkit-1.39.10.tgz#513407af73e79f9940e7ec7650f2e6dceeaf1d81" integrity sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w== -es6-promise@^4.2.8: - version "4.2.8" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" - integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== - escalade@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" @@ -4092,17 +4024,6 @@ glob@^10.3.10: package-json-from-dist "^1.0.0" path-scurry "^1.11.1" -glob@^6.0.1: - version "6.0.4" - resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" - integrity sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A== - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@^7.1.3, glob@^7.1.4, glob@^7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -4603,23 +4524,6 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -jwa@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" - integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== - dependencies: - buffer-equal-constant-time "1.0.1" - ecdsa-sig-formatter "1.0.11" - safe-buffer "^5.0.1" - -jws@^3.1.3: - version "3.2.2" - resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" - integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== - dependencies: - jwa "^1.4.1" - safe-buffer "^5.0.1" - katex@^0.16.9: version "0.16.10" resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" @@ -4738,11 +4642,6 @@ lodash-es@4.17.21, lodash-es@^4.17.21: resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== -lodash.clonedeep@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" - integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== - lodash.defaults@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -4773,7 +4672,7 @@ lodash.union@^4.6.0: resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw== -lodash@^4.11.2, lodash@^4.17.21: +lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4790,23 +4689,18 @@ logform@^2.3.2, logform@^2.4.0: safe-stable-stringify "^2.3.1" triple-beam "^1.3.0" -long@^5.2.0: - version "5.2.3" - resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" - integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== -lru-cache@6.0.0, lru-cache@^6.0.0: +lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" -lru-cache@^10.2.0: - version "10.4.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" - integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== - magic-string@^0.30.11: version "0.30.17" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" @@ -5237,7 +5131,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -"minimatch@2 || 3", minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -5287,13 +5181,6 @@ mkdirp-classic@^0.5.2: resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== -mkdirp@~0.5.1: - version "0.5.6" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" - integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== - dependencies: - minimist "^1.2.6" - mlly@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" @@ -5309,11 +5196,6 @@ module-details-from-path@^1.0.3: resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== -moment@^2.19.3: - version "2.30.1" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" - integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== - morgan@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" @@ -5345,15 +5227,6 @@ ms@2.1.3, ms@^2.1.1, ms@^2.1.3: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -mv@~2: - version "2.1.1" - resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" - integrity sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg== - dependencies: - mkdirp "~0.5.1" - ncp "~2.0.0" - rimraf "~2.4.0" - mylas@^2.1.9: version "2.1.13" resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" @@ -5368,11 +5241,6 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.14.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.20.0.tgz#08c5ea813dd54ed16e5bd6505bf42af4f7838ca3" - integrity sha512-bk3gXBZDGILuuo/6sKtr0DQmSThYHLtNCdSdXk9YkxD/jK6X2vmCyyXBBxyqZ4XcnzTyYEAThfX3DCEnLf6igw== - nanoid@^3.3.8: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" @@ -5383,11 +5251,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== -ncp@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" - integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== - negotiator@0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -5436,26 +5299,6 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-forge@^1.2.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" - integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== - -node-jose@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/node-jose/-/node-jose-2.2.0.tgz#b64f3225ad6bec328509a420800de597ba2bf3ed" - integrity sha512-XPCvJRr94SjLrSIm4pbYHKLEaOsDvJCpyFw/6V/KK/IXmyZ6SFBzAUDO9HQf4DB/nTEFcRGH87mNciOP23kFjw== - dependencies: - base64url "^3.0.1" - buffer "^6.0.3" - es6-promise "^4.2.8" - lodash "^4.17.21" - long "^5.2.0" - node-forge "^1.2.1" - pako "^2.0.4" - process "^0.11.10" - uuid "^9.0.0" - nodemon@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1" @@ -5542,11 +5385,6 @@ nypm@^0.6.0: pkg-types "^2.2.0" tinyexec "^1.0.1" -oauth@0.9.15: - version "0.9.15" - resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" - integrity sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA== - object-assign@^4, object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5719,11 +5557,6 @@ package-manager-detector@^0.2.8: dependencies: quansync "^0.2.7" -pako@^2.0.4: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" - integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5746,46 +5579,6 @@ parseurl@^1.3.3, parseurl@~1.3.3: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== -passport-azure-ad@^4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/passport-azure-ad/-/passport-azure-ad-4.3.5.tgz#107d709409170478d1a66ec1efb4c094dd3d321b" - integrity sha512-LBpXEght7hCMuMNFK4oegdN0uPBa3lpDMy71zQoB0zPg1RrGwdzpjwTiN1WzN0hY77fLyjz9tBr3TGAxnSgtEg== - dependencies: - async "^3.2.3" - base64url "^3.0.0" - bunyan "^1.8.14" - cache-manager "^3.6.1" - https-proxy-agent "^5.0.0" - jws "^3.1.3" - lodash "^4.11.2" - node-jose "^2.2.0" - oauth "0.9.15" - passport "^0.6.0" - valid-url "^1.0.6" - -passport-strategy@1.x.x: - version "1.0.0" - resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4" - integrity sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA== - -passport@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.6.0.tgz#e869579fab465b5c0b291e841e6cc95c005fac9d" - integrity sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - utils-merge "^1.0.1" - -passport@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/passport/-/passport-0.7.0.tgz#3688415a59a48cf8068417a8a8092d4492ca3a05" - integrity sha512-cPLl+qZpSc+ireUvt+IzqbED1cHHkDoVYMo30jbJIdOOjQ1MQYZBPiNvmi8UM6lJuOpTPXJGZQk0DtC4y61MYQ== - dependencies: - passport-strategy "1.x.x" - pause "0.0.1" - utils-merge "^1.0.1" - path-data-parser@0.1.0, path-data-parser@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" @@ -5839,11 +5632,6 @@ pathe@^2.0.1, pathe@^2.0.3: resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== -pause@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" - integrity sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg== - pend@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" @@ -6583,13 +6371,6 @@ rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@~2.4.0: - version "2.4.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" - integrity sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ== - dependencies: - glob "^6.0.1" - robust-predicates@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" @@ -6640,16 +6421,11 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-json-stringify@~1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" - integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== - safe-stable-stringify@^2.3.1: version "2.4.3" resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" @@ -7463,7 +7239,7 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -utils-merge@1.0.1, utils-merge@^1.0.1: +utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== @@ -7503,11 +7279,6 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -valid-url@^1.0.6: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha512-QQDsV8OnSf5Uc30CKSwG9lnhMPe6exHtTXLRYX8uMwKENy640pU+2BgBL0LRbDh/eYRahNCS7aewCx0wf3NYVA== - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" From ee312706adea9220624b683cd1636366fe356b10 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 27 Sep 2025 09:50:48 +0000 Subject: [PATCH 11/89] fix prisma schema --- prisma/schema.prisma | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prisma/schema.prisma b/prisma/schema.prisma index f61f6ba..2c4dbeb 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,6 +1,6 @@ generator client { provider = "prisma-client-js" - previewFeatures = ["postgresqlExtensions", "views", "relationJoins", "queryCompiler", "driverAdapters"] + previewFeatures = ["postgresqlExtensions", "views", "relationJoins"] } generator docs { From 7412f5d3e82e9391e78231ac07aba376c846904d Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 27 Sep 2025 12:15:00 +0000 Subject: [PATCH 12/89] fix seed --- prisma/seed.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/prisma/seed.ts b/prisma/seed.ts index d6608bc..78d4bbe 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -1,23 +1,23 @@ import { Access, PrismaClient, User } from '@prisma/client'; import { FOO_BAR_ID, TEST_USER_ID, users as seedUsers } from './seed-files/users'; -import { documents as seedDocuments } from '@/prisma/seed-files/documents'; +import { documents as seedDocuments } from './seed-files/documents'; import { ALL_USERS_GROUP_ID, CLASS_GROUP_ID, PROJECT_GROUP_ID, studentGroups as seedStudentGroups -} from '@/prisma/seed-files/student-groups'; +} from './seed-files/student-groups'; import { documentRoots as seedDocumentRoots, NONE_EXAM_DOCUMENT_ID, RW_EXERCISE_IMPSUM_DOCUMENT_ROOT_ID, RO_VISIBILITY_WRAPPER_DOCUMENT_ROOT_ID, RW_EXERCISE_LOREM_DOCUMENT_ROOT_ID -} from '@/prisma/seed-files/document-roots'; +} from './seed-files/document-roots'; import { rootUserPermissions as seedRootUserPermissions, rootGroupPermissions as seedRootGroupPermissions -} from '@/prisma/seed-files/document-root-permissions'; +} from './seed-files/document-root-permissions'; const prisma = new PrismaClient(); From 759293ad12af0a843f44d7ffe9c7f87f870f2e8f Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 27 Sep 2025 12:20:12 +0000 Subject: [PATCH 13/89] update prisma --- package.json | 11 +- src/auth.ts | 11 ++ yarn.lock | 470 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 394 insertions(+), 98 deletions(-) create mode 100644 src/auth.ts diff --git a/package.json b/package.json index 439b945..dd96c40 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,11 @@ "sentry:sourcemaps": "sentry-cli sourcemaps inject --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist && sentry-cli sourcemaps upload --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist" }, "dependencies": { - "@prisma/adapter-pg": "^6.15.0", - "@prisma/client": "^6.15.0", + "@prisma/adapter-pg": "^6.16.2", + "@prisma/client": "^6.16.2", "@sentry/cli": "^2.52.0", "@sentry/node": "^10.8.0", + "better-auth": "^1.3.18", "connect-pg-simple": "^9.0.1", "cors": "^2.8.5", "cross-env": "^10.0.0", @@ -56,10 +57,10 @@ "eslint-plugin-prettier": "^5.5.4", "nodemon": "^3.1.10", "prettier": "^3.6.2", - "prisma": "^6.15.0", + "prisma": "^6.16.2", "prisma-dbml-generator": "^0.12.0", "prisma-docs-generator": "^0.8.0", - "prisma-erd-generator": "^2.0.4", + "prisma-erd-generator": "^2.1.0", "ts-node": "^10.9.2", "tsc-alias": "^1.8.16", "tsconfig-paths": "^4.2.0", @@ -69,4 +70,4 @@ "engines": { "node": "^22.11.0" } -} \ No newline at end of file +} diff --git a/src/auth.ts b/src/auth.ts new file mode 100644 index 0000000..9451225 --- /dev/null +++ b/src/auth.ts @@ -0,0 +1,11 @@ +import { PrismaClient } from '@prisma/client'; +import { betterAuth } from 'better-auth'; +import { prismaAdapter } from 'better-auth/adapters/prisma'; +// If your Prisma file is located elsewhere, you can change the path + +const prisma = new PrismaClient(); +export const auth = betterAuth({ + database: prismaAdapter(prisma, { + provider: 'postgresql' // or "mysql", "sqlite", ...etc + }) +}); diff --git a/yarn.lock b/yarn.lock index 7dafb98..561a308 100644 --- a/yarn.lock +++ b/yarn.lock @@ -73,6 +73,21 @@ "@babel/helper-string-parser" "^7.25.9" "@babel/helper-validator-identifier" "^7.25.9" +"@better-auth/core@1.3.18": + version "1.3.18" + resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.18.tgz#e99fee9ea040b9be7b233a55a0ae5cab1b90e031" + integrity sha512-eVTpiyFOA70SecGuiXs2qxQq1oWbEiLJMpyOYF8HAHFXHH+iK0Ab8F0stdyJTTYOc9ydjFQgYXmbENG6JqQ3UA== + +"@better-auth/utils@0.3.0", "@better-auth/utils@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@better-auth/utils/-/utils-0.3.0.tgz#066c5ce82bf393421547dd887b14a6899310003d" + integrity sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw== + +"@better-fetch/fetch@^1.1.18", "@better-fetch/fetch@^1.1.4": + version "1.1.18" + resolved "https://registry.yarnpkg.com/@better-fetch/fetch/-/fetch-1.1.18.tgz#4ddc65a703c65e6036947ff335e635a5a38e6225" + integrity sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA== + "@braintree/sanitize-url@^6.0.1": version "6.0.4" resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" @@ -257,6 +272,11 @@ dependencies: "@tanstack/vue-virtual" "^3.0.0-beta.60" +"@hexagon/base64@^1.1.27": + version "1.1.28" + resolved "https://registry.yarnpkg.com/@hexagon/base64/-/base64-1.1.28.tgz#7d306a97f1423829be5b27c9d388fe50e3099d48" + integrity sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw== + "@humanfs/core@^0.19.1": version "0.19.1" resolved "https://registry.yarnpkg.com/@humanfs/core/-/core-0.19.1.tgz#17c55ca7d426733fe3c561906b8173c336b40a77" @@ -356,6 +376,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@levischuck/tiny-cbor@^0.2.2": + version "0.2.11" + resolved "https://registry.yarnpkg.com/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz#833ddf7f3627dcb62d855d9c184061b4a1a875b3" + integrity sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow== + "@mermaid-js/mermaid-cli@^10.9.1": version "10.9.1" resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-cli/-/mermaid-cli-10.9.1.tgz#9ccd0a9fdb09275817617665ee5432d352c838cc" @@ -366,14 +391,14 @@ mermaid "^10.8.0" puppeteer "^19.0.0" -"@mermaid-js/mermaid-cli@^11.4.2": - version "11.4.2" - resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-cli/-/mermaid-cli-11.4.2.tgz#908e3db346f05242960a5eb0c46d06354f2d76cc" - integrity sha512-nBsEW1AxHsjsjTBrqFInkh91Vvb5vNPmnN7UGWkutExcQQZev6XzMlEZp0i6HYFSoGTHZT2tOT0l/KLzvDyPfg== +"@mermaid-js/mermaid-cli@^11.9.0": + version "11.12.0" + resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-cli/-/mermaid-cli-11.12.0.tgz#dfbe8865e1dc26bf4bcd5afe99dcafb3cb402e97" + integrity sha512-a0swOS6PByXKi0dZnLQQIhbtUEu7ubc6bojmIqXqvUPq7mIJukCNEvVBTv6IAbuEWqB3Ti8QntupoGdz3ej+kg== dependencies: "@mermaid-js/mermaid-zenuml" "^0.2.0" chalk "^5.0.1" - commander "^12.1.0" + commander "^14.0.0" import-meta-resolve "^4.1.0" mermaid "^11.0.2" @@ -391,6 +416,16 @@ dependencies: langium "3.3.1" +"@noble/ciphers@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-2.0.1.tgz#fb07d6479d11fd10d7f601b6fb8fb9925b7accf7" + integrity sha512-xHK3XHPUW8DTAobU+G0XT+/w+JLM7/8k1UFdB5xg/zTFPnFCobhftzw8wl4Lw2aq/Rvir5pxfZV5fEazmeCJ2g== + +"@noble/hashes@^2.0.0": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" + integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -698,6 +733,138 @@ dependencies: "@opentelemetry/core" "^2.0.0" +"@peculiar/asn1-android@^2.3.10": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-android/-/asn1-android-2.5.0.tgz#039c3b08dbd80cfb9b4c7f239c43a91247b58f98" + integrity sha512-t8A83hgghWQkcneRsgGs2ebAlRe54ns88p7ouv8PW2tzF1nAW4yHcL4uZKrFpIU+uszIRzTkcCuie37gpkId0A== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-cms@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-cms/-/asn1-cms-2.5.0.tgz#3a7e857d86686898ce78efdbf481922bb805c68a" + integrity sha512-p0SjJ3TuuleIvjPM4aYfvYw8Fk1Hn/zAVyPJZTtZ2eE9/MIer6/18ROxX6N/e6edVSfvuZBqhxAj3YgsmSjQ/A== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + "@peculiar/asn1-x509-attr" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-csr@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-csr/-/asn1-csr-2.5.0.tgz#4dd7534bd7d7db5bbbbde4d00d4836bf7e818d1c" + integrity sha512-ioigvA6WSYN9h/YssMmmoIwgl3RvZlAYx4A/9jD2qaqXZwGcNlAxaw54eSx2QG1Yu7YyBC5Rku3nNoHrQ16YsQ== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-ecc@^2.3.8", "@peculiar/asn1-ecc@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-ecc/-/asn1-ecc-2.5.0.tgz#3bbeaa3443567055be112b4c7e9d5562951242cf" + integrity sha512-t4eYGNhXtLRxaP50h3sfO6aJebUCDGQACoeexcelL4roMFRRVgB20yBIu2LxsPh/tdW9I282gNgMOyg3ywg/mg== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pfx@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-pfx/-/asn1-pfx-2.5.0.tgz#22d12e676c063dfc6244278fe18eb75c2c121880" + integrity sha512-Vj0d0wxJZA+Ztqfb7W+/iu8Uasw6hhKtCdLKXLG/P3kEPIQpqGI4P4YXlROfl7gOCqFIbgsj1HzFIFwQ5s20ug== + dependencies: + "@peculiar/asn1-cms" "^2.5.0" + "@peculiar/asn1-pkcs8" "^2.5.0" + "@peculiar/asn1-rsa" "^2.5.0" + "@peculiar/asn1-schema" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pkcs8@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.5.0.tgz#1939643773e928a4802813b595e324a05b453709" + integrity sha512-L7599HTI2SLlitlpEP8oAPaJgYssByI4eCwQq2C9eC90otFpm8MRn66PpbKviweAlhinWQ3ZjDD2KIVtx7PaVw== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-pkcs9@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.5.0.tgz#8c5b873a721bb92b4fe758da9de1ead63165106d" + integrity sha512-UgqSMBLNLR5TzEZ5ZzxR45Nk6VJrammxd60WMSkofyNzd3DQLSNycGWSK5Xg3UTYbXcDFyG8pA/7/y/ztVCa6A== + dependencies: + "@peculiar/asn1-cms" "^2.5.0" + "@peculiar/asn1-pfx" "^2.5.0" + "@peculiar/asn1-pkcs8" "^2.5.0" + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + "@peculiar/asn1-x509-attr" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-rsa@^2.3.8", "@peculiar/asn1-rsa@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-rsa/-/asn1-rsa-2.5.0.tgz#7283756ec596ccfbef23ff0e7eda0c37133ebed8" + integrity sha512-qMZ/vweiTHy9syrkkqWFvbT3eLoedvamcUdnnvwyyUNv5FgFXA3KP8td+ATibnlZ0EANW5PYRm8E6MJzEB/72Q== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-schema@^2.3.8", "@peculiar/asn1-schema@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.5.0.tgz#4e58d7c3087c4259cebf5363e092f85b9cbf0ca1" + integrity sha512-YM/nFfskFJSlHqv59ed6dZlLZqtZQwjRVJ4bBAiWV08Oc+1rSd5lDZcBEx0lGDHfSoH3UziI2pXt2UM33KerPQ== + dependencies: + asn1js "^3.0.6" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/asn1-x509-attr@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.5.0.tgz#d413597dfe097620a00780e9e2ae851b06f32aed" + integrity sha512-9f0hPOxiJDoG/bfNLAFven+Bd4gwz/VzrCIIWc1025LEI4BXO0U5fOCTNDPbbp2ll+UzqKsZ3g61mpBp74gk9A== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + asn1js "^3.0.6" + tslib "^2.8.1" + +"@peculiar/asn1-x509@^2.3.8", "@peculiar/asn1-x509@^2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-x509/-/asn1-x509-2.5.0.tgz#305f9cd534f4b6a723d27fc59363f382debf5500" + integrity sha512-CpwtMCTJvfvYTFMuiME5IH+8qmDe3yEWzKHe7OOADbGfq7ohxeLaXwQo0q4du3qs0AII3UbLCvb9NF/6q0oTKQ== + dependencies: + "@peculiar/asn1-schema" "^2.5.0" + asn1js "^3.0.6" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/x509@^1.13.0": + version "1.14.0" + resolved "https://registry.yarnpkg.com/@peculiar/x509/-/x509-1.14.0.tgz#4b1abdf7ca5e46f2cb303fba608ef0507762e84a" + integrity sha512-Yc4PDxN3OrxUPiXgU63c+ZRXKGE8YKF2McTciYhUHFtHVB0KMnjeFSU0qpztGhsp4P0uKix4+J2xEpIEDu8oXg== + dependencies: + "@peculiar/asn1-cms" "^2.5.0" + "@peculiar/asn1-csr" "^2.5.0" + "@peculiar/asn1-ecc" "^2.5.0" + "@peculiar/asn1-pkcs9" "^2.5.0" + "@peculiar/asn1-rsa" "^2.5.0" + "@peculiar/asn1-schema" "^2.5.0" + "@peculiar/asn1-x509" "^2.5.0" + pvtsutils "^1.3.6" + reflect-metadata "^0.2.2" + tslib "^2.8.1" + tsyringe "^4.10.0" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -708,24 +875,24 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@prisma/adapter-pg@^6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-6.15.0.tgz#4602a8cbb70214e9b771cf13c0737744ba328f3f" - integrity sha512-UDqysvOwrSLUDgSnLOKPmTvIrXhod5bMOBwb4GzSR/b6qqSO/SEb3Fq2ddGi1hZt6fAOSp+sXmdaQBy5Sakvkw== +"@prisma/adapter-pg@^6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-6.16.2.tgz#c1ca0eb801889b2e455d2379a8e9c26f21b0eefc" + integrity sha512-C+JZmKDBm13anIRhhJYxNw0EZ3zT11n9i6JCPBf2sg7HCNlQiYAPBegqYzAYwGw8VG8xlkM0aV9xJ4AH2mQqaQ== dependencies: - "@prisma/driver-adapter-utils" "6.15.0" + "@prisma/driver-adapter-utils" "6.16.2" pg "^8.11.3" postgres-array "3.0.4" -"@prisma/client@^6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.15.0.tgz#c4166aa8492878c842e63c515853d7a4125e6168" - integrity sha512-wR2LXUbOH4cL/WToatI/Y2c7uzni76oNFND7+23ypLllBmIS8e3ZHhO+nud9iXSXKFt1SoM3fTZvHawg63emZw== +"@prisma/client@^6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.16.2.tgz#db11b9af568d1761c0b712fccfc6ee484d2310d7" + integrity sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw== -"@prisma/config@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.15.0.tgz#b9a4fd87620baae3ce71015ee4ad632995838d89" - integrity sha512-KMEoec9b2u6zX0EbSEx/dRpx1oNLjqJEBZYyK0S3TTIbZ7GEGoVyGyFRk4C72+A38cuPLbfQGQvgOD+gBErKlA== +"@prisma/config@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.16.2.tgz#bb4816d8f1854eb281dab00d34a2392fe290ee25" + integrity sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg== dependencies: c12 "3.1.0" deepmerge-ts "7.1.5" @@ -750,32 +917,27 @@ debug "4.3.4" strip-ansi "6.0.1" -"@prisma/debug@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.15.0.tgz#8595f8ae91eadd20d926398449b8602c74e36bbf" - integrity sha512-y7cSeLuQmyt+A3hstAs6tsuAiVXSnw9T55ra77z0nbNkA8Lcq9rNcQg6PI00by/+WnE/aMRJ/W7sZWn2cgIy1g== - -"@prisma/debug@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.6.0.tgz#150bbbda5e9f665c08eed6c4c394cda38bb70cce" - integrity sha512-DL6n4IKlW5k2LEXzpN60SQ1kP/F6fqaCgU/McgaYsxSf43GZ8lwtmXLke9efS+L1uGmrhtBUP4npV/QKF8s2ZQ== +"@prisma/debug@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.16.2.tgz#d1358392f68ea29cad905e44be67f5cc4930d866" + integrity sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA== -"@prisma/dmmf@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@prisma/dmmf/-/dmmf-6.6.0.tgz#20a01a89cb67e751787a28f82ef945371b71535b" - integrity sha512-2LoSX0ZVwIiKck5wMCVxeGg9K9z6CULB8xyTbLF3YTvuhOp+fQozelUphaGZA9jN4MF58z6TfUXIMMPVwtxjbQ== +"@prisma/dmmf@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/dmmf/-/dmmf-6.16.2.tgz#a808af49eaa6975ef965bf38dc1195edeed9e039" + integrity sha512-o9ztgdbj2KZXl6DL+oP56TTC0poTLPns9/MeU761b49E1IQ/fd0jwdov1bidlNOiwio8Nsou23xNrYE/db10aA== -"@prisma/driver-adapter-utils@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/driver-adapter-utils/-/driver-adapter-utils-6.15.0.tgz#7e1803eb8ad18f3c8a8e9843049226b66ef3447d" - integrity sha512-tzcMG1eEBM3IJ8TBHo4jGeoUaalctqGXbrvxIoZb8jSEtgR82IUhdVyHHLVTlT8MdrHovcQJJ3jfcQfJARRnaQ== +"@prisma/driver-adapter-utils@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/driver-adapter-utils/-/driver-adapter-utils-6.16.2.tgz#10505585f94ac7b84ac2e754e96cbd2ef167881a" + integrity sha512-DMgfafnG0zPd+QoAQOC0Trn1xlb0fVAfQi2MpkpzSf641KiVkVPkJRXDSbcTbxGxO2HRdd0vI9U6LlesWad4XA== dependencies: - "@prisma/debug" "6.15.0" + "@prisma/debug" "6.16.2" -"@prisma/engines-version@6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb": - version "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb.tgz#718b17890287447360107bef3675487d8cb0ae15" - integrity sha512-a/46aK5j6L3ePwilZYEgYDPrhBQ/n4gYjLxT5YncUTJJNRnTCVjPF86QdzUOLRdYjCLfhtZp9aum90W0J+trrg== +"@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43": + version "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz#84904768af0d29a7fb6122a5d9f91cf4658886f9" + integrity sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA== "@prisma/engines@4.16.2": version "4.16.2" @@ -787,15 +949,15 @@ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.0.0.tgz#5249650eabe77c458c90f2be97d8210353c2e22e" integrity sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg== -"@prisma/engines@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.15.0.tgz#77a220e40f4ed3345ef27407f8f0323e80debea8" - integrity sha512-opITiR5ddFJ1N2iqa7mkRlohCZqVSsHhRcc29QXeldMljOf4FSellLT0J5goVb64EzRTKcIDeIsJBgmilNcKxA== +"@prisma/engines@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.16.2.tgz#49421086f1a1a83b725bbb1bab6d682e8e497811" + integrity sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA== dependencies: - "@prisma/debug" "6.15.0" - "@prisma/engines-version" "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb" - "@prisma/fetch-engine" "6.15.0" - "@prisma/get-platform" "6.15.0" + "@prisma/debug" "6.16.2" + "@prisma/engines-version" "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + "@prisma/fetch-engine" "6.16.2" + "@prisma/get-platform" "6.16.2" "@prisma/fetch-engine@4.16.2": version "4.16.2" @@ -843,14 +1005,14 @@ temp-dir "2.0.0" tempy "1.0.1" -"@prisma/fetch-engine@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.15.0.tgz#ec7e57030789ed42a87bf5b66be4db6e612412e9" - integrity sha512-xcT5f6b+OWBq6vTUnRCc7qL+Im570CtwvgSj+0MTSGA1o9UDSKZ/WANvwtiRXdbYWECpyC3CukoG3A04VTAPHw== +"@prisma/fetch-engine@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.16.2.tgz#dfdf9fa49887cc0ac04f1296e4c1a5f64490ce71" + integrity sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ== dependencies: - "@prisma/debug" "6.15.0" - "@prisma/engines-version" "6.15.0-5.85179d7826409ee107a6ba334b5e305ae3fba9fb" - "@prisma/get-platform" "6.15.0" + "@prisma/debug" "6.16.2" + "@prisma/engines-version" "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" + "@prisma/get-platform" "6.16.2" "@prisma/generator-helper@4.16.2", "@prisma/generator-helper@^4.14.0": version "4.16.2" @@ -872,19 +1034,19 @@ cross-spawn "7.0.3" kleur "4.1.5" -"@prisma/generator-helper@^5.0.0 || ^6.0.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-6.6.0.tgz#17baec7b5db2dc3a8fbb9f044ededb224d51ec15" - integrity sha512-pKxkyb+tCb5vPaMkK6SdHkK5qkQIPDSw1T3BAfl6XWDwDwnP4f5CsJ6/VaBhtvqZ5bqfUQLvT+slaGrJQXiw9g== +"@prisma/generator-helper@^6.15.0": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-6.16.2.tgz#b0ea198e3690eacf02e44fc661146fb983ed229f" + integrity sha512-8tVnWM8ETJNrvI5CT9eKCW23+aPLNkidC+g9NJn7ghXm60Q7GGlLX5tmvn5dE8tXvs/FSX3MN7KNmNJpOr89Hw== dependencies: - "@prisma/debug" "6.6.0" - "@prisma/dmmf" "6.6.0" - "@prisma/generator" "6.6.0" + "@prisma/debug" "6.16.2" + "@prisma/dmmf" "6.16.2" + "@prisma/generator" "6.16.2" -"@prisma/generator@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@prisma/generator/-/generator-6.6.0.tgz#6e7e94a824fb8356d318f68fbece09c9aac0cc26" - integrity sha512-UO1PFYd8Qh0LZoN/9wwAukgoDs8chLqGPho7ZBZejVKv1UpaEJvxgwS+LwlmkQ3Ay0GdsL6mjN8QxEi91xIomQ== +"@prisma/generator@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/generator/-/generator-6.16.2.tgz#3ac40f6adf46f17f77dacfe35d27900cd1aeaebd" + integrity sha512-7bwRmtMIgfe1rUynh1p9VlmYvEiidbRO6aBphPBS6YGEGSvNe8+QExbRpsqFlFBvIX76BhZCxuEj7ZwALMYRKQ== "@prisma/get-platform@4.16.2": version "4.16.2" @@ -918,12 +1080,12 @@ terminal-link "2.1.1" ts-pattern "4.3.0" -"@prisma/get-platform@6.15.0": - version "6.15.0" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.15.0.tgz#86a114534a534090b931801b83356b0bbe676f29" - integrity sha512-Jbb+Xbxyp05NSR1x2epabetHiXvpO8tdN2YNoWoA/ZsbYyxxu/CO/ROBauIFuMXs3Ti+W7N7SJtWsHGaWte9Rg== +"@prisma/get-platform@6.16.2": + version "6.16.2" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.16.2.tgz#6814078c97f2ad14bbee8fa25659784b00cafcda" + integrity sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA== dependencies: - "@prisma/debug" "6.15.0" + "@prisma/debug" "6.16.2" "@prisma/instrumentation@6.14.0": version "6.14.0" @@ -1176,6 +1338,25 @@ dependencies: "@sentry/core" "10.8.0" +"@simplewebauthn/browser@^13.1.2": + version "13.2.0" + resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-13.2.0.tgz#20ed07457d6ed4e28aaa94e8c2ee0545e95bfc89" + integrity sha512-N3fuA1AAnTo5gCStYoIoiasPccC+xPLx2YU88Dv0GeAmPQTWHETlZQq5xZ0DgUq1H9loXMWQH5qqUjcI7BHJ1A== + +"@simplewebauthn/server@^13.1.2": + version "13.2.1" + resolved "https://registry.yarnpkg.com/@simplewebauthn/server/-/server-13.2.1.tgz#2971e999a3c209e257d601e30bb53b0fa84501cc" + integrity sha512-Inmfye5opZXe3HI0GaksqBnQiM7glcNySoG6DH1GgkO1Lh9dvuV4XSV9DK02DReUVX39HpcDob9nxHELjECoQw== + dependencies: + "@hexagon/base64" "^1.1.27" + "@levischuck/tiny-cbor" "^0.2.2" + "@peculiar/asn1-android" "^2.3.10" + "@peculiar/asn1-ecc" "^2.3.8" + "@peculiar/asn1-rsa" "^2.3.8" + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/asn1-x509" "^2.3.8" + "@peculiar/x509" "^1.13.0" + "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" @@ -2158,6 +2339,15 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +asn1js@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.6.tgz#53e002ebe00c5f7fd77c1c047c3557d7c04dce25" + integrity sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA== + dependencies: + pvtsutils "^1.3.6" + pvutils "^1.1.3" + tslib "^2.8.1" + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -2195,6 +2385,36 @@ basic-auth@~2.0.1: dependencies: safe-buffer "5.1.2" +better-auth@^1.3.18: + version "1.3.18" + resolved "https://registry.yarnpkg.com/better-auth/-/better-auth-1.3.18.tgz#3690b5f351fd7f029859b3d102057b7ddb1ebc9c" + integrity sha512-d4/Wlvvg8irDSblQP1KiLEWYppTlDiNXV9U4oP6D463MlMbMn7kbBcJvM6Us7M//rgi/mAzg5xKzuE3Y5B2NrQ== + dependencies: + "@better-auth/core" "1.3.18" + "@better-auth/utils" "0.3.0" + "@better-fetch/fetch" "^1.1.18" + "@noble/ciphers" "^2.0.0" + "@noble/hashes" "^2.0.0" + "@simplewebauthn/browser" "^13.1.2" + "@simplewebauthn/server" "^13.1.2" + better-call "1.0.19" + defu "^6.1.4" + jose "^6.1.0" + kysely "^0.28.5" + nanostores "^1.0.1" + zod "^4.1.5" + +better-call@1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/better-call/-/better-call-1.0.19.tgz#037b0d90d3ad01c434dd247b3f6778fb4f3161d4" + integrity sha512-sI3GcA1SCVa3H+CDHl8W8qzhlrckwXOTKhqq3OOPXjgn5aTOMIqGY34zLY/pHA6tRRMjTUC3lz5Mi7EbDA24Kw== + dependencies: + "@better-auth/utils" "^0.3.0" + "@better-fetch/fetch" "^1.1.4" + rou3 "^0.5.1" + set-cookie-parser "^2.7.1" + uncrypto "^0.1.3" + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -2549,10 +2769,10 @@ commander@^10.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-10.0.1.tgz#881ee46b4f77d1c1dccc5823433aa39b022cbe06" integrity sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug== -commander@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== +commander@^14.0.0: + version "14.0.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.1.tgz#2f9225c19e6ebd0dc4404dd45821b2caa17ea09b" + integrity sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A== commander@^4.0.0: version "4.1.1" @@ -3278,11 +3498,6 @@ dotenv@^16.3.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== -dotenv@^16.4.7: - version "16.5.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" - integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== - dotenv@^16.6.1: version "16.6.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" @@ -4478,6 +4693,11 @@ jiti@^2.4.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.5.1.tgz#bd099c1c2be1c59bbea4e5adcd127363446759d0" integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== +jose@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.0.tgz#96285365689d16f2845a353964d2284bf19f464c" + integrity sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4568,6 +4788,11 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== +kysely@^0.28.5: + version "0.28.7" + resolved "https://registry.yarnpkg.com/kysely/-/kysely-0.28.7.tgz#461d160865825f89173a7f814489e92a91b13864" + integrity sha512-u/cAuTL4DRIiO2/g4vNGRgklEKNIj5Q3CG7RoUB5DV5SfEC2hMvPxKi0GWPmnzwL2ryIeud2VTcEEmqzTzEPNw== + langium@3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/langium/-/langium-3.3.1.tgz#da745a40d5ad8ee565090fed52eaee643be4e591" @@ -5246,6 +5471,11 @@ nanoid@^3.3.8: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +nanostores@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nanostores/-/nanostores-1.0.1.tgz#bcc352ff7bf622e9274a3109c92e823a452d6028" + integrity sha512-kNZ9xnoJYKg/AfxjrVL4SS0fKX++4awQReGqWnwTRHxeHGZ1FJFVgTqr/eMrNQdp0Tz7M7tG/TDaX8QfHDwVCw== + natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" @@ -6010,22 +6240,22 @@ prisma-docs-generator@^0.8.0: prismjs "^1.29.0" ts-toolbelt "^9.6.0" -prisma-erd-generator@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/prisma-erd-generator/-/prisma-erd-generator-2.0.4.tgz#64ff2c3b2050fc634e8c2d305f7ffbda7372c2bb" - integrity sha512-XVdaojAc75GaWq2Ia6orFqDcP8vEQZdooKtMWNJNV9cC/JCTh3OW6Zs+mMLedLEv96Xnjfzp7Tzld6dm/KuOnA== +prisma-erd-generator@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/prisma-erd-generator/-/prisma-erd-generator-2.1.0.tgz#bad74f1b32372d8d17feaff7631128b2770d30fb" + integrity sha512-1BWerhaHkebNwPW3Xz8IeHeWFlQb/j59bIScyC4QdO03+Ry8bJLEvRZRy3skWCc07PMSkTSdZlqtnCfKuke0Rg== dependencies: - "@mermaid-js/mermaid-cli" "^11.4.2" - "@prisma/generator-helper" "^5.0.0 || ^6.0.0" - dotenv "^16.4.7" + "@mermaid-js/mermaid-cli" "^11.9.0" + "@prisma/generator-helper" "^6.15.0" + dotenv "^16.6.1" -prisma@^6.15.0: - version "6.15.0" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.15.0.tgz#198f95a4468aba8f3c95b58bf3400f65daeb8942" - integrity sha512-E6RCgOt+kUVtjtZgLQDBJ6md2tDItLJNExwI0XJeBc1FKL+Vwb+ovxXxuok9r8oBgsOXBA33fGDuE/0qDdCWqQ== +prisma@^6.16.2: + version "6.16.2" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.16.2.tgz#ab1f977632754245af1a7bab864c315694b6293c" + integrity sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA== dependencies: - "@prisma/config" "6.15.0" - "@prisma/engines" "6.15.0" + "@prisma/config" "6.16.2" + "@prisma/engines" "6.16.2" prismjs@^1.29.0: version "1.29.0" @@ -6125,6 +6355,18 @@ pure-rand@^6.1.0: resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2" integrity sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA== +pvtsutils@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== + dependencies: + tslib "^2.8.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + qs@6.11.0: version "6.11.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -6298,6 +6540,11 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" +reflect-metadata@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.2.2.tgz#400c845b6cba87a21f2c65c4aeb158f4fa4d9c5b" + integrity sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q== + replace-string@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/replace-string/-/replace-string-3.1.0.tgz#77a087d88580fbac59851237891aa4b0e283db72" @@ -6376,6 +6623,11 @@ robust-predicates@^3.0.2: resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== +rou3@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/rou3/-/rou3-0.5.1.tgz#414d1123631f45474df743c9fc904d757bb2e43c" + integrity sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ== + roughjs@^4.6.6: version "4.6.6" resolved "https://registry.yarnpkg.com/roughjs/-/roughjs-4.6.6.tgz#1059f49a5e0c80dee541a005b20cc322b222158b" @@ -6517,6 +6769,11 @@ serve-static@^2.2.0: parseurl "^1.3.3" send "^1.2.0" +set-cookie-parser@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" + integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -7112,6 +7369,23 @@ tsconfig-paths@^4.2.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@^1.9.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsyringe@^4.10.0: + version "4.10.0" + resolved "https://registry.yarnpkg.com/tsyringe/-/tsyringe-4.10.0.tgz#d0c95815d584464214060285eaaadd94aa03299c" + integrity sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw== + dependencies: + tslib "^1.9.3" + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -7193,6 +7467,11 @@ unbzip2-stream@1.4.3: buffer "^5.2.1" through "^2.3.8" +uncrypto@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/uncrypto/-/uncrypto-0.1.3.tgz#e1288d609226f2d02d8d69ee861fa20d8348ef2b" + integrity sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q== + undefsafe@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" @@ -7517,3 +7796,8 @@ zip-stream@^4.1.0: archiver-utils "^3.0.4" compress-commons "^4.1.2" readable-stream "^3.6.0" + +zod@^4.1.5: + version "4.1.11" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" + integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== From cbc4a2e621e8d66a483946602a8d8a8c67fcada5 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 27 Sep 2025 12:24:46 +0000 Subject: [PATCH 14/89] config --- src/auth.ts | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 9451225..fb0c2c3 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,11 +1,39 @@ -import { PrismaClient } from '@prisma/client'; import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; +import prisma from './prisma'; +import { Role } from '@prisma/client'; // If your Prisma file is located elsewhere, you can change the path -const prisma = new PrismaClient(); export const auth = betterAuth({ database: prismaAdapter(prisma, { - provider: 'postgresql' // or "mysql", "sqlite", ...etc - }) + provider: 'postgresql', + usePlural: true + }), + user: { + modelName: 'users', + additionalFields: { + role: { + type: 'string', + required: false, + defaultValue: Role.STUDENT, + input: false // don't allow user to set role + }, + firstName: { + type: 'string', + required: false, + input: false + }, + lastName: { + type: 'string', + required: false, + input: false + } + } + }, + session: { + modelName: 'sessions' + }, + account: { + modelName: 'accounts' + } }); From ba78e4f64eb0acfef82b7645cef0308e14acc109 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 11:34:54 +0000 Subject: [PATCH 15/89] add migration --- .../20250927122610_better_auth/migration.sql | 86 +++++++++++++++++++ prisma/schema.prisma | 72 +++++++++++++--- 2 files changed, 145 insertions(+), 13 deletions(-) create mode 100644 prisma/migrations/20250927122610_better_auth/migration.sql diff --git a/prisma/migrations/20250927122610_better_auth/migration.sql b/prisma/migrations/20250927122610_better_auth/migration.sql new file mode 100644 index 0000000..8f72891 --- /dev/null +++ b/prisma/migrations/20250927122610_better_auth/migration.sql @@ -0,0 +1,86 @@ +/* + Warnings: + + - The primary key for the `sessions` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `expire` on the `sessions` table. All the data in the column will be lost. + - You are about to drop the column `sess` on the `sessions` table. All the data in the column will be lost. + - You are about to drop the column `sid` on the `sessions` table. All the data in the column will be lost. + - A unique constraint covering the columns `[token]` on the table `sessions` will be added. If there are existing duplicate values, this will fail. + - Added the required column `createdAt` to the `sessions` table without a default value. This is not possible if the table is not empty. + - Added the required column `expiresAt` to the `sessions` table without a default value. This is not possible if the table is not empty. + - Added the required column `id` to the `sessions` table without a default value. This is not possible if the table is not empty. + - Added the required column `token` to the `sessions` table without a default value. This is not possible if the table is not empty. + - Added the required column `updatedAt` to the `sessions` table without a default value. This is not possible if the table is not empty. + - Added the required column `user_id` to the `sessions` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropIndex +DROP INDEX "public"."IDX_session_expire"; + +-- AlterTable +ALTER TABLE "public"."sessions" DROP CONSTRAINT "sessions_pkey", +DROP COLUMN "expire", +DROP COLUMN "sess", +DROP COLUMN "sid", +ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL, +ADD COLUMN "expiresAt" TIMESTAMP(3) NOT NULL, +ADD COLUMN "id" TEXT NOT NULL, +ADD COLUMN "ipAddress" TEXT, +ADD COLUMN "token" TEXT NOT NULL, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL, +ADD COLUMN "userAgent" TEXT, +ADD COLUMN "user_id" UUID NOT NULL, +ADD CONSTRAINT "sessions_pkey" PRIMARY KEY ("id"); + +-- AlterTable +ALTER TABLE "public"."users" ADD COLUMN "email_verified" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "image" TEXT, +ADD COLUMN "name" TEXT NOT NULL DEFAULT ''; + +UPDATE "public"."users" SET "name" = CASE + WHEN role = 'STUDENT' THEN + first_name || ' ' || LEFT(last_name, 1) || '.' + ELSE + LEFT(first_name, 1) || '. ' || last_name + END; + +-- CreateTable +CREATE TABLE "public"."accounts" ( + "id" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "providerId" TEXT NOT NULL, + "userId" UUID NOT NULL, + "accessToken" TEXT, + "refreshToken" TEXT, + "idToken" TEXT, + "expiresAt" TIMESTAMP(3), + "password" TEXT, + "accessTokenExpiresAt" TIMESTAMP(3), + "refreshTokenExpiresAt" TIMESTAMP(3), + "scope" TEXT, + "createdAt" TIMESTAMP(3) NOT NULL, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "accounts_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."verifications" ( + "id" TEXT NOT NULL, + "identifier" TEXT NOT NULL, + "value" TEXT NOT NULL, + "expiresAt" TIMESTAMP(3) NOT NULL, + "createdAt" TIMESTAMP(3), + "updatedAt" TIMESTAMP(3), + + CONSTRAINT "verifications_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "sessions_token_key" ON "public"."sessions"("token"); + +-- AddForeignKey +ALTER TABLE "public"."sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2c4dbeb..9567a7e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -15,13 +15,17 @@ datasource db { } model User { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - email String @unique + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + name String @default("") + email String @unique + emailVerified Boolean @default(false) @map("email_verified") + image String? + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @default(now()) @updatedAt @map("updated_at") + firstName String @map("first_name") lastName String @map("last_name") role Role @default(STUDENT) @map("role") - createdAt DateTime @default(now()) @map("created_at") - updatedAt DateTime @default(now()) @updatedAt @map("updated_at") documents Document[] @relation("documents") rootUserPermissions RootUserPermission[] @relation("root_user_to_user_permission") view_DocumentUserPermissions view_DocumentUserPermissions[] @@ -29,9 +33,59 @@ model User { cmsSettings CmsSettings? studentGroups UserStudentGroup[] @relation("user_student_groups") + sessions Session[] + accounts Account[] + @@map("users") } +model Session { + id String @id + expiresAt DateTime + ipAddress String? + userAgent String? + userId String @map("user_id") @db.Uuid + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + token String + createdAt DateTime + updatedAt DateTime + + @@unique([token]) + @@map("sessions") +} + +model Account { + id String @id + accountId String + providerId String + userId String @db.Uuid + user User @relation(fields: [userId], references: [id], onDelete: Cascade) + accessToken String? + refreshToken String? + idToken String? + expiresAt DateTime? + password String? + accessTokenExpiresAt DateTime? + refreshTokenExpiresAt DateTime? + scope String? + createdAt DateTime + updatedAt DateTime + + @@map("accounts") +} + +model Verification { + id String @id + identifier String + value String + expiresAt DateTime + + createdAt DateTime? + updatedAt DateTime? + + @@map("verifications") +} + model CmsSettings { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) @@ -152,18 +206,10 @@ model RootUserPermission { @@map("root_user_permissions") } -model Sessions { - sid String @id @db.VarChar - sess Json @db.Json - expire DateTime @db.Timestamp(6) - - @@index([expire], map: "IDX_session_expire") - @@map("sessions") -} - // This is a view ranked by the highest access rank. // This is used to create the DocumentUserPermissions view and should // not be used directly. + view view_AllDocumentUserPermissions { documentRootId String @map("document_root_id") @db.Uuid userId String @map("user_id") @db.Uuid From 5b2e13a74bfcab1e4776c1cd251d6ec5dc71382a Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 11:57:59 +0000 Subject: [PATCH 16/89] rename user.role to user.tdev_role --- prisma/migrations/20250928115531_rename_user_role/migration.sql | 2 ++ prisma/schema.prisma | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20250928115531_rename_user_role/migration.sql diff --git a/prisma/migrations/20250928115531_rename_user_role/migration.sql b/prisma/migrations/20250928115531_rename_user_role/migration.sql new file mode 100644 index 0000000..64d87d1 --- /dev/null +++ b/prisma/migrations/20250928115531_rename_user_role/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "public"."users" RENAME COLUMN "role" TO "tdev_role"; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 9567a7e..3df164e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,7 +25,7 @@ model User { firstName String @map("first_name") lastName String @map("last_name") - role Role @default(STUDENT) @map("role") + tdevRole Role @default(STUDENT) @map("tdev_role") documents Document[] @relation("documents") rootUserPermissions RootUserPermission[] @relation("root_user_to_user_permission") view_DocumentUserPermissions view_DocumentUserPermissions[] From 464a2c6c4eabb68f26e4ddc37d246404aa72186e Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 11:59:32 +0000 Subject: [PATCH 17/89] add admin-plugin --- .../migration.sql | 8 ++++++++ prisma/schema.prisma | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql diff --git a/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql b/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql new file mode 100644 index 0000000..33727d6 --- /dev/null +++ b/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql @@ -0,0 +1,8 @@ +-- AlterTable +ALTER TABLE "public"."sessions" ADD COLUMN "impersonatedBy" TEXT; + +-- AlterTable +ALTER TABLE "public"."users" ADD COLUMN "banExpires" TIMESTAMP(3), +ADD COLUMN "banReason" TEXT, +ADD COLUMN "banned" BOOLEAN DEFAULT false, +ADD COLUMN "role" TEXT; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3df164e..81a4df8 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,3 +1,4 @@ + generator client { provider = "prisma-client-js" previewFeatures = ["postgresqlExtensions", "views", "relationJoins"] @@ -36,6 +37,11 @@ model User { sessions Session[] accounts Account[] + role String? + banned Boolean? @default(false) + banReason String? + banExpires DateTime? + @@map("users") } @@ -50,6 +56,8 @@ model Session { createdAt DateTime updatedAt DateTime + impersonatedBy String? + @@unique([token]) @@map("sessions") } From 556278ad8bcddf4c2cbbc093527c49324b3cb9ae Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 12:14:01 +0000 Subject: [PATCH 18/89] add sso plugin --- .../migration.sql | 19 +++++++++++++++++++ prisma/schema.prisma | 18 +++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql diff --git a/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql b/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql new file mode 100644 index 0000000..5d22b82 --- /dev/null +++ b/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql @@ -0,0 +1,19 @@ +-- CreateTable +CREATE TABLE "public"."ssoProvider" ( + "id" TEXT NOT NULL, + "issuer" TEXT NOT NULL, + "oidcConfig" TEXT, + "samlConfig" TEXT, + "userId" UUID, + "providerId" TEXT NOT NULL, + "organizationId" TEXT, + "domain" TEXT NOT NULL, + + CONSTRAINT "ssoProvider_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "ssoProvider_providerId_key" ON "public"."ssoProvider"("providerId"); + +-- AddForeignKey +ALTER TABLE "public"."ssoProvider" ADD CONSTRAINT "ssoProvider_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 81a4df8..3403584 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1,4 +1,3 @@ - generator client { provider = "prisma-client-js" previewFeatures = ["postgresqlExtensions", "views", "relationJoins"] @@ -42,6 +41,8 @@ model User { banReason String? banExpires DateTime? + ssoproviders SsoProvider[] + @@map("users") } @@ -94,6 +95,21 @@ model Verification { @@map("verifications") } +model SsoProvider { + id String @id + issuer String + oidcConfig String? + samlConfig String? + userId String? @db.Uuid + user User? @relation(fields: [userId], references: [id], onDelete: Cascade) + providerId String + organizationId String? + domain String + + @@unique([providerId]) + @@map("ssoProvider") +} + model CmsSettings { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) From e059d53c323b8689325fe46291725e0a5f0ca2f7 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 12:14:10 +0000 Subject: [PATCH 19/89] add sso plugin --- package.json | 1 + yarn.lock | 271 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 268 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index dd96c40..9feb26d 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "sentry:sourcemaps": "sentry-cli sourcemaps inject --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist && sentry-cli sourcemaps upload --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist" }, "dependencies": { + "@better-auth/sso": "^1.3.18", "@prisma/adapter-pg": "^6.16.2", "@prisma/client": "^6.16.2", "@sentry/cli": "^2.52.0", diff --git a/yarn.lock b/yarn.lock index 561a308..df08b84 100644 --- a/yarn.lock +++ b/yarn.lock @@ -25,6 +25,15 @@ resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-8.1.1.tgz#95b1947d292a9a2efffba2081796dcaa05ecedfb" integrity sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ== +"@authenio/xml-encryption@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@authenio/xml-encryption/-/xml-encryption-2.0.2.tgz#df1f491dacb9b1f65bc7a9a554c189644f72bbe0" + integrity sha512-cTlrKttbrRHEw3W+0/I609A2Matj5JQaRvfLtEIGZvlN0RaPi+3ANsMeqAyCAVlH/lUIW2tmtBlSMni74lcXeg== + dependencies: + "@xmldom/xmldom" "^0.8.6" + escape-html "^1.0.3" + xpath "0.0.32" + "@babel/code-frame@^7.0.0": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" @@ -78,6 +87,18 @@ resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.18.tgz#e99fee9ea040b9be7b233a55a0ae5cab1b90e031" integrity sha512-eVTpiyFOA70SecGuiXs2qxQq1oWbEiLJMpyOYF8HAHFXHH+iK0Ab8F0stdyJTTYOc9ydjFQgYXmbENG6JqQ3UA== +"@better-auth/sso@^1.3.18": + version "1.3.18" + resolved "https://registry.yarnpkg.com/@better-auth/sso/-/sso-1.3.18.tgz#f8afacdbab253229801653f3d4ac58f4d7d6fa96" + integrity sha512-usN8PD4oWDDVSJrhEhUDc+c2mE7G1IdET2fhmDMa7ZXCvg3B8I+gGjs2AaTlXppnvESrBOw31Q07IhLyjvcm8g== + dependencies: + "@better-fetch/fetch" "^1.1.18" + fast-xml-parser "^5.2.5" + jose "^6.1.0" + oauth2-mock-server "^7.2.1" + samlify "^2.10.1" + zod "^4.1.5" + "@better-auth/utils@0.3.0", "@better-auth/utils@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@better-auth/utils/-/utils-0.3.0.tgz#066c5ce82bf393421547dd887b14a6899310003d" @@ -2096,6 +2117,16 @@ resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f" integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== +"@xmldom/is-dom-node@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@xmldom/is-dom-node/-/is-dom-node-1.0.1.tgz#83b9f3e1260fb008061c6fa787b93a00f9be0629" + integrity sha512-CJDxIgE5I0FH+ttq/Fxy6nRpxP70+e2O048EPe85J2use3XKdatVM7dDVvFNjQudd9B49NPoZ+8PG49zj4Er8Q== + +"@xmldom/xmldom@^0.8.10", "@xmldom/xmldom@^0.8.6": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608" + integrity sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw== + "@zenuml/core@^3.17.2": version "3.29.7" resolved "https://registry.yarnpkg.com/@zenuml/core/-/core-3.29.7.tgz#54a551a8ca0bdd6c417dc0b5dcf0f4430d85607c" @@ -2339,6 +2370,13 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +asn1@^0.2.4: + version "0.2.6" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" + integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== + dependencies: + safer-buffer "~2.1.0" + asn1js@^3.0.6: version "3.0.6" resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.6.tgz#53e002ebe00c5f7fd77c1c047c3557d7c04dce25" @@ -2378,7 +2416,7 @@ base64id@2.0.0, base64id@~2.0.0: resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6" integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog== -basic-auth@~2.0.1: +basic-auth@^2.0.1, basic-auth@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/basic-auth/-/basic-auth-2.0.1.tgz#b998279bf47ce38344b4f3cf916d4679bbf51e3a" integrity sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg== @@ -2447,6 +2485,24 @@ body-parser@1.20.2: type-is "~1.6.18" unpipe "1.0.0" +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== + dependencies: + bytes "3.1.2" + content-type "~1.0.5" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.13.0" + raw-body "2.5.2" + type-is "~1.6.18" + unpipe "1.0.0" + body-parser@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa" @@ -2579,6 +2635,11 @@ camelcase@^5.3.1: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -2870,6 +2931,11 @@ cookie@0.6.0: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== +cookie@0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" + integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== + cookie@0.7.2, cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" @@ -3560,7 +3626,7 @@ enabled@2.0.x: resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2" integrity sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ== -encodeurl@^2.0.0: +encodeurl@^2.0.0, encodeurl@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== @@ -3854,6 +3920,43 @@ express@^4.18.2: utils-merge "1.0.1" vary "~1.1.2" +express@^4.21.2: + version "4.21.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" + integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.3" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.7.1" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~2.0.0" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.3.1" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.3" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.12" + proxy-addr "~2.0.7" + qs "6.13.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.19.0" + serve-static "1.16.2" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + express@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/express/-/express-5.1.0.tgz#d31beaf715a0016f0d53f47d3b4d7acf28c75cc9" @@ -3967,6 +4070,13 @@ fast-write-atomic@0.2.1: resolved "https://registry.yarnpkg.com/fast-write-atomic/-/fast-write-atomic-0.2.1.tgz#7ee8ef0ce3c1f531043c09ae8e5143361ab17ede" integrity sha512-WvJe06IfNYlr+6cO3uQkdKdy3Cb1LlCJSF8zRs2eT8yuhdbSlR9nIt+TgQ92RUxiRrQm+/S7RARnMfCs5iuAjw== +fast-xml-parser@^5.2.5: + version "5.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz#4809fdfb1310494e341098c25cb1341a01a9144a" + integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ== + dependencies: + strnum "^2.1.0" + fastq@^1.6.0: version "1.17.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" @@ -4018,6 +4128,19 @@ finalhandler@1.2.0: statuses "2.0.1" unpipe "~1.0.0" +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== + dependencies: + debug "2.6.9" + encodeurl "~2.0.0" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + finalhandler@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-2.1.0.tgz#72306373aa89d05a8242ed569ed86a1bff7c561f" @@ -4642,6 +4765,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== + is-promise@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3" @@ -4693,6 +4821,11 @@ jiti@^2.4.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.5.1.tgz#bd099c1c2be1c59bbea4e5adcd127363446759d0" integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== +jose@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/jose/-/jose-5.10.0.tgz#c37346a099d6467c401351a9a0c2161e0f52c4be" + integrity sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg== + jose@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.0.tgz#96285365689d16f2845a353964d2284bf19f464c" @@ -5028,6 +5161,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== + merge-descriptors@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-2.0.0.tgz#ea922f660635a2249ee565e0449f951e6b603808" @@ -5529,6 +5667,18 @@ node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" +node-forge@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + +node-rsa@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/node-rsa/-/node-rsa-1.1.1.tgz#efd9ad382097782f506153398496f79e4464434d" + integrity sha512-Jd4cvbJMryN21r5HgxQOpMEqv+ooke/korixNNK3mGqfGJmy0M77WDDzo/05969+OkMy3XW1UuZsSmW9KQm7Fw== + dependencies: + asn1 "^0.2.4" + nodemon@^3.1.10: version "3.1.10" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.1.10.tgz#5015c5eb4fffcb24d98cf9454df14f4fecec9bc1" @@ -5615,6 +5765,17 @@ nypm@^0.6.0: pkg-types "^2.2.0" tinyexec "^1.0.1" +oauth2-mock-server@^7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/oauth2-mock-server/-/oauth2-mock-server-7.2.1.tgz#7f5a01def55883adfe749a6a542bae7412265c45" + integrity sha512-ZXL+VuJU2pvzehseq+7b47ZSN7p2Z7J5GoI793X0oECgdLYdol7tnBbTY/aUxuMkk+xpnE186ZzhnigwCAEBOQ== + dependencies: + basic-auth "^2.0.1" + cors "^2.8.5" + express "^4.21.2" + is-plain-object "^5.0.0" + jose "^5.10.0" + object-assign@^4, object-assign@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -5787,6 +5948,11 @@ package-manager-detector@^0.2.8: dependencies: quansync "^0.2.7" +pako@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5842,6 +6008,11 @@ path-scurry@^1.11.1: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" + integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== + path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" @@ -6374,6 +6545,13 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== + dependencies: + side-channel "^1.0.6" + qs@^6.14.0: version "6.14.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" @@ -6683,11 +6861,28 @@ safe-stable-stringify@^2.3.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +samlify@^2.10.1: + version "2.10.1" + resolved "https://registry.yarnpkg.com/samlify/-/samlify-2.10.1.tgz#615f2ebf51c8a121abe021479a9c11978765c1b5" + integrity sha512-4zHbKKTvPnnqfGu4tks26K4fJjsY99ylsP7TPMobW5rggwcsxNlyhLE9ucxW3JFCsUcoKXb77QjQjwQo1TtRgw== + dependencies: + "@authenio/xml-encryption" "^2.0.2" + "@xmldom/xmldom" "^0.8.6" + camelcase "^6.2.0" + node-forge "^1.3.0" + node-rsa "^1.1.1" + pako "^1.0.10" + uuid "^8.3.2" + xml "^1.0.1" + xml-crypto "^6.1.2" + xml-escape "^1.1.0" + xpath "^0.0.32" + "semver@2 || 3 || 4 || 5": version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -6732,6 +6927,25 @@ send@0.18.0: range-parser "~1.2.1" statuses "2.0.1" +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + send@^1.1.0, send@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/send/-/send-1.2.0.tgz#32a7554fb777b831dfa828370f773a3808d37212" @@ -6759,6 +6973,16 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== + dependencies: + encodeurl "~2.0.0" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.19.0" + serve-static@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-2.2.0.tgz#9c02564ee259bdd2251b82d659a2e7e1938d66f9" @@ -6847,7 +7071,7 @@ side-channel@^1.0.4: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -side-channel@^1.1.0: +side-channel@^1.0.6, side-channel@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== @@ -7072,6 +7296,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.1.1.tgz#cf2a6e0cf903728b8b2c4b971b7e36b4e82d46ab" + integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw== + stylis@^4.1.3: version "4.3.2" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" @@ -7538,6 +7767,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + uuid@^9.0.0: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" @@ -7727,6 +7961,35 @@ ws@~8.17.1: resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== +xml-crypto@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/xml-crypto/-/xml-crypto-6.1.2.tgz#ed93e87d9538f92ad1ad2db442e9ec586723d07d" + integrity sha512-leBOVQdVi8FvPJrMYoum7Ici9qyxfE4kVi+AkpUoYCSXaQF4IlBm1cneTK9oAxR61LpYxTx7lNcsnBIeRpGW2w== + dependencies: + "@xmldom/is-dom-node" "^1.0.1" + "@xmldom/xmldom" "^0.8.10" + xpath "^0.0.33" + +xml-escape@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xml-escape/-/xml-escape-1.1.0.tgz#3904c143fa8eb3a0030ec646d2902a2f1b706c44" + integrity sha512-B/T4sDK8Z6aUh/qNr7mjKAwwncIljFuUP+DO/D5hloYFj+90O88z8Wf7oSucZTHxBAsC1/CTP4rtx/x1Uf72Mg== + +xml@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + integrity sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw== + +xpath@0.0.32, xpath@^0.0.32: + version "0.0.32" + resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.32.tgz#1b73d3351af736e17ec078d6da4b8175405c48af" + integrity sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw== + +xpath@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.33.tgz#5136b6094227c5df92002e7c3a13516a5074eb07" + integrity sha512-NNXnzrkDrAzalLhIUc01jO2mOzXGXh1JwPgkihcLLzw98c0WgYDmmjSh1Kl3wzaxSVWMuA+fe0WTWOBDWCBmNA== + xtend@^4.0.0: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" From 6ca021d274f23a8d3fc44787c2b673458539db2a Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 28 Sep 2025 12:14:20 +0000 Subject: [PATCH 20/89] some implementations --- src/app.ts | 57 +++++++++++------------------------------------------ src/auth.ts | 22 ++++++++++++++------- 2 files changed, 27 insertions(+), 52 deletions(-) diff --git a/src/app.ts b/src/app.ts index 88b95ce..0b45277 100644 --- a/src/app.ts +++ b/src/app.ts @@ -10,7 +10,9 @@ import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRul import authConfig from './routes/authConfig'; import { type User } from '@prisma/client'; import BaseError, { HttpStatusCode } from './utils/errors/BaseError'; -import { HTTP401Error } from './utils/errors/Errors'; +import { fromNodeHeaders, toNodeHandler } from 'better-auth/node'; +import { auth } from './auth'; + import connectPgSimple from 'connect-pg-simple'; import Logger from './utils/logger'; import type { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; @@ -44,58 +46,18 @@ app.use( }) ); +// make sure to configure *before* the json middleware +app.all('/api/auth/{*route}', toNodeHandler(auth)); + // received packages should be presented in the JSON format app.use(express.json({ limit: '5mb' })); app.use(morganMiddleware); -const store = new (connectPgSimple(session))({ - conString: process.env.DATABASE_URL, - tableName: 'sessions' -}); - -const SESSION_MAX_AGE = 2592000000 as const; // 1000 * 60 * 60 * 24 * 30 = 2592000000 = 30 days - /** make sure to have 1 (reverse) proxy in front of the application * as is the case with dokku (nginx) */ app.set('trust proxy', 1); -const SESSION_KEY = `${process.env.APP_NAME || 'twa'}ApiKey`; - -/** https://medium.com/developer-rants/how-to-handle-sessions-properly-in-express-js-with-heroku-c35ea8c0e500 */ -export const sessionMiddleware = session({ - name: SESSION_KEY /** twa stands for "TeachingWebsiteApi" */, - store: store, - secret: process.env.SESSION_SECRET || 'secret', - saveUninitialized: false, - resave: false, - proxy: process.env.NODE_ENV === 'production', - cookie: { - secure: process.env.NODE_ENV === 'production', - httpOnly: true, - sameSite: SAME_SITE, - maxAge: SESSION_MAX_AGE // 30 days - } -}); - -// app.use(sessionMiddleware); - -// app.use(passport.initialize()); - -/** alias for passport.authenticate('session'); e.g. to use the session... */ -// app.use(passport.session()); - -// // passport.use(strategyForEnvironment()); - -// passport.serializeUser((user, done) => { -// done(null, user.id); -// }); - -const deserializeUser = async (id: string, done: (err: any, user?: User | null) => void) => { - const user = await prisma.user.findUnique({ where: { id: id } }); - done(null, user); -}; - // passport.deserializeUser(deserializeUser); // Serve the static files to be accessed by the docs app @@ -116,7 +78,12 @@ const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) = }; const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - return res.status(200).send('OK'); + const session = await auth.api.getSession({ + headers: fromNodeHeaders(req.headers) + }); + return res.json(session); + + // return res.status(200).send('OK'); // if (req.user) { // } // throw new HTTP401Error(); diff --git a/src/auth.ts b/src/auth.ts index fb0c2c3..54d2764 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -2,15 +2,28 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; import { Role } from '@prisma/client'; +import { admin } from 'better-auth/plugins'; +import { sso } from '@better-auth/sso'; + // If your Prisma file is located elsewhere, you can change the path export const auth = betterAuth({ + socialProviders: { + github: { + clientId: process.env.GITHUB_CLIENT_ID!, + clientSecret: process.env.GITHUB_CLIENT_SECRET! + } + }, database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: true }), + advanced: { + database: { + generateId: false + } + }, user: { - modelName: 'users', additionalFields: { role: { type: 'string', @@ -30,10 +43,5 @@ export const auth = betterAuth({ } } }, - session: { - modelName: 'sessions' - }, - account: { - modelName: 'accounts' - } + plugins: [admin(), sso()] }); From f17ef7950edac51a1582e79218ce7687ec2d358d Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 08:04:39 +0000 Subject: [PATCH 21/89] poc of better-auth --- .gitignore | 1 + package.json | 11 +- .../20250927122610_better_auth/migration.sql | 86 - .../migration.sql | 2 - .../migration.sql | 8 - .../migration.sql | 19 - .../migration.sql | 8 + .../migration.sql | 117 + prisma/schema.prisma | 79 +- prisma/seed-files/users.ts | 18 +- src/app.ts | 92 +- src/auth.ts | 75 +- src/auth/azureAD.ts | 52 - src/auth/guard.ts | 29 +- src/auth/index.ts | 39 - src/auth/mock.ts | 65 - src/controllers/users.ts | 2 +- src/helpers/authInfo.ts | 52 - src/models/Document.ts | 120 +- src/models/DocumentRoot.ts | 137 +- src/models/RootGroupPermission.ts | 35 +- src/models/RootUserPermission.ts | 36 +- src/models/StudentGroup.ts | 157 +- src/models/User.ts | 68 +- src/routes/authConfig.ts | 139 +- src/routes/event-handlers/action.handler.ts | 39 +- src/routes/event-handlers/joinRoom.handler.ts | 19 +- src/routes/socketEvents.ts | 30 +- src/server.ts | 42 +- src/types/express/index.d.ts | 5 +- src/utils/originConfig.ts | 10 + tsconfig.json | 12 +- yarn.lock | 2674 +++++++---------- 33 files changed, 1443 insertions(+), 2835 deletions(-) delete mode 100644 prisma/migrations/20250927122610_better_auth/migration.sql delete mode 100644 prisma/migrations/20250928115531_rename_user_role/migration.sql delete mode 100644 prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql delete mode 100644 prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql create mode 100644 prisma/migrations/20251005091234_remove_express_sessions/migration.sql create mode 100644 prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql delete mode 100644 src/auth/azureAD.ts delete mode 100644 src/auth/index.ts delete mode 100644 src/auth/mock.ts delete mode 100644 src/helpers/authInfo.ts diff --git a/.gitignore b/.gitignore index b53b451..5f68277 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ node_modules docs/prisma/**/* docs/*.svg dist/ +build/ # Sentry Config File .sentryclirc diff --git a/package.json b/package.json index 9feb26d..e940c6d 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "license": "CC-BY-SA", "scripts": { "dev": "cross-env NODE_ENV=development nodemon -r tsconfig-paths/register --exec ts-node ./src/server.ts --files", - "build": "tsc && tsc-alias", - "start": "cross-env NODE_ENV=production node ./build/src/server.js", + "build": "tsc --build ./tsconfig.build.json", + "start": "cross-env NODE_ENV=production node ./dist/src/server.js", "lint": "eslint . --ignore-pattern node_modules --fix", "format": "prettier --write ./**/*.{ts,json}", "format:check": "prettier --check .", @@ -20,19 +20,17 @@ "sentry:sourcemaps": "sentry-cli sourcemaps inject --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist && sentry-cli sourcemaps upload --org $SENTRY_ORG --project $SENTRY_PROJECT ./dist" }, "dependencies": { - "@better-auth/sso": "^1.3.18", + "@better-auth/sso": "^1.3.26", "@prisma/adapter-pg": "^6.16.2", "@prisma/client": "^6.16.2", "@sentry/cli": "^2.52.0", "@sentry/node": "^10.8.0", "better-auth": "^1.3.18", - "connect-pg-simple": "^9.0.1", "cors": "^2.8.5", "cross-env": "^10.0.0", "dotenv": "^17.2.2", "es-toolkit": "^1.39.10", "express": "^5.1.0", - "express-session": "^1.18.2", "global": "^4.4.0", "morgan": "^1.10.0", "socket.io": "^4.8.1", @@ -45,7 +43,6 @@ }, "devDependencies": { "@mermaid-js/mermaid-cli": "^10.9.1", - "@types/connect-pg-simple": "^7.0.3", "@types/cors": "^2.8.17", "@types/express": "^5.0.3", "@types/morgan": "^1.9.9", @@ -71,4 +68,4 @@ "engines": { "node": "^22.11.0" } -} +} \ No newline at end of file diff --git a/prisma/migrations/20250927122610_better_auth/migration.sql b/prisma/migrations/20250927122610_better_auth/migration.sql deleted file mode 100644 index 8f72891..0000000 --- a/prisma/migrations/20250927122610_better_auth/migration.sql +++ /dev/null @@ -1,86 +0,0 @@ -/* - Warnings: - - - The primary key for the `sessions` table will be changed. If it partially fails, the table could be left without primary key constraint. - - You are about to drop the column `expire` on the `sessions` table. All the data in the column will be lost. - - You are about to drop the column `sess` on the `sessions` table. All the data in the column will be lost. - - You are about to drop the column `sid` on the `sessions` table. All the data in the column will be lost. - - A unique constraint covering the columns `[token]` on the table `sessions` will be added. If there are existing duplicate values, this will fail. - - Added the required column `createdAt` to the `sessions` table without a default value. This is not possible if the table is not empty. - - Added the required column `expiresAt` to the `sessions` table without a default value. This is not possible if the table is not empty. - - Added the required column `id` to the `sessions` table without a default value. This is not possible if the table is not empty. - - Added the required column `token` to the `sessions` table without a default value. This is not possible if the table is not empty. - - Added the required column `updatedAt` to the `sessions` table without a default value. This is not possible if the table is not empty. - - Added the required column `user_id` to the `sessions` table without a default value. This is not possible if the table is not empty. - -*/ --- DropIndex -DROP INDEX "public"."IDX_session_expire"; - --- AlterTable -ALTER TABLE "public"."sessions" DROP CONSTRAINT "sessions_pkey", -DROP COLUMN "expire", -DROP COLUMN "sess", -DROP COLUMN "sid", -ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL, -ADD COLUMN "expiresAt" TIMESTAMP(3) NOT NULL, -ADD COLUMN "id" TEXT NOT NULL, -ADD COLUMN "ipAddress" TEXT, -ADD COLUMN "token" TEXT NOT NULL, -ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL, -ADD COLUMN "userAgent" TEXT, -ADD COLUMN "user_id" UUID NOT NULL, -ADD CONSTRAINT "sessions_pkey" PRIMARY KEY ("id"); - --- AlterTable -ALTER TABLE "public"."users" ADD COLUMN "email_verified" BOOLEAN NOT NULL DEFAULT false, -ADD COLUMN "image" TEXT, -ADD COLUMN "name" TEXT NOT NULL DEFAULT ''; - -UPDATE "public"."users" SET "name" = CASE - WHEN role = 'STUDENT' THEN - first_name || ' ' || LEFT(last_name, 1) || '.' - ELSE - LEFT(first_name, 1) || '. ' || last_name - END; - --- CreateTable -CREATE TABLE "public"."accounts" ( - "id" TEXT NOT NULL, - "accountId" TEXT NOT NULL, - "providerId" TEXT NOT NULL, - "userId" UUID NOT NULL, - "accessToken" TEXT, - "refreshToken" TEXT, - "idToken" TEXT, - "expiresAt" TIMESTAMP(3), - "password" TEXT, - "accessTokenExpiresAt" TIMESTAMP(3), - "refreshTokenExpiresAt" TIMESTAMP(3), - "scope" TEXT, - "createdAt" TIMESTAMP(3) NOT NULL, - "updatedAt" TIMESTAMP(3) NOT NULL, - - CONSTRAINT "accounts_pkey" PRIMARY KEY ("id") -); - --- CreateTable -CREATE TABLE "public"."verifications" ( - "id" TEXT NOT NULL, - "identifier" TEXT NOT NULL, - "value" TEXT NOT NULL, - "expiresAt" TIMESTAMP(3) NOT NULL, - "createdAt" TIMESTAMP(3), - "updatedAt" TIMESTAMP(3), - - CONSTRAINT "verifications_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "sessions_token_key" ON "public"."sessions"("token"); - --- AddForeignKey -ALTER TABLE "public"."sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20250928115531_rename_user_role/migration.sql b/prisma/migrations/20250928115531_rename_user_role/migration.sql deleted file mode 100644 index 64d87d1..0000000 --- a/prisma/migrations/20250928115531_rename_user_role/migration.sql +++ /dev/null @@ -1,2 +0,0 @@ --- AlterTable -ALTER TABLE "public"."users" RENAME COLUMN "role" TO "tdev_role"; diff --git a/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql b/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql deleted file mode 100644 index 33727d6..0000000 --- a/prisma/migrations/20250928115923_add_better_auth_admin_plugin/migration.sql +++ /dev/null @@ -1,8 +0,0 @@ --- AlterTable -ALTER TABLE "public"."sessions" ADD COLUMN "impersonatedBy" TEXT; - --- AlterTable -ALTER TABLE "public"."users" ADD COLUMN "banExpires" TIMESTAMP(3), -ADD COLUMN "banReason" TEXT, -ADD COLUMN "banned" BOOLEAN DEFAULT false, -ADD COLUMN "role" TEXT; diff --git a/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql b/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql deleted file mode 100644 index 5d22b82..0000000 --- a/prisma/migrations/20250928120837_add_better_auth_sso_plugin/migration.sql +++ /dev/null @@ -1,19 +0,0 @@ --- CreateTable -CREATE TABLE "public"."ssoProvider" ( - "id" TEXT NOT NULL, - "issuer" TEXT NOT NULL, - "oidcConfig" TEXT, - "samlConfig" TEXT, - "userId" UUID, - "providerId" TEXT NOT NULL, - "organizationId" TEXT, - "domain" TEXT NOT NULL, - - CONSTRAINT "ssoProvider_pkey" PRIMARY KEY ("id") -); - --- CreateIndex -CREATE UNIQUE INDEX "ssoProvider_providerId_key" ON "public"."ssoProvider"("providerId"); - --- AddForeignKey -ALTER TABLE "public"."ssoProvider" ADD CONSTRAINT "ssoProvider_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/migrations/20251005091234_remove_express_sessions/migration.sql b/prisma/migrations/20251005091234_remove_express_sessions/migration.sql new file mode 100644 index 0000000..1a2718b --- /dev/null +++ b/prisma/migrations/20251005091234_remove_express_sessions/migration.sql @@ -0,0 +1,8 @@ +/* + Warnings: + + - You are about to drop the `sessions` table. If the table is not empty, all the data it contains will be lost. + +*/ +-- DropTable +DROP TABLE "public"."sessions"; diff --git a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql new file mode 100644 index 0000000..b71f828 --- /dev/null +++ b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql @@ -0,0 +1,117 @@ +/* + Warnings: + + - The `role` column on the `users` table would be dropped and recreated. This will lead to data loss if there is data in the column. + +*/ +-- AlterTable +ALTER TABLE "public"."users" ADD COLUMN "ban_expires" TIMESTAMP(3), +ADD COLUMN "ban_reason" TEXT, +ADD COLUMN "banned" BOOLEAN DEFAULT false, +ADD COLUMN "email_verified" BOOLEAN NOT NULL DEFAULT false, +ADD COLUMN "image" TEXT, +ADD COLUMN "name" TEXT NOT NULL DEFAULT '', +ADD COLUMN "trole" TEXT NOT NULL DEFAULT 'student'; + +UPDATE "public"."users" SET "trole" = 'admin' WHERE "role" = 'ADMIN'; +UPDATE "public"."users" SET "trole" = 'teacher' WHERE "role" = 'TEACHER'; + +ALTER TABLE "public"."users" +DROP COLUMN "role", +ADD COLUMN "role" TEXT NOT NULL DEFAULT 'student'; + +UPDATE "public"."users" SET "role" = trole; + +ALTER TABLE "public"."users" +DROP COLUMN "trole"; + +-- DropEnum +DROP TYPE "public"."Role"; + +-- CreateTable +CREATE TABLE "public"."sessions" ( + "id" UUID NOT NULL DEFAULT gen_random_uuid(), + "ip_address" TEXT, + "user_agent" TEXT, + "user_id" UUID NOT NULL, + "token" TEXT NOT NULL, + "expires_at" TIMESTAMP(3) NOT NULL, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "impersonated_by" UUID, + + CONSTRAINT "sessions_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."accounts" ( + "id" UUID NOT NULL DEFAULT gen_random_uuid(), + "account_id" TEXT NOT NULL, + "provider_id" TEXT NOT NULL, + "userId" UUID NOT NULL, + "access_token" TEXT, + "refresh_token" TEXT, + "id_token" TEXT, + "expires_at" TIMESTAMP(3), + "password" TEXT, + "access_token_expires_at" TIMESTAMP(3), + "refresh_token_expires_at" TIMESTAMP(3), + "scope" TEXT, + "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "accounts_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."verifications" ( + "id" UUID NOT NULL DEFAULT gen_random_uuid(), + "identifier" TEXT NOT NULL, + "value" TEXT NOT NULL, + "expires_at" TIMESTAMP(3) NOT NULL, + "created_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + "updated_at" TIMESTAMP(3) DEFAULT CURRENT_TIMESTAMP, + + CONSTRAINT "verifications_pkey" PRIMARY KEY ("id") +); + +-- CreateTable +CREATE TABLE "public"."ssoProviders" ( + "id" UUID NOT NULL DEFAULT gen_random_uuid(), + "issuer" TEXT NOT NULL, + "oidc_config" TEXT, + "saml_config" TEXT, + "user_id" UUID, + "provider_id" TEXT NOT NULL, + "organization_id" TEXT, + "domain" TEXT NOT NULL, + + CONSTRAINT "ssoProviders_pkey" PRIMARY KEY ("id") +); + +-- CreateIndex +CREATE UNIQUE INDEX "sessions_token_key" ON "public"."sessions"("token"); + +-- CreateIndex +CREATE INDEX "sessions_user_id_idx" ON "public"."sessions"("user_id"); + +-- CreateIndex +CREATE INDEX "sessions_user_id_token_idx" ON "public"."sessions"("user_id", "token"); + +-- CreateIndex +CREATE INDEX "accounts_userId_idx" ON "public"."accounts"("userId"); + +-- CreateIndex +CREATE INDEX "verifications_identifier_idx" ON "public"."verifications"("identifier"); + +-- CreateIndex +CREATE UNIQUE INDEX "ssoProviders_provider_id_key" ON "public"."ssoProviders"("provider_id"); + +-- AddForeignKey +ALTER TABLE "public"."sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; + +-- AddForeignKey +ALTER TABLE "public"."ssoProviders" ADD CONSTRAINT "ssoProviders_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 3403584..71f8fcc 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -25,7 +25,6 @@ model User { firstName String @map("first_name") lastName String @map("last_name") - tdevRole Role @default(STUDENT) @map("tdev_role") documents Document[] @relation("documents") rootUserPermissions RootUserPermission[] @relation("root_user_to_user_permission") view_DocumentUserPermissions view_DocumentUserPermissions[] @@ -36,10 +35,10 @@ model User { sessions Session[] accounts Account[] - role String? + role String @default("student") banned Boolean? @default(false) - banReason String? - banExpires DateTime? + banReason String? @map("ban_reason") + banExpires DateTime? @map("ban_expires") ssoproviders SsoProvider[] @@ -47,67 +46,69 @@ model User { } model Session { - id String @id - expiresAt DateTime - ipAddress String? - userAgent String? + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + ipAddress String? @map("ip_address") + userAgent String? @map("user_agent") userId String @map("user_id") @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) - token String - createdAt DateTime - updatedAt DateTime + token String @unique + expiresAt DateTime @map("expires_at") + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @default(now()) @updatedAt @map("updated_at") - impersonatedBy String? + impersonatedBy String? @map("impersonated_by") @db.Uuid - @@unique([token]) + @@index([userId]) + @@index([userId, token]) @@map("sessions") } model Account { - id String @id - accountId String - providerId String + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid + accountId String @map("account_id") + providerId String @map("provider_id") userId String @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) - accessToken String? - refreshToken String? - idToken String? - expiresAt DateTime? + accessToken String? @map("access_token") + refreshToken String? @map("refresh_token") + idToken String? @map("id_token") + expiresAt DateTime? @map("expires_at") password String? - accessTokenExpiresAt DateTime? - refreshTokenExpiresAt DateTime? + accessTokenExpiresAt DateTime? @map("access_token_expires_at") + refreshTokenExpiresAt DateTime? @map("refresh_token_expires_at") scope String? - createdAt DateTime - updatedAt DateTime + createdAt DateTime @default(now()) @map("created_at") + updatedAt DateTime @default(now()) @updatedAt @map("updated_at") + @@index([userId]) @@map("accounts") } model Verification { - id String @id + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid identifier String value String - expiresAt DateTime + expiresAt DateTime @map("expires_at") - createdAt DateTime? - updatedAt DateTime? + createdAt DateTime? @default(now()) @map("created_at") + updatedAt DateTime? @default(now()) @updatedAt @map("updated_at") + @@index([identifier]) @@map("verifications") } model SsoProvider { - id String @id + id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid issuer String - oidcConfig String? - samlConfig String? - userId String? @db.Uuid + oidcConfig String? @map("oidc_config") + samlConfig String? @map("saml_config") + userId String? @map("user_id") @db.Uuid user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - providerId String - organizationId String? + providerId String @unique @map("provider_id") + organizationId String? @map("organization_id") domain String - @@unique([providerId]) - @@map("ssoProvider") + @@map("ssoProviders") } model CmsSettings { @@ -297,9 +298,3 @@ enum Access { RW_User None_User } - -enum Role { - STUDENT - TEACHER - ADMIN -} diff --git a/prisma/seed-files/users.ts b/prisma/seed-files/users.ts index 720e233..240a5e6 100644 --- a/prisma/seed-files/users.ts +++ b/prisma/seed-files/users.ts @@ -1,4 +1,4 @@ -import { Prisma, Role } from '@prisma/client'; +import { Prisma } from '@prisma/client'; export const FOO_BAR_ID = '96651c13-3af6-4cc0-b242-ea38d438dc41'; export const TEST_USER_ID = '4b6d8b5d-3b6c-4c8b-8d3c-6f2c3f6e2b4b'; @@ -6,18 +6,8 @@ export const TEST_USER_ID = '4b6d8b5d-3b6c-4c8b-8d3c-6f2c3f6e2b4b'; const { USER_EMAIL, USER_ID } = process.env; const users: Prisma.UserCreateInput[] = [ - { - email: 'foo@bar.ch', - id: FOO_BAR_ID, - firstName: 'Foo', - lastName: 'Bar' - }, - { - email: 'test@user.ch', - id: TEST_USER_ID, - firstName: 'Test', - lastName: 'User' - } + { email: 'foo@bar.ch', id: FOO_BAR_ID, firstName: 'Foo', lastName: 'Bar' }, + { email: 'test@user.ch', id: TEST_USER_ID, firstName: 'Test', lastName: 'User' } ]; // Add admin user from .env-file. @@ -28,7 +18,7 @@ if (USER_EMAIL && USER_ID) { id: USER_ID, firstName: name.split('.')[0], lastName: name.split('.')[1] || name, - role: Role.ADMIN + role: 'admin' }); } diff --git a/src/app.ts b/src/app.ts index 0b45277..406ec57 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,23 +1,20 @@ import express, { NextFunction, Request, Response } from 'express'; -import session from 'express-session'; -import prisma from '@/prisma'; import path from 'path'; import cors from 'cors'; import morganMiddleware from './middleware/morgan.middleware'; // import passport from 'passport'; import router from './routes/router'; -import routeGuard, { PUBLIC_GET_ACCESS, PUBLIC_GET_ACCESS_REGEX, createAccessRules } from './auth/guard'; +import routeGuard, { createAccessRules } from './auth/guard'; import authConfig from './routes/authConfig'; import { type User } from '@prisma/client'; -import BaseError, { HttpStatusCode } from './utils/errors/BaseError'; +import BaseError from './utils/errors/BaseError'; import { fromNodeHeaders, toNodeHandler } from 'better-auth/node'; import { auth } from './auth'; -import connectPgSimple from 'connect-pg-simple'; import Logger from './utils/logger'; import type { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; import type { Server } from 'socket.io'; -import { CORS_ORIGIN, SAME_SITE } from './utils/originConfig'; +import { CORS_ORIGIN } from './utils/originConfig'; const AccessRules = createAccessRules(authConfig.accessMatrix); @@ -47,7 +44,7 @@ app.use( ); // make sure to configure *before* the json middleware -app.all('/api/auth/{*route}', toNodeHandler(auth)); +app.all('/api/auth/{*any}', toNodeHandler(auth)); // received packages should be presented in the JSON format app.use(express.json({ limit: '5mb' })); @@ -70,42 +67,6 @@ const welcomeApi = (req: Request, res: Response) => { // Public Endpoints app.get(`${API_URL}`, welcomeApi); -const SessionOauthStrategy = (req: Request, res: Response, next: NextFunction) => { - return next(); - // if (req.isAuthenticated()) { - // } - // passport.authenticate('oauth-bearer', { session: true })(req, res, next); -}; - -const checkLogin = async (req: Request, res: Response, next: NextFunction) => { - const session = await auth.api.getSession({ - headers: fromNodeHeaders(req.headers) - }); - return res.json(session); - - // return res.status(200).send('OK'); - // if (req.user) { - // } - // throw new HTTP401Error(); -}; - -app.get(`${API_URL}/checklogin`, SessionOauthStrategy, checkLogin); - -const logout = async (req: Request, res: Response, next: NextFunction) => { - // req.logout({ keepSessionInfo: false }, (err) => { - // if (err) { - // Logger.error(err); - // return next(err); - // } - // }); - // Logger.info(req.user); - // Logger.info(req.session); - // await prisma.sessions.delete({ where: { sid: req.session.id } }); - res.clearCookie(SESSION_KEY).send(); -}; - -app.post(`${API_URL}/logout`, logout); - const errorHandler = (err: Error, req: Request, res: Response, next: NextFunction) => { if ((err as BaseError).isHttpError) { const httpErr = err as BaseError; @@ -143,7 +104,7 @@ export const configure = (_app: typeof app) => { const except: string[] = []; /** ignore this socket */ if (!notification.toSelf) { - const socketID = req.headers['x-metadata-socketid'] as string; + const socketID = req.headers['x-metadata-sid'] as string; if (socketID) { except.push(socketID); } @@ -162,37 +123,20 @@ export const configure = (_app: typeof app) => { * permissions to access the requested route. */ _app.use( - `${API_URL}`, + API_URL, (req, res, next) => { - return next(); - // if (req.isAuthenticated()) { - // } - // passport.authenticate('oauth-bearer', { session: true }, (err: Error, user: User, info: any) => { - // if (err) { - // /** - // * An error occurred during authorization. Send a Not Autohrized - // * status code. - // */ - // return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: err.message }); - // } - - // if ( - // !user && - // !( - // PUBLIC_GET_ACCESS.has(req.path.toLowerCase()) || - // PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(req.path)) - // ) - // ) { - // // If no user object found, send a 401 response. - // return res.status(HttpStatusCode.UNAUTHORIZED).json({ error: 'Unauthorized' }); - // } - // req.user = user; - // if (info) { - // // access token payload will be available in req.authInfo downstream - // req.authInfo = info; - // return next(); - // } - // })(req, res, next); + return auth.api + .getSession({ headers: fromNodeHeaders(req.headers) }) + .then((session) => { + if (!session?.user) { + return res.status(401).json({ error: 'Unauthorized' }); + } + req.user = session.user as User; + return next(); + }) + .catch((err) => { + return res.status(401).json({ error: err.message }); + }); }, routeGuard(AccessRules), // route guard middleware router // the router with all the routes diff --git a/src/auth.ts b/src/auth.ts index 54d2764..9cf524a 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,47 +1,60 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { Role } from '@prisma/client'; -import { admin } from 'better-auth/plugins'; +import { admin, oneTimeToken } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; +import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; +import { getNameFromEmail } from './helpers/email'; +import type { MicrosoftEntraIDProfile } from 'better-auth/social-providers'; // If your Prisma file is located elsewhere, you can change the path +const COOKIE_PREFIX = process.env.APP_NAME || 'tdev'; + +const getNameFromMsftProfile = (profile: MicrosoftEntraIDProfile) => { + if (profile.name) { + const parts = profile.name.split(', ')[0]?.split(' ') || []; + if (parts.length > 1) { + const firstName = parts.pop()!; + const lastName = parts.join(' '); + return { firstName, lastName }; + } + } + return getNameFromEmail(profile.email || profile.preferred_username); +}; + export const auth = betterAuth({ socialProviders: { - github: { - clientId: process.env.GITHUB_CLIENT_ID!, - clientSecret: process.env.GITHUB_CLIENT_SECRET! - } - }, - database: prismaAdapter(prisma, { - provider: 'postgresql', - usePlural: true - }), - advanced: { - database: { - generateId: false + github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! }, + microsoft: { + clientId: process.env.MSAL_CLIENT_ID as string, + clientSecret: process.env.MSAL_CLIENT_SECRET as string, + // Optional + tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications + authority: 'https://login.microsoftonline.com', // Authentication authority URL + prompt: 'select_account', // Forces account selection, + mapProfileToUser: (profile) => { + console.log('MSFT Profile:', profile); + const email = (profile.email || profile.preferred_username)?.toLowerCase(); + const name = getNameFromMsftProfile(profile); + return { + id: profile.oid, + email: email, + firstName: name.firstName || '', + lastName: name.lastName || '' + // You can extract and map other fields as needed + }; + } } }, + trustedOrigins: CORS_ORIGIN_STRINGIFIED, + database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), + advanced: { cookiePrefix: 'express-bootstrap', database: { generateId: false, useNumberId: false } }, user: { additionalFields: { - role: { - type: 'string', - required: false, - defaultValue: Role.STUDENT, - input: false // don't allow user to set role - }, - firstName: { - type: 'string', - required: false, - input: false - }, - lastName: { - type: 'string', - required: false, - input: false - } + firstName: { type: 'string', required: false, input: false }, + lastName: { type: 'string', required: false, input: false } } }, - plugins: [admin(), sso()] + plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()] }); diff --git a/src/auth/azureAD.ts b/src/auth/azureAD.ts deleted file mode 100644 index 36a7ed7..0000000 --- a/src/auth/azureAD.ts +++ /dev/null @@ -1,52 +0,0 @@ -import prisma from '../prisma'; -// import { BearerStrategy, IBearerStrategyOptionWithRequest, VerifyBearerFunction } from 'passport-azure-ad'; -import { getAuthInfo, userProps } from '../helpers/authInfo'; -import authConfig from '../routes/authConfig'; -import Logger from '../utils/logger'; -// Set the Azure AD B2C options -const auth = { - tenantID: authConfig.credentials.tenantID, - clientID: authConfig.credentials.clientID, - audience: authConfig.credentials.clientID, - authority: authConfig.metadata.authority, - version: authConfig.metadata.version, - discovery: authConfig.metadata.discovery, - scope: ['access_as_user'], - validateIssuer: authConfig.settings.validateIssuer, - passReqToCallback: authConfig.settings.passReqToCallback, - loggingLevel: authConfig.settings.loggingLevel -}; - -const options = { - identityMetadata: `https://${auth.authority}/${auth.tenantID}/${auth.version}/${auth.discovery}`, - issuer: `https://${auth.authority}/${auth.tenantID}/${auth.version}`, - clientID: auth.clientID, - audience: auth.audience, - validateIssuer: auth.validateIssuer, - passReqToCallback: auth.passReqToCallback, - loggingLevel: auth.loggingLevel as 'info' | 'warn' | 'error' | undefined, - loggingNoPII: true, - scope: auth.scope -}; - -const BearerVerify = async (token: any, done: any) => { - const { oid } = getAuthInfo(token); - // @link https://medium.com/@prashantramnyc/node-js-with-passport-authentication-simplified-76ca65ee91e5 - const user = await prisma.user - .upsert({ - where: { id: oid }, - update: userProps(token, false), - create: userProps(token, true) - }) - .catch((err) => { - Logger.error('Bearer Verify Error', err); - return false; - }); - // Send user info using the second argument - done(null, user, token); -}; - -// export const getStrategy = () => { -// const strategy = new BearerStrategy(options, BearerVerify); -// return strategy; -// }; diff --git a/src/auth/guard.ts b/src/auth/guard.ts index c4d51b2..7524c99 100644 --- a/src/auth/guard.ts +++ b/src/auth/guard.ts @@ -1,19 +1,14 @@ import { NextFunction, Request, Response } from 'express'; -import { AccessMatrix, PUBLIC_ROUTES } from '../routes/authConfig'; +import { AccessMatrix } from '../routes/authConfig'; import Logger from '../utils/logger'; import { HttpStatusCode } from '../utils/errors/BaseError'; -import { Role } from '@prisma/client'; -import { getAccessLevel, hasElevatedAccess } from '../models/User'; -import { user } from '../controllers/users'; +import { getAccessLevel, Role } from '../models/User'; interface AccessRegexRule { path: string; regex: RegExp; weight: number; - access: { - methods: ('GET' | 'POST' | 'PUT' | 'DELETE')[]; - minRole: Role; - }[]; + access: { methods: ('GET' | 'POST' | 'PUT' | 'DELETE')[]; minRole: Role }[]; } const regexFromRoute = (route: string) => { @@ -29,12 +24,6 @@ const regexFromRoute = (route: string) => { return new RegExp(`^${regex}$`, 'i'); }; -export const PUBLIC_GET_ACCESS = new Set(PUBLIC_ROUTES.filter((route) => !route.includes(':'))); - -export const PUBLIC_GET_ACCESS_REGEX = PUBLIC_ROUTES.filter((route) => route.includes(':')).map( - regexFromRoute -); - export const createAccessRules = (accessMatrix: AccessMatrix): AccessRegexRule[] => { const accessRules = Object.values(accessMatrix); const maxParts = accessRules.reduce((max, accessRule) => { @@ -56,12 +45,7 @@ export const createAccessRules = (accessMatrix: AccessMatrix): AccessRegexRule[] .join('\\/'); const regex = new RegExp(`^${path}`, 'i'); - return { - ...accessRule, - path: accessRule.path.toLowerCase(), - regex: regex, - weight: weight - }; + return { ...accessRule, path: accessRule.path.toLowerCase(), regex: regex, weight: weight }; }); const rules = accessRulesWithRegex.sort((a, b) => b.weight - a.weight); Object.freeze(rules); @@ -76,10 +60,7 @@ const routeGuard = (accessMatrix: AccessRegexRule[]) => { return (req: Request, res: Response, next: NextFunction) => { const reqPath = req.path.toLowerCase(); /* istanbul ignore if */ - if ( - !(req as any).user && - !(PUBLIC_GET_ACCESS.has(reqPath) || PUBLIC_GET_ACCESS_REGEX.some((regex) => regex.test(reqPath))) - ) { + if (!(req as any).user) { return res.status(HttpStatusCode.FORBIDDEN).json({ error: 'No roles claim found!' }); } diff --git a/src/auth/index.ts b/src/auth/index.ts deleted file mode 100644 index 419fdc1..0000000 --- a/src/auth/index.ts +++ /dev/null @@ -1,39 +0,0 @@ -import Logger from '../utils/logger'; -import { getStrategy as mockStrategy } from './mock'; -import { getStrategy } from './azureAD'; -export const strategyForEnvironment = () => { - if (process.env.NODE_ENV === 'test' || (process.env.NO_AUTH && process.env.NODE_ENV !== 'production')) { - if (process.env.NO_AUTH) { - if (process.env.NODE_ENV !== 'test') { - Logger.info( - [ - '', - '┌──────────────────────────────────────────────────────────┐', - '│ │', - '│ _ _ _ _ │', - '│ | \\ | | /\\ | | | | │', - '│ | \\| | ___ / \\ _ _| |_| |__ │', - "│ | . ` |/ _ \\ / /\\ \\| | | | __| '_ \\ │", - '│ | |\\ | (_) | / ____ \\ |_| | |_| | | | │', - '│ |_| \\_|\\___/ /_/ \\_\\__,_|\\__|_| |_| │', - '│ │', - '│ │', - '│ │', - '│ │', - '│ --> enable authentication by removing "NO_AUTH" │', - '│ from the environment (or the .env file) │', - '│ │', - '└──────────────────────────────────────────────────────────┘' - ].join('\n') - ); - } - } - if (process.env.NODE_ENV !== 'test') { - Logger.info(`NODE_ENV: ${process.env.NODE_ENV}`); - Logger.info('USING MOCK STRATEGY'); - } - return mockStrategy(); - } - /* istanbul ignore next */ - return getStrategy(); -}; diff --git a/src/auth/mock.ts b/src/auth/mock.ts deleted file mode 100644 index 4079548..0000000 --- a/src/auth/mock.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* istanbul ignore file */ -import { Request } from 'express'; -import { ParamsDictionary } from 'express-serve-static-core'; -// import { Strategy, StrategyCreated, StrategyCreatedStatic } from 'passport'; -import { ParsedQs } from 'qs'; -import prisma from '../prisma'; -import Logger from '../utils/logger'; -class MockStrat { - name = 'oauth-bearer'; - constructor() { - // super(); - } - async authenticate( - this: any, - req: Request>, - options?: any - ) { - if (process.env.NODE_ENV === 'production') { - return this.fail('Mock Strategy not available in production'); - } - - let where: { email: string } | { id: string } | undefined = undefined; - if (process.env.NODE_ENV === 'test' && req.headers.authorization) { - try { - const auth = JSON.parse(req.headers.authorization) as { email: string }; - where = { email: auth.email || 'anonymous@user.ch' }; - } catch (/* istanbul ignore next */ err) { - Logger.warn('Bearer Verify Error', err); - return this.fail('Could not parse authorization header'); - } - } else if (req.headers.authorization) { - try { - const auth = JSON.parse(req.headers.authorization) as { email: string } | { id: string }; - if ('id' in auth) { - where = { id: auth.id }; - } else if ('email' in auth) { - where = { email: auth.email.toLowerCase() }; - } - } catch (/* istanbul ignore next */ err) { - Logger.warn('Bearer Verify Error', err); - return this.fail('Could not parse authorization header'); - } - } - if (!where) { - return this.fail('No User provided in request'); - } - try { - const user = await prisma.user.findUnique({ - where: where - }); - if (!user) { - return this.fail(`No User found for ${where}`); - } - return this.success(user, { preferred_username: user.email }); - } catch (/* istanbul ignore next */ err) { - Logger.error('Bearer Verify Error', err); - return this.fail(`No User found for ${where}`); - } - } -} - -export const getStrategy = () => { - const strategy = new MockStrat(); - return strategy; -}; diff --git a/src/controllers/users.ts b/src/controllers/users.ts index 5e92ce0..7c1bd4c 100644 --- a/src/controllers/users.ts +++ b/src/controllers/users.ts @@ -1,4 +1,4 @@ -import { User as DbUser, Role } from '@prisma/client'; +import { User as DbUser } from '@prisma/client'; import { RequestHandler } from 'express'; import User from '../models/User'; import Logger from '../utils/logger'; diff --git a/src/helpers/authInfo.ts b/src/helpers/authInfo.ts deleted file mode 100644 index aa32bf5..0000000 --- a/src/helpers/authInfo.ts +++ /dev/null @@ -1,52 +0,0 @@ -import type { Prisma } from '@prisma/client'; -import prisma from '../prisma'; -import { getNameFromEmail } from './email'; - -export const getAuthInfo = (authInfo?: Express.AuthInfo) => { - if (!authInfo) { - throw 'No valid authorization provided'; - } - const { name, preferred_username, oid } = (authInfo as any) || {}; - if (!(name || preferred_username) || !oid) { - throw 'No valid authorization provided'; - } - let firstName = ''; - let lastName = ''; - if (name) { - const parts = name.split(', ')[0]?.split(' ') || []; - if (parts.length > 1) { - firstName = parts.pop()!; - lastName = parts.join(' '); - } - } - if (!firstName && !lastName) { - const mailName = getNameFromEmail(preferred_username); - firstName = mailName.firstName; - lastName = mailName.lastName; - } - return { - email: preferred_username?.toLowerCase(), - firstName: firstName, - lastName: lastName, - oid: oid - }; -}; - -export const userProps = (authInfo?: Express.AuthInfo, includeId?: boolean): Prisma.UserCreateInput => { - const { email, firstName, lastName, oid } = getAuthInfo(authInfo); - return { - id: includeId ? oid : undefined, - email: email, - firstName: firstName, - lastName: lastName - }; -}; - -export const findUser = async (authInfo?: Express.AuthInfo) => { - const { oid } = getAuthInfo(authInfo); - return await prisma.user.upsert({ - where: { id: oid }, - update: userProps(authInfo, false), - create: userProps(authInfo, true) - }); -}; diff --git a/src/models/Document.ts b/src/models/Document.ts index 093b38c..39bc626 100644 --- a/src/models/Document.ts +++ b/src/models/Document.ts @@ -1,4 +1,4 @@ -import { Access, Document as DbDocument, PrismaClient, Role, User } from '@prisma/client'; +import { Access, Document as DbDocument, PrismaClient, User } from '@prisma/client'; import prisma from '../prisma'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; import { JsonObject } from '@prisma/client/runtime/library'; @@ -7,11 +7,9 @@ import { highestAccess, NoneAccess, RWAccess } from '../helpers/accessPolicy'; import { ApiGroupPermission } from './RootGroupPermission'; import { ApiUserPermission } from './RootUserPermission'; import Logger from '../utils/logger'; -import { hasElevatedAccess, whereStudentGroupAccess } from './User'; +import { hasElevatedAccess, Role, whereStudentGroupAccess } from './User'; -type AccessCheckableDocument = DbDocument & { - documentRoot: AccessCheckableDocumentRoot; -}; +type AccessCheckableDocument = DbDocument & { documentRoot: AccessCheckableDocumentRoot }; export type ApiDocument = DbDocument; @@ -71,28 +69,14 @@ function Document(db: PrismaClient['document']) { async findModel(actor: User, id: string): Promise { return db .findUnique({ - where: { - id: id - }, + where: { id: id }, include: { documentRoot: { include: { rootGroupPermissions: { - where: { - studentGroup: { - users: { - some: { - userId: actor.id - } - } - } - } + where: { studentGroup: { users: { some: { userId: actor.id } } } } }, - rootUserPermissions: { - where: { - user: actor - } - } + rootUserPermissions: { where: { user: actor } } } } } @@ -120,10 +104,7 @@ function Document(db: PrismaClient['document']) { where: actor.role === Role.ADMIN ? { id: _onBehalfOfUserId } - : { - id: _onBehalfOfUserId, - ...whereStudentGroupAccess(actor.id, true) - } + : { id: _onBehalfOfUserId, ...whereStudentGroupAccess(actor.id, true) } }); if (!onBehalfOfUser) { throw new HTTP404Error('On Behalf Of user not found or no required access'); @@ -150,11 +131,7 @@ function Document(db: PrismaClient['document']) { } if (uniqueMain) { const mainDoc = await db.findFirst({ - where: { - documentRootId: documentRootId, - authorId: authorId, - type: type - } + where: { documentRootId: documentRootId, authorId: authorId, type: type } }); if (mainDoc) { Logger.warn( @@ -181,23 +158,9 @@ function Document(db: PrismaClient['document']) { documentRoot: { include: { rootGroupPermissions: { - where: { - studentGroup: { - users: { - some: { - userId: authorId - } - } - } - } + where: { studentGroup: { users: { some: { userId: authorId } } } } }, - rootUserPermissions: { - where: { - user: { - id: authorId - } - } - } + rootUserPermissions: { where: { user: { id: authorId } } } } } } @@ -210,11 +173,7 @@ function Document(db: PrismaClient['document']) { const canCreate = RWAccess.has(model.highestPermission); if (!canCreate && !onBehalfOf) { Logger.info(`❌ New Model [${model.document.id}]: ${model.highestPermission}`); - db.delete({ - where: { - id: model.document.id - } - }); + db.delete({ where: { id: model.document.id } }); throw new HTTP403Error('Insufficient access permission'); } return { @@ -244,10 +203,7 @@ function Document(db: PrismaClient['document']) { where: actor.role === Role.ADMIN ? { id } - : { - id: id, - author: whereStudentGroupAccess(actor.id, true) - } + : { id: id, author: whereStudentGroupAccess(actor.id, true) } }); if (!record) { throw new HTTP404Error('Document not found'); @@ -269,27 +225,13 @@ function Document(db: PrismaClient['document']) { * only the data field is allowed to be updated */ const model = (await db.update({ - where: { - id: id - }, - data: { - data: docData - }, + where: { id: id }, + data: { data: docData }, include: { documentRoot: { include: { - rootGroupPermissions: { - select: { - access: true, - studentGroupId: true - } - }, - rootUserPermissions: { - select: { - access: true, - userId: true - } - } + rootGroupPermissions: { select: { access: true, studentGroupId: true } }, + rootUserPermissions: { select: { access: true, userId: true } } } } } @@ -311,24 +253,12 @@ function Document(db: PrismaClient['document']) { } const model = (await db.delete({ - where: { - id: id - }, + where: { id: id }, include: { documentRoot: { include: { - rootGroupPermissions: { - select: { - access: true, - studentGroupId: true - } - }, - rootUserPermissions: { - select: { - access: true, - userId: true - } - } + rootGroupPermissions: { select: { access: true, studentGroupId: true } }, + rootUserPermissions: { select: { access: true, userId: true } } } } } @@ -341,20 +271,12 @@ function Document(db: PrismaClient['document']) { throw new HTTP403Error('Not authorized'); } if (actor.role === Role.ADMIN) { - return db.findMany({ - where: { - documentRootId: { - in: documentRootIds - } - } - }); + return db.findMany({ where: { documentRootId: { in: documentRootIds } } }); } // only include documents where the author is in the same group as the actor. const documents = await db.findMany({ where: { - documentRootId: { - in: documentRootIds - }, + documentRootId: { in: documentRootIds }, author: whereStudentGroupAccess(actor.id, true) } }); diff --git a/src/models/DocumentRoot.ts b/src/models/DocumentRoot.ts index 1ceefcc..7fa35e7 100644 --- a/src/models/DocumentRoot.ts +++ b/src/models/DocumentRoot.ts @@ -6,15 +6,14 @@ import { PrismaClient, RootGroupPermission, RootUserPermission, - User, - Role + User } from '@prisma/client'; import { ApiDocument } from './Document'; import { ApiUserPermission } from './RootUserPermission'; import { ApiGroupPermission } from './RootGroupPermission'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; import { asDocumentRootAccess, asGroupAccess, asUserAccess } from '../helpers/accessPolicy'; -import { hasElevatedAccess, whereStudentGroupAccess } from './User'; +import { hasElevatedAccess, Role, whereStudentGroupAccess } from './User'; export type ApiDocumentRoot = DbDocumentRoot & { documents: ApiDocument[]; @@ -52,19 +51,11 @@ export interface UpdateConfig { } const prepareGroupPermission = (permission: RootGroupPermission): ApiGroupPermission => { - return { - id: permission.id, - access: permission.access, - groupId: permission.studentGroupId - }; + return { id: permission.id, access: permission.access, groupId: permission.studentGroupId }; }; const prepareUserPermission = (permission: RootUserPermission): ApiUserPermission => { - return { - id: permission.id, - access: permission.access, - userId: permission.userId - }; + return { id: permission.id, access: permission.access, userId: permission.userId }; }; const { ADMIN_USER_GROUP_ID } = process.env; @@ -73,12 +64,7 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { return Object.assign(db, { async findModel(actor: User, id: string): Promise { const documentRoot = (await prisma.view_UsersDocuments.findUnique({ - where: { - id_userId: { - id: id, - userId: actor.id - } - } + where: { id_userId: { id: id, userId: actor.id } } })) as ApiDocumentRoot | null; if (!documentRoot) { /** @@ -86,25 +72,11 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { * In this case, we have to load the document root directly. */ const docRoot = await db.findUnique({ - where: { - id: id - }, + where: { id: id }, include: { - rootUserPermissions: { - where: { - userId: actor.id - } - }, + rootUserPermissions: { where: { userId: actor.id } }, rootGroupPermissions: { - where: { - studentGroup: { - users: { - some: { - userId: actor.id - } - } - } - } + where: { studentGroup: { users: { some: { userId: actor.id } } } } } } }); @@ -127,12 +99,7 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { ignoreMissingRoots: boolean = false ): Promise { const documentRoots = (await prisma.view_UsersDocuments.findMany({ - where: { - id: { - in: ids - }, - userId: actorId - }, + where: { id: { in: ids }, userId: actorId }, relationLoadStrategy: 'query' })) as unknown as ApiDocumentRoot[]; const response = documentRoots @@ -150,27 +117,11 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { */ if (missingDocumentRoots.length > 0 && !ignoreMissingRoots) { const docRoots = await db.findMany({ - where: { - id: { - in: missingDocumentRoots - } - }, + where: { id: { in: missingDocumentRoots } }, include: { - rootUserPermissions: { - where: { - userId: actorId - } - }, + rootUserPermissions: { where: { userId: actorId } }, rootGroupPermissions: { - where: { - studentGroup: { - users: { - some: { - userId: actorId - } - } - } - } + where: { studentGroup: { users: { some: { userId: actorId } } } } } } }); @@ -193,10 +144,7 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { ADMIN_USER_GROUP_ID && !groupPermissions.some((gp) => gp.groupId === ADMIN_USER_GROUP_ID) ) { - groupPermissions.push({ - groupId: ADMIN_USER_GROUP_ID, - access: Access.RW_DocumentRoot - }); + groupPermissions.push({ groupId: ADMIN_USER_GROUP_ID, access: Access.RW_DocumentRoot }); } const model = await db.create({ data: { @@ -225,10 +173,7 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { } : undefined }, - include: { - rootGroupPermissions: true, - rootUserPermissions: true - } + include: { rootGroupPermissions: true, rootUserPermissions: true } }); return { @@ -241,17 +186,9 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { }, async updateModel(id: string, data: UpdateConfig): Promise { const model = await db.update({ - where: { - id: id - }, - data: { - access: asDocumentRootAccess(data.access), - sharedAccess: data.sharedAccess - }, - include: { - rootGroupPermissions: true, - rootUserPermissions: true - } + where: { id: id }, + data: { access: asDocumentRootAccess(data.access), sharedAccess: data.sharedAccess }, + include: { rootGroupPermissions: true, rootUserPermissions: true } }); return { @@ -269,30 +206,16 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { const userPermissions = await prisma.rootUserPermission.findMany({ where: actor.role === Role.ADMIN - ? { - documentRootId: id - } - : { - documentRootId: id, - user: whereStudentGroupAccess(actor.id, true) - } + ? { documentRootId: id } + : { documentRootId: id, user: whereStudentGroupAccess(actor.id, true) } }); const groupPermissions = await prisma.rootGroupPermission.findMany({ where: actor.role === Role.ADMIN - ? { - documentRootId: id - } + ? { documentRootId: id } : { documentRootId: id, - studentGroup: { - users: { - some: { - userId: actor.id, - isAdmin: true - } - } - } + studentGroup: { users: { some: { userId: actor.id, isAdmin: true } } } } }); return { @@ -311,22 +234,10 @@ function DocumentRoot(db: PrismaClient['documentRoot']) { } const model = await db.delete({ - where: { - id: id - }, + where: { id: id }, include: { - rootGroupPermissions: { - select: { - access: true, - studentGroupId: true - } - }, - rootUserPermissions: { - select: { - access: true, - userId: true - } - } + rootGroupPermissions: { select: { access: true, studentGroupId: true } }, + rootUserPermissions: { select: { access: true, userId: true } } } }); return model; diff --git a/src/models/RootGroupPermission.ts b/src/models/RootGroupPermission.ts index 632f4af..8595b28 100644 --- a/src/models/RootGroupPermission.ts +++ b/src/models/RootGroupPermission.ts @@ -1,16 +1,12 @@ -import { Access, PrismaClient, RootGroupPermission as DbGroupPermission, User, Role } from '@prisma/client'; +import { Access, PrismaClient, RootGroupPermission as DbGroupPermission, User } from '@prisma/client'; import prisma from '../prisma'; import { asGroupAccess } from '../helpers/accessPolicy'; -import { hasElevatedAccess } from './User'; +import { hasElevatedAccess, Role } from './User'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; // TODO: Consider checking existence of documentRoot / studentGroup to provide better error messages / exceptions. -export type ApiGroupPermission = { - id: string; - groupId: string; - access: Access; -}; +export type ApiGroupPermission = { id: string; groupId: string; access: Access }; export type CompleteApiGroupPermission = { id: string; @@ -29,15 +25,7 @@ function asCompleteApiRecord(dbResult: DbGroupPermission): CompleteApiGroupPermi } const ensureAccessOrThrow = async (actor: User, groupId: string) => { const group = await prisma.studentGroup.findUnique({ - where: { - id: groupId, - users: { - some: { - userId: actor.id, - isAdmin: true - } - } - } + where: { id: groupId, users: { some: { userId: actor.id, isAdmin: true } } } }); if (!group) { throw new HTTP403Error('Not authorized'); @@ -81,14 +69,7 @@ function RootGroupPermission(db: PrismaClient['rootGroupPermission']) { await ensureAccessOrThrow(actor, record.studentGroupId); } - const result = await db.update({ - where: { - id: id - }, - data: { - access: asGroupAccess(access) - } - }); + const result = await db.update({ where: { id: id }, data: { access: asGroupAccess(access) } }); return asCompleteApiRecord(result); }, @@ -104,11 +85,7 @@ function RootGroupPermission(db: PrismaClient['rootGroupPermission']) { await ensureAccessOrThrow(actor, record.studentGroupId); } - const result = await db.delete({ - where: { - id: id - } - }); + const result = await db.delete({ where: { id: id } }); return asCompleteApiRecord(result); } }); diff --git a/src/models/RootUserPermission.ts b/src/models/RootUserPermission.ts index ea24b4d..ef946e3 100644 --- a/src/models/RootUserPermission.ts +++ b/src/models/RootUserPermission.ts @@ -1,24 +1,17 @@ -import { Access, PrismaClient, Role } from '@prisma/client'; +import { Access, PrismaClient } from '@prisma/client'; import prisma from '../prisma'; import { RootUserPermission as DbRootUserPermission, User } from '@prisma/client'; import { asUserAccess } from '../helpers/accessPolicy'; -import { hasElevatedAccess, whereStudentGroupAccess } from './User'; +import { hasElevatedAccess, Role, whereStudentGroupAccess } from './User'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; // TODO: Consider checking existence of documentRoot / user to provide better error messages / exceptions. -export type ApiUserPermission = { - id: string; - userId: string; - access: Access; -}; +export type ApiUserPermission = { id: string; userId: string; access: Access }; const ensureAccessOrThrow = async (actor: User, userId: string) => { const user = await prisma.user.findUnique({ - where: { - id: userId, - ...whereStudentGroupAccess(actor.id, true) - } + where: { id: userId, ...whereStudentGroupAccess(actor.id, true) } }); if (!user) { throw new HTTP403Error('Not authorized'); @@ -40,11 +33,7 @@ function RootUserPermission(db: PrismaClient['rootUserPermission']) { await ensureAccessOrThrow(actor, userId); } const result = await db.create({ - data: { - documentRootId: documentRootId, - userId: userId, - access: asUserAccess(access) - } + data: { documentRootId: documentRootId, userId: userId, access: asUserAccess(access) } }); return result; }, @@ -60,14 +49,7 @@ function RootUserPermission(db: PrismaClient['rootUserPermission']) { if (actor.role === Role.TEACHER) { await ensureAccessOrThrow(actor, record.userId); } - const result = await db.update({ - where: { - id: id - }, - data: { - access: asUserAccess(access) - } - }); + const result = await db.update({ where: { id: id }, data: { access: asUserAccess(access) } }); return result; }, @@ -82,11 +64,7 @@ function RootUserPermission(db: PrismaClient['rootUserPermission']) { if (actor.role === Role.TEACHER) { await ensureAccessOrThrow(actor, record.userId); } - const result = await db.delete({ - where: { - id: id - } - }); + const result = await db.delete({ where: { id: id } }); return result; } }); diff --git a/src/models/StudentGroup.ts b/src/models/StudentGroup.ts index ee8af81..dfbb665 100644 --- a/src/models/StudentGroup.ts +++ b/src/models/StudentGroup.ts @@ -1,18 +1,15 @@ -import { Prisma, PrismaClient, StudentGroup as DbStudentGroup, User, Role } from '@prisma/client'; +import { Prisma, PrismaClient, StudentGroup as DbStudentGroup, User } from '@prisma/client'; import prisma from '../prisma'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; import { createDataExtractor } from '../helpers/dataExtractor'; -import { hasElevatedAccess } from './User'; +import { hasElevatedAccess, Role } from './User'; const getData = createDataExtractor( ['description', 'name'], ['parentId'] ); -export type ApiStudentGroup = DbStudentGroup & { - userIds: string[]; - adminIds: string[]; -}; +export type ApiStudentGroup = DbStudentGroup & { userIds: string[]; adminIds: string[] }; function asApiRecord( record: DbStudentGroup & { users: { userId: string; isAdmin: boolean }[] } @@ -62,24 +59,8 @@ function StudentGroup(db: PrismaClient['studentGroup']) { async findModel(actor: User, id: string): Promise { const adminAccess = actor.role === Role.ADMIN; const model = await db.findUnique({ - where: adminAccess - ? { id } - : { - id: id, - users: { - some: { - userId: actor.id - } - } - }, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + where: adminAccess ? { id } : { id: id, users: { some: { userId: actor.id } } }, + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(model); }, @@ -95,29 +76,16 @@ function StudentGroup(db: PrismaClient['studentGroup']) { typeof sanitized.parentId === 'string' ? sanitized.parentId : sanitized.parentId?.set; if (parentId && actor.role !== Role.ADMIN) { const isParentAdmin = await prisma.userStudentGroup.findFirst({ - where: { - studentGroupId: parentId, - userId: actor.id, - isAdmin: true - } + where: { studentGroupId: parentId, userId: actor.id, isAdmin: true } }); if (!isParentAdmin) { throw new HTTP403Error('Not authorized to create subgroup in this group'); } } const result = await db.update({ - where: { - id: id - }, + where: { id: id }, data: sanitized, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(result); }, @@ -143,32 +111,16 @@ function StudentGroup(db: PrismaClient['studentGroup']) { /** remove fields not updatable*/ const result = await db.update({ - where: { - id: id - }, + where: { id: id }, data: { users: { update: { - where: { - id: { - userId: userId, - studentGroupId: record.id - } - }, - data: { - isAdmin: isAdmin - } + where: { id: { userId: userId, studentGroupId: record.id } }, + data: { isAdmin: isAdmin } } } }, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(result)!; }, @@ -180,32 +132,16 @@ function StudentGroup(db: PrismaClient['studentGroup']) { } /** remove fields not updatable*/ const result = await db.update({ - where: { - id: id - }, + where: { id: id }, data: { users: { connectOrCreate: { - where: { - id: { - userId: userId, - studentGroupId: record.id - } - }, - create: { - userId: userId - } + where: { id: { userId: userId, studentGroupId: record.id } }, + create: { userId: userId } } } }, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(result)!; }, @@ -220,27 +156,9 @@ function StudentGroup(db: PrismaClient['studentGroup']) { } /** remove fields not updatable*/ const result = await db.update({ - where: { - id: id - }, - data: { - users: { - delete: { - id: { - userId: userId, - studentGroupId: record.id - } - } - } - }, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + where: { id: id }, + data: { users: { delete: { id: { userId: userId, studentGroupId: record.id } } } }, + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(result)!; }, @@ -255,14 +173,7 @@ function StudentGroup(db: PrismaClient['studentGroup']) { // user IDs should be provided, otherwise the frontend will not be able to relate the groups to the users const all = await db.findMany({ ...(actor.role === Role.ADMIN ? {} : { where: { users: { some: { userId: actor.id } } } }), - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + include: { users: { select: { userId: true, isAdmin: true } } } }); return all.map((group) => asApiRecord(group)!); }, @@ -278,11 +189,7 @@ function StudentGroup(db: PrismaClient['studentGroup']) { } if (actor.role !== Role.ADMIN && parentId) { const isParentAdmin = await prisma.userStudentGroup.findFirst({ - where: { - studentGroupId: parentId, - userId: actor.id, - isAdmin: true - } + where: { studentGroupId: parentId, userId: actor.id, isAdmin: true } }); if (!isParentAdmin) { throw new HTTP403Error('Not authorized to create subgroup in this group'); @@ -293,21 +200,9 @@ function StudentGroup(db: PrismaClient['studentGroup']) { name: name, description: description, parentId: parentId, - users: { - create: { - userId: actor.id, - isAdmin: true - } - } + users: { create: { userId: actor.id, isAdmin: true } } }, - include: { - users: { - select: { - userId: true, - isAdmin: true - } - } - } + include: { users: { select: { userId: true, isAdmin: true } } } }); return asApiRecord(model)!; }, @@ -317,11 +212,7 @@ function StudentGroup(db: PrismaClient['studentGroup']) { if (!hasAdminAccess(actor, record)) { throw new HTTP403Error('Not authorized'); } - return db.delete({ - where: { - id: id - } - }); + return db.delete({ where: { id: id } }); } }); } diff --git a/src/models/User.ts b/src/models/User.ts index 712e76c..e8912f3 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -1,15 +1,17 @@ -import { Prisma, PrismaClient, User as DbUser, Role } from '@prisma/client'; +import { Prisma, PrismaClient, User as DbUser } from '@prisma/client'; import prisma from '../prisma'; import { HTTP403Error, HTTP404Error } from '../utils/errors/Errors'; import { createDataExtractor } from '../helpers/dataExtractor'; import _ from 'es-toolkit/compat'; const getData = createDataExtractor(['firstName', 'lastName']); -const RoleAccessLevel: { [key in Role]: number } = { - [Role.STUDENT]: 0, - [Role.TEACHER]: 1, - [Role.ADMIN]: 2 -}; +export enum Role { + STUDENT = 'student', + TEACHER = 'teacher', + ADMIN = 'admin' +} + +const RoleAccessLevel: { [key in Role]: number } = { [Role.STUDENT]: 0, [Role.TEACHER]: 1, [Role.ADMIN]: 2 }; export const getAccessLevel = (role?: Role | null) => { if (!role) { @@ -18,28 +20,16 @@ export const getAccessLevel = (role?: Role | null) => { return RoleAccessLevel[role] || 0; }; -export const hasElevatedAccess = (role?: Role | null) => { +export const hasElevatedAccess = (role?: string | null) => { if (!role) { return false; } - return RoleAccessLevel[role] > 0; + return RoleAccessLevel[role as Role] > 0; }; export const whereStudentGroupAccess = (userId: string, isAdmin?: boolean) => ({ studentGroups: { - some: { - studentGroup: { - users: { - some: - isAdmin === undefined - ? { userId } - : { - userId, - isAdmin - } - } - } - } + some: { studentGroup: { users: { some: isAdmin === undefined ? { userId } : { userId, isAdmin } } } } } }); @@ -63,12 +53,7 @@ function User(db: PrismaClient['user']) { } /** remove fields not updatable*/ const sanitized = getData(data, false, record.id === actor.id ? false : elevatedAccess); - return db.update({ - where: { - id: id - }, - data: sanitized - }); + return db.update({ where: { id: id }, data: sanitized }); }, async all(actor: DbUser): Promise { @@ -80,14 +65,7 @@ function User(db: PrismaClient['user']) { return db.findMany({}); } const users = await db.findMany({ - where: { - OR: [ - { - id: actor.id - }, - whereStudentGroupAccess(actor.id) - ] - }, + where: { OR: [{ id: actor.id }, whereStudentGroupAccess(actor.id)] }, distinct: ['id'] }); return users; @@ -97,8 +75,11 @@ function User(db: PrismaClient['user']) { if (!hasElevatedAccess(actor.role)) { throw new HTTP403Error('Not authorized'); } - const actorLevel = RoleAccessLevel[actor.role]; - const roleLevel = RoleAccessLevel[role]; + const actorLevel = RoleAccessLevel[actor.role as Role]; + const roleLevel = RoleAccessLevel[role as Role]; + if (actorLevel === undefined || roleLevel === undefined) { + throw new HTTP403Error('Not allowed to set this role'); + } if (roleLevel > actorLevel) { throw new HTTP403Error('Not allowed to set a higher role'); } @@ -109,18 +90,11 @@ function User(db: PrismaClient['user']) { if (!record) { throw new HTTP404Error('User not found'); } - const recordLevel = RoleAccessLevel[record.role]; - if (actorLevel < recordLevel) { + const recordLevel = RoleAccessLevel[record.role as Role]; + if (recordLevel === undefined || actorLevel < recordLevel) { throw new HTTP403Error('Not allowed to change the role of user with a higher role'); } - return db.update({ - where: { - id: userId - }, - data: { - role: role - } - }); + return db.update({ where: { id: userId }, data: { role: role } }); } }); } diff --git a/src/routes/authConfig.ts b/src/routes/authConfig.ts index 2029d4c..2256957 100644 --- a/src/routes/authConfig.ts +++ b/src/routes/authConfig.ts @@ -1,4 +1,4 @@ -import { Role } from '@prisma/client'; +import { Role } from 'src/models/User'; interface Credentials { tenantID: string; @@ -17,10 +17,7 @@ interface Settings { export interface AccessMatrix { [key: string]: { path: string; - access: { - methods: ('GET' | 'POST' | 'PUT' | 'DELETE')[]; - minRole: Role; - }[]; + access: { methods: ('GET' | 'POST' | 'PUT' | 'DELETE')[]; minRole: Role }[]; }; } @@ -31,153 +28,55 @@ interface Config { accessMatrix: AccessMatrix; } -/** - * Routes that are accessible without authentication - * only for GET requests, e.g. ['/public'] - */ -export const PUBLIC_ROUTES: string[] = ['/logout']; - const authConfig: Config = { - credentials: { - tenantID: process.env.MSAL_TENANT_ID || '', - clientID: process.env.MSAL_CLIENT_ID || '' - }, + credentials: { tenantID: process.env.MSAL_TENANT_ID || '', clientID: process.env.MSAL_CLIENT_ID || '' }, metadata: { authority: 'login.microsoftonline.com', discovery: '.well-known/openid-configuration', version: 'v2.0' }, - settings: { - validateIssuer: true, - passReqToCallback: false, - loggingLevel: 'warn' - }, + settings: { validateIssuer: true, passReqToCallback: false, loggingLevel: 'warn' }, accessMatrix: { - checklogin: { - path: '/checklogin', - access: [ - { - methods: ['GET'], - minRole: Role.STUDENT - } - ] - }, - user: { - path: '/user', - access: [ - { - methods: ['GET', 'POST'], - minRole: Role.STUDENT - } - ] - }, + checklogin: { path: '/checklogin', access: [{ methods: ['GET'], minRole: Role.STUDENT }] }, + user: { path: '/user', access: [{ methods: ['GET', 'POST'], minRole: Role.STUDENT }] }, admin: { path: '/admin', - access: [ - { - methods: ['DELETE', 'GET', 'POST', 'PUT'], - minRole: Role.TEACHER - } - ] - }, - users: { - path: '/users', - access: [ - { - methods: ['GET'], - minRole: Role.STUDENT - } - ] - }, - userFind: { - path: '/users/:id', - access: [ - { - methods: ['GET', 'PUT'], - minRole: Role.STUDENT - } - ] + access: [{ methods: ['DELETE', 'GET', 'POST', 'PUT'], minRole: Role.TEACHER }] }, + users: { path: '/users', access: [{ methods: ['GET'], minRole: Role.STUDENT }] }, + userFind: { path: '/users/:id', access: [{ methods: ['GET', 'PUT'], minRole: Role.STUDENT }] }, usersDocumentRoots: { path: '/users/:id/documentRoots', - access: [ - { - methods: ['GET'], - minRole: Role.STUDENT - } - ] + access: [{ methods: ['GET'], minRole: Role.STUDENT }] }, studentGroups: { path: '/studentGroups', access: [ - { - methods: ['GET'], - minRole: Role.STUDENT - }, - { - methods: ['GET', 'PUT', 'POST', 'DELETE'], - minRole: Role.TEACHER - } + { methods: ['GET'], minRole: Role.STUDENT }, + { methods: ['GET', 'PUT', 'POST', 'DELETE'], minRole: Role.TEACHER } ] }, permissions: { path: '/permissions', - access: [ - { - methods: ['POST', 'PUT', 'DELETE'], - minRole: Role.TEACHER - } - ] + access: [{ methods: ['POST', 'PUT', 'DELETE'], minRole: Role.TEACHER }] }, documents: { path: '/documents', - access: [ - { - methods: ['GET', 'PUT', 'POST', 'DELETE'], - minRole: Role.STUDENT - } - ] + access: [{ methods: ['GET', 'PUT', 'POST', 'DELETE'], minRole: Role.STUDENT }] }, documentRoots: { path: '/documentRoots', access: [ - { - methods: ['GET', 'POST'], - minRole: Role.STUDENT - }, - { - methods: ['PUT', 'DELETE'], - minRole: Role.TEACHER - } + { methods: ['GET', 'POST'], minRole: Role.STUDENT }, + { methods: ['PUT', 'DELETE'], minRole: Role.TEACHER } ] }, documentRootPermissions: { path: '/documentRoots/:id/permissions', - access: [ - { - methods: ['GET'], - minRole: Role.TEACHER - } - ] + access: [{ methods: ['GET'], minRole: Role.TEACHER }] }, - githubToken: { - path: '/cms', - access: [ - { - methods: ['GET', 'PUT'], - minRole: Role.STUDENT - } - ] - }, - githubLogout: { - path: '/cms/logout', - access: [ - { - methods: ['POST'], - minRole: Role.STUDENT - } - ] - } + githubToken: { path: '/cms', access: [{ methods: ['GET', 'PUT'], minRole: Role.STUDENT }] }, + githubLogout: { path: '/cms/logout', access: [{ methods: ['POST'], minRole: Role.STUDENT }] } } }; diff --git a/src/routes/event-handlers/action.handler.ts b/src/routes/event-handlers/action.handler.ts index 71a4ccd..c738569 100644 --- a/src/routes/event-handlers/action.handler.ts +++ b/src/routes/event-handlers/action.handler.ts @@ -1,7 +1,8 @@ -import { Role, User } from '@prisma/client'; +import { User } from '@prisma/client'; import { ClientToServerEvents, IoClientEvent, IoEvent, ServerToClientEvents } from '../socketEventTypes'; import type { DefaultEventsMap, Socket } from 'socket.io'; import prisma from '../../prisma'; +import { Role } from 'src/models/User'; const onAction: ( user: User, @@ -20,16 +21,9 @@ const onAction: ( .findMany({ where: { id: { in: navRequest.roomIds }, - users: { - some: { - userId: user.id, - isAdmin: true - } - } + users: { some: { userId: user.id, isAdmin: true } } }, - select: { - id: true - } + select: { id: true } }) .then((sg) => { return sg.map((group) => group.id); @@ -42,30 +36,11 @@ const onAction: ( .findMany({ where: { AND: [ - { - users: { - some: { - userId: { in: navRequest.userIds } - } - } - }, - { - users: { - some: { - userId: user.id, - isAdmin: true - } - } - } + { users: { some: { userId: { in: navRequest.userIds } } } }, + { users: { some: { userId: user.id, isAdmin: true } } } ] }, - select: { - users: { - select: { - userId: true - } - } - } + select: { users: { select: { userId: true } } } }) .then((studentGroups) => { return studentGroups diff --git a/src/routes/event-handlers/joinRoom.handler.ts b/src/routes/event-handlers/joinRoom.handler.ts index 9bbd618..0bd1afa 100644 --- a/src/routes/event-handlers/joinRoom.handler.ts +++ b/src/routes/event-handlers/joinRoom.handler.ts @@ -1,4 +1,4 @@ -import { Role, User } from '@prisma/client'; +import { User } from '@prisma/client'; import { ClientToServerEvents, IoClientEvent, ServerToClientEvents } from '../socketEventTypes'; import type { DefaultEventsMap, Socket } from 'socket.io'; import prisma from '../../prisma'; @@ -6,6 +6,7 @@ import StudentGroup from '../../models/StudentGroup'; import onStreamUpdate from './streamUpdate.handler'; import DocumentRoot from '../../models/DocumentRoot'; import { highestAccess, RWAccess } from '../../helpers/accessPolicy'; +import { Role } from 'src/models/User'; type SocketType = Socket; const isDocumentRoot = (roomId: string) => { @@ -29,21 +30,7 @@ const findDocumentRoot = (user: User, roomId: string) => { const findStudentGroup = (userId: string, roomId: string) => { return prisma.studentGroup.findFirst({ - where: { - users: { - some: { - AND: [ - { - userId: userId, - isAdmin: true - }, - { - userId: roomId - } - ] - } - } - } + where: { users: { some: { AND: [{ userId: userId, isAdmin: true }, { userId: roomId }] } } } }); }; diff --git a/src/routes/socketEvents.ts b/src/routes/socketEvents.ts index 27fb68e..ae85fc2 100644 --- a/src/routes/socketEvents.ts +++ b/src/routes/socketEvents.ts @@ -1,14 +1,15 @@ /* istanbul ignore file */ -import { Role, type User } from '@prisma/client'; +import { type User } from '@prisma/client'; import { Server } from 'socket.io'; import Logger from '../utils/logger'; import { ClientToServerEvents, IoEvent, IoClientEvent, ServerToClientEvents } from './socketEventTypes'; import StudentGroup from '../models/StudentGroup'; -import { hasElevatedAccess } from '../models/User'; +import { hasElevatedAccess, Role } from '../models/User'; import onAction from './event-handlers/action.handler'; import onJoinRoom from './event-handlers/joinRoom.handler'; import onLeaveRoom from './event-handlers/leaveRoom.handler'; +import { auth } from '../auth'; export enum IoRoom { ADMIN = 'admin', @@ -17,7 +18,17 @@ export enum IoRoom { const EventRouter = (io: Server) => { io.on('connection', async (socket) => { - const user = (socket.request as { user?: User }).user; + const token = socket.handshake.auth.token; + + const session = await auth.api.verifyOneTimeToken({ body: { token } }).catch(() => null); + console.log(`Socket.io connection ${session?.user?.email}`, token); + + if (!session?.user) { + return socket.disconnect(); + } + const user = session.user as User; + console.log(`Socket.io user`, user); + socket.join(user.id); if (!user) { return socket.disconnect(); } @@ -28,10 +39,7 @@ const EventRouter = (io: Server) => const rooms = [...io.sockets.adapter.rooms.keys()].map( (id) => [id, io.sockets.adapter.rooms.get(id)?.size || 0] as [string, number] ); - io.to(IoRoom.ADMIN).emit(IoEvent.CONNECTED_CLIENTS, { - rooms: rooms, - type: 'full' - }); + io.to(IoRoom.ADMIN).emit(IoEvent.CONNECTED_CLIENTS, { rooms: rooms, type: 'full' }); } if (hasElevatedAccess(user.role)) { socket.on(IoClientEvent.ACTION, onAction(user, socket)); @@ -47,17 +55,15 @@ const EventRouter = (io: Server) => }); io.on('disconnect', (socket) => { - const { user } = socket.request as { user?: User }; - Logger.info(`Socket.io disconnect ${user?.email}`); + Logger.info(`Socket.io disconnect ${socket.id}`); }); io.on('error', (socket) => { - Logger.error(`Socket.io error`); + Logger.error(`Socket.io error ${socket.id}`); }); io.on('reconnect', (socket) => { - const { user } = socket.request as { user?: User }; - Logger.info(`Socket.io reconnect ${user?.email}`); + Logger.info(`Socket.io reconnect ${socket.id}`); }); io.of('/').adapter.on('join-room', (room, id) => { diff --git a/src/server.ts b/src/server.ts index 9d464e1..cf538ed 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,7 +1,6 @@ import './instrumentation'; -import app, { configure, sessionMiddleware } from './app'; +import app, { configure } from './app'; import http from 'http'; -import Logger from '@/utils/logger'; import { Server } from 'socket.io'; import { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; // import passport from 'passport'; @@ -10,56 +9,21 @@ import type { NextFunction, Request, Response } from 'express'; import { HTTP403Error } from './utils/errors/Errors'; import { CORS_ORIGIN } from './utils/originConfig'; import * as Sentry from '@sentry/node'; +import Logger from './utils/logger'; const PORT = process.env.PORT || 3002; const server = http.createServer(app); const io = new Server(server, { - cors: { - origin: CORS_ORIGIN, - credentials: true, - methods: ['GET', 'POST', 'PUT', 'DELETE'] - }, + cors: { origin: CORS_ORIGIN, credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'] }, pingInterval: 15_000, pingTimeout: 20_000, transports: ['websocket', 'webtransport' /* , 'polling' */] }); -// convert a connect middleware to a Socket.IO middleware -// io.use((socket, next) => { -// sessionMiddleware( -// socket.request as Request, -// {} as Response, -// next as NextFunction -// ); -// }); -// io.use((socket, next) => { -// passport.initialize()( -// socket.request as Request, -// {} as Response, -// next as NextFunction -// ); -// }); -// io.use((socket, next) => { -// passport.session()( -// socket.request as Request, -// {} as Response, -// next as NextFunction -// ); -// }); - EventRouter(io); -// only allow authenticated users in socketio -io.use((socket, next) => { - if ((socket.request as any).user) { - next(); - } else { - next(new HTTP403Error('unauthorized')); - } -}); - // Make io accessible to our router app.use((req: Request, res, next) => { req.io = io; diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts index b247c47..1a1d67f 100644 --- a/src/types/express/index.d.ts +++ b/src/types/express/index.d.ts @@ -1,13 +1,14 @@ import type { User as pUser } from '@prisma/client'; -import { Notification } from '../../routes/socketEventTypes'; +import type { ClientToServerEvents, Notification, ServerToClientEvents } from '../../routes/socketEventTypes'; +import { Server } from 'socket.io'; // to make the file a module and avoid a TypeScript error export {}; declare global { namespace Express { - export interface User extends pUser {} export interface Request { + user: pUser; io?: Server; } diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index b079a20..93ca7b0 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -21,6 +21,7 @@ const netlifyProjectName = process.env.NETLIFY_PROJECT_NAME; // Build the CORS origin array export const CORS_ORIGIN: (string | RegExp)[] = []; +export const CORS_ORIGIN_STRINGIFIED: string[] = []; const isLoclhost = (origin: string) => { return origin.startsWith('localhost') || origin.startsWith('127.0.0.1'); @@ -34,10 +35,17 @@ allowedOrigins.forEach((origin) => { return; } if (isLoclhost(origin)) { + CORS_ORIGIN_STRINGIFIED.push(`http://${origin}`); return CORS_ORIGIN.push(`http://${origin}`); } if (allowSubdomains) { + if (origin.startsWith('http')) { + const [protocol, host] = origin.split('://'); + CORS_ORIGIN_STRINGIFIED.push(`$${protocol}://*.${host}`, origin); + } else { + CORS_ORIGIN_STRINGIFIED.push(`*.${origin}`, `https://${origin}`); + } // Escape dots and create regex for domain with optional subdomains const escapedDomain = origin.replace(/\./g, '\\.'); CORS_ORIGIN.push(new RegExp(`^https?://(.*\\.)?${escapedDomain}$`, 'i')); @@ -46,6 +54,7 @@ allowedOrigins.forEach((origin) => { if (!origin.startsWith('http')) { origin = `https://${origin}`; } + CORS_ORIGIN_STRINGIFIED.push(origin); CORS_ORIGIN.push(origin); } }); @@ -53,6 +62,7 @@ allowedOrigins.forEach((origin) => { // Add Netlify deploy previews if enabled if (netlifyProjectName) { CORS_ORIGIN.push(new RegExp(`https://deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i')); + CORS_ORIGIN_STRINGIFIED.push(`https://*.${netlifyProjectName}.netlify.app`); } export const SAME_SITE = allowedOrigins.length > 1 || netlifyProjectName ? 'none' : 'strict'; diff --git a/tsconfig.json b/tsconfig.json index c84cb80..544148d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,16 +1,21 @@ { + "ts-node": { + "transpileOnly": true, + "require": ["tsconfig-paths/register"] + }, "compilerOptions": { "target": "es6", "module": "NodeNext", "moduleResolution": "NodeNext", + // "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "baseUrl": ".", - "outDir": "build", + "outDir": "dist", "sourceMap": true, "strict": true, "isolatedModules": true, "esModuleInterop": true, - "types": ["node", "express"], + "types": ["node"], "typeRoots": [ "./src/types", "./node_modules/@types/", @@ -26,8 +31,7 @@ } ], "paths": { - "@/prisma/*": ["prisma/*"], - "@/*": ["src/*"] + "@/prisma/*": ["prisma/*"] } }, "include": ["process.env.d.ts", "./**/*.ts"], diff --git a/yarn.lock b/yarn.lock index df08b84..b1c0283 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7,23 +7,23 @@ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30" integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw== -"@antfu/install-pkg@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.0.0.tgz#2912a150fc8b35ec912f583f90074ee98f64d66a" - integrity sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw== +"@antfu/install-pkg@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz#78fa036be1a6081b5a77a5cf59f50c7752b6ba26" + integrity sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ== dependencies: - package-manager-detector "^0.2.8" - tinyexec "^0.3.2" + package-manager-detector "^1.3.0" + tinyexec "^1.0.1" "@antfu/ni@0.21.4": version "0.21.4" resolved "https://registry.yarnpkg.com/@antfu/ni/-/ni-0.21.4.tgz#a6c1e3d6fbd86e4cb36ec5ff97302ae8878f3eee" integrity sha512-O0Uv9LbLDSoEg26fnMDdDRiPwFJnQSoD4WnrflDwKCJm8Cx/0mV4cGxwBLXan5mGIrpK4Dd7vizf4rQm0QCEAA== -"@antfu/utils@^8.1.0": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-8.1.1.tgz#95b1947d292a9a2efffba2081796dcaa05ecedfb" - integrity sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ== +"@antfu/utils@^9.2.0": + version "9.2.1" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-9.2.1.tgz#0a73683cf0a8c4cd38397b002439488229651cdb" + integrity sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg== "@authenio/xml-encryption@^2.0.2": version "2.0.2" @@ -35,62 +35,31 @@ xpath "0.0.32" "@babel/code-frame@^7.0.0": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/helper-validator-identifier@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" - integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== - -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== - dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" + integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== + dependencies: + "@babel/helper-validator-identifier" "^7.27.1" js-tokens "^4.0.0" - picocolors "^1.0.0" + picocolors "^1.1.1" -"@babel/parser@^7.25.3": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" - integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== - dependencies: - "@babel/types" "^7.27.0" +"@babel/helper-validator-identifier@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" + integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/types@^7.27.0": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" - integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== +"@better-auth/core@1.3.26": + version "1.3.26" + resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.26.tgz#32ffae583124437b4929672cdb007d6543aaf156" + integrity sha512-S5ooXaOcn9eLV3/JayfbMsAB5PkfoTRaRrtpb5djwvI/UAJOgLyjqhd+rObsBycovQ/nPQvMKjzyM/G1oBKngA== dependencies: - "@babel/helper-string-parser" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - -"@better-auth/core@1.3.18": - version "1.3.18" - resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.18.tgz#e99fee9ea040b9be7b233a55a0ae5cab1b90e031" - integrity sha512-eVTpiyFOA70SecGuiXs2qxQq1oWbEiLJMpyOYF8HAHFXHH+iK0Ab8F0stdyJTTYOc9ydjFQgYXmbENG6JqQ3UA== + better-call "1.0.19" + zod "^4.1.5" -"@better-auth/sso@^1.3.18": - version "1.3.18" - resolved "https://registry.yarnpkg.com/@better-auth/sso/-/sso-1.3.18.tgz#f8afacdbab253229801653f3d4ac58f4d7d6fa96" - integrity sha512-usN8PD4oWDDVSJrhEhUDc+c2mE7G1IdET2fhmDMa7ZXCvg3B8I+gGjs2AaTlXppnvESrBOw31Q07IhLyjvcm8g== +"@better-auth/sso@^1.3.26": + version "1.3.26" + resolved "https://registry.yarnpkg.com/@better-auth/sso/-/sso-1.3.26.tgz#963e5e66e37f499b30e9e4fdf79433fcd4b7a9c0" + integrity sha512-Zjtmu0vq1kx7Txmj/Hb06FPlBqFuAcOQpT6bMK+lXYEcpCOsUxuxuvxJc7ad6EENa9qJ4jrUBtHooQTqRHxbOg== dependencies: "@better-fetch/fetch" "^1.1.18" fast-xml-parser "^5.2.5" @@ -114,7 +83,7 @@ resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== -"@braintree/sanitize-url@^7.0.4": +"@braintree/sanitize-url@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-7.1.1.tgz#15e19737d946559289b915e5dad3b4c28407735e" integrity sha512-i1L7noDNxtFyL5DmZafWy1wRVhGehQmzZaz1HiN5e7iylJMSZR7ekOV7NsIqa5qBldlLrsKv4HbgFUVlQrz8Mw== @@ -163,12 +132,12 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@dabh/diagnostics@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.3.tgz#7f7e97ee9a725dffc7808d93668cc984e1dc477a" - integrity sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA== +"@dabh/diagnostics@^2.0.8": + version "2.0.8" + resolved "https://registry.yarnpkg.com/@dabh/diagnostics/-/diagnostics-2.0.8.tgz#ead97e72ca312cf0e6dd7af0d300b58993a31a5e" + integrity sha512-R4MSXTVnuMzGD7bzHdW2ZhhdPC/igELENcq5IjEverBvq5hn1SXCWcsi6eSsdWP0/Ur+SItRRjAktmdoX/8R/Q== dependencies: - colorspace "1.1.x" + "@so-ric/colorspace" "^1.1.6" enabled "2.0.x" kuler "^2.0.0" @@ -198,15 +167,17 @@ debug "^4.3.1" minimatch "^3.1.2" -"@eslint/config-helpers@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.3.1.tgz#d316e47905bd0a1a931fa50e669b9af4104d1617" - integrity sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA== +"@eslint/config-helpers@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.0.tgz#e9f94ba3b5b875e32205cb83fece18e64486e9e6" + integrity sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog== + dependencies: + "@eslint/core" "^0.16.0" -"@eslint/core@^0.15.2": - version "0.15.2" - resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.15.2.tgz#59386327d7862cc3603ebc7c78159d2dcc4a868f" - integrity sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg== +"@eslint/core@^0.16.0": + version "0.16.0" + resolved "https://registry.yarnpkg.com/@eslint/core/-/core-0.16.0.tgz#490254f275ba9667ddbab344f4f0a6b7a7bd7209" + integrity sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q== dependencies: "@types/json-schema" "^7.0.15" @@ -225,74 +196,85 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.36.0": - version "9.36.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.36.0.tgz#b1a3893dd6ce2defed5fd49de805ba40368e8fef" - integrity sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw== +"@eslint/js@9.37.0": + version "9.37.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.37.0.tgz#0cfd5aa763fe5d1ee60bedf84cd14f54bcf9e21b" + integrity sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg== "@eslint/object-schema@^2.1.6": version "2.1.6" resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== -"@eslint/plugin-kit@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz#fd8764f0ee79c8ddab4da65460c641cefee017c5" - integrity sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w== +"@eslint/plugin-kit@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz#f6a245b42886abf6fc9c7ab7744a932250335ab2" + integrity sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A== dependencies: - "@eslint/core" "^0.15.2" + "@eslint/core" "^0.16.0" levn "^0.4.1" -"@floating-ui/core@^1.5.3", "@floating-ui/core@^1.6.0": - version "1.6.9" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" - integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== +"@floating-ui/core@^1.7.3": + version "1.7.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7" + integrity sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w== dependencies: - "@floating-ui/utils" "^0.2.9" + "@floating-ui/utils" "^0.2.10" -"@floating-ui/dom@^1.0.0", "@floating-ui/dom@^1.5.4": - version "1.6.13" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" - integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== +"@floating-ui/dom@^1.7.4": + version "1.7.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.4.tgz#ee667549998745c9c3e3e84683b909c31d6c9a77" + integrity sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA== dependencies: - "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.9" + "@floating-ui/core" "^1.7.3" + "@floating-ui/utils" "^0.2.10" -"@floating-ui/utils@^0.2.9": - version "0.2.9" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" - integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== +"@floating-ui/react-dom@^2.1.2", "@floating-ui/react-dom@^2.1.6": + version "2.1.6" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.6.tgz#189f681043c1400561f62972f461b93f01bf2231" + integrity sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw== + dependencies: + "@floating-ui/dom" "^1.7.4" -"@floating-ui/vue@^1.0.3": - version "1.1.6" - resolved "https://registry.yarnpkg.com/@floating-ui/vue/-/vue-1.1.6.tgz#1c7e8f257fae5b71a72d10c1746e6b0ba338399c" - integrity sha512-XFlUzGHGv12zbgHNk5FN2mUB7ROul3oG2ENdTpWdE+qMFxyNxWSRmsoyhiEnpmabNm6WnUvR1OvJfUfN4ojC1A== +"@floating-ui/react@^0.26.16": + version "0.26.28" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" + integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== dependencies: - "@floating-ui/dom" "^1.0.0" - "@floating-ui/utils" "^0.2.9" - vue-demi ">=0.13.0" + "@floating-ui/react-dom" "^2.1.2" + "@floating-ui/utils" "^0.2.8" + tabbable "^6.0.0" + +"@floating-ui/react@^0.27.8": + version "0.27.16" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.27.16.tgz#6e485b5270b7a3296fdc4d0faf2ac9abf955a2f7" + integrity sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g== + dependencies: + "@floating-ui/react-dom" "^2.1.6" + "@floating-ui/utils" "^0.2.10" + tabbable "^6.0.0" + +"@floating-ui/utils@^0.2.10", "@floating-ui/utils@^0.2.8": + version "0.2.10" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" + integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== -"@headlessui-float/vue@^0.14.0": - version "0.14.4" - resolved "https://registry.yarnpkg.com/@headlessui-float/vue/-/vue-0.14.4.tgz#3cfd134f5b65a10c86290180faca2f9c4e7ed3a6" - integrity sha512-MSyWCxUTueeex+veRCf++q4KM/fa4HOe9HDttzGrtgVDBULkGduFK6ItJh7EHJp2U/dY7qpyDUqp2KCHpCEplw== +"@headlessui/react@^2.2.1": + version "2.2.9" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-2.2.9.tgz#213f78534c86e03a7c986d2c2abe1270622b3e13" + integrity sha512-Mb+Un58gwBn0/yWZfyrCh0TJyurtT+dETj7YHleylHk5od3dv2XqETPGWMyQ5/7sYN7oWdyM1u9MvC0OC8UmzQ== dependencies: - "@floating-ui/core" "^1.5.3" - "@floating-ui/dom" "^1.5.4" - "@floating-ui/vue" "^1.0.3" + "@floating-ui/react" "^0.26.16" + "@react-aria/focus" "^3.20.2" + "@react-aria/interactions" "^3.25.0" + "@tanstack/react-virtual" "^3.13.9" + use-sync-external-store "^1.5.0" -"@headlessui/tailwindcss@^0.2.0": +"@headlessui/tailwindcss@^0.2.2": version "0.2.2" resolved "https://registry.yarnpkg.com/@headlessui/tailwindcss/-/tailwindcss-0.2.2.tgz#8ebde73fabca72d48636ea56ae790209dc5f0d49" integrity sha512-xNe42KjdyA4kfUKLLPGzME9zkH7Q3rOZ5huFihWNWOQFxnItxPB3/67yBI8/qBfY8nwBRx5GHn4VprsoluVMGw== -"@headlessui/vue@^1.7.16": - version "1.7.23" - resolved "https://registry.yarnpkg.com/@headlessui/vue/-/vue-1.7.23.tgz#7fe19dbeca35de9e6270c82c78c4864e6a6f7391" - integrity sha512-JzdCNqurrtuu0YW6QaDtR2PIYCKPUWq28csDyMvN4zmGccmE7lz40Is6hc3LA4HFeCI7sekZ/PQMTNmn9I/4Wg== - dependencies: - "@tanstack/vue-virtual" "^3.0.0-beta.60" - "@hexagon/base64@^1.1.27": version "1.1.28" resolved "https://registry.yarnpkg.com/@hexagon/base64/-/base64-1.1.28.tgz#7d306a97f1423829be5b27c9d388fe50e3099d48" @@ -326,18 +308,18 @@ resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== -"@iconify/utils@^2.1.33": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-2.3.0.tgz#1bbbf8c477ebe9a7cacaea78b1b7e8937f9cbfba" - integrity sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA== +"@iconify/utils@^3.0.1": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-3.0.2.tgz#9599607f20690cd3e7a5d2d459af0eb81a89dc2b" + integrity sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ== dependencies: - "@antfu/install-pkg" "^1.0.0" - "@antfu/utils" "^8.1.0" + "@antfu/install-pkg" "^1.1.0" + "@antfu/utils" "^9.2.0" "@iconify/types" "^2.0.0" - debug "^4.4.0" - globals "^15.14.0" + debug "^4.4.1" + globals "^15.15.0" kolorist "^1.8.0" - local-pkg "^1.0.0" + local-pkg "^1.1.1" mlly "^1.7.4" "@isaacs/cliui@^8.0.2": @@ -353,12 +335,11 @@ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" "@jridgewell/gen-mapping@^0.3.2": - version "0.3.8" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" - integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== dependencies: - "@jridgewell/set-array" "^1.2.1" - "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/sourcemap-codec" "^1.5.0" "@jridgewell/trace-mapping" "^0.3.24" "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": @@ -366,20 +347,10 @@ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== -"@jridgewell/set-array@^1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" - integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" - integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== "@jridgewell/trace-mapping@0.3.9": version "0.3.9" @@ -390,9 +361,9 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping@^0.3.24": - version "0.3.25" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" - integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + version "0.3.31" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -424,16 +395,16 @@ mermaid "^11.0.2" "@mermaid-js/mermaid-zenuml@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-zenuml/-/mermaid-zenuml-0.2.0.tgz#6a418409804e25039d2a5c3ec7df0679cf53ed30" - integrity sha512-Lv7xNlFT5y2TIlts+yYl1HfeEgjoqw5cfSZsWYejoJvt9K0QfdPBoj5D9Tft1aN0pj1mxjuTZbZQ1Anmem/RMg== + version "0.2.2" + resolved "https://registry.yarnpkg.com/@mermaid-js/mermaid-zenuml/-/mermaid-zenuml-0.2.2.tgz#7c8ae997890b18f208cee95a4ac8c16c3ca61686" + integrity sha512-sUjwk4NWUpy9uaHypYSIGJDks10ZaZo5CHH9lx9xcmyqv9w7yvd4vecUmlUQxmlHStYO+aqSkYKX5/gFjDfypw== dependencies: - "@zenuml/core" "^3.17.2" + "@zenuml/core" "^3.35.2" -"@mermaid-js/parser@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.4.0.tgz#c1de1f5669f8fcbd0d0c9d124927d36ddc00d8a6" - integrity sha512-wla8XOWvQAwuqy+gxiZqY+c7FokraOTHRWMsbB4AgRx9Sy7zKslNyejy7E+a77qHfey5GXw/ik3IXv/NHMJgaA== +"@mermaid-js/parser@^0.6.2": + version "0.6.2" + resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.6.2.tgz#6d505a33acb52ddeb592c596b14f9d92a30396a9" + integrity sha512-+PO02uGF6L6Cs0Bw8RpGhikVvMWEysfAyl27qTlroUB8jSWr1lL0Sf6zi78ZxlSnmgSY2AMMKVgghnN9jTtwkQ== dependencies: langium "3.3.1" @@ -468,10 +439,10 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@opentelemetry/api-logs@0.203.0": - version "0.203.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.203.0.tgz#3309a76c51a848ea820cd7f00ee62daf36b06380" - integrity sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ== +"@opentelemetry/api-logs@0.204.0": + version "0.204.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.204.0.tgz#c0285aa5c79625a1c424854393902d21732fd76b" + integrity sha512-DqxY8yoAaiBPivoJD4UtgrMS8gEmzZ5lnaxzPojzLVHBGqPxgWm4zcuvcUHZiqQ6kRX2Klel2r9y8cA2HAtqpw== dependencies: "@opentelemetry/api" "^1.3.0" @@ -492,214 +463,214 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/context-async-hooks@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.0.1.tgz#4416bc2df780c1dda1129afb9392d55831dd861d" - integrity sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw== +"@opentelemetry/context-async-hooks@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-2.1.0.tgz#de1de21d9536abfe73769f822b52a59a8c97b083" + integrity sha512-zOyetmZppnwTyPrt4S7jMfXiSX9yyfF0hxlA8B5oo2TtKl+/RGCy7fi4DrBfIf3lCPrkKsRBWZZD7RFojK7FDg== -"@opentelemetry/core@2.0.1", "@opentelemetry/core@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.0.1.tgz#44e1149d5666a4743cde943ef89841db3ce0f8bc" - integrity sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw== +"@opentelemetry/core@2.1.0", "@opentelemetry/core@^2.0.0", "@opentelemetry/core@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-2.1.0.tgz#5539f04eb9e5245e000b0c3f77bdfaa07557e3a7" + integrity sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ== dependencies: "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/instrumentation-amqplib@0.50.0": - version "0.50.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.50.0.tgz#91899a7e2821db956daeaa803d3bd8f5af8b8050" - integrity sha512-kwNs/itehHG/qaQBcVrLNcvXVPW0I4FCOVtw3LHMLdYIqD7GJ6Yv2nX+a4YHjzbzIeRYj8iyMp0Bl7tlkidq5w== +"@opentelemetry/instrumentation-amqplib@0.51.0": + version "0.51.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.51.0.tgz#1779326433f1ab8a743bbf8e1957e1b1252cf036" + integrity sha512-XGmjYwjVRktD4agFnWBWQXo9SiYHKBxR6Ag3MLXwtLE4R99N3a08kGKM5SC1qOFKIELcQDGFEFT9ydXMH00Luw== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-connect@0.47.0": - version "0.47.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.47.0.tgz#47271b8454fa88d97aa78e175c3d0cb7e10bd9e2" - integrity sha512-pjenvjR6+PMRb6/4X85L4OtkQCootgb/Jzh/l/Utu3SJHBid1F+gk9sTGU2FWuhhEfV6P7MZ7BmCdHXQjgJ42g== +"@opentelemetry/instrumentation-connect@0.48.0": + version "0.48.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.48.0.tgz#4481c84315b33b54a67c6e787be0eb72a84b23b3" + integrity sha512-OMjc3SFL4pC16PeK+tDhwP7MRvDPalYCGSvGqUhX5rASkI2H0RuxZHOWElYeXkV0WP+70Gw6JHWac/2Zqwmhdw== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" "@types/connect" "3.4.38" -"@opentelemetry/instrumentation-dataloader@0.21.1": - version "0.21.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.21.1.tgz#46fbbe59d9d6796980707768cf733225d43adea5" - integrity sha512-hNAm/bwGawLM8VDjKR0ZUDJ/D/qKR3s6lA5NV+btNaPVm2acqhPcT47l2uCVi+70lng2mywfQncor9v8/ykuyw== +"@opentelemetry/instrumentation-dataloader@0.22.0": + version "0.22.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.22.0.tgz#a34f8ac6ec18e8f1585dcd89f9f611570868d1a2" + integrity sha512-bXnTcwtngQsI1CvodFkTemrrRSQjAjZxqHVc+CJZTDnidT0T6wt3jkKhnsjU/Kkkc0lacr6VdRpCu2CUWa0OKw== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation-express@0.52.0": - version "0.52.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.52.0.tgz#d87d2130fe779dd757db28edb78262af83510d5b" - integrity sha512-W7pizN0Wh1/cbNhhTf7C62NpyYw7VfCFTYg0DYieSTrtPBT1vmoSZei19wfKLnrMsz3sHayCg0HxCVL2c+cz5w== +"@opentelemetry/instrumentation-express@0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.53.0.tgz#902634e3de640bd4fa5370924397e716608ecb90" + integrity sha512-r/PBafQmFYRjuxLYEHJ3ze1iBnP2GDA1nXOSS6E02KnYNZAVjj6WcDA1MSthtdAUUK0XnotHvvWM8/qz7DMO5A== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-fs@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.23.0.tgz#e3cd3a53fa975c69de33e207b35561f3f90106f0" - integrity sha512-Puan+QopWHA/KNYvDfOZN6M/JtF6buXEyD934vrb8WhsX1/FuM7OtoMlQyIqAadnE8FqqDL4KDPiEfCQH6pQcQ== +"@opentelemetry/instrumentation-fs@0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.24.0.tgz#edf0f7418f6a1cdcbe135857ab75629e7d94b910" + integrity sha512-HjIxJ6CBRD770KNVaTdMXIv29Sjz4C1kPCCK5x1Ujpc6SNnLGPqUVyJYZ3LUhhnHAqdbrl83ogVWjCgeT4Q0yw== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation-generic-pool@0.47.0": - version "0.47.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.47.0.tgz#f5fa9d42236eb7d57fa544954f316faee937b0b4" - integrity sha512-UfHqf3zYK+CwDwEtTjaD12uUqGGTswZ7ofLBEdQ4sEJp9GHSSJMQ2hT3pgBxyKADzUdoxQAv/7NqvL42ZI+Qbw== +"@opentelemetry/instrumentation-generic-pool@0.48.0": + version "0.48.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.48.0.tgz#76fc08d76515db04f3833d730c5cb18cb0b237d4" + integrity sha512-TLv/On8pufynNR+pUbpkyvuESVASZZKMlqCm4bBImTpXKTpqXaJJ3o/MUDeMlM91rpen+PEv2SeyOKcHCSlgag== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation-graphql@0.51.0": - version "0.51.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.51.0.tgz#1b29aa6330d196d523460e593167dca7dbcd42bb" - integrity sha512-LchkOu9X5DrXAnPI1+Z06h/EH/zC7D6sA86hhPrk3evLlsJTz0grPrkL/yUJM9Ty0CL/y2HSvmWQCjbJEz/ADg== +"@opentelemetry/instrumentation-graphql@0.52.0": + version "0.52.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.52.0.tgz#a2d23a669bdd0a1b031f785fe447d5a34ac56343" + integrity sha512-3fEJ8jOOMwopvldY16KuzHbRhPk8wSsOTSF0v2psmOCGewh6ad+ZbkTx/xyUK9rUdUMWAxRVU0tFpj4Wx1vkPA== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation-hapi@0.50.0": - version "0.50.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.50.0.tgz#c755e9c21bfeb82046221bfd51303f816ae649e8" - integrity sha512-5xGusXOFQXKacrZmDbpHQzqYD1gIkrMWuwvlrEPkYOsjUqGUjl1HbxCsn5Y9bUXOCgP1Lj6A4PcKt1UiJ2MujA== +"@opentelemetry/instrumentation-hapi@0.51.0": + version "0.51.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.51.0.tgz#879926dfbb2e1609cc8658392167b1456c75d9e0" + integrity sha512-qyf27DaFNL1Qhbo/da+04MSCw982B02FhuOS5/UF+PMhM61CcOiu7fPuXj8TvbqyReQuJFljXE6UirlvoT/62g== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-http@0.203.0": - version "0.203.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.203.0.tgz#21f198547b5c72fc64e83ed25cdc991aef7b8fee" - integrity sha512-y3uQAcCOAwnO6vEuNVocmpVzG3PER6/YZqbPbbffDdJ9te5NkHEkfSMNzlC3+v7KlE+WinPGc3N7MR30G1HY2g== +"@opentelemetry/instrumentation-http@0.204.0": + version "0.204.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.204.0.tgz#faaf009b75e6a68729923b0a2a5270dc7d336f1d" + integrity sha512-1afJYyGRA4OmHTv0FfNTrTAzoEjPQUYgd+8ih/lX0LlZBnGio/O80vxA0lN3knsJPS7FiDrsDrWq25K7oAzbkw== dependencies: - "@opentelemetry/core" "2.0.1" - "@opentelemetry/instrumentation" "0.203.0" + "@opentelemetry/core" "2.1.0" + "@opentelemetry/instrumentation" "0.204.0" "@opentelemetry/semantic-conventions" "^1.29.0" forwarded-parse "2.1.2" -"@opentelemetry/instrumentation-ioredis@0.51.0": - version "0.51.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.51.0.tgz#47360999ad2b035aa2ac604c410272da671142d3" - integrity sha512-9IUws0XWCb80NovS+17eONXsw1ZJbHwYYMXiwsfR9TSurkLV5UNbRSKb9URHO+K+pIJILy9wCxvyiOneMr91Ig== +"@opentelemetry/instrumentation-ioredis@0.52.0": + version "0.52.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.52.0.tgz#ca5d7b1a49798ed2d29a0f212a7ca5ef95c173c5" + integrity sha512-rUvlyZwI90HRQPYicxpDGhT8setMrlHKokCtBtZgYxQWRF5RBbG4q0pGtbZvd7kyseuHbFpA3I/5z7M8b/5ywg== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/redis-common" "^0.38.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-kafkajs@0.13.0": - version "0.13.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.13.0.tgz#f959fecd0a9d53bed2fd662e41a5c155295ffbc8" - integrity sha512-FPQyJsREOaGH64hcxlzTsIEQC4DYANgTwHjiB7z9lldmvua1LRMVn3/FfBlzXoqF179B0VGYviz6rn75E9wsDw== +"@opentelemetry/instrumentation-kafkajs@0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.14.0.tgz#ffc30728b5845907d2c5b9f3883676c754ef4927" + integrity sha512-kbB5yXS47dTIdO/lfbbXlzhvHFturbux4EpP0+6H78Lk0Bn4QXiZQW7rmZY1xBCY16mNcCb8Yt0mhz85hTnSVA== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.30.0" -"@opentelemetry/instrumentation-knex@0.48.0": - version "0.48.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.48.0.tgz#ed24a81dfe6099cfe56136a3fed90565e1259f58" - integrity sha512-V5wuaBPv/lwGxuHjC6Na2JFRjtPgstw19jTFl1B1b6zvaX8zVDYUDaR5hL7glnQtUSCMktPttQsgK4dhXpddcA== +"@opentelemetry/instrumentation-knex@0.49.0": + version "0.49.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.49.0.tgz#8c04c80c00ead5fbdf600cd2460dcd21b4069157" + integrity sha512-NKsRRT27fbIYL4Ix+BjjP8h4YveyKc+2gD6DMZbr5R5rUeDqfC8+DTfIt3c3ex3BIc5Vvek4rqHnN7q34ZetLQ== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.33.1" -"@opentelemetry/instrumentation-koa@0.51.0": - version "0.51.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.51.0.tgz#1ff57866b7882033639477d3d2d9bada19a2129f" - integrity sha512-XNLWeMTMG1/EkQBbgPYzCeBD0cwOrfnn8ao4hWgLv0fNCFQu1kCsJYygz2cvKuCs340RlnG4i321hX7R8gj3Rg== +"@opentelemetry/instrumentation-koa@0.52.0": + version "0.52.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.52.0.tgz#7266785ea85334366c3e50dc2b45468df438eb3f" + integrity sha512-JJSBYLDx/mNSy8Ibi/uQixu2rH0bZODJa8/cz04hEhRaiZQoeJ5UrOhO/mS87IdgVsHrnBOsZ6vDu09znupyuA== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-lru-memoizer@0.48.0": - version "0.48.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.48.0.tgz#b9fbbd45b7a742a6795bf7166f65684251f184b1" - integrity sha512-KUW29wfMlTPX1wFz+NNrmE7IzN7NWZDrmFWHM/VJcmFEuQGnnBuTIdsP55CnBDxKgQ/qqYFp4udQFNtjeFosPw== +"@opentelemetry/instrumentation-lru-memoizer@0.49.0": + version "0.49.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.49.0.tgz#6353b877628339e3f07189f4fb15919a73fe1503" + integrity sha512-ctXu+O/1HSadAxtjoEg2w307Z5iPyLOMM8IRNwjaKrIpNAthYGSOanChbk1kqY6zU5CrpkPHGdAT6jk8dXiMqw== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation-mongodb@0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.56.0.tgz#81281d2d151c3bfb26864c50b938a82ba2831b2d" - integrity sha512-YG5IXUUmxX3Md2buVMvxm9NWlKADrnavI36hbJsihqqvBGsWnIfguf0rUP5Srr0pfPqhQjUP+agLMsvu0GmUpA== +"@opentelemetry/instrumentation-mongodb@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.57.0.tgz#e697261b2eac05280134e1851b72c89d5b4b3da8" + integrity sha512-KD6Rg0KSHWDkik+qjIOWoksi1xqSpix8TSPfquIK1DTmd9OTFb5PHmMkzJe16TAPVEuElUW8gvgP59cacFcrMQ== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-mongoose@0.50.0": - version "0.50.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.50.0.tgz#1fae5d2769ca7e67d15291fb91b61403839ad91d" - integrity sha512-Am8pk1Ct951r4qCiqkBcGmPIgGhoDiFcRtqPSLbJrUZqEPUsigjtMjoWDRLG1Ki1NHgOF7D0H7d+suWz1AAizw== +"@opentelemetry/instrumentation-mongoose@0.51.0": + version "0.51.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.51.0.tgz#688e9f3448e3d0979c4aaab5b566e14f30a1aa72" + integrity sha512-gwWaAlhhV2By7XcbyU3DOLMvzsgeaymwP/jktDC+/uPkCmgB61zurwqOQdeiRq9KAf22Y2dtE5ZLXxytJRbEVA== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-mysql2@0.50.0": - version "0.50.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.50.0.tgz#259344ba8771fd59c70a1a91360215b4b047a323" - integrity sha512-PoOMpmq73rOIE3nlTNLf3B1SyNYGsp7QXHYKmeTZZnJ2Ou7/fdURuOhWOI0e6QZ5gSem18IR1sJi6GOULBQJ9g== +"@opentelemetry/instrumentation-mysql2@0.51.0": + version "0.51.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.51.0.tgz#7eec3a0b9e4b27759df5df1c82eaedcf34b27528" + integrity sha512-zT2Wg22Xn43RyfU3NOUmnFtb5zlDI0fKcijCj9AcK9zuLZ4ModgtLXOyBJSSfO+hsOCZSC1v/Fxwj+nZJFdzLQ== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" "@opentelemetry/sql-common" "^0.41.0" -"@opentelemetry/instrumentation-mysql@0.49.0": - version "0.49.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.49.0.tgz#24fa7473134867236ed4068ee645e51922bcb654" - integrity sha512-QU9IUNqNsrlfE3dJkZnFHqLjlndiU39ll/YAAEvWE40sGOCi9AtOF6rmEGzJ1IswoZ3oyePV7q2MP8SrhJfVAA== +"@opentelemetry/instrumentation-mysql@0.50.0": + version "0.50.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.50.0.tgz#25de9de05191cecf8b01df379544eba50fa6f548" + integrity sha512-duKAvMRI3vq6u9JwzIipY9zHfikN20bX05sL7GjDeLKr2qV0LQ4ADtKST7KStdGcQ+MTN5wghWbbVdLgNcB3rA== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" "@types/mysql" "2.15.27" -"@opentelemetry/instrumentation-pg@0.55.0": - version "0.55.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.55.0.tgz#f411d1e48c50b1c1f0f185d9fe94cfbb8812d8f6" - integrity sha512-yfJ5bYE7CnkW/uNsnrwouG/FR7nmg09zdk2MSs7k0ZOMkDDAE3WBGpVFFApGgNu2U+gtzLgEzOQG4I/X+60hXw== +"@opentelemetry/instrumentation-pg@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.57.0.tgz#346cb613ccd1100221cef9692271468a3fe92eb0" + integrity sha512-dWLGE+r5lBgm2A8SaaSYDE3OKJ/kwwy5WLyGyzor8PLhUL9VnJRiY6qhp4njwhnljiLtzeffRtG2Mf/YyWLeTw== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" - "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation" "^0.204.0" + "@opentelemetry/semantic-conventions" "^1.34.0" "@opentelemetry/sql-common" "^0.41.0" - "@types/pg" "8.15.4" + "@types/pg" "8.15.5" "@types/pg-pool" "2.0.6" -"@opentelemetry/instrumentation-redis@0.51.0": - version "0.51.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.51.0.tgz#70504ba6c3856fcb25e436b4915e85efaa7d38a6" - integrity sha512-uL/GtBA0u72YPPehwOvthAe+Wf8k3T+XQPBssJmTYl6fzuZjNq8zTfxVFhl9nRFjFVEe+CtiYNT0Q3AyqW1Z0A== +"@opentelemetry/instrumentation-redis@0.53.0": + version "0.53.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.53.0.tgz#826cfeacebaf7ce571bb932ad410f23caf170b9c" + integrity sha512-WUHV8fr+8yo5RmzyU7D5BIE1zwiaNQcTyZPwtxlfr7px6NYYx7IIpSihJK7WA60npWynfxxK1T67RAVF0Gdfjg== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/redis-common" "^0.38.0" "@opentelemetry/semantic-conventions" "^1.27.0" -"@opentelemetry/instrumentation-tedious@0.22.0": - version "0.22.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.22.0.tgz#f71374c52cb9c57a6b879bea3256a1465c02efbb" - integrity sha512-XrrNSUCyEjH1ax9t+Uo6lv0S2FCCykcF7hSxBMxKf7Xn0bPRxD3KyFUZy25aQXzbbbUHhtdxj3r2h88SfEM3aA== +"@opentelemetry/instrumentation-tedious@0.23.0": + version "0.23.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.23.0.tgz#a781de2cb33ff71ef65bbefba11c9fe2d79c4b32" + integrity sha512-3TMTk/9VtlRonVTaU4tCzbg4YqW+Iq/l5VnN2e5whP6JgEg/PKfrGbqQ+CxQWNLfLaQYIUgEZqAn5gk/inh1uQ== dependencies: - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" "@opentelemetry/semantic-conventions" "^1.27.0" "@types/tedious" "^4.0.14" -"@opentelemetry/instrumentation-undici@0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.14.0.tgz#7a9cd276f7664773b5daf5ae53365b3593e6e7a9" - integrity sha512-2HN+7ztxAReXuxzrtA3WboAKlfP5OsPA57KQn2AdYZbJ3zeRPcLXyW4uO/jpLE6PLm0QRtmeGCmfYpqRlwgSwg== +"@opentelemetry/instrumentation-undici@0.15.0": + version "0.15.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.15.0.tgz#c8193a162d4abe61c2fd247912e0cb8c0c3bc10c" + integrity sha512-sNFGA/iCDlVkNjzTzPRcudmI11vT/WAfAguRdZY9IspCw02N4WSC72zTuQhSMheh2a1gdeM9my1imnKRvEEvEg== dependencies: "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" + "@opentelemetry/instrumentation" "^0.204.0" -"@opentelemetry/instrumentation@0.203.0", "@opentelemetry/instrumentation@^0.203.0": - version "0.203.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.203.0.tgz#5c74a41cd6868f7ba47b346ff5a58ea7b18cf381" - integrity sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ== +"@opentelemetry/instrumentation@0.204.0", "@opentelemetry/instrumentation@^0.204.0": + version "0.204.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.204.0.tgz#587c104c02c9ccb38932ce508d9c81514ec7a7c4" + integrity sha512-vV5+WSxktzoMP8JoYWKeopChy6G3HKk4UQ2hESCRDUUTZqQ3+nM3u8noVG0LmNfRWwcFBnbZ71GKC7vaYYdJ1g== dependencies: - "@opentelemetry/api-logs" "0.203.0" + "@opentelemetry/api-logs" "0.204.0" import-in-the-middle "^1.8.1" require-in-the-middle "^7.1.1" @@ -716,41 +687,36 @@ shimmer "^1.2.1" "@opentelemetry/redis-common@^0.38.0": - version "0.38.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.0.tgz#87d2a792dcbcf466a41bb7dfb8a7cd094d643d0b" - integrity sha512-4Wc0AWURII2cfXVVoZ6vDqK+s5n4K5IssdrlVrvGsx6OEOKdghKtJZqXAHWFiZv4nTDLH2/2fldjIHY8clMOjQ== + version "0.38.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz#cefa4f3e79db1cd54f19e233b7dfb56621143955" + integrity sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA== -"@opentelemetry/resources@2.0.1", "@opentelemetry/resources@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.0.1.tgz#0365d134291c0ed18d96444a1e21d0e6a481c840" - integrity sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw== +"@opentelemetry/resources@2.1.0", "@opentelemetry/resources@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-2.1.0.tgz#11772e732af4f27953cf55567a6630d8b4d8282d" + integrity sha512-1CJjf3LCvoefUOgegxi8h6r4B/wLSzInyhGP2UmIBYNlo4Qk5CZ73e1eEyWmfXvFtm1ybkmfb2DqWvspsYLrWw== dependencies: - "@opentelemetry/core" "2.0.1" + "@opentelemetry/core" "2.1.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/sdk-trace-base@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.0.1.tgz#25808bb6a3d08a501ad840249e4d43d3493eb6e5" - integrity sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ== +"@opentelemetry/sdk-trace-base@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.1.0.tgz#9d31474824e9ed215f94bf71260d5321f64d402a" + integrity sha512-uTX9FBlVQm4S2gVQO1sb5qyBLq/FPjbp+tmGoxu4tIgtYGmBYB44+KX/725RFDe30yBSaA9Ml9fqphe1hbUyLQ== dependencies: - "@opentelemetry/core" "2.0.1" - "@opentelemetry/resources" "2.0.1" + "@opentelemetry/core" "2.1.0" + "@opentelemetry/resources" "2.1.0" "@opentelemetry/semantic-conventions" "^1.29.0" -"@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.30.0": - version "1.32.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.32.0.tgz#a15e8f78f32388a7e4655e7f539570e40958ca3f" - integrity sha512-s0OpmpQFSfMrmedAn9Lhg4KWJELHCU6uU9dtIJ28N8UGhf9Y55im5X8fEzwhwDwiSqN+ZPSNrDJF7ivf/AuRPQ== - -"@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0": - version "1.36.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.36.0.tgz#149449bd4df4d0464220915ad4164121e0d75d4d" - integrity sha512-TtxJSRD8Ohxp6bKkhrm27JRHAxPczQA7idtcTOMYI+wQRRrfgqxHv1cFbCApcSnNjtXkmzFozn6jQtFrOmbjPQ== +"@opentelemetry/semantic-conventions@^1.27.0", "@opentelemetry/semantic-conventions@^1.29.0", "@opentelemetry/semantic-conventions@^1.30.0", "@opentelemetry/semantic-conventions@^1.33.1", "@opentelemetry/semantic-conventions@^1.34.0", "@opentelemetry/semantic-conventions@^1.37.0": + version "1.37.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz#aa2b4fa0b910b66a050c5ddfcac1d262e91a321a" + integrity sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA== "@opentelemetry/sql-common@^0.41.0": - version "0.41.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sql-common/-/sql-common-0.41.0.tgz#7ddef1ea7fb6338dcca8a9d2485c7dfd53c076b4" - integrity sha512-pmzXctVbEERbqSfiAgdes9Y63xjoOyXcD7B6IXBkVb+vbM7M9U98mn33nGXxPf4dfYR0M+vhcKRZmbSJ7HfqFA== + version "0.41.2" + resolved "https://registry.yarnpkg.com/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz#7f4a14166cfd6c9ffe89096db1cc75eaf6443b19" + integrity sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ== dependencies: "@opentelemetry/core" "^2.0.0" @@ -897,23 +863,23 @@ integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== "@prisma/adapter-pg@^6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-6.16.2.tgz#c1ca0eb801889b2e455d2379a8e9c26f21b0eefc" - integrity sha512-C+JZmKDBm13anIRhhJYxNw0EZ3zT11n9i6JCPBf2sg7HCNlQiYAPBegqYzAYwGw8VG8xlkM0aV9xJ4AH2mQqaQ== + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/adapter-pg/-/adapter-pg-6.16.3.tgz#ce1c80c11539cc3cc13d8629c9551257e9e6e96e" + integrity sha512-7P0+NbVQYrFcwpfmCWiFUUdXTi2GU+CtSnWLrR93oupvFG+GtZXociT9eXbsOUNF9+g74yVe6hsOgsuW/uPHaQ== dependencies: - "@prisma/driver-adapter-utils" "6.16.2" + "@prisma/driver-adapter-utils" "6.16.3" pg "^8.11.3" postgres-array "3.0.4" "@prisma/client@^6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.16.2.tgz#db11b9af568d1761c0b712fccfc6ee484d2310d7" - integrity sha512-E00PxBcalMfYO/TWnXobBVUai6eW/g5OsifWQsQDzJYm7yaY+IRLo7ZLsaefi0QkTpxfuhFcQ/w180i6kX3iJw== + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.16.3.tgz#6c3a9b749a8155f3dfea1358068a6b1e41080182" + integrity sha512-JfNfAtXG+/lIopsvoZlZiH2k5yNx87mcTS4t9/S5oufM1nKdXYxOvpDC1XoTCFBa5cQh7uXnbMPsmZrwZY80xw== -"@prisma/config@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.16.2.tgz#bb4816d8f1854eb281dab00d34a2392fe290ee25" - integrity sha512-mKXSUrcqXj0LXWPmJsK2s3p9PN+aoAbyMx7m5E1v1FufofR1ZpPoIArjjzOIm+bJRLLvYftoNYLx1tbHgF9/yg== +"@prisma/config@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.16.3.tgz#ac21ce44017393e86bec19f51a4074298787666c" + integrity sha512-VlsLnG4oOuKGGMToEeVaRhoTBZu5H3q51jTQXb/diRags3WV0+BQK5MolJTtP6G7COlzoXmWeS11rNBtvg+qFQ== dependencies: c12 "3.1.0" deepmerge-ts "7.1.5" @@ -938,27 +904,27 @@ debug "4.3.4" strip-ansi "6.0.1" -"@prisma/debug@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.16.2.tgz#d1358392f68ea29cad905e44be67f5cc4930d866" - integrity sha512-bo4/gA/HVV6u8YK2uY6glhNsJ7r+k/i5iQ9ny/3q5bt9ijCj7WMPUwfTKPvtEgLP+/r26Z686ly11hhcLiQ8zA== +"@prisma/debug@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.16.3.tgz#a4892e41ada976fe209e405adcacee02cc34f969" + integrity sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA== -"@prisma/dmmf@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/dmmf/-/dmmf-6.16.2.tgz#a808af49eaa6975ef965bf38dc1195edeed9e039" - integrity sha512-o9ztgdbj2KZXl6DL+oP56TTC0poTLPns9/MeU761b49E1IQ/fd0jwdov1bidlNOiwio8Nsou23xNrYE/db10aA== +"@prisma/dmmf@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/dmmf/-/dmmf-6.16.3.tgz#f5ee854466f6517b81e929f3fef5f031b67ad2cb" + integrity sha512-8QBQi7Pa/aTFviCx5xW1Uv+88VqpxV6XTlSZQpT7+Dj01lLUI5+2h+TZvH90uWIGLwmPEahrOjxkSBMu8W+KqQ== -"@prisma/driver-adapter-utils@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/driver-adapter-utils/-/driver-adapter-utils-6.16.2.tgz#10505585f94ac7b84ac2e754e96cbd2ef167881a" - integrity sha512-DMgfafnG0zPd+QoAQOC0Trn1xlb0fVAfQi2MpkpzSf641KiVkVPkJRXDSbcTbxGxO2HRdd0vI9U6LlesWad4XA== +"@prisma/driver-adapter-utils@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/driver-adapter-utils/-/driver-adapter-utils-6.16.3.tgz#2bdce37ef8f5421f5f04d7347c16d3615719d1cf" + integrity sha512-FliuxCf08NTsV0lexYe5YuT7rlwdb0yofd3fROONnEUuo60Tu4DMe2URoVpkDScOaCDtWi/2VFyAhOMQNgIeHw== dependencies: - "@prisma/debug" "6.16.2" + "@prisma/debug" "6.16.3" -"@prisma/engines-version@6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43": - version "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43.tgz#84904768af0d29a7fb6122a5d9f91cf4658886f9" - integrity sha512-ThvlDaKIVrnrv97ujNFDYiQbeMQpLa0O86HFA2mNoip4mtFqM7U5GSz2ie1i2xByZtvPztJlNRgPsXGeM/kqAA== +"@prisma/engines-version@6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a": + version "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a.tgz#695d03994f428ea2d7a9658b4bb84d57e8ef499d" + integrity sha512-fftRmosBex48Ph1v2ll1FrPpirwtPZpNkE5CDCY1Lw2SD2ctyrLlVlHiuxDAAlALwWBOkPbAll4+EaqdGuMhJw== "@prisma/engines@4.16.2": version "4.16.2" @@ -970,15 +936,15 @@ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.0.0.tgz#5249650eabe77c458c90f2be97d8210353c2e22e" integrity sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg== -"@prisma/engines@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.16.2.tgz#49421086f1a1a83b725bbb1bab6d682e8e497811" - integrity sha512-7yf3AjfPUgsg/l7JSu1iEhsmZZ/YE00yURPjTikqm2z4btM0bCl2coFtTGfeSOWbQMmq45Jab+53yGUIAT1sjA== +"@prisma/engines@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.16.3.tgz#6ae2082961692ace7ec7e4b744abf6f47076520f" + integrity sha512-b+Rl4nzQDcoqe6RIpSHv8f5lLnwdDGvXhHjGDiokObguAAv/O1KaX1Oc69mBW/GFWKQpCkOraobLjU6s1h8HGg== dependencies: - "@prisma/debug" "6.16.2" - "@prisma/engines-version" "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" - "@prisma/fetch-engine" "6.16.2" - "@prisma/get-platform" "6.16.2" + "@prisma/debug" "6.16.3" + "@prisma/engines-version" "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" + "@prisma/fetch-engine" "6.16.3" + "@prisma/get-platform" "6.16.3" "@prisma/fetch-engine@4.16.2": version "4.16.2" @@ -1026,14 +992,14 @@ temp-dir "2.0.0" tempy "1.0.1" -"@prisma/fetch-engine@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.16.2.tgz#dfdf9fa49887cc0ac04f1296e4c1a5f64490ce71" - integrity sha512-wPnZ8DMRqpgzye758ZvfAMiNJRuYpz+rhgEBZi60ZqDIgOU2694oJxiuu3GKFeYeR/hXxso4/2oBC243t/whxQ== +"@prisma/fetch-engine@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.16.3.tgz#72d26421d4793bb6d99218b7e9d571cd6bcb1d3a" + integrity sha512-bUoRIkVaI+CCaVGrSfcKev0/Mk4ateubqWqGZvQ9uCqFv2ENwWIR3OeNuGin96nZn5+SkebcD7RGgKr/+mJelw== dependencies: - "@prisma/debug" "6.16.2" - "@prisma/engines-version" "6.16.0-7.1c57fdcd7e44b29b9313256c76699e91c3ac3c43" - "@prisma/get-platform" "6.16.2" + "@prisma/debug" "6.16.3" + "@prisma/engines-version" "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" + "@prisma/get-platform" "6.16.3" "@prisma/generator-helper@4.16.2", "@prisma/generator-helper@^4.14.0": version "4.16.2" @@ -1056,18 +1022,18 @@ kleur "4.1.5" "@prisma/generator-helper@^6.15.0": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-6.16.2.tgz#b0ea198e3690eacf02e44fc661146fb983ed229f" - integrity sha512-8tVnWM8ETJNrvI5CT9eKCW23+aPLNkidC+g9NJn7ghXm60Q7GGlLX5tmvn5dE8tXvs/FSX3MN7KNmNJpOr89Hw== + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/generator-helper/-/generator-helper-6.16.3.tgz#3a1f258fbff2604d4274ef26a2ff3127075bcbe0" + integrity sha512-mjkqpvVc8KaR2p71DLFFhfzI8w/8QqitPF2Uszz4JzMX30biZ61TMMk4J1tIQk8OyzsX1yUWv3ya4HV0m6pfgw== dependencies: - "@prisma/debug" "6.16.2" - "@prisma/dmmf" "6.16.2" - "@prisma/generator" "6.16.2" + "@prisma/debug" "6.16.3" + "@prisma/dmmf" "6.16.3" + "@prisma/generator" "6.16.3" -"@prisma/generator@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/generator/-/generator-6.16.2.tgz#3ac40f6adf46f17f77dacfe35d27900cd1aeaebd" - integrity sha512-7bwRmtMIgfe1rUynh1p9VlmYvEiidbRO6aBphPBS6YGEGSvNe8+QExbRpsqFlFBvIX76BhZCxuEj7ZwALMYRKQ== +"@prisma/generator@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/generator/-/generator-6.16.3.tgz#a82686395593fc7e99381700b9a9ab67e87ee558" + integrity sha512-R8Z+FGcCRWA+v7H7vwr/QF+uAgUtWfz+elscioIIGo+ncBULo2kJ+ILtGkmpm/YeINxEjvD4BbyKYTvkFwowLg== "@prisma/get-platform@4.16.2": version "4.16.2" @@ -1101,17 +1067,17 @@ terminal-link "2.1.1" ts-pattern "4.3.0" -"@prisma/get-platform@6.16.2": - version "6.16.2" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.16.2.tgz#6814078c97f2ad14bbee8fa25659784b00cafcda" - integrity sha512-U/P36Uke5wS7r1+omtAgJpEB94tlT4SdlgaeTc6HVTTT93pXj7zZ+B/cZnmnvjcNPfWddgoDx8RLjmQwqGDYyA== +"@prisma/get-platform@6.16.3": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.16.3.tgz#54704555f1eb652a7dd893c816307f016dba4d18" + integrity sha512-X1LxiFXinJ4iQehrodGp0f66Dv6cDL0GbRlcCoLtSu6f4Wi+hgo7eND/afIs5029GQLgNWKZ46vn8hjyXTsHLA== dependencies: - "@prisma/debug" "6.16.2" + "@prisma/debug" "6.16.3" -"@prisma/instrumentation@6.14.0": - version "6.14.0" - resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-6.14.0.tgz#8f6e43b73ee2b88b98cec901457f4da7da13aea3" - integrity sha512-Po/Hry5bAeunRDq0yAQueKookW3glpP+qjjvvyOfm6dI2KG5/Y6Bgg3ahyWd7B0u2E+Wf9xRk2rtdda7ySgK1A== +"@prisma/instrumentation@6.15.0": + version "6.15.0" + resolved "https://registry.yarnpkg.com/@prisma/instrumentation/-/instrumentation-6.15.0.tgz#40b066dc6b1ea621aa5ae0fd6d54319550b7d8c9" + integrity sha512-6TXaH6OmDkMOQvOxwLZ8XS51hU2v4A3vmE2pSijCIiGRJYyNeMcL6nMHQMyYdZRD8wl7LF3Wzc+AMPMV/9Oo7A== dependencies: "@opentelemetry/instrumentation" "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" @@ -1237,50 +1203,110 @@ unbzip2-stream "1.4.3" yargs "17.7.1" -"@sentry/cli-darwin@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.52.0.tgz#05178cd819c2a33eb22a6e90bf7bb8f853f1b476" - integrity sha512-ieQs/p4yTHT27nBzy0wtAb8BSISfWlpXdgsACcwXimYa36NJRwyCqgOXUaH/BYiTdwWSHpuANbUHGJW6zljzxw== - -"@sentry/cli-linux-arm64@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.52.0.tgz#1979141afc93022614f868374ecc4d3090e84833" - integrity sha512-RxT5uzxjCkcvplmx0bavJIEYerRex2Rg/2RAVBdVvWLKFOcmeerTn/VVxPZVuDIVMVyjlZsteWPYwfUm+Ia3wQ== - -"@sentry/cli-linux-arm@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.52.0.tgz#6957e11af62e50d1040488ec75b3d96ae33fbb5a" - integrity sha512-tWMLU+hj+iip5Akx+S76biAOE1eMMWTDq8c0MqMv/ahHgb6/HiVngMcUsp59Oz3EczJGbTkcnS3vRTDodEcMDw== - -"@sentry/cli-linux-i686@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.52.0.tgz#e369ce3afa4b83a482d34cfd25fae4af792b211a" - integrity sha512-sKcJmIg7QWFtlNU5Bs5OZprwdIzzyYMRpFkWioPZ4TE82yvP1+2SAX31VPUlTx+7NLU6YVEWNwvSxh8LWb7iOw== - -"@sentry/cli-linux-x64@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.52.0.tgz#2b447afac1bb96624823a49c0d9f23c54475bff2" - integrity sha512-aPZ7bP02zGkuEqTiOAm4np/ggfgtzrq4ti1Xze96Csi/DV3820SCfLrPlsvcvnqq7x69IL9cI3kXjdEpgrfGxw== - -"@sentry/cli-win32-arm64@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.52.0.tgz#059063774ab5437ea05d82ce316faa77582b8b51" - integrity sha512-90hrB5XdwJVhRpCmVrEcYoKW8nl5/V9OfVvOGeKUPvUkApLzvsInK74FYBZEVyAn1i/NdUv+Xk9q2zqUGK1aLQ== - -"@sentry/cli-win32-i686@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.52.0.tgz#bee3cded721fcf45db2e77bf84ea8653e4d803d9" - integrity sha512-HXlSE4CaLylNrELx4KVmOQjV5bURCNuky6sjCWiTH7HyDqHEak2Rk8iLE0JNLj5RETWMvmaZnZZFfmyGlY1opg== - -"@sentry/cli-win32-x64@2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.52.0.tgz#16e501e5f00834b1f64765774c59740580043dfc" - integrity sha512-hJT0C3FwHk1Mt9oFqcci88wbO1D+yAWUL8J29HEGM5ZAqlhdh7sAtPDIC3P2LceUJOjnXihow47Bkj62juatIQ== +"@react-aria/focus@^3.20.2": + version "3.21.2" + resolved "https://registry.yarnpkg.com/@react-aria/focus/-/focus-3.21.2.tgz#3ce90450c3ee69f11c0647b4717c26d10941231c" + integrity sha512-JWaCR7wJVggj+ldmM/cb/DXFg47CXR55lznJhZBh4XVqJjMKwaOOqpT5vNN7kpC1wUpXicGNuDnJDN1S/+6dhQ== + dependencies: + "@react-aria/interactions" "^3.25.6" + "@react-aria/utils" "^3.31.0" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-aria/interactions@^3.25.0", "@react-aria/interactions@^3.25.6": + version "3.25.6" + resolved "https://registry.yarnpkg.com/@react-aria/interactions/-/interactions-3.25.6.tgz#6fdf287337c5e4285045c35cf94b2ec8ae3b3a49" + integrity sha512-5UgwZmohpixwNMVkMvn9K1ceJe6TzlRlAfuYoQDUuOkk62/JVJNDLAPKIf5YMRc7d2B0rmfgaZLMtbREb0Zvkw== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-aria/utils" "^3.31.0" + "@react-stately/flags" "^3.1.2" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + +"@react-aria/ssr@^3.9.10": + version "3.9.10" + resolved "https://registry.yarnpkg.com/@react-aria/ssr/-/ssr-3.9.10.tgz#7fdc09e811944ce0df1d7e713de1449abd7435e6" + integrity sha512-hvTm77Pf+pMBhuBm760Li0BVIO38jv1IBws1xFm1NoL26PU+fe+FMW5+VZWyANR6nYL65joaJKZqOdTQMkO9IQ== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-aria/utils@^3.31.0": + version "3.31.0" + resolved "https://registry.yarnpkg.com/@react-aria/utils/-/utils-3.31.0.tgz#4710e35bf658234cf4b53eec9742f25e51637b12" + integrity sha512-ABOzCsZrWzf78ysswmguJbx3McQUja7yeGj6/vZo4JVsZNlxAN+E9rs381ExBRI0KzVo6iBTeX5De8eMZPJXig== + dependencies: + "@react-aria/ssr" "^3.9.10" + "@react-stately/flags" "^3.1.2" + "@react-stately/utils" "^3.10.8" + "@react-types/shared" "^3.32.1" + "@swc/helpers" "^0.5.0" + clsx "^2.0.0" + +"@react-stately/flags@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@react-stately/flags/-/flags-3.1.2.tgz#5c8e5ae416d37d37e2e583d2fcb3a046293504f2" + integrity sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-stately/utils@^3.10.8": + version "3.10.8" + resolved "https://registry.yarnpkg.com/@react-stately/utils/-/utils-3.10.8.tgz#fdb9d172f7bbc2d083e69190f5ef0edfa4b4392f" + integrity sha512-SN3/h7SzRsusVQjQ4v10LaVsDc81jyyR0DD5HnsQitm/I5WDpaSr2nRHtyloPFU48jlql1XX/S04T2DLQM7Y3g== + dependencies: + "@swc/helpers" "^0.5.0" + +"@react-types/shared@^3.32.1": + version "3.32.1" + resolved "https://registry.yarnpkg.com/@react-types/shared/-/shared-3.32.1.tgz#abfeb839d65d0abe923576f34ac08342c25dfa55" + integrity sha512-famxyD5emrGGpFuUlgOP6fVW2h/ZaF405G5KDi3zPHzyjAWys/8W6NAVJtNbkCkhedmvL0xOhvt8feGXyXaw5w== + +"@sentry/cli-darwin@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-darwin/-/cli-darwin-2.56.0.tgz#53fa7de2c26f6450d5454ba997c26c2471d112c8" + integrity sha512-CzXFWbv3GrjU0gFlUM9jt0fvJmyo5ktty4HGxRFfS/eMC6xW58Gg/sEeMVEkdvk5osKooX/YEgfLBdo4zvuWDA== + +"@sentry/cli-linux-arm64@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.56.0.tgz#5041c8877416a607ddae87b948cbe6c9e86d7f54" + integrity sha512-91d5ZlC989j/t+TXor/glPyx6SnLFS/SlJ9fIrHIQohdGKyWWSFb4VKUan8Ok3GYu9SUzKTMByryIOoYEmeGVw== + +"@sentry/cli-linux-arm@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-arm/-/cli-linux-arm-2.56.0.tgz#c7875cf5f76e254ff1c0f49cf99d8c26b6ec4959" + integrity sha512-vQCCMhZLugPmr25XBoP94dpQsFa110qK5SBUVJcRpJKyzMZd+6ueeHNslq2mB0OF4BwL1qd/ZDIa4nxa1+0rjQ== + +"@sentry/cli-linux-i686@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-i686/-/cli-linux-i686-2.56.0.tgz#aeaff32f9f0d405e413373223e406d66b1d56176" + integrity sha512-MZzXuq1Q/TktN81DUs6XSBU752pG3XWSJdZR+NCStIg3l8s3O/Pwh6OcDHTYqgwsYJaGBpA0fP2Afl5XeSAUNg== + +"@sentry/cli-linux-x64@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-linux-x64/-/cli-linux-x64-2.56.0.tgz#3dd4ef83c2d710c3e6f5d078d05391fda2ce23ee" + integrity sha512-INOO2OQ90Y3UzYgHRdrHdKC/0es3YSHLv0iNNgQwllL0YZihSVNYSSrZqcPq8oSDllEy9Vt9oOm/7qEnUP2Kfw== + +"@sentry/cli-win32-arm64@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.56.0.tgz#2113bcac721970ca4dbd04a6dab37dfb0ec147d2" + integrity sha512-eUvkVk9KK01q6/qyugQPh7dAxqFPbgOa62QAoSwo11WQFYc3NPgJLilFWLQo+nahHGYKh6PKuCJ5tcqnQq5Hkg== + +"@sentry/cli-win32-i686@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-i686/-/cli-win32-i686-2.56.0.tgz#bd8e646f4b5a98aa80bc9751a6e0db6514a935f5" + integrity sha512-mpCA8hKXuvT17bl1H/54KOa5i+02VBBHVlOiP3ltyBuQUqfvX/30Zl/86Spy+ikodovZWAHv5e5FpyXbY1/mPw== + +"@sentry/cli-win32-x64@2.56.0": + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli-win32-x64/-/cli-win32-x64-2.56.0.tgz#1acc7ca166ed531075a31b2bc1700294747da6b8" + integrity sha512-UV0pXNls+/ViAU/3XsHLLNEHCsRYaGEwJdY3HyGIufSlglxrX6BVApkV9ziGi4WAxcJWLjQdfcEs6V5B+wBy0A== "@sentry/cli@^2.52.0": - version "2.52.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.52.0.tgz#5162900bbfae57ddfc414bbe5780837622125aed" - integrity sha512-PXyo7Yv7+rVMSBGZfI/eFEzzhiKedTs25sDCjz4a3goAZ/F5R5tn3MKq30pnze5wNnoQmLujAa0uUjfNcWP+uQ== + version "2.56.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-2.56.0.tgz#13dc043c78687b47285cc45db5bcfb65bbdb6dd9" + integrity sha512-br6+1nTPUV5EG1oaxLzxv31kREFKr49Y1+3jutfMUz9Nl8VyVP7o9YwakB/YWl+0Vi0NXg5vq7qsd/OOuV5j8w== dependencies: https-proxy-agent "^5.0.0" node-fetch "^2.6.7" @@ -1288,86 +1314,86 @@ proxy-from-env "^1.1.0" which "^2.0.2" optionalDependencies: - "@sentry/cli-darwin" "2.52.0" - "@sentry/cli-linux-arm" "2.52.0" - "@sentry/cli-linux-arm64" "2.52.0" - "@sentry/cli-linux-i686" "2.52.0" - "@sentry/cli-linux-x64" "2.52.0" - "@sentry/cli-win32-arm64" "2.52.0" - "@sentry/cli-win32-i686" "2.52.0" - "@sentry/cli-win32-x64" "2.52.0" - -"@sentry/core@10.8.0": - version "10.8.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.8.0.tgz#71f71f8ecb5a06c41a426f5ccee2d9767b7d7cfd" - integrity sha512-scYzM/UOItu4PjEq6CpHLdArpXjIS0laHYxE4YjkIbYIH6VMcXGQbD/FSBClsnCr1wXRnlXfXBzj0hrQAFyw+Q== - -"@sentry/node-core@10.8.0": - version "10.8.0" - resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.8.0.tgz#c1545e02d5b45aed003401695d9b512dac1566f9" - integrity sha512-KCFy5Otq6KTXge8hBKMgU13EDRFkO4gNwSyZGXub8a7KHYFtoUgpRkborR59SWxeJmC6aEYTyh0PyOoWZJbHUQ== - dependencies: - "@sentry/core" "10.8.0" - "@sentry/opentelemetry" "10.8.0" + "@sentry/cli-darwin" "2.56.0" + "@sentry/cli-linux-arm" "2.56.0" + "@sentry/cli-linux-arm64" "2.56.0" + "@sentry/cli-linux-i686" "2.56.0" + "@sentry/cli-linux-x64" "2.56.0" + "@sentry/cli-win32-arm64" "2.56.0" + "@sentry/cli-win32-i686" "2.56.0" + "@sentry/cli-win32-x64" "2.56.0" + +"@sentry/core@10.17.0": + version "10.17.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-10.17.0.tgz#ea0851532bd6e407e9332e0200d90b34b556c3f5" + integrity sha512-UVIvxSzS0n5QbIDPyFf0WX9I77Of1bcr6a0sCEKfjhJGmGQ8mFWoWgR2gF4wcPw60XUrzbryCr79eOsIHLQ5cw== + +"@sentry/node-core@10.17.0": + version "10.17.0" + resolved "https://registry.yarnpkg.com/@sentry/node-core/-/node-core-10.17.0.tgz#8139423da6e107884931d090b6091b43956ddb7a" + integrity sha512-x6av2pFtsAeN+nZKkhI07cOCugTKux908DCGBlwQEw8ZjghcO5jn3unfAlKZqxZ0ktWgBcSrCM/iJ5Gk2nxPFg== + dependencies: + "@sentry/core" "10.17.0" + "@sentry/opentelemetry" "10.17.0" import-in-the-middle "^1.14.2" "@sentry/node@^10.8.0": - version "10.8.0" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.8.0.tgz#bec335d4324d52cafe0a24836bc7fd8476e9d33c" - integrity sha512-1TtCjxzn4SxoGw+ulLK+jF/v9NaZfP0yCclQIqfvWNDjMf2F+SbZL1UnXx4L184FGlNpRQnJBDrBe88gxnMX0A== + version "10.17.0" + resolved "https://registry.yarnpkg.com/@sentry/node/-/node-10.17.0.tgz#4363cb80103a9ac1c7447d3cd822215ea9eaccad" + integrity sha512-rM+ANC4NKkYHAFa73lqBXq024/YrflcUKBxkqSuo/0jc/Q/svLZfoZ8FW0IVZ4uhXXFZL3PZbkceZYmoOG9ePg== dependencies: "@opentelemetry/api" "^1.9.0" - "@opentelemetry/context-async-hooks" "^2.0.0" - "@opentelemetry/core" "^2.0.0" - "@opentelemetry/instrumentation" "^0.203.0" - "@opentelemetry/instrumentation-amqplib" "0.50.0" - "@opentelemetry/instrumentation-connect" "0.47.0" - "@opentelemetry/instrumentation-dataloader" "0.21.1" - "@opentelemetry/instrumentation-express" "0.52.0" - "@opentelemetry/instrumentation-fs" "0.23.0" - "@opentelemetry/instrumentation-generic-pool" "0.47.0" - "@opentelemetry/instrumentation-graphql" "0.51.0" - "@opentelemetry/instrumentation-hapi" "0.50.0" - "@opentelemetry/instrumentation-http" "0.203.0" - "@opentelemetry/instrumentation-ioredis" "0.51.0" - "@opentelemetry/instrumentation-kafkajs" "0.13.0" - "@opentelemetry/instrumentation-knex" "0.48.0" - "@opentelemetry/instrumentation-koa" "0.51.0" - "@opentelemetry/instrumentation-lru-memoizer" "0.48.0" - "@opentelemetry/instrumentation-mongodb" "0.56.0" - "@opentelemetry/instrumentation-mongoose" "0.50.0" - "@opentelemetry/instrumentation-mysql" "0.49.0" - "@opentelemetry/instrumentation-mysql2" "0.50.0" - "@opentelemetry/instrumentation-pg" "0.55.0" - "@opentelemetry/instrumentation-redis" "0.51.0" - "@opentelemetry/instrumentation-tedious" "0.22.0" - "@opentelemetry/instrumentation-undici" "0.14.0" - "@opentelemetry/resources" "^2.0.0" - "@opentelemetry/sdk-trace-base" "^2.0.0" - "@opentelemetry/semantic-conventions" "^1.34.0" - "@prisma/instrumentation" "6.14.0" - "@sentry/core" "10.8.0" - "@sentry/node-core" "10.8.0" - "@sentry/opentelemetry" "10.8.0" + "@opentelemetry/context-async-hooks" "^2.1.0" + "@opentelemetry/core" "^2.1.0" + "@opentelemetry/instrumentation" "^0.204.0" + "@opentelemetry/instrumentation-amqplib" "0.51.0" + "@opentelemetry/instrumentation-connect" "0.48.0" + "@opentelemetry/instrumentation-dataloader" "0.22.0" + "@opentelemetry/instrumentation-express" "0.53.0" + "@opentelemetry/instrumentation-fs" "0.24.0" + "@opentelemetry/instrumentation-generic-pool" "0.48.0" + "@opentelemetry/instrumentation-graphql" "0.52.0" + "@opentelemetry/instrumentation-hapi" "0.51.0" + "@opentelemetry/instrumentation-http" "0.204.0" + "@opentelemetry/instrumentation-ioredis" "0.52.0" + "@opentelemetry/instrumentation-kafkajs" "0.14.0" + "@opentelemetry/instrumentation-knex" "0.49.0" + "@opentelemetry/instrumentation-koa" "0.52.0" + "@opentelemetry/instrumentation-lru-memoizer" "0.49.0" + "@opentelemetry/instrumentation-mongodb" "0.57.0" + "@opentelemetry/instrumentation-mongoose" "0.51.0" + "@opentelemetry/instrumentation-mysql" "0.50.0" + "@opentelemetry/instrumentation-mysql2" "0.51.0" + "@opentelemetry/instrumentation-pg" "0.57.0" + "@opentelemetry/instrumentation-redis" "0.53.0" + "@opentelemetry/instrumentation-tedious" "0.23.0" + "@opentelemetry/instrumentation-undici" "0.15.0" + "@opentelemetry/resources" "^2.1.0" + "@opentelemetry/sdk-trace-base" "^2.1.0" + "@opentelemetry/semantic-conventions" "^1.37.0" + "@prisma/instrumentation" "6.15.0" + "@sentry/core" "10.17.0" + "@sentry/node-core" "10.17.0" + "@sentry/opentelemetry" "10.17.0" import-in-the-middle "^1.14.2" minimatch "^9.0.0" -"@sentry/opentelemetry@10.8.0": - version "10.8.0" - resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.8.0.tgz#dabf51c51b07126ab72d806e0ba93f128fef7ce6" - integrity sha512-62R/RPwTYVaiZ5lVcxcjHCAGwgCyfn8Q3kaQld8/LPm8FRizZeUJmmtrI80KaYCvPJhSB/Pvfma4X3w+aN5Q3A== +"@sentry/opentelemetry@10.17.0": + version "10.17.0" + resolved "https://registry.yarnpkg.com/@sentry/opentelemetry/-/opentelemetry-10.17.0.tgz#b0aaf23880a5e5cac9db27943c64561265df6798" + integrity sha512-kZONokjkIQjhDUEZLsi7TZ1Bay0g4VFC2rT1MvZqa1fkFZff7Th9qQr0Lv7gt3nrbD6qIctEzmpf75OQN1cR8A== dependencies: - "@sentry/core" "10.8.0" + "@sentry/core" "10.17.0" "@simplewebauthn/browser@^13.1.2": - version "13.2.0" - resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-13.2.0.tgz#20ed07457d6ed4e28aaa94e8c2ee0545e95bfc89" - integrity sha512-N3fuA1AAnTo5gCStYoIoiasPccC+xPLx2YU88Dv0GeAmPQTWHETlZQq5xZ0DgUq1H9loXMWQH5qqUjcI7BHJ1A== + version "13.2.2" + resolved "https://registry.yarnpkg.com/@simplewebauthn/browser/-/browser-13.2.2.tgz#4cde38c4c6969a039c23c2a3d931ecb69f937910" + integrity sha512-FNW1oLQpTJyqG5kkDg5ZsotvWgmBaC6jCHR7Ej0qUNep36Wl9tj2eZu7J5rP+uhXgHaLk+QQ3lqcw2vS5MX1IA== "@simplewebauthn/server@^13.1.2": - version "13.2.1" - resolved "https://registry.yarnpkg.com/@simplewebauthn/server/-/server-13.2.1.tgz#2971e999a3c209e257d601e30bb53b0fa84501cc" - integrity sha512-Inmfye5opZXe3HI0GaksqBnQiM7glcNySoG6DH1GgkO1Lh9dvuV4XSV9DK02DReUVX39HpcDob9nxHELjECoQw== + version "13.2.2" + resolved "https://registry.yarnpkg.com/@simplewebauthn/server/-/server-13.2.2.tgz#42a9ebe64831b91fc1ac6d8aefc553822c7114aa" + integrity sha512-HcWLW28yTMGXpwE9VLx9J+N2KEUaELadLrkPEEI9tpI5la70xNEVEsu/C+m3u7uoq4FulLqZQhgBCzR9IZhFpA== dependencies: "@hexagon/base64" "^1.1.27" "@levischuck/tiny-cbor" "^0.2.2" @@ -1378,6 +1404,14 @@ "@peculiar/asn1-x509" "^2.3.8" "@peculiar/x509" "^1.13.0" +"@so-ric/colorspace@^1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@so-ric/colorspace/-/colorspace-1.1.6.tgz#62515d8b9f27746b76950a83bde1af812d91923b" + integrity sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw== + dependencies: + color "^5.0.2" + text-hex "1.0.x" + "@socket.io/component-emitter@~3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2" @@ -1388,17 +1422,24 @@ resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== -"@tanstack/virtual-core@3.13.6": - version "3.13.6" - resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.13.6.tgz#329f962f1596b3280736c266a982897ed2112157" - integrity sha512-cnQUeWnhNP8tJ4WsGcYiX24Gjkc9ALstLbHcBj1t3E7EimN6n6kHH+DPV4PpDnuw00NApQp+ViojMj1GRdwYQg== +"@swc/helpers@^0.5.0": + version "0.5.17" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.17.tgz#5a7be95ac0f0bf186e7e6e890e7a6f6cda6ce971" + integrity sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A== + dependencies: + tslib "^2.8.0" -"@tanstack/vue-virtual@^3.0.0-beta.60": - version "3.13.6" - resolved "https://registry.yarnpkg.com/@tanstack/vue-virtual/-/vue-virtual-3.13.6.tgz#4857c3539bf838d977b3a04bf157d60f569338a8" - integrity sha512-GYdZ3SJBQPzgxhuCE2fvpiH46qzHiVx5XzBSdtESgiqh4poj8UgckjGWYEhxaBbcVt1oLzh1m3Ql4TyH32TOzQ== +"@tanstack/react-virtual@^3.13.9": + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz#d372dc2783739cc04ec1a728ca8203937687a819" + integrity sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA== dependencies: - "@tanstack/virtual-core" "3.13.6" + "@tanstack/virtual-core" "3.13.12" + +"@tanstack/virtual-core@3.13.12": + version "3.13.12" + resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz#1dff176df9cc8f93c78c5e46bcea11079b397578" + integrity sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA== "@tsconfig/node10@^1.0.7": version "1.0.11" @@ -1420,28 +1461,14 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== -"@types/assert@^1.5.6": - version "1.5.11" - resolved "https://registry.yarnpkg.com/@types/assert/-/assert-1.5.11.tgz#0b022efe761e14cca3d0f8ad1fd77a403de0071e" - integrity sha512-FjS1mxq2dlGr9N4z72/DO+XmyRS3ZZIoVn998MEopAN/OmyN28F4yumRL5pOw2z+hbFLuWGYuF2rrw5p11xM5A== - "@types/body-parser@*": - version "1.19.5" - resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.5.tgz#04ce9a3b677dc8bd681a17da1ab9835dc9d3ede4" - integrity sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg== + version "1.19.6" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.6.tgz#1859bebb8fd7dac9918a45d54c1971ab8b5af474" + integrity sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g== dependencies: "@types/connect" "*" "@types/node" "*" -"@types/connect-pg-simple@^7.0.3": - version "7.0.3" - resolved "https://registry.yarnpkg.com/@types/connect-pg-simple/-/connect-pg-simple-7.0.3.tgz#05b4bdbccbba333787b01730bacd202f15afa480" - integrity sha512-NGCy9WBlW2bw+J/QlLnFZ9WjoGs6tMo3LAut6mY4kK+XHzue//lpNVpAvYRpIwM969vBRAM2Re0izUvV6kt+NA== - dependencies: - "@types/express" "*" - "@types/express-session" "*" - "@types/pg" "*" - "@types/connect@*", "@types/connect@3.4.38": version "3.4.38" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" @@ -1450,9 +1477,9 @@ "@types/node" "*" "@types/cors@^2.8.12", "@types/cors@^2.8.17": - version "2.8.17" - resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b" - integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA== + version "2.8.19" + resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.19.tgz#d93ea2673fd8c9f697367f5eeefc2bbfa94f0342" + integrity sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg== dependencies: "@types/node" "*" @@ -1464,9 +1491,9 @@ "@types/node" "*" "@types/d3-array@*": - version "3.2.1" - resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.1.tgz#1f6658e3d2006c4fceac53fde464166859f8b8c5" - integrity sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg== + version "3.2.2" + resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-3.2.2.tgz#e02151464d02d4a1b44646d0fcdb93faf88fde8c" + integrity sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw== "@types/d3-axis@*": version "3.0.6" @@ -1506,9 +1533,9 @@ integrity sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw== "@types/d3-dispatch@*": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz#096efdf55eb97480e3f5621ff9a8da552f0961e7" - integrity sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ== + version "3.0.7" + resolved "https://registry.yarnpkg.com/@types/d3-dispatch/-/d3-dispatch-3.0.7.tgz#ef004d8a128046cfce434d17182f834e44ef95b2" + integrity sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA== "@types/d3-drag@*": version "3.0.7" @@ -1583,30 +1610,18 @@ resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-3.0.3.tgz#ed995c71ecb15e0cd31e22d9d5d23942e3300cfb" integrity sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ== -"@types/d3-scale-chromatic@*": +"@types/d3-scale-chromatic@*", "@types/d3-scale-chromatic@^3.0.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== -"@types/d3-scale-chromatic@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" - integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== - -"@types/d3-scale@*": +"@types/d3-scale@*", "@types/d3-scale@^4.0.3": version "4.0.9" resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== dependencies: "@types/d3-time" "*" -"@types/d3-scale@^4.0.3": - version "4.0.8" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" - integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== - dependencies: - "@types/d3-time" "*" - "@types/d3-selection@*": version "3.0.11" resolved "https://registry.yarnpkg.com/@types/d3-selection/-/d3-selection-3.0.11.tgz#bd7a45fc0a8c3167a631675e61bc2ca2b058d4a3" @@ -1625,9 +1640,9 @@ integrity sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg== "@types/d3-time@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" - integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== "@types/d3-timer@*": version "3.0.2" @@ -1704,16 +1719,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== -"@types/express-serve-static-core@^4.17.33": - version "4.19.5" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz#218064e321126fcf9048d1ca25dd2465da55d9c6" - integrity sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - "@types/send" "*" - "@types/express-serve-static-core@^5.0.0": version "5.0.7" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz#2fa94879c9d46b11a5df4c74ac75befd6b283de6" @@ -1724,23 +1729,6 @@ "@types/range-parser" "*" "@types/send" "*" -"@types/express-session@*": - version "1.18.0" - resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.18.0.tgz#7c6f25c3604b28d6bc08a2e3929997bbc7672fa2" - integrity sha512-27JdDRgor6PoYlURY+Y5kCakqp5ulC0kmf7y+QwaY+hv9jEFuQOThgkjyA53RP3jmKuBsH5GR6qEfFmvb8mwOA== - dependencies: - "@types/express" "*" - -"@types/express@*": - version "4.17.21" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d" - integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ== - dependencies: - "@types/body-parser" "*" - "@types/express-serve-static-core" "^4.17.33" - "@types/qs" "*" - "@types/serve-static" "*" - "@types/express@^5.0.3": version "5.0.3" resolved "https://registry.yarnpkg.com/@types/express/-/express-5.0.3.tgz#6c4bc6acddc2e2a587142e1d8be0bce20757e956" @@ -1756,9 +1744,9 @@ integrity sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg== "@types/http-errors@*": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.4.tgz#7eb47726c391b7345a6ec35ad7f4de469cf5ba4f" - integrity sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.5.tgz#5b749ab2b16ba113423feb1a64a95dcd30398472" + integrity sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg== "@types/json-schema@^7.0.15": version "7.0.15" @@ -1783,16 +1771,16 @@ integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag== "@types/morgan@^1.9.9": - version "1.9.9" - resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.9.tgz#d60dec3979e16c203a000159daa07d3fb7270d7f" - integrity sha512-iRYSDKVaC6FkGSpEVVIvrRGw0DfJMiQzIn3qr2G5B3C//AWkulhXgaBd7tS9/J79GWSYMTHGs7PfI5b3Y8m+RQ== + version "1.9.10" + resolved "https://registry.yarnpkg.com/@types/morgan/-/morgan-1.9.10.tgz#725c15d95a5e6150237524cd713bc2d68f9edf1a" + integrity sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA== dependencies: "@types/node" "*" "@types/ms@*": - version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" - integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/mysql@2.15.27": version "2.15.27" @@ -1801,26 +1789,19 @@ dependencies: "@types/node" "*" -"@types/node@*": - version "20.12.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.8.tgz#35897bf2bfe3469847ab04634636de09552e8256" - integrity sha512-NU0rJLJnshZWdE/097cdCBbyW1h4hEg0xpovcoAQYHl8dnEyp/NAOiE45pvc+Bd1Dt+2r94v2eGFpQJ4R7g+2w== - dependencies: - undici-types "~5.26.4" - -"@types/node@>=10.0.0": - version "20.14.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.10.tgz#a1a218290f1b6428682e3af044785e5874db469a" - integrity sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ== +"@types/node@*", "@types/node@>=10.0.0": + version "24.6.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.6.2.tgz#59b99878b6fed17e698e7d09e51c729c5877736a" + integrity sha512-d2L25Y4j+W3ZlNAeMKcy7yDsK425ibcAOO2t7aPTz6gNMH0z2GThtwENCDc0d/Pw9wgyRqE5Px1wkV7naz8ang== dependencies: - undici-types "~5.26.4" + undici-types "~7.13.0" "@types/node@^20.14.6": - version "20.14.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.14.6.tgz#f3c19ffc98c2220e18de259bb172dd4d892a6075" - integrity sha512-JbA0XIJPL1IiNnU7PFxDXyfAwcwVVrOoqyzzyQTyMeVhBzkJVMSkC1LlVsRQ2lpqiY4n6Bb9oCS6lzDKVQxbZw== + version "20.19.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.19.tgz#18c8982becd5728f92e5f1939f2f3dc85604abcd" + integrity sha512-pb1Uqj5WJP7wrcbLU7Ru4QtA0+3kAXrkutGiD26wUKzSMgNNaPARTUDQmElUXp64kh3cWdou3Q0C7qwwxqSFmg== dependencies: - undici-types "~5.26.4" + undici-types "~6.21.0" "@types/normalize-package-data@^2.4.0": version "2.4.4" @@ -1834,35 +1815,19 @@ dependencies: "@types/pg" "*" -"@types/pg@*": - version "8.11.6" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.11.6.tgz#a2d0fb0a14b53951a17df5197401569fb9c0c54b" - integrity sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ== - dependencies: - "@types/node" "*" - pg-protocol "*" - pg-types "^4.0.1" - -"@types/pg@8.15.4": - version "8.15.4" - resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.15.4.tgz#419f791c6fac8e0bed66dd8f514b60f8ba8db46d" - integrity sha512-I6UNVBAoYbvuWkkU3oosC8yxqH21f4/Jc4DK71JLG3dT2mdlGe1z+ep/LQGXaKaOgcvUrsQoPRqfgtMcvZiJhg== +"@types/pg@*", "@types/pg@8.15.5": + version "8.15.5" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-8.15.5.tgz#ef43e0f33b62dac95cae2f042888ec7980b30c09" + integrity sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ== dependencies: "@types/node" "*" pg-protocol "*" pg-types "^2.2.0" "@types/qs@*": - version "6.9.15" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce" - integrity sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg== - -"@types/ramda@^0.28.20": - version "0.28.25" - resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.28.25.tgz#68080ef9eed92cddcd2c727cf3fe09f6a093e475" - integrity sha512-HrQNqQAGcITpn9HAJFamDxm7iZeeXiP/95pN5OMbNniDjzCCeOHbBKNGmUy8NRi0fhYS+/cXeo91MFC+06gbow== - dependencies: - ts-toolbelt "^6.15.1" + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== "@types/range-parser@*": version "1.2.7" @@ -1875,21 +1840,28 @@ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/send@*": - version "0.17.4" - resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.4.tgz#6619cd24e7270793702e4e6a4b958a9010cfc57a" - integrity sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/send/-/send-1.2.0.tgz#ae9dfa0e3ab0306d3c566182324a54c4be2fb45a" + integrity sha512-zBF6vZJn1IaMpg3xUF25VK3gd3l8zwE0ZLRX7dsQyQi+jp4E8mMDJNGDYnYse+bQhYwWERTxVwHpi3dMOq7RKQ== + dependencies: + "@types/node" "*" + +"@types/send@<1": + version "0.17.5" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.5.tgz#d991d4f2b16f2b1ef497131f00a9114290791e74" + integrity sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w== dependencies: "@types/mime" "^1" "@types/node" "*" "@types/serve-static@*": - version "1.15.7" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.7.tgz#22174bbd74fb97fe303109738e9b5c2f3064f714" - integrity sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw== + version "1.15.9" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.9.tgz#f9b08ab7dd8bbb076f06f5f983b683654fe0a025" + integrity sha512-dOTIuqpWLyl3BBXU3maNQsS4A3zuuoYRNIvYSxxhebPfXg2mzWQEPne/nlJ37yOse6uGgR386uTpdsx4D0QZWA== dependencies: "@types/http-errors" "*" "@types/node" "*" - "@types/send" "*" + "@types/send" "<1" "@types/shimmer@^1.2.0": version "1.2.0" @@ -1914,9 +1886,9 @@ integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== "@types/unist@^2", "@types/unist@^2.0.0": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" - integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== "@types/yauzl@^2.9.1": version "2.10.3" @@ -1926,78 +1898,78 @@ "@types/node" "*" "@typescript-eslint/eslint-plugin@^8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.1.tgz#011a2b5913d297b3d9d77f64fb78575bab01a1b3" - integrity sha512-molgphGqOBT7t4YKCSkbasmu1tb1MgrZ2szGzHbclF7PNmOkSTQVHy+2jXOSnxvR3+Xe1yySHFZoqMpz3TfQsw== + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.45.0.tgz#9f251d4e85ec5089e7cccb09257ce93dbf0d7744" + integrity sha512-HC3y9CVuevvWCl/oyZuI47dOeDF9ztdMEfMH8/DW/Mhwa9cCLnK1oD7JoTVGW/u7kFzNZUKUoyJEqkaJh5y3Wg== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.44.1" - "@typescript-eslint/type-utils" "8.44.1" - "@typescript-eslint/utils" "8.44.1" - "@typescript-eslint/visitor-keys" "8.44.1" + "@typescript-eslint/scope-manager" "8.45.0" + "@typescript-eslint/type-utils" "8.45.0" + "@typescript-eslint/utils" "8.45.0" + "@typescript-eslint/visitor-keys" "8.45.0" graphemer "^1.4.0" ignore "^7.0.0" natural-compare "^1.4.0" ts-api-utils "^2.1.0" "@typescript-eslint/parser@^8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.44.1.tgz#d4c85791389462823596ad46e2b90d34845e05eb" - integrity sha512-EHrrEsyhOhxYt8MTg4zTF+DJMuNBzWwgvvOYNj/zm1vnaD/IC5zCXFehZv94Piqa2cRFfXrTFxIvO95L7Qc/cw== - dependencies: - "@typescript-eslint/scope-manager" "8.44.1" - "@typescript-eslint/types" "8.44.1" - "@typescript-eslint/typescript-estree" "8.44.1" - "@typescript-eslint/visitor-keys" "8.44.1" + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.45.0.tgz#571660c98824aefb4a6ec3b3766655d1348520a4" + integrity sha512-TGf22kon8KW+DeKaUmOibKWktRY8b2NSAZNdtWh798COm1NWx8+xJ6iFBtk3IvLdv6+LGLJLRlyhrhEDZWargQ== + dependencies: + "@typescript-eslint/scope-manager" "8.45.0" + "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/typescript-estree" "8.45.0" + "@typescript-eslint/visitor-keys" "8.45.0" debug "^4.3.4" -"@typescript-eslint/project-service@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.44.1.tgz#1bccd9796d25032b190f355f55c5fde061158abb" - integrity sha512-ycSa60eGg8GWAkVsKV4E6Nz33h+HjTXbsDT4FILyL8Obk5/mx4tbvCNsLf9zret3ipSumAOG89UcCs/KRaKYrA== +"@typescript-eslint/project-service@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.45.0.tgz#f83dda1bca31dae2fd6821f9131daf1edebfd46c" + integrity sha512-3pcVHwMG/iA8afdGLMuTibGR7pDsn9RjDev6CCB+naRsSYs2pns5QbinF4Xqw6YC/Sj3lMrm/Im0eMfaa61WUg== dependencies: - "@typescript-eslint/tsconfig-utils" "^8.44.1" - "@typescript-eslint/types" "^8.44.1" + "@typescript-eslint/tsconfig-utils" "^8.45.0" + "@typescript-eslint/types" "^8.45.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.44.1.tgz#31c27f92e4aed8d0f4d6fe2b9e5187d1d8797bd7" - integrity sha512-NdhWHgmynpSvyhchGLXh+w12OMT308Gm25JoRIyTZqEbApiBiQHD/8xgb6LqCWCFcxFtWwaVdFsLPQI3jvhywg== +"@typescript-eslint/scope-manager@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.45.0.tgz#59615ba506a9e3479d1efb0d09d6ab52f2a19142" + integrity sha512-clmm8XSNj/1dGvJeO6VGH7EUSeA0FMs+5au/u3lrA3KfG8iJ4u8ym9/j2tTEoacAffdW1TVUzXO30W1JTJS7dA== dependencies: - "@typescript-eslint/types" "8.44.1" - "@typescript-eslint/visitor-keys" "8.44.1" + "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/visitor-keys" "8.45.0" -"@typescript-eslint/tsconfig-utils@8.44.1", "@typescript-eslint/tsconfig-utils@^8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.1.tgz#e1d9d047078fac37d3e638484ab3b56215963342" - integrity sha512-B5OyACouEjuIvof3o86lRMvyDsFwZm+4fBOqFHccIctYgBjqR3qT39FBYGN87khcgf0ExpdCBeGKpKRhSFTjKQ== +"@typescript-eslint/tsconfig-utils@8.45.0", "@typescript-eslint/tsconfig-utils@^8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.45.0.tgz#63d38282790a2566c571bad423e7c1cad1f3d64c" + integrity sha512-aFdr+c37sc+jqNMGhH+ajxPXwjv9UtFZk79k8pLoJ6p4y0snmYpPA52GuWHgt2ZF4gRRW6odsEj41uZLojDt5w== -"@typescript-eslint/type-utils@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.44.1.tgz#be9d31e0f911d17ee8ac99921bb74cf1f9df3906" - integrity sha512-KdEerZqHWXsRNKjF9NYswNISnFzXfXNDfPxoTh7tqohU/PRIbwTmsjGK6V9/RTYWau7NZvfo52lgVk+sJh0K3g== +"@typescript-eslint/type-utils@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.45.0.tgz#04004bdf2598844faa29fb936fb6b0ee10d6d3f3" + integrity sha512-bpjepLlHceKgyMEPglAeULX1vixJDgaKocp0RVJ5u4wLJIMNuKtUXIczpJCPcn2waII0yuvks/5m5/h3ZQKs0A== dependencies: - "@typescript-eslint/types" "8.44.1" - "@typescript-eslint/typescript-estree" "8.44.1" - "@typescript-eslint/utils" "8.44.1" + "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/typescript-estree" "8.45.0" + "@typescript-eslint/utils" "8.45.0" debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.44.1", "@typescript-eslint/types@^8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.44.1.tgz#85d1cad1290a003ff60420388797e85d1c3f76ff" - integrity sha512-Lk7uj7y9uQUOEguiDIDLYLJOrYHQa7oBiURYVFqIpGxclAFQ78f6VUOM8lI2XEuNOKNB7XuvM2+2cMXAoq4ALQ== +"@typescript-eslint/types@8.45.0", "@typescript-eslint/types@^8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.45.0.tgz#fc01cd2a4690b9713b02f895e82fb43f7d960684" + integrity sha512-WugXLuOIq67BMgQInIxxnsSyRLFxdkJEJu8r4ngLR56q/4Q5LrbfkFRH27vMTjxEK8Pyz7QfzuZe/G15qQnVRA== -"@typescript-eslint/typescript-estree@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.1.tgz#4f17650e5adabecfcc13cd8c517937a4ef5cd424" - integrity sha512-qnQJ+mVa7szevdEyvfItbO5Vo+GfZ4/GZWWDRRLjrxYPkhM+6zYB2vRYwCsoJLzqFCdZT4mEqyJoyzkunsZ96A== +"@typescript-eslint/typescript-estree@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.45.0.tgz#3498500f109a89b104d2770497c707e56dfe062d" + integrity sha512-GfE1NfVbLam6XQ0LcERKwdTTPlLvHvXXhOeUGC1OXi4eQBoyy1iVsW+uzJ/J9jtCz6/7GCQ9MtrQ0fml/jWCnA== dependencies: - "@typescript-eslint/project-service" "8.44.1" - "@typescript-eslint/tsconfig-utils" "8.44.1" - "@typescript-eslint/types" "8.44.1" - "@typescript-eslint/visitor-keys" "8.44.1" + "@typescript-eslint/project-service" "8.45.0" + "@typescript-eslint/tsconfig-utils" "8.45.0" + "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/visitor-keys" "8.45.0" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -2005,118 +1977,24 @@ semver "^7.6.0" ts-api-utils "^2.1.0" -"@typescript-eslint/utils@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.44.1.tgz#f23d48eb90791a821dc17d4f67bb96faeb75d63d" - integrity sha512-DpX5Fp6edTlocMCwA+mHY8Mra+pPjRZ0TfHkXI8QFelIKcbADQz1LUPNtzOFUriBB2UYqw4Pi9+xV4w9ZczHFg== +"@typescript-eslint/utils@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.45.0.tgz#6e68e92d99019fdf56018d0e6664c76a70470c95" + integrity sha512-bxi1ht+tLYg4+XV2knz/F7RVhU0k6VrSMc9sb8DQ6fyCTrGQLHfo7lDtN0QJjZjKkLA2ThrKuCdHEvLReqtIGg== dependencies: "@eslint-community/eslint-utils" "^4.7.0" - "@typescript-eslint/scope-manager" "8.44.1" - "@typescript-eslint/types" "8.44.1" - "@typescript-eslint/typescript-estree" "8.44.1" + "@typescript-eslint/scope-manager" "8.45.0" + "@typescript-eslint/types" "8.45.0" + "@typescript-eslint/typescript-estree" "8.45.0" -"@typescript-eslint/visitor-keys@8.44.1": - version "8.44.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.1.tgz#1d96197a7fcceaba647b3bd6a8594df8dc4deb5a" - integrity sha512-576+u0QD+Jp3tZzvfRfxon0EA2lzcDt3lhUbsC6Lgzy9x2VR4E+JUiNyGHi5T8vk0TV+fpJ5GLG1JsJuWCaKhw== +"@typescript-eslint/visitor-keys@8.45.0": + version "8.45.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.45.0.tgz#4e3bcc55da64ac61069ebfe62ca240567ac7d784" + integrity sha512-qsaFBA3e09MIDAGFUrTk+dzqtfv1XPVz8t8d1f0ybTzrCY7BKiMC5cjrl1O/P7UmHsNyW90EYSkU/ZWpmXelag== dependencies: - "@typescript-eslint/types" "8.44.1" + "@typescript-eslint/types" "8.45.0" eslint-visitor-keys "^4.2.1" -"@vue/compat@^3.2.45": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/compat/-/compat-3.5.13.tgz#b8f715dc4ff0b4964165d51e0023bd2631de5ae5" - integrity sha512-Q3xRdTPN4l+kddxU98REyUBgvc0meAo9CefCWE2lW8Fg3dyPn3vSCce52b338ihrJAx1RQQhO5wMWhJ/PAKUpA== - dependencies: - "@babel/parser" "^7.25.3" - estree-walker "^2.0.2" - source-map-js "^1.2.0" - -"@vue/compiler-core@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz#b0ae6c4347f60c03e849a05d34e5bf747c9bda05" - integrity sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q== - dependencies: - "@babel/parser" "^7.25.3" - "@vue/shared" "3.5.13" - entities "^4.5.0" - estree-walker "^2.0.2" - source-map-js "^1.2.0" - -"@vue/compiler-dom@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz#bb1b8758dbc542b3658dda973b98a1c9311a8a58" - integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA== - dependencies: - "@vue/compiler-core" "3.5.13" - "@vue/shared" "3.5.13" - -"@vue/compiler-sfc@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz#461f8bd343b5c06fac4189c4fef8af32dea82b46" - integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ== - dependencies: - "@babel/parser" "^7.25.3" - "@vue/compiler-core" "3.5.13" - "@vue/compiler-dom" "3.5.13" - "@vue/compiler-ssr" "3.5.13" - "@vue/shared" "3.5.13" - estree-walker "^2.0.2" - magic-string "^0.30.11" - postcss "^8.4.48" - source-map-js "^1.2.0" - -"@vue/compiler-ssr@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz#e771adcca6d3d000f91a4277c972a996d07f43ba" - integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA== - dependencies: - "@vue/compiler-dom" "3.5.13" - "@vue/shared" "3.5.13" - -"@vue/devtools-api@^6.0.0-beta.11": - version "6.6.4" - resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" - integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== - -"@vue/reactivity@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.13.tgz#b41ff2bb865e093899a22219f5b25f97b6fe155f" - integrity sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg== - dependencies: - "@vue/shared" "3.5.13" - -"@vue/runtime-core@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz#1fafa4bf0b97af0ebdd9dbfe98cd630da363a455" - integrity sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw== - dependencies: - "@vue/reactivity" "3.5.13" - "@vue/shared" "3.5.13" - -"@vue/runtime-dom@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz#610fc795de9246300e8ae8865930d534e1246215" - integrity sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog== - dependencies: - "@vue/reactivity" "3.5.13" - "@vue/runtime-core" "3.5.13" - "@vue/shared" "3.5.13" - csstype "^3.1.3" - -"@vue/server-renderer@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz#429ead62ee51de789646c22efe908e489aad46f7" - integrity sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA== - dependencies: - "@vue/compiler-ssr" "3.5.13" - "@vue/shared" "3.5.13" - -"@vue/shared@3.5.13": - version "3.5.13" - resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f" - integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== - "@xmldom/is-dom-node@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@xmldom/is-dom-node/-/is-dom-node-1.0.1.tgz#83b9f3e1260fb008061c6fa787b93a00f9be0629" @@ -2127,32 +2005,33 @@ resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz#b79de2d67389734c57c52595f7a7305e30c2d608" integrity sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw== -"@zenuml/core@^3.17.2": - version "3.29.7" - resolved "https://registry.yarnpkg.com/@zenuml/core/-/core-3.29.7.tgz#54a551a8ca0bdd6c417dc0b5dcf0f4430d85607c" - integrity sha512-fW9X58yB4pZjT8iSEz6PtE2wRKoibKjO/ChHavUz/v3OQgTMN/fYItCA9c4aoQGweK2gvJVBfyWrAVNUVMibOA== - dependencies: - "@headlessui-float/vue" "^0.14.0" - "@headlessui/tailwindcss" "^0.2.0" - "@headlessui/vue" "^1.7.16" - "@types/assert" "^1.5.6" - "@types/ramda" "^0.28.20" - "@vue/compat" "^3.2.45" +"@zenuml/core@^3.35.2": + version "3.41.4" + resolved "https://registry.yarnpkg.com/@zenuml/core/-/core-3.41.4.tgz#6461756c47278e57d276aa26d4cf06770d0c155c" + integrity sha512-C3Cr1tqKHKZ0lCuEgjfnCb8+9K/nwQpKrFzDxWVvWP4g60naTpE4bjr355J015uofoiZtWZDAkdTuD9gS2vXRw== + dependencies: + "@floating-ui/react" "^0.27.8" + "@headlessui/react" "^2.2.1" + "@headlessui/tailwindcss" "^0.2.2" antlr4 "~4.11.0" - color-string "^1.5.5" - dom-to-image-more "^2.13.0" - dompurify "^3.1.5" - file-saver "^2.0.5" + class-variance-authority "^0.7.1" + clsx "^2.1.1" + color-string "^2.0.1" + dompurify "^3.2.5" highlight.js "^10.7.3" - html-to-image "^1.11.3" + html-to-image "^1.11.13" + immer "^10.1.1" + jotai "^2.12.2" lodash "^4.17.21" - marked "^4.0.10" + marked "^4.3.0" + pako "^2.1.0" pino "^8.8.0" - postcss "^8.4.31" + radash "^12.1.0" ramda "^0.28.0" + react "^19.0.0" + react-dom "^19.0.0" + tailwind-merge "^3.1.0" tailwindcss "^3.4.17" - vue "^3.2.45" - vuex "^4.1.0" abort-controller@^3.0.0: version "3.0.0" @@ -2188,23 +2067,13 @@ acorn-jsx@^5.3.2: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.1.1: - version "8.3.3" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.3.tgz#9caeac29eefaa0c41e3d4c65137de4d6f34df43e" - integrity sha512-MxXdReSRhGO7VlFe1bRG/oI7/mdLV9B9JJT0N8vZOhF7gFRR5l3M8W9G8JxmKV+JC5mGqJ0QvqfSOLsCPa4nUw== + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== dependencies: acorn "^8.11.0" -acorn@^8.11.0, acorn@^8.4.1: - version "8.12.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.0.tgz#1627bfa2e058148036133b8d9b51a700663c294c" - integrity sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw== - -acorn@^8.14.0: - version "8.14.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" - integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== - -acorn@^8.15.0: +acorn@^8.11.0, acorn@^8.14.0, acorn@^8.15.0, acorn@^8.4.1: version "8.15.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== @@ -2217,11 +2086,9 @@ agent-base@6: debug "4" agent-base@^7.0.2, agent-base@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.1.tgz#bdbded7dfb096b751a2a087eeeb9664725b2e317" - integrity sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA== - dependencies: - debug "^4.3.4" + version "7.1.4" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.4.tgz#e3cd76d4c548ee895d3c3fd8dc1f6c5b9032e7a8" + integrity sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ== aggregate-error@^3.0.0: version "3.1.0" @@ -2254,16 +2121,9 @@ ansi-regex@^5.0.1: integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-regex@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" - integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" @@ -2273,9 +2133,9 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: color-convert "^2.0.1" ansi-styles@^6.1.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" - integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + version "6.2.3" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.3.tgz#c044d5dcc521a076413472597a1acb1f103c4041" + integrity sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg== antlr4@~4.11.0: version "4.11.0" @@ -2392,9 +2252,9 @@ astral-regex@^2.0.0: integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== async@^3.2.3: - version "3.2.5" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" - integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== atomic-sleep@^1.0.0: version "1.0.0" @@ -2424,11 +2284,11 @@ basic-auth@^2.0.1, basic-auth@~2.0.1: safe-buffer "5.1.2" better-auth@^1.3.18: - version "1.3.18" - resolved "https://registry.yarnpkg.com/better-auth/-/better-auth-1.3.18.tgz#3690b5f351fd7f029859b3d102057b7ddb1ebc9c" - integrity sha512-d4/Wlvvg8irDSblQP1KiLEWYppTlDiNXV9U4oP6D463MlMbMn7kbBcJvM6Us7M//rgi/mAzg5xKzuE3Y5B2NrQ== + version "1.3.26" + resolved "https://registry.yarnpkg.com/better-auth/-/better-auth-1.3.26.tgz#0828bcc4eb994539ccce3e21c4179a974248c959" + integrity sha512-umaOGmv29yF4sD6o2zlW6B0Oayko5yD/A8mKJOFDDEIoVP/pR7nJ/2KsqKy+xvBpnDsKdrZseqA8fmczPviUHw== dependencies: - "@better-auth/core" "1.3.18" + "@better-auth/core" "1.3.26" "@better-auth/utils" "0.3.0" "@better-fetch/fetch" "^1.1.18" "@noble/ciphers" "^2.0.0" @@ -2467,24 +2327,6 @@ bl@^4.0.3: inherits "^2.0.4" readable-stream "^3.4.0" -body-parser@1.20.2: - version "1.20.2" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" - integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== - dependencies: - bytes "3.1.2" - content-type "~1.0.5" - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - http-errors "2.0.0" - iconv-lite "0.4.24" - on-finished "2.4.1" - qs "6.11.0" - raw-body "2.5.2" - type-is "~1.6.18" - unpipe "1.0.0" - body-parser@1.20.3: version "1.20.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" @@ -2519,17 +2361,17 @@ body-parser@^2.2.0: type-is "^2.0.0" brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + version "2.0.2" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" + integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ== dependencies: balanced-match "^1.0.0" @@ -2592,17 +2434,6 @@ call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: es-errors "^1.3.0" function-bind "^1.1.2" -call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - set-function-length "^1.2.1" - call-bound@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.4.tgz#238de935d2a2a692928c538c7ccfa91067fd062a" @@ -2640,15 +2471,6 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - chalk@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -2658,9 +2480,9 @@ chalk@^4.0.0: supports-color "^7.1.0" chalk@^5.0.1: - version "5.3.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385" - integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w== + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== character-entities@^2.0.0: version "2.0.2" @@ -2750,6 +2572,13 @@ cjs-module-lexer@^1.2.2: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== +class-variance-authority@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/class-variance-authority/-/class-variance-authority-0.7.1.tgz#4008a798a0e4553a781a57ac5177c9fb5d043787" + integrity sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg== + dependencies: + clsx "^2.1.1" + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -2772,12 +2601,10 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -color-convert@^1.9.0, color-convert@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" +clsx@^2.0.0, clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== color-convert@^2.0.1: version "2.0.1" @@ -2786,39 +2613,37 @@ color-convert@^2.0.1: dependencies: color-name "~1.1.4" -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +color-convert@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-3.1.2.tgz#cef9e0fd4cb90b07c14697b3fa70af9d7f4870f1" + integrity sha512-UNqkvCDXstVck3kdowtOTWROIJQwafjOfXSmddoDrXo4cewMKmusCeF22Q24zvjR8nwWib/3S/dfyzPItPEiJg== + dependencies: + color-name "^2.0.0" -color-name@^1.0.0, color-name@~1.1.4: +color-name@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-2.0.2.tgz#85054825a23e6d6f81d3503f660c4c4a2a15f04f" + integrity sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A== + +color-name@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -color-string@^1.5.5, color-string@^1.6.0: - version "1.9.1" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4" - integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg== - dependencies: - color-name "^1.0.0" - simple-swizzle "^0.2.2" - -color@^3.1.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/color/-/color-3.2.1.tgz#3544dc198caf4490c3ecc9a790b54fe9ff45e164" - integrity sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA== +color-string@^2.0.0, color-string@^2.0.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-2.1.2.tgz#db1dd52414cc9037ada8fa7d936b8e9f6c3366c9" + integrity sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA== dependencies: - color-convert "^1.9.3" - color-string "^1.6.0" + color-name "^2.0.0" -colorspace@1.1.x: - version "1.1.4" - resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243" - integrity sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w== +color@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/color/-/color-5.0.2.tgz#712ec894007ab27b37207732d182784e001b4a3d" + integrity sha512-e2hz5BzbUPcYlIRHo8ieAhYgoajrJr+hWoceg6E345TPsATMUKqDgzt8fSXZJJbxfpiPzkWyphz8yn8At7q3fA== dependencies: - color "^3.1.3" - text-hex "1.0.x" + color-convert "^3.0.1" + color-string "^2.0.0" commander@7: version "7.2.0" @@ -2875,18 +2700,11 @@ confbox@^0.1.8: resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== -confbox@^0.2.1, confbox@^0.2.2: +confbox@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== -connect-pg-simple@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/connect-pg-simple/-/connect-pg-simple-9.0.1.tgz#98637ff17a5bfeaeef638093fcf484bc96fcbbf6" - integrity sha512-BuwWJH3K3aLpONkO9s12WhZ9ceMjIBxIJAh0JD9x4z1Y9nShmWqZvge5PG/+4j2cIOcguUoa2PSQ4HO/oTsrVg== - dependencies: - pg "^8.8.0" - consola@^3.2.3, consola@^3.4.0, consola@^3.4.2: version "3.4.2" resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.2.tgz#5af110145397bb67afdab77013fdc34cae590ea7" @@ -2916,27 +2734,17 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie-signature@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.7.tgz#ab5dd7ab757c54e60f37ef6550f481c426d10454" - integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA== - cookie-signature@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.2.2.tgz#57c7fc3cc293acab9fec54d73e15690ebe4a1793" integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg== -cookie@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" - integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== - cookie@0.7.1: version "0.7.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.1.tgz#2f73c42142d5d5cf71310a74fc4ae61670e5dbc9" integrity sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w== -cookie@0.7.2, cookie@^0.7.1, cookie@~0.7.2: +cookie@^0.7.1, cookie@~0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.7.2.tgz#556369c472a2ba910f2979891b526b3436237ed7" integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w== @@ -2997,9 +2805,9 @@ create-require@^1.1.0: integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== cross-env@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-10.0.0.tgz#ba25823cfa1ed6af293dcded8796fa16cd162456" - integrity sha512-aU8qlEK/nHYtVuN4p7UQgAwVljzMg8hB4YK5ThRqD2l/ziSnryncPNn7bMLt5cFYsKVKBh8HqLqyCoTupEUu7Q== + version "10.1.0" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-10.1.0.tgz#cfd2a6200df9ed75bfb9cb3d7ce609c13ea21783" + integrity sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw== dependencies: "@epic-web/invariant" "^1.0.0" cross-spawn "^7.0.6" @@ -3011,7 +2819,7 @@ cross-fetch@3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@7.0.3, cross-spawn@^7.0.3: +cross-spawn@7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -3020,7 +2828,7 @@ cross-spawn@7.0.3, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -cross-spawn@^7.0.6: +cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -3039,11 +2847,6 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -csstype@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" - integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== - cytoscape-cose-bilkent@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" @@ -3058,15 +2861,10 @@ cytoscape-fcose@^2.2.0: dependencies: cose-base "^2.2.0" -cytoscape@^3.28.1: - version "3.29.2" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.29.2.tgz#c99f42513c80a75e2e94858add32896c860202ac" - integrity sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ== - -cytoscape@^3.29.3: - version "3.31.2" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.2.tgz#94d5b86d142599a2d6e750f6b2f3102518c7d48e" - integrity sha512-/eOXg2uGdMdpGlEes5Sf6zE+jUG+05f3htFNQIxLxduOH/SsaUZiPBfAwP1btVIVzsnhiNOdi+hvDRLYfMZjGw== +cytoscape@^3.28.1, cytoscape@^3.29.3: + version "3.33.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.33.1.tgz#449e05d104b760af2912ab76482d24c01cdd4c97" + integrity sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ== "d3-array@1 - 2": version "2.12.1" @@ -3355,15 +3153,10 @@ dagre-d3-es@7.0.11: d3 "^7.9.0" lodash-es "^4.17.21" -dayjs@^1.11.13: - version "1.11.13" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" - integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== - -dayjs@^1.11.7: - version "1.11.11" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" - integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== +dayjs@^1.11.18, dayjs@^1.11.7: + version "1.11.18" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.18.tgz#835fa712aac52ab9dec8b1494098774ed7070a11" + integrity sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA== debug@2.6.9: version "2.6.9" @@ -3372,12 +3165,12 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@4, debug@^4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: - version "4.3.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" - integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== +debug@4, debug@^4, debug@^4.0.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0, debug@^4.4.1: + version "4.4.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== dependencies: - ms "2.1.2" + ms "^2.1.3" debug@4.3.4: version "4.3.4" @@ -3386,17 +3179,10 @@ debug@4.3.4: dependencies: ms "2.1.2" -debug@^4.3.1, debug@^4.3.2: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - -debug@^4.3.5, debug@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" - integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== +debug@~4.3.1, debug@~4.3.2, debug@~4.3.4: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: ms "^2.1.3" @@ -3414,9 +3200,9 @@ decamelize@^1.1.0, decamelize@^1.2.0: integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== decode-named-character-reference@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" - integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + version "1.2.0" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz#25c32ae6dd5e21889549d40f676030e9514cc0ed" + integrity sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q== dependencies: character-entities "^2.0.0" @@ -3430,15 +3216,6 @@ deepmerge-ts@7.1.5: resolved "https://registry.yarnpkg.com/deepmerge-ts/-/deepmerge-ts-7.1.5.tgz#ff818564007f5c150808d2b7b732cac83aa415ab" integrity sha512-HOJkrhaYsweh+W+e74Yn7YStZOilkoPb6fycpwNLKzSPtruFs48nYis0zy5yJz1+ktUhHxoRDJ27RQAWLIJVJw== -define-data-property@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" - integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== - dependencies: - es-define-property "^1.0.0" - es-errors "^1.3.0" - gopd "^1.0.1" - defu@^6.1.4: version "6.1.4" resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" @@ -3517,34 +3294,29 @@ dlv@^1.1.3: resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79" integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA== -dom-to-image-more@^2.13.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/dom-to-image-more/-/dom-to-image-more-2.16.0.tgz#ffafe86e4561b3a0ecce3b18ddf4ec88fd2ca576" - integrity sha512-RyjtkaM/zVy90uJ20lT+/G7MwBZx6l/ePliq5CQOeAnPeew7aUGS6IqRWBkHpstU+POmhaKA8A9H9qf476gisQ== - dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w== -dompurify@^3.0.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.5.tgz#2c6a113fc728682a0f55684b1388c58ddb79dc38" - integrity sha512-lwG+n5h8QNpxtyrJW/gJWckL+1/DQiYMX8f7t8Z2AZTPw1esVrqjI63i7Zc2Gz0aKzLVMYC1V1PL/ky+aY/NgA== +"dompurify@^3.0.5 <3.1.7": + version "3.1.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" + integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== -dompurify@^3.1.5, dompurify@^3.2.4: - version "3.2.5" - resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.5.tgz#11b108656a5fb72b24d916df17a1421663d7129c" - integrity sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ== +dompurify@^3.2.5: + version "3.2.7" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.2.7.tgz#721d63913db5111dd6dfda8d3a748cfd7982d44a" + integrity sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw== optionalDependencies: "@types/trusted-types" "^2.0.7" dotenv-cli@^7.4.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.4.2.tgz#c158a818de08e1fbc51d310f628cbace9075b734" - integrity sha512-SbUj8l61zIbzyhIbg0FwPJq6+wjbzdn9oEtozQpZ6kW2ihCcapKVZj49oCT3oPM+mgQm+itgvUQcG5szxVrZTA== + version "7.4.4" + resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-7.4.4.tgz#bdcf4df35b03f919171ab6714e17b81b4ee45a21" + integrity sha512-XkBYCG0tPIes+YZr4SpfFv76SQrV/LeCE8CI7JSEMi3VR9MvTihCGTOtbIexD6i2mXF+6px7trb1imVCXSNMDw== dependencies: - cross-spawn "^7.0.3" + cross-spawn "^7.0.6" dotenv "^16.3.0" dotenv-expand "^10.0.0" minimist "^1.2.6" @@ -3559,20 +3331,15 @@ dotenv@16.0.3: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.3.tgz#115aec42bac5053db3c456db30cc243a5a836a07" integrity sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ== -dotenv@^16.3.0: - version "16.4.5" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" - integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== - -dotenv@^16.6.1: +dotenv@^16.3.0, dotenv@^16.6.1: version "16.6.1" resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== dotenv@^17.2.2: - version "17.2.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.2.tgz#4010cfe1c2be4fc0f46fd3d951afb424bc067ac6" - integrity sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q== + version "17.2.3" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-17.2.3.tgz#ad995d6997f639b11065f419a22fabf567cdb9a2" + integrity sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w== dunder-proto@^1.0.1: version "1.0.1" @@ -3637,16 +3404,16 @@ encodeurl@~1.0.2: integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== dependencies: once "^1.4.0" engine.io-parser@~5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" - integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== engine.io@~6.6.0: version "6.6.4" @@ -3663,30 +3430,18 @@ engine.io@~6.6.0: engine.io-parser "~5.2.1" ws "~8.17.1" -entities@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" - integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== - env-paths@2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2" integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A== error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + version "1.3.4" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.4.tgz#b3a8d8bb6f92eecc1629e3e27d3c8607a8a32414" + integrity sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ== dependencies: is-arrayish "^0.2.1" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" - es-define-property@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" @@ -3710,9 +3465,9 @@ es-toolkit@^1.39.10: integrity sha512-E0iGnTtbDhkeczB0T+mxmoVlT4YNweEKBLq7oaU4p11mecdsZpNWOglI4895Vh4usbQ+LsJiuLuI2L0Vdmfm2w== escalade@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" @@ -3724,11 +3479,6 @@ escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== -escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - eslint-config-prettier@^10.1.8: version "10.1.8" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz#15734ce4af8c2778cc32f0b01b37b0b5cd1ecb97" @@ -3761,18 +3511,18 @@ eslint-visitor-keys@^4.2.1: integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== eslint@^9.36.0: - version "9.36.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.36.0.tgz#9cc5cbbfb9c01070425d9bfed81b4e79a1c09088" - integrity sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ== + version "9.37.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.37.0.tgz#ac0222127f76b09c0db63036f4fe289562072d74" + integrity sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig== dependencies: "@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/regexpp" "^4.12.1" "@eslint/config-array" "^0.21.0" - "@eslint/config-helpers" "^0.3.1" - "@eslint/core" "^0.15.2" + "@eslint/config-helpers" "^0.4.0" + "@eslint/core" "^0.16.0" "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.36.0" - "@eslint/plugin-kit" "^0.3.5" + "@eslint/js" "9.37.0" + "@eslint/plugin-kit" "^0.4.0" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.4.2" @@ -3829,11 +3579,6 @@ estraverse@^5.1.0, estraverse@^5.2.0: resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== -estree-walker@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" - integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== - esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -3869,58 +3614,7 @@ execa@5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -express-session@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.2.tgz#34db6252611b57055e877036eea09b4453dec5d8" - integrity sha512-SZjssGQC7TzTs9rpPDuUrR23GNZ9+2+IkA/+IJWmvQilTr5OSliEHGF+D9scbIpdC6yGtTI0/VhaHoVes2AN/A== - dependencies: - cookie "0.7.2" - cookie-signature "1.0.7" - debug "2.6.9" - depd "~2.0.0" - on-headers "~1.1.0" - parseurl "~1.3.3" - safe-buffer "5.2.1" - uid-safe "~2.1.5" - -express@^4.18.2: - version "4.19.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" - integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== - dependencies: - accepts "~1.3.8" - array-flatten "1.1.1" - body-parser "1.20.2" - content-disposition "0.5.4" - content-type "~1.0.4" - cookie "0.6.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "2.0.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.2.0" - fresh "0.5.2" - http-errors "2.0.0" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "2.4.1" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.7" - qs "6.11.0" - range-parser "~1.2.1" - safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" - setprototypeof "1.2.0" - statuses "2.0.1" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -express@^4.21.2: +express@^4.18.2, express@^4.21.2: version "4.21.2" resolved "https://registry.yarnpkg.com/express/-/express-4.21.2.tgz#cf250e48362174ead6cea4a566abef0162c1ec32" integrity sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA== @@ -3990,11 +3684,6 @@ express@^5.1.0: type-is "^2.0.1" vary "^1.1.2" -exsolve@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.4.tgz#7de5c75af82ecd15998328fbf5f2295883be3a39" - integrity sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw== - exsolve@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.7.tgz#3b74e4c7ca5c5f9a19c3626ca857309fa99f9e9e" @@ -4028,18 +3717,7 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== -fast-glob@^3.2.9: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.4" - -fast-glob@^3.3.2: +fast-glob@^3.2.9, fast-glob@^3.3.2: version "3.3.3" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== @@ -4071,16 +3749,16 @@ fast-write-atomic@0.2.1: integrity sha512-WvJe06IfNYlr+6cO3uQkdKdy3Cb1LlCJSF8zRs2eT8yuhdbSlR9nIt+TgQ92RUxiRrQm+/S7RARnMfCs5iuAjw== fast-xml-parser@^5.2.5: - version "5.2.5" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz#4809fdfb1310494e341098c25cb1341a01a9144a" - integrity sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ== + version "5.3.0" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-5.3.0.tgz#ae388d5a0f6ed31c8ce9e413c1ac89c8e57e7b07" + integrity sha512-gkWGshjYcQCF+6qtlrqBqELqNqnt4CxruY6UVAWWnqb3DQ6qaNFEIKqzYep1XzHLM/QtrHVCxyPOtTk4LTQ7Aw== dependencies: strnum "^2.1.0" fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== dependencies: reusify "^1.0.4" @@ -4103,11 +3781,6 @@ file-entry-cache@^8.0.0: dependencies: flat-cache "^4.0.0" -file-saver@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" - integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== - fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -4115,19 +3788,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "2.4.1" - parseurl "~1.3.3" - statuses "2.0.1" - unpipe "~1.0.0" - finalhandler@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" @@ -4270,17 +3930,6 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== - dependencies: - es-errors "^1.3.0" - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - get-intrinsic@^1.2.5, get-intrinsic@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" @@ -4405,7 +4054,7 @@ globals@^14.0.0: resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== -globals@^15.14.0: +globals@^15.15.0: version "15.15.0" resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== @@ -4422,13 +4071,6 @@ globby@11.1.0, globby@^11.0.1, globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" - gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" @@ -4464,23 +4106,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" - integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== - dependencies: - es-define-property "^1.0.0" - -has-proto@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== - -has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - has-symbols@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" @@ -4494,7 +4119,7 @@ hasha@5.2.2: is-stream "^2.0.0" type-fest "^0.8.0" -hasown@^2.0.0, hasown@^2.0.2: +hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== @@ -4518,7 +4143,7 @@ hosted-git-info@^4.0.1: dependencies: lru-cache "^6.0.0" -html-to-image@^1.11.3: +html-to-image@^1.11.13: version "1.11.13" resolved "https://registry.yarnpkg.com/html-to-image/-/html-to-image-1.11.13.tgz#adbc989c993b7aaf90b629c0cacf833db84d5f43" integrity sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg== @@ -4602,37 +4227,32 @@ ignore-walk@^5.0.1: minimatch "^5.0.1" ignore@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== ignore@^7.0.0: version "7.0.5" resolved "https://registry.yarnpkg.com/ignore/-/ignore-7.0.5.tgz#4cb5f6cd7d4c7ab0365738c7aea888baa6d7efd9" integrity sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg== +immer@^10.1.1: + version "10.1.3" + resolved "https://registry.yarnpkg.com/immer/-/immer-10.1.3.tgz#e38a0b97db59949d31d9b381b04c2e441b1c3747" + integrity sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw== + import-fresh@^3.2.1: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@^1.14.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.14.2.tgz#283661625a88ff7c0462bd2984f77715c3bc967c" - integrity sha512-5tCuY9BV8ujfOpwtAGgsTx9CGUapcFMEEyByLv1B+v2+6DhAcw+Zr0nhQT7uwaZ7DiourxFEscghOR8e1aPLQw== - dependencies: - acorn "^8.14.0" - acorn-import-attributes "^1.9.5" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - -import-in-the-middle@^1.8.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.13.1.tgz#789651f9e93dd902a5a306f499ab51eb72b03a12" - integrity sha512-k2V9wNm9B+ysuelDTHjI9d5KPc4l8zAZTGqj+pcynvWkypZd857ryzN8jNC7Pg2YZXNMJcHRPpaDyCBbNyVRpA== +import-in-the-middle@^1.14.2, import-in-the-middle@^1.8.1: + version "1.14.4" + resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.14.4.tgz#5350cf8eba46e3b51cd3e507f5fe36a8faeb3684" + integrity sha512-eWjxh735SJLFJJDs5X82JQ2405OdJeAHDBnaoFCfdr5GVc7AWc9xU7KbrF+3Xd5F2ccP1aQFKtY+65X6EfKZ7A== dependencies: acorn "^8.14.0" acorn-import-attributes "^1.9.5" @@ -4640,9 +4260,9 @@ import-in-the-middle@^1.8.1: module-details-from-path "^1.0.3" import-meta-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706" - integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz#08cb85b5bd37ecc8eb1e0f670dc2767002d43734" + integrity sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg== imurmurhash@^0.1.4: version "0.1.4" @@ -4697,11 +4317,6 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== -is-arrayish@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" - integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== - is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -4709,14 +4324,7 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.5.0: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== - dependencies: - hasown "^2.0.0" - -is-core-module@^2.16.0: +is-core-module@^2.11.0, is-core-module@^2.16.0, is-core-module@^2.5.0: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -4811,15 +4419,15 @@ jackspeak@^3.1.2: optionalDependencies: "@pkgjs/parseargs" "^0.11.0" -jiti@^1.21.6: +jiti@^1.21.7: version "1.21.7" resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.7.tgz#9dd81043424a3d28458b193d965f0d18a2300ba9" integrity sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A== jiti@^2.4.2: - version "2.5.1" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.5.1.tgz#bd099c1c2be1c59bbea4e5adcd127363446759d0" - integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== + version "2.6.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" + integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== jose@^5.10.0: version "5.10.0" @@ -4831,6 +4439,11 @@ jose@^6.1.0: resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.0.tgz#96285365689d16f2845a353964d2284bf19f464c" integrity sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA== +jotai@^2.12.2: + version "2.15.0" + resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.15.0.tgz#2a697924b7dcfff71847e83c7493c92e3b731e88" + integrity sha512-nbp/6jN2Ftxgw0VwoVnOg0m5qYM1rVcfvij+MZx99Z5IK13eGve9FJoCwGv+17JvVthTjhSmNtT5e1coJnr6aw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4869,18 +4482,18 @@ json5@^2.2.2: integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== jsonfile@^6.0.1: - version "6.1.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" - integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== + version "6.2.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.2.0.tgz#7c265bd1b65de6977478300087c99f1c84383f62" + integrity sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg== dependencies: universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" -katex@^0.16.9: - version "0.16.10" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" - integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== +katex@^0.16.22, katex@^0.16.9: + version "0.16.23" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.23.tgz#24f2655a7922d0efb388107743718a4fd176265c" + integrity sha512-7VlC1hsEEolL9xNO05v9VjrvWZePkCVBJqj8ruICxYjZfHaHbaU53AlP+PODyFIXEnaEIEWi3wJy7FPZ95JAVg== dependencies: commander "^8.3.0" @@ -4962,7 +4575,7 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@^3.0.0, lilconfig@^3.1.3: +lilconfig@^3.1.1, lilconfig@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== @@ -4972,14 +4585,14 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== -local-pkg@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.1.tgz#f5fe74a97a3bd3c165788ee08ca9fbe998dc58dd" - integrity sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg== +local-pkg@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" + integrity sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== dependencies: mlly "^1.7.4" - pkg-types "^2.0.1" - quansync "^0.2.8" + pkg-types "^2.3.0" + quansync "^0.2.11" locate-path@^5.0.0: version "5.0.0" @@ -5035,10 +4648,10 @@ lodash@^4.17.21: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== -logform@^2.3.2, logform@^2.4.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/logform/-/logform-2.6.0.tgz#8c82a983f05d6eaeb2d75e3decae7a768b2bf9b5" - integrity sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ== +logform@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/logform/-/logform-2.7.0.tgz#cfca97528ef290f2e125a08396805002b2d060d1" + integrity sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ== dependencies: "@colors/colors" "1.6.0" "@types/triple-beam" "^1.3.2" @@ -5059,13 +4672,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.30.11: - version "0.30.17" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" - integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.5.0" - make-dir@3.1.0, make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5088,12 +4694,12 @@ map-obj@^4.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.3.0.tgz#9304f906e93faae70880da102a9f1df0ea8bb05a" integrity sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ== -marked@^15.0.7: - version "15.0.8" - resolved "https://registry.yarnpkg.com/marked/-/marked-15.0.8.tgz#39873a3fdf91a520111e48aeb2ef3746d58d7166" - integrity sha512-rli4l2LyZqpQuRve5C0rkn6pj3hT8EWPC+zkAxFTAJLxRbENfTAhEQq9itrmf1Y81QtAX5D/MYlGlIomNgj9lA== +marked@^16.2.1: + version "16.3.0" + resolved "https://registry.yarnpkg.com/marked/-/marked-16.3.0.tgz#2f513891f867d6edc4772b4a026db9cc331eb94f" + integrity sha512-K3UxuKu6l6bmA5FUwYho8CfJBlsUWAooKtdGgMcERSpF7gcBUrCGsLH7wDaaNOzwq18JzSUDyoEb/YsrqMac3w== -marked@^4.0.10: +marked@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/marked/-/marked-4.3.0.tgz#796362821b019f734054582038b116481b456cf3" integrity sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A== @@ -5156,11 +4762,6 @@ meow@9: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== - merge-descriptors@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" @@ -5182,9 +4783,9 @@ merge2@^1.3.0, merge2@^1.4.1: integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== mermaid@^10.8.0: - version "10.9.1" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.9.1.tgz#5f582c23f3186c46c6aa673e59eeb46d741b2ea6" - integrity sha512-Mx45Obds5W1UkW1nv/7dHRsbfMM1aOKA2+Pxs/IGHNonygDHwmng8xTHyS9z4KWVi0rbko8gjiBmuwwXQ7tiNA== + version "10.9.4" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.9.4.tgz#985fd4b6d73ae795b87f0b32f620a56d3d6bf1f8" + integrity sha512-VIG2B0R9ydvkS+wShA8sXqkzfpYglM2Qwj7VyUeqzNVqSGPoP/tcaUr3ub4ESykv8eqQJn3p99bHNvYdg3gCHQ== dependencies: "@braintree/sanitize-url" "^6.0.1" "@types/d3-scale" "^4.0.3" @@ -5195,7 +4796,7 @@ mermaid@^10.8.0: d3-sankey "^0.12.3" dagre-d3-es "7.0.10" dayjs "^1.11.7" - dompurify "^3.0.5" + dompurify "^3.0.5 <3.1.7" elkjs "^0.9.0" katex "^0.16.9" khroma "^2.0.0" @@ -5208,13 +4809,13 @@ mermaid@^10.8.0: web-worker "^1.2.0" mermaid@^11.0.2: - version "11.6.0" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-11.6.0.tgz#eee45cdc3087be561a19faf01745596d946bb575" - integrity sha512-PE8hGUy1LDlWIHWBP05SFdqUHGmRcCcK4IzpOKPE35eOw+G9zZgcnMpyunJVUEOgb//KBORPjysKndw8bFLuRg== + version "11.12.0" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-11.12.0.tgz#8e394b6214e33cb52f6e8ad9eb1fd94c67ee5638" + integrity sha512-ZudVx73BwrMJfCFmSSJT84y6u5brEoV8DOItdHomNLz32uBjNrelm7mg95X7g+C6UoQH/W6mBLGDEDv73JdxBg== dependencies: - "@braintree/sanitize-url" "^7.0.4" - "@iconify/utils" "^2.1.33" - "@mermaid-js/parser" "^0.4.0" + "@braintree/sanitize-url" "^7.1.1" + "@iconify/utils" "^3.0.1" + "@mermaid-js/parser" "^0.6.2" "@types/d3" "^7.4.3" cytoscape "^3.29.3" cytoscape-cose-bilkent "^4.1.0" @@ -5222,12 +4823,12 @@ mermaid@^11.0.2: d3 "^7.9.0" d3-sankey "^0.12.3" dagre-d3-es "7.0.11" - dayjs "^1.11.13" - dompurify "^3.2.4" - katex "^0.16.9" + dayjs "^1.11.18" + dompurify "^3.2.5" + katex "^0.16.22" khroma "^2.1.0" lodash-es "^4.17.21" - marked "^15.0.7" + marked "^16.2.1" roughjs "^4.6.6" stylis "^4.3.6" ts-dedent "^2.2.0" @@ -5432,14 +5033,6 @@ micromark@^3.0.0: micromark-util-types "^1.0.1" uvu "^0.5.0" -micromatch@^4.0.4: - version "4.0.7" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.7.tgz#33e8190d9fe474a9895525f5618eee136d46c2e5" - integrity sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q== - dependencies: - braces "^3.0.3" - picomatch "^2.3.1" - micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -5545,30 +5138,30 @@ mkdirp-classic@^0.5.2: integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== mlly@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" - integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== dependencies: - acorn "^8.14.0" - pathe "^2.0.1" - pkg-types "^1.3.0" - ufo "^1.5.4" + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" module-details-from-path@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" - integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== + version "1.0.4" + resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.4.tgz#b662fdcd93f6c83d3f25289da0ce81c8d9685b94" + integrity sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w== morgan@^1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" - integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== + version "1.10.1" + resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.1.tgz#4e02e6a4465a48e26af540191593955d17f61570" + integrity sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A== dependencies: basic-auth "~2.0.1" debug "2.6.9" depd "~2.0.0" on-finished "~2.3.0" - on-headers "~1.0.2" + on-headers "~1.1.0" mri@^1.1.0: version "1.2.0" @@ -5604,7 +5197,7 @@ mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.8: +nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== @@ -5755,14 +5348,14 @@ npm-run-path@^4.0.1: path-key "^3.0.0" nypm@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.6.1.tgz#4905b419641073de25ef0f19fb47c5658ada0c35" - integrity sha512-hlacBiRiv1k9hZFiphPUkfSQ/ZfQzZDzC+8z0wL3lvDAOUu/2NnChkKuMoMjNur/9OpKuz2QsIeiPVN0xM5Q0w== + version "0.6.2" + resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.6.2.tgz#467512024948398fafa73cea30a3ed9efc5af071" + integrity sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g== dependencies: citty "^0.1.6" consola "^3.4.2" pathe "^2.0.3" - pkg-types "^2.2.0" + pkg-types "^2.3.0" tinyexec "^1.0.1" oauth2-mock-server@^7.2.1: @@ -5786,21 +5379,11 @@ object-hash@^3.0.0: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== -object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== - object-inspect@^1.13.3: version "1.13.4" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== -obuf@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" - integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== - ohash@^2.0.11: version "2.0.11" resolved "https://registry.yarnpkg.com/ohash/-/ohash-2.0.11.tgz#60b11e8cff62ca9dee88d13747a5baa145f5900b" @@ -5825,11 +5408,6 @@ on-finished@~2.3.0: dependencies: ee-first "1.1.1" -on-headers@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" - integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== - on-headers@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" @@ -5941,18 +5519,21 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== -package-manager-detector@^0.2.8: - version "0.2.11" - resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-0.2.11.tgz#3af0b34f99d86d24af0a0620603d2e1180d05c9c" - integrity sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ== - dependencies: - quansync "^0.2.7" +package-manager-detector@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.3.0.tgz#b42d641c448826e03c2b354272456a771ce453c0" + integrity sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ== pako@^1.0.10: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" + integrity sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug== + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -6013,11 +5594,6 @@ path-to-regexp@0.1.12: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.12.tgz#d5e1a12e478a976d432ef3c58d534b9923164bb7" integrity sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ== -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== - path-to-regexp@^8.0.0: version "8.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" @@ -6043,21 +5619,11 @@ perfect-debounce@^1.0.0: resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== -pg-cloudflare@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98" - integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q== - pg-cloudflare@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz#a1f3d226bab2c45ae75ea54d65ec05ac6cfafbef" integrity sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg== -pg-connection-string@^2.6.4: - version "2.6.4" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.4.tgz#f543862adfa49fa4e14bc8a8892d2a84d754246d" - integrity sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA== - pg-connection-string@^2.9.1: version "2.9.1" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.9.1.tgz#bb1fd0011e2eb76ac17360dc8fa183b2d3465238" @@ -6068,32 +5634,17 @@ pg-int8@1.0.1: resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-numeric@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a" - integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw== - pg-pool@^3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.10.1.tgz#481047c720be2d624792100cac1816f8850d31b2" integrity sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg== -pg-pool@^3.6.2: - version "3.6.2" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.2.tgz#3a592370b8ae3f02a7c8130d245bc02fa2c5f3f2" - integrity sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg== - -pg-protocol@*, pg-protocol@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3" - integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg== - -pg-protocol@^1.10.3: +pg-protocol@*, pg-protocol@^1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/pg-protocol/-/pg-protocol-1.10.3.tgz#ac9e4778ad3f84d0c5670583bab976ea0a34f69f" integrity sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ== -pg-types@2.2.0, pg-types@^2.1.0, pg-types@^2.2.0: +pg-types@2.2.0, pg-types@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== @@ -6104,19 +5655,6 @@ pg-types@2.2.0, pg-types@^2.1.0, pg-types@^2.2.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg-types@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d" - integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng== - dependencies: - pg-int8 "1.0.1" - pg-numeric "1.0.2" - postgres-array "~3.0.1" - postgres-bytea "~3.0.0" - postgres-date "~2.1.0" - postgres-interval "^3.0.0" - postgres-range "^1.1.1" - pg@^8.11.3: version "8.16.3" resolved "https://registry.yarnpkg.com/pg/-/pg-8.16.3.tgz#160741d0b44fdf64680e45374b06d632e86c99fd" @@ -6130,31 +5668,13 @@ pg@^8.11.3: optionalDependencies: pg-cloudflare "^1.2.7" -pg@^8.8.0: - version "8.12.0" - resolved "https://registry.yarnpkg.com/pg/-/pg-8.12.0.tgz#9341724db571022490b657908f65aee8db91df79" - integrity sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ== - dependencies: - pg-connection-string "^2.6.4" - pg-pool "^3.6.2" - pg-protocol "^1.6.1" - pg-types "^2.1.0" - pgpass "1.x" - optionalDependencies: - pg-cloudflare "^1.1.1" - -pgpass@1.0.5, pgpass@1.x: +pgpass@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: split2 "^4.1.0" -picocolors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== - picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" @@ -6212,7 +5732,7 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" -pkg-types@^1.3.0: +pkg-types@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== @@ -6221,16 +5741,7 @@ pkg-types@^1.3.0: mlly "^1.7.4" pathe "^2.0.1" -pkg-types@^2.0.1: - version "2.1.0" - resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.1.0.tgz#70c9e1b9c74b63fdde749876ee0aa007ea9edead" - integrity sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A== - dependencies: - confbox "^0.2.1" - exsolve "^1.0.1" - pathe "^2.0.3" - -pkg-types@^2.2.0: +pkg-types@^2.2.0, pkg-types@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.3.0.tgz#037f2c19bd5402966ff6810e32706558cb5b5726" integrity sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== @@ -6274,19 +5785,18 @@ postcss-import@^15.1.0: resolve "^1.1.7" postcss-js@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2" - integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw== + version "4.1.0" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.1.0.tgz#003b63c6edde948766e40f3daf7e997ae43a5ce6" + integrity sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw== dependencies: camelcase-css "^2.0.1" -postcss-load-config@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3" - integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ== +"postcss-load-config@^4.0.2 || ^5.0 || ^6.0": + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-6.0.1.tgz#6fd7dcd8ae89badcf1b2d644489cbabf83aa8096" + integrity sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g== dependencies: - lilconfig "^3.0.0" - yaml "^2.3.4" + lilconfig "^3.1.1" postcss-nested@^6.2.0: version "6.2.0" @@ -6308,12 +5818,12 @@ postcss-value-parser@^4.0.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@^8.4.31, postcss@^8.4.47, postcss@^8.4.48: - version "8.5.3" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" - integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== +postcss@^8.4.47: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== dependencies: - nanoid "^3.3.8" + nanoid "^3.3.11" picocolors "^1.1.1" source-map-js "^1.2.1" @@ -6327,33 +5837,16 @@ postgres-array@~2.0.0: resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== -postgres-array@~3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98" - integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog== - postgres-bytea@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w== -postgres-bytea@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089" - integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw== - dependencies: - obuf "~1.1.2" - postgres-date@~1.0.4: version "1.0.7" resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== -postgres-date@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0" - integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA== - postgres-interval@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" @@ -6361,16 +5854,6 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" -postgres-interval@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a" - integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw== - -postgres-range@^1.1.1: - version "1.1.4" - resolved "https://registry.yarnpkg.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863" - integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w== - prelude-ls@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" @@ -6421,17 +5904,17 @@ prisma-erd-generator@^2.1.0: dotenv "^16.6.1" prisma@^6.16.2: - version "6.16.2" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.16.2.tgz#ab1f977632754245af1a7bab864c315694b6293c" - integrity sha512-aRvldGE5UUJTtVmFiH3WfNFNiqFlAtePUxcI0UEGlnXCX7DqhiMT5TRYwncHFeA/Reca5W6ToXXyCMTeFPdSXA== + version "6.16.3" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.16.3.tgz#33a7934bfdfdb191dbf91042c5d510de490b3dc8" + integrity sha512-4tJq3KB9WRshH5+QmzOLV54YMkNlKOtLKaSdvraI5kC/axF47HuOw6zDM8xrxJ6s9o2WodY654On4XKkrobQdQ== dependencies: - "@prisma/config" "6.16.2" - "@prisma/engines" "6.16.2" + "@prisma/config" "6.16.3" + "@prisma/engines" "6.16.3" prismjs@^1.29.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" - integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== + version "1.30.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== process-nextick-args@~2.0.0: version "2.0.1" @@ -6480,9 +5963,9 @@ pstree.remy@^1.1.8: integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w== pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + version "3.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.3.tgz#151d979f1a29668dc0025ec589a455b53282268d" + integrity sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA== dependencies: end-of-stream "^1.1.0" once "^1.3.1" @@ -6538,13 +6021,6 @@ pvutils@^1.1.3: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== -qs@6.11.0: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - qs@6.13.0: version "6.13.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" @@ -6559,10 +6035,10 @@ qs@^6.14.0: dependencies: side-channel "^1.1.0" -quansync@^0.2.7, quansync@^0.2.8: - version "0.2.10" - resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" - integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== +quansync@^0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== queue-lit@^1.5.1: version "1.5.2" @@ -6584,16 +6060,16 @@ quick-lru@^4.0.1: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== +radash@^12.1.0: + version "12.1.1" + resolved "https://registry.yarnpkg.com/radash/-/radash-12.1.1.tgz#4858a08a04318a07d6d92d17d11b7528938edd93" + integrity sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA== + ramda@^0.28.0: version "0.28.0" resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.28.0.tgz#acd785690100337e8b063cab3470019be427cc97" integrity sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA== -random-bytes@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/random-bytes/-/random-bytes-1.0.0.tgz#4f68a1dc0ae58bd3fb95848c30324db75d64360b" - integrity sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ== - range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -6627,6 +6103,18 @@ rc9@^2.1.2: defu "^6.1.4" destr "^2.0.3" +react-dom@^19.0.0: + version "19.2.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.0.tgz#00ed1e959c365e9a9d48f8918377465466ec3af8" + integrity sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ== + dependencies: + scheduler "^0.27.0" + +react@^19.0.0: + version "19.2.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5" + integrity sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ== + read-cache@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" @@ -6666,7 +6154,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.5: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0, readable-stream@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -6761,7 +6249,7 @@ resolve@1.22.2: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.1.7, resolve@^1.22.8: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.22.8: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -6770,24 +6258,15 @@ resolve@^1.1.7, resolve@^1.22.8: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^1.10.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== - dependencies: - is-core-module "^2.13.0" - path-parse "^1.0.7" - supports-preserve-symlinks-flag "^1.0.0" - retry@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" @@ -6857,9 +6336,9 @@ safe-buffer@5.2.1, safe-buffer@~5.2.0: integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-stable-stringify@^2.3.1: - version "2.4.3" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + version "2.5.0" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz#4ca2f8e385f2831c432a719b108a3bf7af42a1dd" + integrity sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA== "safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@~2.1.0: version "2.1.2" @@ -6883,6 +6362,11 @@ samlify@^2.10.1: xml-escape "^1.1.0" xpath "^0.0.32" +scheduler@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.27.0.tgz#0c4ef82d67d1e5c1e359e8fc76d3a87f045fe5bd" + integrity sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q== + "semver@2 || 3 || 4 || 5": version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" @@ -6893,40 +6377,11 @@ semver@^6.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.4, semver@^7.5.3: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - -semver@^7.5.2: - version "7.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" - integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== - -semver@^7.6.0: +semver@^7.3.4, semver@^7.5.2, semver@^7.5.3, semver@^7.6.0: version "7.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== - dependencies: - debug "2.6.9" - depd "2.0.0" - destroy "1.2.0" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "2.0.0" - mime "1.6.0" - ms "2.1.3" - on-finished "2.4.1" - range-parser "~1.2.1" - statuses "2.0.1" - send@0.19.0: version "0.19.0" resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" @@ -6963,16 +6418,6 @@ send@^1.1.0, send@^1.2.0: range-parser "^1.2.1" statuses "^2.0.1" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.18.0" - serve-static@1.16.2: version "1.16.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" @@ -6998,18 +6443,6 @@ set-cookie-parser@^2.7.1: resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz#3016f150072202dfbe90fadee053573cc89d2943" integrity sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ== -set-function-length@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" - integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== - dependencies: - define-data-property "^1.1.4" - es-errors "^1.3.0" - function-bind "^1.1.2" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-property-descriptors "^1.0.2" - setprototypeof@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" @@ -7061,16 +6494,6 @@ side-channel-weakmap@^1.0.2: object-inspect "^1.13.3" side-channel-map "^1.0.1" -side-channel@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== - dependencies: - call-bind "^1.0.7" - es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" - side-channel@^1.0.6, side-channel@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" @@ -7092,13 +6515,6 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -simple-swizzle@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" - integrity sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg== - dependencies: - is-arrayish "^0.3.1" - simple-update-notifier@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb" @@ -7161,7 +6577,7 @@ sonic-boom@^3.7.0: dependencies: atomic-sleep "^1.0.0" -source-map-js@^1.2.0, source-map-js@^1.2.1: +source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== @@ -7188,9 +6604,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.18" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz#22aa922dcf2f2885a6494a261f2d8b75345d0326" - integrity sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ== + version "3.0.22" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz#abf5a08a6f5d7279559b669f47f0a43e8f3464ef" + integrity sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ== split2@^4.0.0, split2@^4.1.0: version "4.2.0" @@ -7268,9 +6684,9 @@ strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1: ansi-regex "^5.0.1" strip-ansi@^7.0.1: - version "7.1.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" - integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + version "7.1.2" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.2.tgz#132875abde678c7ea8d691533f2e7e22bb744dba" + integrity sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA== dependencies: ansi-regex "^6.0.1" @@ -7301,12 +6717,7 @@ strnum@^2.1.0: resolved "https://registry.yarnpkg.com/strnum/-/strnum-2.1.1.tgz#cf2a6e0cf903728b8b2c4b971b7e36b4e82d46ab" integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw== -stylis@^4.1.3: - version "4.3.2" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" - integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== - -stylis@^4.3.6: +stylis@^4.1.3, stylis@^4.3.6: version "4.3.6" resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== @@ -7324,7 +6735,7 @@ sucrase@^3.35.0: pirates "^4.0.1" ts-interface-checker "^0.1.9" -supports-color@^5.3.0, supports-color@^5.5.0: +supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== @@ -7358,10 +6769,20 @@ synckit@^0.11.7: dependencies: "@pkgr/core" "^0.2.9" +tabbable@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + +tailwind-merge@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-3.3.1.tgz#a7e7db7c714f6020319e626ecfb7e7dac8393a4b" + integrity sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g== + tailwindcss@^3.4.17: - version "3.4.17" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.17.tgz#ae8406c0f96696a631c790768ff319d46d5e5a63" - integrity sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og== + version "3.4.18" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.18.tgz#9fa9650aace186644b608242f1e57d2d55593301" + integrity sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ== dependencies: "@alloc/quick-lru" "^5.2.0" arg "^5.0.2" @@ -7371,7 +6792,7 @@ tailwindcss@^3.4.17: fast-glob "^3.3.2" glob-parent "^6.0.2" is-glob "^4.0.3" - jiti "^1.21.6" + jiti "^1.21.7" lilconfig "^3.1.3" micromatch "^4.0.8" normalize-path "^3.0.0" @@ -7380,7 +6801,7 @@ tailwindcss@^3.4.17: postcss "^8.4.47" postcss-import "^15.1.0" postcss-js "^4.0.1" - postcss-load-config "^4.0.2" + postcss-load-config "^4.0.2 || ^5.0 || ^6.0" postcss-nested "^6.2.0" postcss-selector-parser "^6.1.2" resolve "^1.22.8" @@ -7478,11 +6899,6 @@ through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -tinyexec@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" - integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== - tinyexec@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.1.tgz#70c31ab7abbb4aea0a24f55d120e5990bfa1e0b1" @@ -7566,11 +6982,6 @@ ts-pattern@4.3.0: resolved "https://registry.yarnpkg.com/ts-pattern/-/ts-pattern-4.3.0.tgz#7a995b39342f1b00d1507c2d2f3b90ea16e178a6" integrity sha512-pefrkcd4lmIVR0LA49Imjf9DYLK8vtWhqBPA3Ya1ir8xCW0O2yjL9dsCVvI7pCodLC5q7smNpEtDR2yVulQxOg== -ts-toolbelt@^6.15.1: - version "6.15.5" - resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz#cb3b43ed725cb63644782c64fbcad7d8f28c0a83" - integrity sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A== - ts-toolbelt@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-9.6.0.tgz#50a25426cfed500d4a09bd1b3afb6f28879edfd5" @@ -7603,7 +7014,7 @@ tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.8.1: +tslib@^2.8.0, tslib@^2.8.1: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -7672,22 +7083,15 @@ typescript-transform-paths@^3.5.5: minimatch "^9.0.5" typescript@^5.9.2: - version "5.9.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.2.tgz#d93450cddec5154a2d5cabe3b8102b83316fb2a6" - integrity sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A== + version "5.9.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== -ufo@^1.5.4: +ufo@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== -uid-safe@~2.1.5: - version "2.1.5" - resolved "https://registry.yarnpkg.com/uid-safe/-/uid-safe-2.1.5.tgz#2b3d5c7240e8fc2e58f8aa269e5ee49c0857bd3a" - integrity sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA== - dependencies: - random-bytes "~1.0.0" - unbzip2-stream@1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz#b0da04c4371311df771cdc215e87f2130991ace7" @@ -7706,10 +7110,15 @@ undefsafe@^2.0.5: resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c" integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA== -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.13.0: + version "7.13.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.13.0.tgz#a20ba7c0a2be0c97bd55c308069d29d167466bff" + integrity sha512-Ov2Rr9Sx+fRgagJ5AX0qvItZG/JKKoBRAVITs1zk7IqZGTJUwgUr7qoYBpWwakpWilTZFM98rG/AFRocu10iIQ== unique-string@^2.0.0: version "2.0.0" @@ -7742,6 +7151,11 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" +use-sync-external-store@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" + integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7840,33 +7254,10 @@ vscode-uri@~3.0.8: resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== -vue-demi@>=0.13.0: - version "0.14.10" - resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04" - integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg== - -vue@^3.2.45: - version "3.5.13" - resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.13.tgz#9f760a1a982b09c0c04a867903fc339c9f29ec0a" - integrity sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ== - dependencies: - "@vue/compiler-dom" "3.5.13" - "@vue/compiler-sfc" "3.5.13" - "@vue/runtime-dom" "3.5.13" - "@vue/server-renderer" "3.5.13" - "@vue/shared" "3.5.13" - -vuex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vuex/-/vuex-4.1.0.tgz#aa1b3ea5c7385812b074c86faeeec2217872e36c" - integrity sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ== - dependencies: - "@vue/devtools-api" "^6.0.0-beta.11" - web-worker@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" - integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5" + integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== webidl-conversions@^3.0.0: version "3.0.1" @@ -7888,31 +7279,31 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" -winston-transport@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.7.0.tgz#e302e6889e6ccb7f383b926df6936a5b781bd1f0" - integrity sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg== +winston-transport@^4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.9.0.tgz#3bba345de10297654ea6f33519424560003b3bf9" + integrity sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A== dependencies: - logform "^2.3.2" - readable-stream "^3.6.0" + logform "^2.7.0" + readable-stream "^3.6.2" triple-beam "^1.3.0" winston@^3.13.0: - version "3.13.0" - resolved "https://registry.yarnpkg.com/winston/-/winston-3.13.0.tgz#e76c0d722f78e04838158c61adc1287201de7ce3" - integrity sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ== + version "3.18.3" + resolved "https://registry.yarnpkg.com/winston/-/winston-3.18.3.tgz#93ac10808c8e1081d723bc8811cd2f445ddfdcd1" + integrity sha512-NoBZauFNNWENgsnC9YpgyYwOVrl2m58PpQ8lNHjV3kosGs7KJ7Npk9pCUE+WJlawVSe8mykWDKWFSVfs3QO9ww== dependencies: "@colors/colors" "^1.6.0" - "@dabh/diagnostics" "^2.0.2" + "@dabh/diagnostics" "^2.0.8" async "^3.2.3" is-stream "^2.0.0" - logform "^2.4.0" + logform "^2.7.0" one-time "^1.0.0" readable-stream "^3.4.0" safe-stable-stringify "^2.3.1" stack-trace "0.0.x" triple-beam "^1.3.0" - winston-transport "^4.7.0" + winston-transport "^4.9.0" word-wrap@^1.2.5: version "1.2.5" @@ -8005,11 +7396,6 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@^2.3.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.7.1.tgz#44a247d1b88523855679ac7fa7cda6ed7e135cf6" - integrity sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ== - yargs-parser@^20.2.3: version "20.2.9" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" From f52b4540846eb5731fee96f1306243bd68d68b25 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 09:43:42 +0000 Subject: [PATCH 22/89] add readme section about dumping db --- .gitignore | 2 +- README.md | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5f68277..2928013 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,5 @@ dist/ build/ # Sentry Config File .sentryclirc - +*.dump src/generated/prisma \ No newline at end of file diff --git a/README.md b/README.md index 6bff8d0..ceb106d 100644 --- a/README.md +++ b/README.md @@ -296,7 +296,15 @@ dokku letsencrypt:enable dev-teaching-api ## when it succeeds, re-enable the cloudflare proxy for domain.tld... ``` -### Speed Improvements +## Dump from production + +```bash +# inside shell of VSCode DevContainer (with configured dokku git remote) +dokku postgres:export dev-teaching-api > tdev-backup.dump +pg_restore -h localhost --verbose --clean --no-owner --no-privileges -U postgres -d teaching_api < tdev-backup.dump +``` + +## Speed Improvements If the API and the Database are running on the same server, you can improve the speed by disabling the tcp connection for the database. This can be done by setting the `DATABASE_URL` to `postgresql://teaching_website:teaching_website@localhost/teaching_website?sslmode=disable`. ## Troubleshooting From 517848265dd7ef0d9b1c9e2dab4b58a46686c68b Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:04:01 +0000 Subject: [PATCH 23/89] fix migrations --- .../20251005093734_migrate_to_better_auth/migration.sql | 7 +++++-- src/auth.ts | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql index b71f828..ff8ebef 100644 --- a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql +++ b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql @@ -5,7 +5,8 @@ */ -- AlterTable -ALTER TABLE "public"."users" ADD COLUMN "ban_expires" TIMESTAMP(3), +ALTER TABLE "public"."users" +ADD COLUMN "ban_expires" TIMESTAMP(3), ADD COLUMN "ban_reason" TEXT, ADD COLUMN "banned" BOOLEAN DEFAULT false, ADD COLUMN "email_verified" BOOLEAN NOT NULL DEFAULT false, @@ -17,7 +18,9 @@ UPDATE "public"."users" SET "trole" = 'admin' WHERE "role" = 'ADMIN'; UPDATE "public"."users" SET "trole" = 'teacher' WHERE "role" = 'TEACHER'; ALTER TABLE "public"."users" -DROP COLUMN "role", +DROP COLUMN "role"; + +ALTER TABLE "public"."users" ADD COLUMN "role" TEXT NOT NULL DEFAULT 'student'; UPDATE "public"."users" SET "role" = trole; diff --git a/src/auth.ts b/src/auth.ts index 9cf524a..eb886af 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,7 +34,6 @@ export const auth = betterAuth({ authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, mapProfileToUser: (profile) => { - console.log('MSFT Profile:', profile); const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); return { From 3efff15bc26d8a27c7cd168ea1998ce5cd250b9e Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:08:46 +0000 Subject: [PATCH 24/89] fix build command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e940c6d..e90df0b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "license": "CC-BY-SA", "scripts": { "dev": "cross-env NODE_ENV=development nodemon -r tsconfig-paths/register --exec ts-node ./src/server.ts --files", - "build": "tsc --build ./tsconfig.build.json", + "build": "yarn run prisma generate && tsc --build ./tsconfig.build.json", "start": "cross-env NODE_ENV=production node ./dist/src/server.js", "lint": "eslint . --ignore-pattern node_modules --fix", "format": "prettier --write ./**/*.{ts,json}", From 68f07f7d47896bb0b0f25e0fe0c8b5b61af83996 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:26:25 +0000 Subject: [PATCH 25/89] update dependencies --- tsconfig.json | 1 + yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index 544148d..96e1dd8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,6 +10,7 @@ // "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "baseUrl": ".", + "skipLibCheck": true, // better auth checks for sqlite... "outDir": "dist", "sourceMap": true, "strict": true, diff --git a/yarn.lock b/yarn.lock index b1c0283..1876aa8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7446,7 +7446,7 @@ zip-stream@^4.1.0: compress-commons "^4.1.2" readable-stream "^3.6.0" -zod@^4.1.5: - version "4.1.11" - resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.11.tgz#4aab62f76cfd45e6c6166519ba31b2ea019f75f5" - integrity sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg== +zod@^4.1.11, zod@^4.1.5: + version "4.1.12" + resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0" + integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ== From be09f6d49f5e2c1d11e86517f98c96440542a4de Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:35:13 +0000 Subject: [PATCH 26/89] fix imports --- src/routes/authConfig.ts | 2 +- src/routes/event-handlers/action.handler.ts | 2 +- src/routes/event-handlers/joinRoom.handler.ts | 2 +- src/routes/socketEvents.ts | 1 - tsconfig.build.json | 3 +++ tsconfig.json | 1 - 6 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/routes/authConfig.ts b/src/routes/authConfig.ts index 2256957..8ec5104 100644 --- a/src/routes/authConfig.ts +++ b/src/routes/authConfig.ts @@ -1,4 +1,4 @@ -import { Role } from 'src/models/User'; +import { Role } from '../models/User'; interface Credentials { tenantID: string; diff --git a/src/routes/event-handlers/action.handler.ts b/src/routes/event-handlers/action.handler.ts index c738569..66f48b8 100644 --- a/src/routes/event-handlers/action.handler.ts +++ b/src/routes/event-handlers/action.handler.ts @@ -2,7 +2,7 @@ import { User } from '@prisma/client'; import { ClientToServerEvents, IoClientEvent, IoEvent, ServerToClientEvents } from '../socketEventTypes'; import type { DefaultEventsMap, Socket } from 'socket.io'; import prisma from '../../prisma'; -import { Role } from 'src/models/User'; +import { Role } from '../../models/User'; const onAction: ( user: User, diff --git a/src/routes/event-handlers/joinRoom.handler.ts b/src/routes/event-handlers/joinRoom.handler.ts index 0bd1afa..bc3b2d9 100644 --- a/src/routes/event-handlers/joinRoom.handler.ts +++ b/src/routes/event-handlers/joinRoom.handler.ts @@ -6,7 +6,7 @@ import StudentGroup from '../../models/StudentGroup'; import onStreamUpdate from './streamUpdate.handler'; import DocumentRoot from '../../models/DocumentRoot'; import { highestAccess, RWAccess } from '../../helpers/accessPolicy'; -import { Role } from 'src/models/User'; +import { Role } from '../../models/User'; type SocketType = Socket; const isDocumentRoot = (roomId: string) => { diff --git a/src/routes/socketEvents.ts b/src/routes/socketEvents.ts index ae85fc2..a65a3bb 100644 --- a/src/routes/socketEvents.ts +++ b/src/routes/socketEvents.ts @@ -27,7 +27,6 @@ const EventRouter = (io: Server) => return socket.disconnect(); } const user = session.user as User; - console.log(`Socket.io user`, user); socket.join(user.id); if (!user) { return socket.disconnect(); diff --git a/tsconfig.build.json b/tsconfig.build.json index eabda20..d401491 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,4 +1,7 @@ { "extends": "./tsconfig", + "compilerOptions": { + "skipLibCheck": true, // better-auth failures for sqlite, timer and zod, try turning on later... + }, "exclude": ["**/*.test.*", "**/__mocks__/*", "**/__tests__/*"] } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 96e1dd8..544148d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,6 @@ // "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "baseUrl": ".", - "skipLibCheck": true, // better auth checks for sqlite... "outDir": "dist", "sourceMap": true, "strict": true, From e3646b31bdac6ad6d02929497d0acf954c4bbf28 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:55:07 +0000 Subject: [PATCH 27/89] pin node version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e90df0b..fd982d8 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "^22.11.0" + "node": "^22.15.0" } } \ No newline at end of file From 4ae14aaa1bc9540e267a9fbe72bc09e1ffd919ef Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:57:54 +0000 Subject: [PATCH 28/89] pin v22.20 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd982d8..482da8a 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "^22.15.0" + "node": "^22.20.0" } } \ No newline at end of file From c92b0dd1fac8fb4dba44eef0af8cdb188a2b83c0 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:58:14 +0000 Subject: [PATCH 29/89] 15.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 482da8a..f40baf5 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "^22.20.0" + "node": "^22.15.1" } } \ No newline at end of file From 9113297f384bc23dbdfed84afb25c19e703532ee Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:58:48 +0000 Subject: [PATCH 30/89] 24 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f40baf5..1ee003d 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "^22.15.1" + "node": "^24.x" } } \ No newline at end of file From fd47e9b7626e3fb6a52aa2df285dd98363a1c62f Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 20:59:13 +0000 Subject: [PATCH 31/89] 24.x --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1ee003d..4833b5d 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "^24.x" + "node": "24.x" } } \ No newline at end of file From 82c57cf758bb616139180c10c74498bd79355960 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 6 Oct 2025 21:00:39 +0000 Subject: [PATCH 32/89] heroku --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4833b5d..9187c97 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "24.x" + "node": "22.x" } } \ No newline at end of file From f1d3383f7c6c3addb80dcc530d0b7b35e558d2cd Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 7 Oct 2025 15:38:43 +0000 Subject: [PATCH 33/89] 22.15.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9187c97..187906b 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "22.x" + "node": "22.15.0" } } \ No newline at end of file From 0cd66be871b9ce63fdf7a5bf94a30d42cf44feda Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 7 Oct 2025 15:43:01 +0000 Subject: [PATCH 34/89] ^22.15.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 187906b..fd982d8 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,6 @@ "typescript-transform-paths": "^3.5.5" }, "engines": { - "node": "22.15.0" + "node": "^22.15.0" } } \ No newline at end of file From 7bc9bc60f4be1d2738c48471d63e7a9333f63e12 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 7 Oct 2025 16:02:52 +0000 Subject: [PATCH 35/89] fix to --- src/utils/originConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index 93ca7b0..34494ec 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -62,7 +62,7 @@ allowedOrigins.forEach((origin) => { // Add Netlify deploy previews if enabled if (netlifyProjectName) { CORS_ORIGIN.push(new RegExp(`https://deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i')); - CORS_ORIGIN_STRINGIFIED.push(`https://*.${netlifyProjectName}.netlify.app`); + CORS_ORIGIN_STRINGIFIED.push(`https://*${netlifyProjectName}.netlify.app`); } export const SAME_SITE = allowedOrigins.length > 1 || netlifyProjectName ? 'none' : 'strict'; From cc672d834a59bac3b54a5a457770024619f9ec6c Mon Sep 17 00:00:00 2001 From: bh0fer Date: Thu, 9 Oct 2025 11:16:35 +0000 Subject: [PATCH 36/89] tmp fix origin --- src/utils/originConfig.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index 34494ec..6bda9d1 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -62,6 +62,7 @@ allowedOrigins.forEach((origin) => { // Add Netlify deploy previews if enabled if (netlifyProjectName) { CORS_ORIGIN.push(new RegExp(`https://deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i')); + CORS_ORIGIN_STRINGIFIED.push(`https://*.netlify.app`); CORS_ORIGIN_STRINGIFIED.push(`https://*${netlifyProjectName}.netlify.app`); } From 4a6daac219da286e6df90ec707acced547ed5f55 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:01:06 +0000 Subject: [PATCH 37/89] add oAuthProxy Plugin --- src/auth.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index eb886af..946b0ef 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,7 +1,7 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { admin, oneTimeToken } from 'better-auth/plugins'; +import { admin, oneTimeToken, oAuthProxy } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; @@ -55,5 +55,13 @@ export const auth = betterAuth({ lastName: { type: 'string', required: false, input: false } } }, - plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()] + plugins: [ + oneTimeToken(), + admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), + sso(), + oAuthProxy({ + productionURL: process.env.NODE_ENV === 'production' ? process.env.FRONTEND_URL : undefined, // Main App + currentURL: process.env.FRONTEND_URL || 'http://localhost:3000' // Current instance + }) + ] }); From 008914f983f057c22307daea098dded080491598 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:10:19 +0000 Subject: [PATCH 38/89] set redirectURI --- src/auth.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 946b0ef..1669979 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,6 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, + redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -59,9 +60,6 @@ export const auth = betterAuth({ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso(), - oAuthProxy({ - productionURL: process.env.NODE_ENV === 'production' ? process.env.FRONTEND_URL : undefined, // Main App - currentURL: process.env.FRONTEND_URL || 'http://localhost:3000' // Current instance - }) + oAuthProxy() ] }); From f288b37e84a7557b737a8933544e173283deb814 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:16:57 +0000 Subject: [PATCH 39/89] rm --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 1669979..7e23f74 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, + // redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -59,7 +59,7 @@ export const auth = betterAuth({ plugins: [ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso(), - oAuthProxy() + sso() + // oAuthProxy() ] }); From 08457f5e242a6d103ec0db7abc207e01f49cb3c1 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:22:37 +0000 Subject: [PATCH 40/89] set betterauth url --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 7e23f74..1669979 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - // redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, + redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -59,7 +59,7 @@ export const auth = betterAuth({ plugins: [ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso() - // oAuthProxy() + sso(), + oAuthProxy() ] }); From 38ab82ddb2d5246f2dce9b52873508b6c570d564 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:23:04 +0000 Subject: [PATCH 41/89] use ba --- src/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 1669979..c3be2e0 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - redirectURI: `${process.env.API_URL}/auth/callback/microsoft`, + redirectURI: `${process.env.BETTER_AUTH_URL}/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); From 42f34ea23425a9f819737a71bef782e3ac99b229 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:30:30 +0000 Subject: [PATCH 42/89] set cp --- src/auth.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index c3be2e0..59a77e2 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -49,7 +49,10 @@ export const auth = betterAuth({ }, trustedOrigins: CORS_ORIGIN_STRINGIFIED, database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), - advanced: { cookiePrefix: 'express-bootstrap', database: { generateId: false, useNumberId: false } }, + advanced: { + cookiePrefix: process.env.APP_NAME ?? 'tdev', + database: { generateId: false, useNumberId: false } + }, user: { additionalFields: { firstName: { type: 'string', required: false, input: false }, From 2bfa4f3e48cd8a4480915e6224089b78ca7ba50e Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:32:50 +0000 Subject: [PATCH 43/89] fix redirect url --- src/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 59a77e2..474ed52 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - redirectURI: `${process.env.BETTER_AUTH_URL}/auth/callback/microsoft`, + redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); From cf1630384b0a62c9707325e0bb8ac55770e80860 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 15:40:18 +0000 Subject: [PATCH 44/89] setup logger --- src/auth.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 474ed52..625144e 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -64,5 +64,8 @@ export const auth = betterAuth({ admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso(), oAuthProxy() - ] + ], + logger: { + level: 'info' + } }); From 4608c78df2a3aa10da82f195869fc4b3d8e389f0 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 16:36:15 +0000 Subject: [PATCH 45/89] rm redirect --- src/auth.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 625144e..27d7081 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,6 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); From d2329dc9f5b31a7ac18ce11de47d9b1be36e16d3 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 16:36:41 +0000 Subject: [PATCH 46/89] rm --- src/auth.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 27d7081..9716850 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,6 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, + // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -61,8 +62,8 @@ export const auth = betterAuth({ plugins: [ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso(), - oAuthProxy() + sso() + // oAuthProxy() ], logger: { level: 'info' From 4df442af081e54335536f5c4852774ea3fc65ce2 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 16:44:20 +0000 Subject: [PATCH 47/89] proxy --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 9716850..625144e 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, + redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -62,8 +62,8 @@ export const auth = betterAuth({ plugins: [ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso() - // oAuthProxy() + sso(), + oAuthProxy() ], logger: { level: 'info' From c58c5d76cd7df6e7d7ec611dd2a421bd1aba0d64 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 16:52:36 +0000 Subject: [PATCH 48/89] us csdc --- src/auth.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/auth.ts b/src/auth.ts index 625144e..c7d4f0e 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -51,6 +51,9 @@ export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: process.env.APP_NAME ?? 'tdev', + crossSubDomainCookies: { + enabled: true + }, database: { generateId: false, useNumberId: false } }, user: { From a3a13deee5e0e18fb45aa0c792280945ce20960a Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 18:11:06 +0000 Subject: [PATCH 49/89] debug logs --- src/auth.ts | 6 +++--- src/utils/logger.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index c7d4f0e..d38c62b 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -33,7 +33,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, + // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -65,8 +65,8 @@ export const auth = betterAuth({ plugins: [ oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso(), - oAuthProxy() + sso() + // oAuthProxy() ], logger: { level: 'info' diff --git a/src/utils/logger.ts b/src/utils/logger.ts index d486793..5e600f6 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -15,7 +15,7 @@ const level = () => { const isDevelopment = env === 'development'; const isProd = env === 'production'; if (isProd) { - return 'http'; + return 'debug'; } return isDevelopment ? 'debug' : 'warn'; }; From bba206cc58aaeef51b8ba7edc894e702a2a01a00 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 18:21:02 +0000 Subject: [PATCH 50/89] sdf --- src/auth.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index d38c62b..1f69777 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -6,6 +6,7 @@ import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; import type { MicrosoftEntraIDProfile } from 'better-auth/social-providers'; +import Logger from './utils/logger'; // If your Prisma file is located elsewhere, you can change the path @@ -69,6 +70,12 @@ export const auth = betterAuth({ // oAuthProxy() ], logger: { - level: 'info' + level: 'info', + log: (level, message, ...args) => { + // Custom logging implementation + Logger.info( + `[${level}] ${message}: ${args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(', ')}` + ); + } } }); From 5c521fd1e8506da567ff6ba29191fdaae1800de0 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 20:44:40 +0000 Subject: [PATCH 51/89] ensure domain --- src/app.ts | 4 ++-- src/auth.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app.ts b/src/app.ts index 406ec57..7b8d2ca 100644 --- a/src/app.ts +++ b/src/app.ts @@ -37,9 +37,9 @@ export const API_URL = `/api/${API_VERSION}`; // ensure the server can call other domains: enable cross origin resource sharing (cors) app.use( cors({ - credentials: true, + methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], origin: CORS_ORIGIN, - methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'] + credentials: true }) ); diff --git a/src/auth.ts b/src/auth.ts index 1f69777..7822aab 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -53,7 +53,8 @@ export const auth = betterAuth({ advanced: { cookiePrefix: process.env.APP_NAME ?? 'tdev', crossSubDomainCookies: { - enabled: true + enabled: true, + domain: '.gbsl.website' }, database: { generateId: false, useNumberId: false } }, From 4d3c2b002866c37b7c22f99fa01496d5e32510ff Mon Sep 17 00:00:00 2001 From: bh0fer Date: Fri, 10 Oct 2025 21:20:00 +0000 Subject: [PATCH 52/89] update --- package.json | 4 ++-- yarn.lock | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index fd982d8..11c1b89 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "@prisma/client": "^6.16.2", "@sentry/cli": "^2.52.0", "@sentry/node": "^10.8.0", - "better-auth": "^1.3.18", + "better-auth": "^1.3.27", "cors": "^2.8.5", "cross-env": "^10.0.0", "dotenv": "^17.2.2", @@ -68,4 +68,4 @@ "engines": { "node": "^22.15.0" } -} \ No newline at end of file +} diff --git a/yarn.lock b/yarn.lock index 1876aa8..67461c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -48,10 +48,10 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@better-auth/core@1.3.26": - version "1.3.26" - resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.26.tgz#32ffae583124437b4929672cdb007d6543aaf156" - integrity sha512-S5ooXaOcn9eLV3/JayfbMsAB5PkfoTRaRrtpb5djwvI/UAJOgLyjqhd+rObsBycovQ/nPQvMKjzyM/G1oBKngA== +"@better-auth/core@1.3.27": + version "1.3.27" + resolved "https://registry.yarnpkg.com/@better-auth/core/-/core-1.3.27.tgz#4d8723529286b3bdd3a3a4715b79a09966774a7e" + integrity sha512-3Sfdax6MQyronY+znx7bOsfQHI6m1SThvJWb0RDscFEAhfqLy95k1sl+/PgGyg0cwc2cUXoEiAOSqYdFYrg3vA== dependencies: better-call "1.0.19" zod "^4.1.5" @@ -73,7 +73,7 @@ resolved "https://registry.yarnpkg.com/@better-auth/utils/-/utils-0.3.0.tgz#066c5ce82bf393421547dd887b14a6899310003d" integrity sha512-W+Adw6ZA6mgvnSnhOki270rwJ42t4XzSK6YWGF//BbVXL6SwCLWfyzBc1lN2m/4RM28KubdBKQ4X5VMoLRNPQw== -"@better-fetch/fetch@^1.1.18", "@better-fetch/fetch@^1.1.4": +"@better-fetch/fetch@1.1.18", "@better-fetch/fetch@^1.1.18", "@better-fetch/fetch@^1.1.4": version "1.1.18" resolved "https://registry.yarnpkg.com/@better-fetch/fetch/-/fetch-1.1.18.tgz#4ddc65a703c65e6036947ff335e635a5a38e6225" integrity sha512-rEFOE1MYIsBmoMJtQbl32PGHHXuG2hDxvEd7rUHE0vCBoFQVSDqaVs9hkZEtHCxRoY+CljXKFCOuJ8uxqw1LcA== @@ -2283,14 +2283,14 @@ basic-auth@^2.0.1, basic-auth@~2.0.1: dependencies: safe-buffer "5.1.2" -better-auth@^1.3.18: - version "1.3.26" - resolved "https://registry.yarnpkg.com/better-auth/-/better-auth-1.3.26.tgz#0828bcc4eb994539ccce3e21c4179a974248c959" - integrity sha512-umaOGmv29yF4sD6o2zlW6B0Oayko5yD/A8mKJOFDDEIoVP/pR7nJ/2KsqKy+xvBpnDsKdrZseqA8fmczPviUHw== +better-auth@^1.3.27: + version "1.3.27" + resolved "https://registry.yarnpkg.com/better-auth/-/better-auth-1.3.27.tgz#d5a6758de0258250279c8206d7e26d0b7b93d168" + integrity sha512-SwiGAJ7yU6dBhNg0NdV1h5M8T5sa7/AszZVc4vBfMDrLLmvUfbt9JoJ0uRUJUEdKRAAxTyl9yA+F3+GhtAD80w== dependencies: - "@better-auth/core" "1.3.26" + "@better-auth/core" "1.3.27" "@better-auth/utils" "0.3.0" - "@better-fetch/fetch" "^1.1.18" + "@better-fetch/fetch" "1.1.18" "@noble/ciphers" "^2.0.0" "@noble/hashes" "^2.0.0" "@simplewebauthn/browser" "^13.1.2" @@ -7446,7 +7446,7 @@ zip-stream@^4.1.0: compress-commons "^4.1.2" readable-stream "^3.6.0" -zod@^4.1.11, zod@^4.1.5: +zod@^4.1.5: version "4.1.12" resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0" integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ== From 5eefd5afa85e67217dbe3651f7cb206a380f4dae Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 13:57:07 +0000 Subject: [PATCH 53/89] explicitely set cors --- src/app.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/app.ts b/src/app.ts index 7b8d2ca..1963779 100644 --- a/src/app.ts +++ b/src/app.ts @@ -38,11 +38,17 @@ export const API_URL = `/api/${API_VERSION}`; app.use( cors({ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], - origin: CORS_ORIGIN, - credentials: true + origin: ['https://teaching-dev.gbsl.website', 'https://teaching-dev-api.gbsl.website'], + credentials: true, + allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-metadata-sid'] }) ); +/** make sure to have 1 (reverse) proxy in front of the application + * as is the case with dokku (nginx) + */ +app.set('trust proxy', 1); + // make sure to configure *before* the json middleware app.all('/api/auth/{*any}', toNodeHandler(auth)); @@ -50,11 +56,6 @@ app.all('/api/auth/{*any}', toNodeHandler(auth)); app.use(express.json({ limit: '5mb' })); app.use(morganMiddleware); -/** make sure to have 1 (reverse) proxy in front of the application - * as is the case with dokku (nginx) - */ -app.set('trust proxy', 1); - // passport.deserializeUser(deserializeUser); // Serve the static files to be accessed by the docs app From 0a7ee9c8442324f4e6f22402fed95caf3d741f16 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:06:24 +0000 Subject: [PATCH 54/89] configure morgan --- src/app.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.ts b/src/app.ts index 1963779..9cb65c7 100644 --- a/src/app.ts +++ b/src/app.ts @@ -48,13 +48,13 @@ app.use( * as is the case with dokku (nginx) */ app.set('trust proxy', 1); +app.use(morganMiddleware); // make sure to configure *before* the json middleware app.all('/api/auth/{*any}', toNodeHandler(auth)); // received packages should be presented in the JSON format app.use(express.json({ limit: '5mb' })); -app.use(morganMiddleware); // passport.deserializeUser(deserializeUser); From bea11bf6c9d2f5d91c9701c26115b2d1311ab47c Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:11:10 +0000 Subject: [PATCH 55/89] fp --- src/auth.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/auth.ts b/src/auth.ts index 7822aab..a45b77b 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,6 +34,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, + responseMode: 'form_post', // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); From 82fe2bb39efe88e90fe6d4b861645492f4b9b9cb Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:14:26 +0000 Subject: [PATCH 56/89] query --- src/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index a45b77b..eb91c61 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,7 +34,7 @@ export const auth = betterAuth({ tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, - responseMode: 'form_post', + responseMode: 'query', // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); From f46422b781d33fefd5d126a3b34d51bd0db42142 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:29:43 +0000 Subject: [PATCH 57/89] rd --- src/auth.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index eb91c61..a4f0196 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -30,7 +30,6 @@ export const auth = betterAuth({ microsoft: { clientId: process.env.MSAL_CLIENT_ID as string, clientSecret: process.env.MSAL_CLIENT_SECRET as string, - // Optional tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, From dbd67348d5feba08cb4d6832d80be95241633bd0 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:40:22 +0000 Subject: [PATCH 58/89] try --- src/app.ts | 4 ++-- src/auth.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/app.ts b/src/app.ts index 9cb65c7..c9caac8 100644 --- a/src/app.ts +++ b/src/app.ts @@ -39,8 +39,8 @@ app.use( cors({ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], origin: ['https://teaching-dev.gbsl.website', 'https://teaching-dev-api.gbsl.website'], - credentials: true, - allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-metadata-sid'] + credentials: true + // allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-metadata-sid'] }) ); diff --git a/src/auth.ts b/src/auth.ts index a4f0196..ecf0689 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -51,10 +51,10 @@ export const auth = betterAuth({ trustedOrigins: CORS_ORIGIN_STRINGIFIED, database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { - cookiePrefix: process.env.APP_NAME ?? 'tdev', + cookiePrefix: COOKIE_PREFIX, crossSubDomainCookies: { - enabled: true, - domain: '.gbsl.website' + enabled: true + // domain: '.gbsl.website' }, database: { generateId: false, useNumberId: false } }, From 3fa2833e56d6849e8df9df13c6ecced4c8a47399 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 14:50:50 +0000 Subject: [PATCH 59/89] optimize --- src/app.ts | 3 +-- src/auth.ts | 1 - src/utils/originConfig.ts | 6 +++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app.ts b/src/app.ts index c9caac8..7c29de6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -38,9 +38,8 @@ export const API_URL = `/api/${API_VERSION}`; app.use( cors({ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], - origin: ['https://teaching-dev.gbsl.website', 'https://teaching-dev-api.gbsl.website'], + origin: CORS_ORIGIN, credentials: true - // allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With', 'x-metadata-sid'] }) ); diff --git a/src/auth.ts b/src/auth.ts index ecf0689..c10f8d0 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -54,7 +54,6 @@ export const auth = betterAuth({ cookiePrefix: COOKIE_PREFIX, crossSubDomainCookies: { enabled: true - // domain: '.gbsl.website' }, database: { generateId: false, useNumberId: false } }, diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index 6bda9d1..0394fc2 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -38,11 +38,15 @@ allowedOrigins.forEach((origin) => { CORS_ORIGIN_STRINGIFIED.push(`http://${origin}`); return CORS_ORIGIN.push(`http://${origin}`); } + if (process.env.BETTER_AUTH_URL) { + CORS_ORIGIN_STRINGIFIED.push(`${process.env.BETTER_AUTH_URL}`); + CORS_ORIGIN.push(`${process.env.BETTER_AUTH_URL}`); + } if (allowSubdomains) { if (origin.startsWith('http')) { const [protocol, host] = origin.split('://'); - CORS_ORIGIN_STRINGIFIED.push(`$${protocol}://*.${host}`, origin); + CORS_ORIGIN_STRINGIFIED.push(`${protocol}://*.${host}`, origin); } else { CORS_ORIGIN_STRINGIFIED.push(`*.${origin}`, `https://${origin}`); } From 651e4fb41ca280b13fd1416b2bb1b265d4e4aa25 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 15:43:01 +0000 Subject: [PATCH 60/89] update --- src/utils/originConfig.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index 0394fc2..c1c428e 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -66,8 +66,7 @@ allowedOrigins.forEach((origin) => { // Add Netlify deploy previews if enabled if (netlifyProjectName) { CORS_ORIGIN.push(new RegExp(`https://deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i')); - CORS_ORIGIN_STRINGIFIED.push(`https://*.netlify.app`); - CORS_ORIGIN_STRINGIFIED.push(`https://*${netlifyProjectName}.netlify.app`); + CORS_ORIGIN_STRINGIFIED.push(`https://*--${netlifyProjectName}.netlify.app`); } export const SAME_SITE = allowedOrigins.length > 1 || netlifyProjectName ? 'none' : 'strict'; From 89320abb7bd248a94e0149f5564591cd77c22d8b Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sat, 11 Oct 2025 17:05:47 +0000 Subject: [PATCH 61/89] try setting for deploy preview --- src/auth.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index c10f8d0..27b42cc 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,7 +1,7 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { admin, oneTimeToken, oAuthProxy } from 'better-auth/plugins'; +import { admin, oneTimeToken } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; @@ -34,7 +34,6 @@ export const auth = betterAuth({ authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, responseMode: 'query', - // redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -55,6 +54,12 @@ export const auth = betterAuth({ crossSubDomainCookies: { enabled: true }, + + defaultCookieAttributes: { + sameSite: 'none', + secure: true, + partitioned: true // New browser standards will mandate this for foreign cookies + }, database: { generateId: false, useNumberId: false } }, user: { @@ -63,12 +68,7 @@ export const auth = betterAuth({ lastName: { type: 'string', required: false, input: false } } }, - plugins: [ - oneTimeToken(), - admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso() - // oAuthProxy() - ], + plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], logger: { level: 'info', log: (level, message, ...args) => { From 5c3e8a6f5a31110da901ee612dfcdb7806fb21a1 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 09:22:08 +0000 Subject: [PATCH 62/89] tmp --- src/auth.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 27b42cc..339ca0c 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -54,7 +54,6 @@ export const auth = betterAuth({ crossSubDomainCookies: { enabled: true }, - defaultCookieAttributes: { sameSite: 'none', secure: true, From 19fc940b82373f154b93e9e0a575c06c6678923b Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 09:48:43 +0000 Subject: [PATCH 63/89] fix escaping --- src/app.ts | 2 +- src/auth.ts | 2 +- src/utils/originConfig.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/app.ts b/src/app.ts index 7c29de6..ceac1ae 100644 --- a/src/app.ts +++ b/src/app.ts @@ -38,7 +38,7 @@ export const API_URL = `/api/${API_VERSION}`; app.use( cors({ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], - origin: CORS_ORIGIN, + origin: [...CORS_ORIGIN, 'https://deploy-preview-246--teaching-dev.netlify.app'], credentials: true }) ); diff --git a/src/auth.ts b/src/auth.ts index 339ca0c..3a099fb 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -47,7 +47,7 @@ export const auth = betterAuth({ } } }, - trustedOrigins: CORS_ORIGIN_STRINGIFIED, + trustedOrigins: [...CORS_ORIGIN_STRINGIFIED, 'https://deploy-preview-246--teaching-dev.netlify.app'], database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: COOKIE_PREFIX, diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index c1c428e..768dac2 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -52,7 +52,7 @@ allowedOrigins.forEach((origin) => { } // Escape dots and create regex for domain with optional subdomains const escapedDomain = origin.replace(/\./g, '\\.'); - CORS_ORIGIN.push(new RegExp(`^https?://(.*\\.)?${escapedDomain}$`, 'i')); + CORS_ORIGIN.push(new RegExp(`^https?:\/\/(.*\\.)?${escapedDomain}$`, 'i')); } else { // Add exact domain match (ensuring it has protocol) if (!origin.startsWith('http')) { @@ -65,7 +65,9 @@ allowedOrigins.forEach((origin) => { // Add Netlify deploy previews if enabled if (netlifyProjectName) { - CORS_ORIGIN.push(new RegExp(`https://deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i')); + CORS_ORIGIN.push( + new RegExp(`^https:\/\/deploy-preview-\\d+--${netlifyProjectName}\\.netlify\\.app$`, 'i') + ); CORS_ORIGIN_STRINGIFIED.push(`https://*--${netlifyProjectName}.netlify.app`); } From f116613a7da692ec886e20f8efa0ecc46a9a576b Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 09:55:10 +0000 Subject: [PATCH 64/89] no crossSubDomain --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 3a099fb..049c568 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -51,9 +51,9 @@ export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: COOKIE_PREFIX, - crossSubDomainCookies: { - enabled: true - }, + // crossSubDomainCookies: { + // enabled: true + // }, defaultCookieAttributes: { sameSite: 'none', secure: true, From e1d4ca946f5d04d5fd7fc24eaae8da6ac98243e9 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 09:58:12 +0000 Subject: [PATCH 65/89] disable csrf --- src/auth.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 049c568..0d36846 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -59,7 +59,8 @@ export const auth = betterAuth({ secure: true, partitioned: true // New browser standards will mandate this for foreign cookies }, - database: { generateId: false, useNumberId: false } + database: { generateId: false, useNumberId: false }, + disableCSRFCheck: true }, user: { additionalFields: { From ca928c23140f6015a84f955a5511d7817703865e Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:04:50 +0000 Subject: [PATCH 66/89] re-enable csd --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 0d36846..7f929ad 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -51,9 +51,9 @@ export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: COOKIE_PREFIX, - // crossSubDomainCookies: { - // enabled: true - // }, + crossSubDomainCookies: { + enabled: true + }, defaultCookieAttributes: { sameSite: 'none', secure: true, From eea8213a1d7e404d062abbbfa7e037d23b513c9d Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:08:31 +0000 Subject: [PATCH 67/89] rm --- src/auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 7f929ad..89b47d3 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -59,8 +59,8 @@ export const auth = betterAuth({ secure: true, partitioned: true // New browser standards will mandate this for foreign cookies }, - database: { generateId: false, useNumberId: false }, - disableCSRFCheck: true + database: { generateId: false, useNumberId: false } + // disableCSRFCheck: true }, user: { additionalFields: { From c5832bda774aa2e9f6fd1063905a55a6babeaae4 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:11:40 +0000 Subject: [PATCH 68/89] csrf --- src/auth.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 89b47d3..7f929ad 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -59,8 +59,8 @@ export const auth = betterAuth({ secure: true, partitioned: true // New browser standards will mandate this for foreign cookies }, - database: { generateId: false, useNumberId: false } - // disableCSRFCheck: true + database: { generateId: false, useNumberId: false }, + disableCSRFCheck: true }, user: { additionalFields: { From c92e673cc295d1f32f3e4971e4383cb508dc8a69 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:20:23 +0000 Subject: [PATCH 69/89] rm cs --- src/auth.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 7f929ad..0d36846 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -51,9 +51,9 @@ export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: COOKIE_PREFIX, - crossSubDomainCookies: { - enabled: true - }, + // crossSubDomainCookies: { + // enabled: true + // }, defaultCookieAttributes: { sameSite: 'none', secure: true, From 6eda2bd2aeb18d801aedc17047a2d7b6f37c3f9e Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:28:31 +0000 Subject: [PATCH 70/89] add proxy --- src/auth.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 0d36846..b6eff23 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,7 +1,7 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { admin, oneTimeToken } from 'better-auth/plugins'; +import { admin, oneTimeToken, oAuthProxy } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; @@ -34,6 +34,7 @@ export const auth = betterAuth({ authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, responseMode: 'query', + redirectURI: process.env.BETTER_AUTH_URL, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -68,7 +69,12 @@ export const auth = betterAuth({ lastName: { type: 'string', required: false, input: false } } }, - plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], + plugins: [ + oneTimeToken(), + admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), + sso(), + oAuthProxy() + ], logger: { level: 'info', log: (level, message, ...args) => { From 5d1029a8de7dc50d17e7feaf5183d225a6f1d346 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:32:13 +0000 Subject: [PATCH 71/89] fix cb --- src/auth.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index b6eff23..ccab5fb 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -34,7 +34,7 @@ export const auth = betterAuth({ authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, responseMode: 'query', - redirectURI: process.env.BETTER_AUTH_URL, + redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); From 7c656ea326089865db1904b697f2b241b8d01d41 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 10:58:01 +0000 Subject: [PATCH 72/89] undo --- src/app.ts | 2 +- src/auth.ts | 24 ++++++------------------ 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/app.ts b/src/app.ts index ceac1ae..7c29de6 100644 --- a/src/app.ts +++ b/src/app.ts @@ -38,7 +38,7 @@ export const API_URL = `/api/${API_VERSION}`; app.use( cors({ methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'], - origin: [...CORS_ORIGIN, 'https://deploy-preview-246--teaching-dev.netlify.app'], + origin: CORS_ORIGIN, credentials: true }) ); diff --git a/src/auth.ts b/src/auth.ts index ccab5fb..064d6df 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,7 +1,7 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { admin, oneTimeToken, oAuthProxy } from 'better-auth/plugins'; +import { admin, oneTimeToken } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; @@ -34,7 +34,6 @@ export const auth = betterAuth({ authority: 'https://login.microsoftonline.com', // Authentication authority URL prompt: 'select_account', // Forces account selection, responseMode: 'query', - redirectURI: `${process.env.BETTER_AUTH_URL}/api/auth/callback/microsoft`, mapProfileToUser: (profile) => { const email = (profile.email || profile.preferred_username)?.toLowerCase(); const name = getNameFromMsftProfile(profile); @@ -48,20 +47,14 @@ export const auth = betterAuth({ } } }, - trustedOrigins: [...CORS_ORIGIN_STRINGIFIED, 'https://deploy-preview-246--teaching-dev.netlify.app'], + trustedOrigins: CORS_ORIGIN_STRINGIFIED, database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), advanced: { cookiePrefix: COOKIE_PREFIX, - // crossSubDomainCookies: { - // enabled: true - // }, - defaultCookieAttributes: { - sameSite: 'none', - secure: true, - partitioned: true // New browser standards will mandate this for foreign cookies + crossSubDomainCookies: { + enabled: true }, - database: { generateId: false, useNumberId: false }, - disableCSRFCheck: true + database: { generateId: false, useNumberId: false } }, user: { additionalFields: { @@ -69,12 +62,7 @@ export const auth = betterAuth({ lastName: { type: 'string', required: false, input: false } } }, - plugins: [ - oneTimeToken(), - admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), - sso(), - oAuthProxy() - ], + plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], logger: { level: 'info', log: (level, message, ...args) => { From b60faab8895ee86b989c4c90f64fbca5cdb2d2fd Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 12:01:07 +0000 Subject: [PATCH 73/89] add gh --- src/auth.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 064d6df..4a8261a 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -26,7 +26,18 @@ const getNameFromMsftProfile = (profile: MicrosoftEntraIDProfile) => { export const auth = betterAuth({ socialProviders: { - github: { clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! }, + github: { + clientId: process.env.BETTER_AUTH_GITHUB_ID!, + clientSecret: process.env.BETTER_AUTH_GITHUB_SECRET!, + mapProfileToUser: (profile) => { + const [firstName, lastName] = profile.name.split(' '); + return { + ...profile, + firstName: firstName || '', + lastName: lastName || '' + }; + } + }, microsoft: { clientId: process.env.MSAL_CLIENT_ID as string, clientSecret: process.env.MSAL_CLIENT_SECRET as string, From 4fead424a07cf75029d340d40c67d9b261dd300b Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 12:42:56 +0000 Subject: [PATCH 74/89] samesit cookie --- src/auth.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/auth.ts b/src/auth.ts index 4a8261a..e9c3848 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -65,6 +65,14 @@ export const auth = betterAuth({ crossSubDomainCookies: { enabled: true }, + cookies: { + state: { + attributes: { + sameSite: 'none', + secure: true + } + } + }, database: { generateId: false, useNumberId: false } }, user: { From 65775588007f47d894f802b7b55d6b76cecbb652 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 13:16:41 +0000 Subject: [PATCH 75/89] configure usernamePw Login --- src/auth.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index e9c3848..4b79271 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -25,6 +25,15 @@ const getNameFromMsftProfile = (profile: MicrosoftEntraIDProfile) => { }; export const auth = betterAuth({ + user: { + additionalFields: { + firstName: { type: 'string', required: true, input: true }, + lastName: { type: 'string', required: true, input: true } + } + }, + emailAndPassword: { + enabled: true + }, socialProviders: { github: { clientId: process.env.BETTER_AUTH_GITHUB_ID!, @@ -75,12 +84,6 @@ export const auth = betterAuth({ }, database: { generateId: false, useNumberId: false } }, - user: { - additionalFields: { - firstName: { type: 'string', required: false, input: false }, - lastName: { type: 'string', required: false, input: false } - } - }, plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], logger: { level: 'info', From 5bd4a6fc0b74fc69462dff9f2956b86a6630dd0f Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 13:39:35 +0000 Subject: [PATCH 76/89] session token cookie config --- src/auth.ts | 2 +- src/utils/originConfig.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 4b79271..56f8520 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -75,7 +75,7 @@ export const auth = betterAuth({ enabled: true }, cookies: { - state: { + session_token: { attributes: { sameSite: 'none', secure: true diff --git a/src/utils/originConfig.ts b/src/utils/originConfig.ts index 768dac2..a9e8a8d 100644 --- a/src/utils/originConfig.ts +++ b/src/utils/originConfig.ts @@ -23,7 +23,7 @@ const netlifyProjectName = process.env.NETLIFY_PROJECT_NAME; export const CORS_ORIGIN: (string | RegExp)[] = []; export const CORS_ORIGIN_STRINGIFIED: string[] = []; -const isLoclhost = (origin: string) => { +const isLocalhost = (origin: string) => { return origin.startsWith('localhost') || origin.startsWith('127.0.0.1'); }; @@ -34,7 +34,7 @@ allowedOrigins.forEach((origin) => { if (!origin) { return; } - if (isLoclhost(origin)) { + if (isLocalhost(origin)) { CORS_ORIGIN_STRINGIFIED.push(`http://${origin}`); return CORS_ORIGIN.push(`http://${origin}`); } From 5ad46189c2c4966d670aa5e420181b613b29fe17 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Sun, 12 Oct 2025 15:17:53 +0000 Subject: [PATCH 77/89] setup account linking --- src/auth.ts | 103 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 56f8520..3a8ba8c 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -24,6 +24,9 @@ const getNameFromMsftProfile = (profile: MicrosoftEntraIDProfile) => { return getNameFromEmail(profile.email || profile.preferred_username); }; +const HAS_PROVIDER_GH = !!process.env.BETTER_AUTH_GITHUB_ID && !!process.env.BETTER_AUTH_GITHUB_SECRET; +const HAS_PROVIDER_MSFT = !!process.env.MSAL_CLIENT_ID && !!process.env.MSAL_CLIENT_SECRET; + export const auth = betterAuth({ user: { additionalFields: { @@ -31,41 +34,59 @@ export const auth = betterAuth({ lastName: { type: 'string', required: true, input: true } } }, + account: { + encryptOAuthTokens: false, + accountLinking: { + enabled: true, + trustedProviders: ['github', 'microsoft', 'email-password'], + allowDifferentEmails: true + } + }, emailAndPassword: { - enabled: true + enabled: true, + disableSignUp: true, + revokeSessionsOnPasswordReset: true }, socialProviders: { - github: { - clientId: process.env.BETTER_AUTH_GITHUB_ID!, - clientSecret: process.env.BETTER_AUTH_GITHUB_SECRET!, - mapProfileToUser: (profile) => { - const [firstName, lastName] = profile.name.split(' '); - return { - ...profile, - firstName: firstName || '', - lastName: lastName || '' - }; - } - }, - microsoft: { - clientId: process.env.MSAL_CLIENT_ID as string, - clientSecret: process.env.MSAL_CLIENT_SECRET as string, - tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications - authority: 'https://login.microsoftonline.com', // Authentication authority URL - prompt: 'select_account', // Forces account selection, - responseMode: 'query', - mapProfileToUser: (profile) => { - const email = (profile.email || profile.preferred_username)?.toLowerCase(); - const name = getNameFromMsftProfile(profile); - return { - id: profile.oid, - email: email, - firstName: name.firstName || '', - lastName: name.lastName || '' - // You can extract and map other fields as needed - }; - } - } + ...(HAS_PROVIDER_GH + ? { + github: { + clientId: process.env.BETTER_AUTH_GITHUB_ID!, + clientSecret: process.env.BETTER_AUTH_GITHUB_SECRET!, + mapProfileToUser: (profile) => { + const [firstName, lastName] = profile.name.split(' '); + return { + ...profile, + firstName: firstName || '', + lastName: lastName || '' + }; + } + } + } + : {}), + ...(HAS_PROVIDER_MSFT + ? { + microsoft: { + clientId: process.env.MSAL_CLIENT_ID as string, + clientSecret: process.env.MSAL_CLIENT_SECRET as string, + tenantId: process.env.MSAL_TENANT_ID || 'common', // Use 'common' for multi-tenant applications + authority: 'https://login.microsoftonline.com', // Authentication authority URL + prompt: 'select_account', // Forces account selection, + responseMode: 'query', + mapProfileToUser: (profile) => { + const email = (profile.email || profile.preferred_username)?.toLowerCase(); + const name = getNameFromMsftProfile(profile); + return { + id: profile.oid, + email: email, + firstName: name.firstName || '', + lastName: name.lastName || '' + // You can extract and map other fields as needed + }; + } + } + } + : {}) }, trustedOrigins: CORS_ORIGIN_STRINGIFIED, database: prismaAdapter(prisma, { provider: 'postgresql', usePlural: false }), @@ -74,14 +95,16 @@ export const auth = betterAuth({ crossSubDomainCookies: { enabled: true }, - cookies: { - session_token: { - attributes: { - sameSite: 'none', - secure: true - } - } - }, + cookies: process.env.NETLIFY_PROJECT_NAME + ? { + session_token: { + attributes: { + sameSite: 'none', + secure: true + } + } + } + : undefined, database: { generateId: false, useNumberId: false } }, plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], From 7fa99d38145ac0f197dca94014ce7fdead32bab9 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 14:35:12 +0000 Subject: [PATCH 78/89] fix camel-case --- .../20251005093734_migrate_to_better_auth/migration.sql | 6 +++--- prisma/schema.prisma | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql index ff8ebef..f1e3167 100644 --- a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql +++ b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql @@ -51,7 +51,7 @@ CREATE TABLE "public"."accounts" ( "id" UUID NOT NULL DEFAULT gen_random_uuid(), "account_id" TEXT NOT NULL, "provider_id" TEXT NOT NULL, - "userId" UUID NOT NULL, + "user_id" UUID NOT NULL, "access_token" TEXT, "refresh_token" TEXT, "id_token" TEXT, @@ -102,7 +102,7 @@ CREATE INDEX "sessions_user_id_idx" ON "public"."sessions"("user_id"); CREATE INDEX "sessions_user_id_token_idx" ON "public"."sessions"("user_id", "token"); -- CreateIndex -CREATE INDEX "accounts_userId_idx" ON "public"."accounts"("userId"); +CREATE INDEX "accounts_user_id_idx" ON "public"."accounts"("user_id"); -- CreateIndex CREATE INDEX "verifications_identifier_idx" ON "public"."verifications"("identifier"); @@ -114,7 +114,7 @@ CREATE UNIQUE INDEX "ssoProviders_provider_id_key" ON "public"."ssoProviders"("p ALTER TABLE "public"."sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey -ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_userId_fkey" FOREIGN KEY ("userId") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; +ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "public"."ssoProviders" ADD CONSTRAINT "ssoProviders_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 71f8fcc..da076d6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -67,7 +67,7 @@ model Account { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid accountId String @map("account_id") providerId String @map("provider_id") - userId String @db.Uuid + userId String @map("user_id") @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) accessToken String? @map("access_token") refreshToken String? @map("refresh_token") From 46492c68bc997d17125d9e6997cd696236d28010 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 14:38:15 +0000 Subject: [PATCH 79/89] add link-pw route --- src/auth.ts | 3 ++ src/controllers/admins.ts | 69 +++++++++++++++++++++++++++++++++++++++ src/routes/router.ts | 10 +++++- 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/auth.ts b/src/auth.ts index 3a8ba8c..368d17e 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -32,6 +32,9 @@ export const auth = betterAuth({ additionalFields: { firstName: { type: 'string', required: true, input: true }, lastName: { type: 'string', required: true, input: true } + }, + deleteUser: { + enabled: false } }, account: { diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index 2e92bf3..e42e0c9 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -4,6 +4,9 @@ import { IoRoom } from '../routes/socketEvents'; import { Prisma } from '@prisma/client'; import { HTTP403Error } from '../utils/errors/Errors'; import prisma from '../prisma'; +import { auth } from 'src/auth'; +import { fromNodeHeaders } from 'better-auth/node'; +import { hasElevatedAccess } from 'src/models/User'; export const createAllowedAction: RequestHandler = async ( req, @@ -51,3 +54,69 @@ export const destroyAllowedAction: RequestHandler<{ id: string }> = async (req, ]; res.status(204).send(); }; + +export const linkUserPassword: RequestHandler<{ id: string }, any, { pw: string }> = async ( + req, + res, + next +) => { + if (!hasElevatedAccess(req.user?.role)) { + throw new HTTP403Error('cannot link password to elevated user'); + } + const user = await prisma.user.findUnique({ + where: { id: req.params.id }, + include: { accounts: true } + }); + if (!user) { + throw new HTTP403Error('unknown user'); + } + if (user.accounts.some((a) => a.providerId === 'credential' && !!a.password)) { + throw new HTTP403Error('user already has email-password account'); + } + const account = await prisma.account.create({ + data: { + providerId: 'credential', + accountId: user.id, + user: { connect: { id: user.id } }, + password: '' // will be set by better-auth + } + }); + const data = await auth.api.setUserPassword({ + body: { + newPassword: req.body.pw, // required + userId: user.id // required + }, + headers: fromNodeHeaders(req.headers) + }); + if (!data.status) { + await prisma.account.delete({ + where: { id: account.id } + }); + throw new HTTP403Error('could not set password'); + } + res.status(201).json({ success: true }); +}; + +export const revokeUserPassword: RequestHandler<{ id: string }> = async (req, res, next) => { + if (!hasElevatedAccess(req.user?.role)) { + throw new HTTP403Error('cannot revoke password from elevated user'); + } + const user = await prisma.user.findUnique({ + where: { id: req.params.id }, + include: { accounts: true } + }); + if (!user) { + return res.status(204).send(); + } + if (user.accounts.length === 1 && user.accounts[0].providerId === 'credential') { + throw new HTTP403Error('cannot revoke only login method of user'); + } + const toDelete = user.accounts.filter((a) => a.providerId === 'credential'); + if (toDelete.length === 0) { + return res.status(204).send(); + } + await prisma.account.deleteMany({ + where: { id: { in: toDelete.map((a) => a.id) } } + }); + res.status(204).send(); +}; diff --git a/src/routes/router.ts b/src/routes/router.ts index 094ad48..d623cc4 100644 --- a/src/routes/router.ts +++ b/src/routes/router.ts @@ -37,7 +37,13 @@ import { allDocuments, destroy as deleteDocumentRoot } from '../controllers/documentRoots'; -import { allowedActions, createAllowedAction, destroyAllowedAction } from '../controllers/admins'; +import { + allowedActions, + createAllowedAction, + destroyAllowedAction, + linkUserPassword, + revokeUserPassword +} from '../controllers/admins'; import { githubToken, find as findCmsSettings, @@ -106,6 +112,8 @@ router.delete('/documents/:id', deleteDocument); router.get('/admin/allowedActions', allowedActions); router.post('/admin/allowedActions', createAllowedAction); router.delete('/admin/allowedActions/:id', destroyAllowedAction); +router.post('/admin/users/:id/linkUserPassword', linkUserPassword); +router.post('/admin/users/:id/revokeUserPassword', revokeUserPassword); router.get('/cms/settings', findCmsSettings); router.put('/cms/settings', updateCmsSettings); From 591bdb67795055d871bff79b2cdb3c5ccd46c7a2 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 15:53:28 +0000 Subject: [PATCH 80/89] set default name --- .../20251005093734_migrate_to_better_auth/migration.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql index f1e3167..bbfe81a 100644 --- a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql +++ b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql @@ -24,6 +24,7 @@ ALTER TABLE "public"."users" ADD COLUMN "role" TEXT NOT NULL DEFAULT 'student'; UPDATE "public"."users" SET "role" = trole; +UPDATE "public"."users" SET "name" = CONCAT(first_name, ' ', last_name) WHERE name = ''; ALTER TABLE "public"."users" DROP COLUMN "trole"; From d34eb32b80a8e908abe7131b190a511328362f9f Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 18:36:04 +0000 Subject: [PATCH 81/89] fix import --- src/controllers/admins.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index e42e0c9..f533039 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -4,7 +4,7 @@ import { IoRoom } from '../routes/socketEvents'; import { Prisma } from '@prisma/client'; import { HTTP403Error } from '../utils/errors/Errors'; import prisma from '../prisma'; -import { auth } from 'src/auth'; +import { auth } from '../auth'; import { fromNodeHeaders } from 'better-auth/node'; import { hasElevatedAccess } from 'src/models/User'; From 8d5a70b32ab9e063e17a1927ff1dbfaf5614613f Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 19:27:56 +0000 Subject: [PATCH 82/89] fix import --- src/app.ts | 1 - src/controllers/admins.ts | 29 ++++++++++++++--- src/models/User.ts | 59 ++++++++++++++++++++++++++++------ src/routes/socketEventTypes.ts | 3 +- src/routes/socketEvents.ts | 2 -- 5 files changed, 77 insertions(+), 17 deletions(-) diff --git a/src/app.ts b/src/app.ts index 7c29de6..c2c4854 100644 --- a/src/app.ts +++ b/src/app.ts @@ -98,7 +98,6 @@ export const configure = (_app: typeof app) => { return; } const io = req.io as Server; - if (res.notifications && io) { res.notifications.forEach((notification) => { const except: string[] = []; diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index f533039..febde4a 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -6,7 +6,7 @@ import { HTTP403Error } from '../utils/errors/Errors'; import prisma from '../prisma'; import { auth } from '../auth'; import { fromNodeHeaders } from 'better-auth/node'; -import { hasElevatedAccess } from 'src/models/User'; +import User, { hasElevatedAccess } from 'src/models/User'; export const createAllowedAction: RequestHandler = async ( req, @@ -77,8 +77,7 @@ export const linkUserPassword: RequestHandler<{ id: string }, any, { pw: string data: { providerId: 'credential', accountId: user.id, - user: { connect: { id: user.id } }, - password: '' // will be set by better-auth + user: { connect: { id: user.id } } } }); const data = await auth.api.setUserPassword({ @@ -94,7 +93,18 @@ export const linkUserPassword: RequestHandler<{ id: string }, any, { pw: string }); throw new HTTP403Error('could not set password'); } - res.status(201).json({ success: true }); + const updated = await User.findModel(req.params.id); + if (updated) { + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { type: RecordType.User, record: updated }, + to: [IoRoom.ADMIN, user.id], + toSelf: true + } + ]; + } + res.status(201).json(updated); }; export const revokeUserPassword: RequestHandler<{ id: string }> = async (req, res, next) => { @@ -118,5 +128,16 @@ export const revokeUserPassword: RequestHandler<{ id: string }> = async (req, re await prisma.account.deleteMany({ where: { id: { in: toDelete.map((a) => a.id) } } }); + const updated = await User.findModel(req.params.id); + if (updated) { + res.notifications = [ + { + event: IoEvent.CHANGED_RECORD, + message: { type: RecordType.User, record: updated }, + to: [IoRoom.ADMIN, user.id], + toSelf: true + } + ]; + } res.status(204).send(); }; diff --git a/src/models/User.ts b/src/models/User.ts index e8912f3..557d520 100644 --- a/src/models/User.ts +++ b/src/models/User.ts @@ -33,13 +33,37 @@ export const whereStudentGroupAccess = (userId: string, isAdmin?: boolean) => ({ } }); +export type ApiUser = DbUser & { authProviders?: string[] }; + +export const prepareUser = ( + user: (DbUser & { accounts: { providerId: string }[] }) | null | undefined, + includeAuthProvidersFor?: string +): ApiUser | null => { + if (!user) { + return null; + } + if (!includeAuthProvidersFor || user.id === includeAuthProvidersFor) { + (user as unknown as ApiUser).authProviders = (user.accounts || []).map((a) => a.providerId); + } + delete (user as any).accounts; + return user; +}; + +const prepareUsers = ( + users: (DbUser & { accounts: { providerId: string }[] })[] | null | undefined +): ApiUser[] => { + return users?.filter((u) => !!u).map((u) => prepareUser(u)!) || []; +}; + function User(db: PrismaClient['user']) { return Object.assign(db, { - async findModel(id: string): Promise { - return db.findUnique({ where: { id } }); + async findModel(id: string): Promise { + return db + .findUnique({ where: { id }, include: { accounts: { select: { providerId: true } } } }) + .then(prepareUser); }, - async updateModel(actor: DbUser, id: string, data: Partial): Promise { + async updateModel(actor: DbUser, id: string, data: Partial): Promise { const record = await db.findUnique({ where: { id: id } }); if (!record) { throw new HTTP404Error('User not found'); @@ -53,25 +77,36 @@ function User(db: PrismaClient['user']) { } /** remove fields not updatable*/ const sanitized = getData(data, false, record.id === actor.id ? false : elevatedAccess); - return db.update({ where: { id: id }, data: sanitized }); + return db + .update({ + where: { id: id }, + data: sanitized, + include: { accounts: { select: { providerId: true } } } + }) + .then((u) => prepareUser(u)!); }, - async all(actor: DbUser): Promise { + async all(actor: DbUser): Promise { if (hasElevatedAccess(actor.role)) { /** * Admins and teachers can see all users. * Reason: teachers need to add new users to their student groups */ - return db.findMany({}); + return db + .findMany({ + include: { accounts: { select: { providerId: true } } } + }) + .then(prepareUsers); } const users = await db.findMany({ where: { OR: [{ id: actor.id }, whereStudentGroupAccess(actor.id)] }, + include: { accounts: { select: { providerId: true } } }, distinct: ['id'] }); - return users; + return users.filter((u) => !!u).map((u) => prepareUser(u, actor.id)!); }, - async setRole(actor: DbUser, userId: string, role: Role): Promise { + async setRole(actor: DbUser, userId: string, role: Role): Promise { if (!hasElevatedAccess(actor.role)) { throw new HTTP403Error('Not authorized'); } @@ -94,7 +129,13 @@ function User(db: PrismaClient['user']) { if (recordLevel === undefined || actorLevel < recordLevel) { throw new HTTP403Error('Not allowed to change the role of user with a higher role'); } - return db.update({ where: { id: userId }, data: { role: role } }); + return db + .update({ + where: { id: userId }, + data: { role: role }, + include: { accounts: { select: { providerId: true } } } + }) + .then((u) => prepareUser(u)!); } }); } diff --git a/src/routes/socketEventTypes.ts b/src/routes/socketEventTypes.ts index 114f0fa..20767b7 100644 --- a/src/routes/socketEventTypes.ts +++ b/src/routes/socketEventTypes.ts @@ -4,6 +4,7 @@ import { ApiUserPermission } from '../models/RootUserPermission'; import { ApiGroupPermission } from '../models/RootGroupPermission'; import { ApiDocumentRootWithoutDocuments } from '../models/DocumentRoot'; import { ApiStudentGroup } from '../models/StudentGroup'; +import { ApiUser } from 'src/models/User'; export enum IoEvent { NEW_RECORD = 'NEW_RECORD', @@ -27,7 +28,7 @@ export enum RecordType { type TypeRecordMap = { [RecordType.Document]: ApiDocument; - [RecordType.User]: User; + [RecordType.User]: ApiUser; [RecordType.UserPermission]: ApiUserPermission; [RecordType.GroupPermission]: ApiGroupPermission; [RecordType.DocumentRoot]: ApiDocumentRootWithoutDocuments; diff --git a/src/routes/socketEvents.ts b/src/routes/socketEvents.ts index a65a3bb..c61805b 100644 --- a/src/routes/socketEvents.ts +++ b/src/routes/socketEvents.ts @@ -21,7 +21,6 @@ const EventRouter = (io: Server) => const token = socket.handshake.auth.token; const session = await auth.api.verifyOneTimeToken({ body: { token } }).catch(() => null); - console.log(`Socket.io connection ${session?.user?.email}`, token); if (!session?.user) { return socket.disconnect(); @@ -32,7 +31,6 @@ const EventRouter = (io: Server) => return socket.disconnect(); } socket.join(user.id); - if (user.role === Role.ADMIN) { socket.join(IoRoom.ADMIN); const rooms = [...io.sockets.adapter.rooms.keys()].map( From 44eef509acfea4d8ee81ddd69928616270b61739 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 19:40:40 +0000 Subject: [PATCH 83/89] fix imports --- src/controllers/admins.ts | 2 +- src/routes/socketEventTypes.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index febde4a..4735d14 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -6,7 +6,7 @@ import { HTTP403Error } from '../utils/errors/Errors'; import prisma from '../prisma'; import { auth } from '../auth'; import { fromNodeHeaders } from 'better-auth/node'; -import User, { hasElevatedAccess } from 'src/models/User'; +import User, { hasElevatedAccess } from '../models/User'; export const createAllowedAction: RequestHandler = async ( req, diff --git a/src/routes/socketEventTypes.ts b/src/routes/socketEventTypes.ts index 20767b7..fc305e5 100644 --- a/src/routes/socketEventTypes.ts +++ b/src/routes/socketEventTypes.ts @@ -4,7 +4,7 @@ import { ApiUserPermission } from '../models/RootUserPermission'; import { ApiGroupPermission } from '../models/RootGroupPermission'; import { ApiDocumentRootWithoutDocuments } from '../models/DocumentRoot'; import { ApiStudentGroup } from '../models/StudentGroup'; -import { ApiUser } from 'src/models/User'; +import { ApiUser } from '../models/User'; export enum IoEvent { NEW_RECORD = 'NEW_RECORD', From 8bb462dc0dac867d77ea447e0d3d196d70c40098 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 22:53:58 +0000 Subject: [PATCH 84/89] expose socketIo server in it's own scope --- src/app.ts | 19 +++------------- src/auth.ts | 34 ++++++++++++++++++++++++++++- src/controllers/admins.ts | 13 +---------- src/routes/socketEventTypes.ts | 2 +- src/server.ts | 25 +++------------------ src/socketIoServer.ts | 40 ++++++++++++++++++++++++++++++++++ src/types/express/index.d.ts | 4 +--- 7 files changed, 82 insertions(+), 55 deletions(-) create mode 100644 src/socketIoServer.ts diff --git a/src/app.ts b/src/app.ts index c2c4854..d015f06 100644 --- a/src/app.ts +++ b/src/app.ts @@ -2,7 +2,6 @@ import express, { NextFunction, Request, Response } from 'express'; import path from 'path'; import cors from 'cors'; import morganMiddleware from './middleware/morgan.middleware'; -// import passport from 'passport'; import router from './routes/router'; import routeGuard, { createAccessRules } from './auth/guard'; import authConfig from './routes/authConfig'; @@ -12,9 +11,8 @@ import { fromNodeHeaders, toNodeHandler } from 'better-auth/node'; import { auth } from './auth'; import Logger from './utils/logger'; -import type { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; -import type { Server } from 'socket.io'; import { CORS_ORIGIN } from './utils/originConfig'; +import { notify } from './socketIoServer'; const AccessRules = createAccessRules(authConfig.accessMatrix); @@ -97,20 +95,9 @@ export const configure = (_app: typeof app) => { if (res.statusCode >= 400) { return; } - const io = req.io as Server; - if (res.notifications && io) { + if (res.notifications) { res.notifications.forEach((notification) => { - const except: string[] = []; - /** ignore this socket */ - if (!notification.toSelf) { - const socketID = req.headers['x-metadata-sid'] as string; - if (socketID) { - except.push(socketID); - } - } - io.except(except) - .to(notification.to) - .emit(notification.event, notification.message as any); + notify(notification, req.headers['x-metadata-sid'] as string); }); } }); diff --git a/src/auth.ts b/src/auth.ts index 368d17e..0d9cf74 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,12 +1,16 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; -import { admin, oneTimeToken } from 'better-auth/plugins'; +import { admin, createAuthMiddleware, oneTimeToken } from 'better-auth/plugins'; import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; import type { MicrosoftEntraIDProfile } from 'better-auth/social-providers'; import Logger from './utils/logger'; +import { getIo, notify } from './socketIoServer'; +import User from './models/User'; +import { IoRoom } from './routes/socketEvents'; +import { IoEvent, RecordType } from './routes/socketEventTypes'; // If your Prisma file is located elsewhere, you can change the path @@ -110,6 +114,34 @@ export const auth = betterAuth({ : undefined, database: { generateId: false, useNumberId: false } }, + hooks: { + after: createAuthMiddleware(async (ctx) => { + console.log(ctx.path, ctx.body); + switch (ctx.path) { + case '/admin/update-user': + case '/admin/ban-user': + case '/admin/unban-user': + case '/admin/set-user-password': + const { userId } = ctx.body as { userId?: string }; + if (userId) { + const user = await User.findModel(userId); + if (user) { + notify({ + to: [user.id, IoRoom.ADMIN], + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.User, + record: user + } + }); + } + } + break; + default: + return; + } + }) + }, plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], logger: { level: 'info', diff --git a/src/controllers/admins.ts b/src/controllers/admins.ts index 4735d14..e2e3b47 100644 --- a/src/controllers/admins.ts +++ b/src/controllers/admins.ts @@ -93,18 +93,7 @@ export const linkUserPassword: RequestHandler<{ id: string }, any, { pw: string }); throw new HTTP403Error('could not set password'); } - const updated = await User.findModel(req.params.id); - if (updated) { - res.notifications = [ - { - event: IoEvent.CHANGED_RECORD, - message: { type: RecordType.User, record: updated }, - to: [IoRoom.ADMIN, user.id], - toSelf: true - } - ]; - } - res.status(201).json(updated); + res.status(201).send(); }; export const revokeUserPassword: RequestHandler<{ id: string }> = async (req, res, next) => { diff --git a/src/routes/socketEventTypes.ts b/src/routes/socketEventTypes.ts index fc305e5..0071704 100644 --- a/src/routes/socketEventTypes.ts +++ b/src/routes/socketEventTypes.ts @@ -1,4 +1,4 @@ -import { AllowedAction, CmsSettings, Prisma, User } from '@prisma/client'; +import { AllowedAction, CmsSettings, Prisma } from '@prisma/client'; import { ApiDocument } from '../models/Document'; import { ApiUserPermission } from '../models/RootUserPermission'; import { ApiGroupPermission } from '../models/RootGroupPermission'; diff --git a/src/server.ts b/src/server.ts index cf538ed..70453ec 100644 --- a/src/server.ts +++ b/src/server.ts @@ -1,34 +1,15 @@ import './instrumentation'; import app, { configure } from './app'; +import { initialize as initializeSocketIo } from './socketIoServer'; import http from 'http'; -import { Server } from 'socket.io'; -import { ClientToServerEvents, ServerToClientEvents } from './routes/socketEventTypes'; -// import passport from 'passport'; -import EventRouter from './routes/socketEvents'; -import type { NextFunction, Request, Response } from 'express'; -import { HTTP403Error } from './utils/errors/Errors'; -import { CORS_ORIGIN } from './utils/originConfig'; +import type { Request } from 'express'; import * as Sentry from '@sentry/node'; import Logger from './utils/logger'; const PORT = process.env.PORT || 3002; const server = http.createServer(app); - -const io = new Server(server, { - cors: { origin: CORS_ORIGIN, credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'] }, - pingInterval: 15_000, - pingTimeout: 20_000, - transports: ['websocket', 'webtransport' /* , 'polling' */] -}); - -EventRouter(io); - -// Make io accessible to our router -app.use((req: Request, res, next) => { - req.io = io; - next(); -}); +initializeSocketIo(server); configure(app); diff --git a/src/socketIoServer.ts b/src/socketIoServer.ts new file mode 100644 index 0000000..d4c8ddf --- /dev/null +++ b/src/socketIoServer.ts @@ -0,0 +1,40 @@ +import { Server } from 'socket.io'; +import type http from 'http'; +import type { ClientToServerEvents, ServerToClientEvents, Notification } from './routes/socketEventTypes'; +import { CORS_ORIGIN } from './utils/originConfig'; +import EventRouter from './routes/socketEvents'; + +let _io: Server; + +export const initialize = (server: http.Server) => { + if (_io) { + return _io; + } + _io = new Server(server, { + cors: { origin: CORS_ORIGIN, credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE'] }, + pingInterval: 15_000, + pingTimeout: 20_000, + transports: ['websocket', 'webtransport' /* , 'polling' */] + }); + EventRouter(_io); + return _io; +}; + +export const getIo = () => { + if (!_io) { + throw new Error('Socket.io not initialized'); + } + return _io; +}; + +export const notify = (notification: Notification, sid?: string) => { + const io = getIo(); + const except: string[] = []; + /** ignore this socket */ + if (!notification.toSelf && sid) { + except.push(sid); + } + io.except(except) + .to(notification.to) + .emit(notification.event, notification.message as any); +}; diff --git a/src/types/express/index.d.ts b/src/types/express/index.d.ts index 1a1d67f..51627a3 100644 --- a/src/types/express/index.d.ts +++ b/src/types/express/index.d.ts @@ -1,6 +1,5 @@ import type { User as pUser } from '@prisma/client'; -import type { ClientToServerEvents, Notification, ServerToClientEvents } from '../../routes/socketEventTypes'; -import { Server } from 'socket.io'; +import type { Notification } from '../../routes/socketEventTypes'; // to make the file a module and avoid a TypeScript error export {}; @@ -9,7 +8,6 @@ declare global { namespace Express { export interface Request { user: pUser; - io?: Server; } export interface Response { From e421e351de987576a7de7a005565b9d8aafde739 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 23:01:58 +0000 Subject: [PATCH 85/89] cleanup --- README.md | 8 -------- src/routes/authConfig.ts | 24 ------------------------ 2 files changed, 32 deletions(-) diff --git a/README.md b/README.md index ceb106d..f3c9501 100644 --- a/README.md +++ b/README.md @@ -307,14 +307,6 @@ pg_restore -h localhost --verbose --clean --no-owner --no-privileges -U postgres ## Speed Improvements If the API and the Database are running on the same server, you can improve the speed by disabling the tcp connection for the database. This can be done by setting the `DATABASE_URL` to `postgresql://teaching_website:teaching_website@localhost/teaching_website?sslmode=disable`. -## Troubleshooting - -> [!Caution] -> Authentication Error: When your API can not authenticate requests -> - set the debug level in authConfig to 'info' and check the logs -> - when it is a 401 error and the issue is about `Strategy.prototype.jwtVerify can not verify the token`, ensure to set `"requestedAccessTokenVersion": 2` in the API manifest (!! **not** in the Frontend's manifest, there it must still be `null` !!) - - ## CMS For the cms to work properly, you need to register a github app under https://github.com/settings/apps. The following settings are required: diff --git a/src/routes/authConfig.ts b/src/routes/authConfig.ts index 8ec5104..ba2af37 100644 --- a/src/routes/authConfig.ts +++ b/src/routes/authConfig.ts @@ -1,19 +1,5 @@ import { Role } from '../models/User'; -interface Credentials { - tenantID: string; - clientID: string; -} -interface Metadata { - authority: string; - discovery: string; - version: string; -} -interface Settings { - validateIssuer: boolean; - passReqToCallback: boolean; - loggingLevel: 'info' | 'warn' | 'error'; -} export interface AccessMatrix { [key: string]: { path: string; @@ -22,20 +8,10 @@ export interface AccessMatrix { } interface Config { - credentials: Credentials; - metadata: Metadata; - settings: Settings; accessMatrix: AccessMatrix; } const authConfig: Config = { - credentials: { tenantID: process.env.MSAL_TENANT_ID || '', clientID: process.env.MSAL_CLIENT_ID || '' }, - metadata: { - authority: 'login.microsoftonline.com', - discovery: '.well-known/openid-configuration', - version: 'v2.0' - }, - settings: { validateIssuer: true, passReqToCallback: false, loggingLevel: 'warn' }, accessMatrix: { checklogin: { path: '/checklogin', access: [{ methods: ['GET'], minRole: Role.STUDENT }] }, user: { path: '/user', access: [{ methods: ['GET', 'POST'], minRole: Role.STUDENT }] }, From 61355ce1720139e4f07162f79e519b3330407b27 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Mon, 13 Oct 2025 23:15:07 +0000 Subject: [PATCH 86/89] fix type-error --- src/auth.ts | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 0d9cf74..38c2575 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -116,13 +116,11 @@ export const auth = betterAuth({ }, hooks: { after: createAuthMiddleware(async (ctx) => { - console.log(ctx.path, ctx.body); + const userId = ctx.body?.userId as string | undefined; switch (ctx.path) { case '/admin/update-user': - case '/admin/ban-user': case '/admin/unban-user': case '/admin/set-user-password': - const { userId } = ctx.body as { userId?: string }; if (userId) { const user = await User.findModel(userId); if (user) { @@ -137,6 +135,21 @@ export const auth = betterAuth({ } } break; + case '/admin/ban-user': + if (userId) { + const user = await User.findModel(userId); + if (user) { + notify({ + to: [IoRoom.ADMIN], + event: IoEvent.CHANGED_RECORD, + message: { + type: RecordType.User, + record: user + } + }); + getIo().to(user.id).emit(IoEvent.ACTION, 'nav-reload'); + } + } default: return; } From 7ca35c87668bcfdb1bba17894d7fd89482287be9 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 14 Oct 2025 10:31:59 +0000 Subject: [PATCH 87/89] remove unused sso plugin --- README.md | 1 + .../migration.sql | 20 ------------------- prisma/schema.prisma | 16 --------------- src/auth.ts | 3 +-- 4 files changed, 2 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index f3c9501..9eb38cf 100644 --- a/README.md +++ b/README.md @@ -302,6 +302,7 @@ dokku letsencrypt:enable dev-teaching-api # inside shell of VSCode DevContainer (with configured dokku git remote) dokku postgres:export dev-teaching-api > tdev-backup.dump pg_restore -h localhost --verbose --clean --no-owner --no-privileges -U postgres -d teaching_api < tdev-backup.dump +# when ai-pr was once merged/deployed to the db, run `delete from _prisma_migrations where migration_name ilike '%_ai_%';` ``` ## Speed Improvements diff --git a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql index bbfe81a..ff7707d 100644 --- a/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql +++ b/prisma/migrations/20251005093734_migrate_to_better_auth/migration.sql @@ -79,20 +79,6 @@ CREATE TABLE "public"."verifications" ( CONSTRAINT "verifications_pkey" PRIMARY KEY ("id") ); --- CreateTable -CREATE TABLE "public"."ssoProviders" ( - "id" UUID NOT NULL DEFAULT gen_random_uuid(), - "issuer" TEXT NOT NULL, - "oidc_config" TEXT, - "saml_config" TEXT, - "user_id" UUID, - "provider_id" TEXT NOT NULL, - "organization_id" TEXT, - "domain" TEXT NOT NULL, - - CONSTRAINT "ssoProviders_pkey" PRIMARY KEY ("id") -); - -- CreateIndex CREATE UNIQUE INDEX "sessions_token_key" ON "public"."sessions"("token"); @@ -108,14 +94,8 @@ CREATE INDEX "accounts_user_id_idx" ON "public"."accounts"("user_id"); -- CreateIndex CREATE INDEX "verifications_identifier_idx" ON "public"."verifications"("identifier"); --- CreateIndex -CREATE UNIQUE INDEX "ssoProviders_provider_id_key" ON "public"."ssoProviders"("provider_id"); - -- AddForeignKey ALTER TABLE "public"."sessions" ADD CONSTRAINT "sessions_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "public"."accounts" ADD CONSTRAINT "accounts_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; - --- AddForeignKey -ALTER TABLE "public"."ssoProviders" ADD CONSTRAINT "ssoProviders_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index da076d6..33adbee 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -40,8 +40,6 @@ model User { banReason String? @map("ban_reason") banExpires DateTime? @map("ban_expires") - ssoproviders SsoProvider[] - @@map("users") } @@ -97,20 +95,6 @@ model Verification { @@map("verifications") } -model SsoProvider { - id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid - issuer String - oidcConfig String? @map("oidc_config") - samlConfig String? @map("saml_config") - userId String? @map("user_id") @db.Uuid - user User? @relation(fields: [userId], references: [id], onDelete: Cascade) - providerId String @unique @map("provider_id") - organizationId String? @map("organization_id") - domain String - - @@map("ssoProviders") -} - model CmsSettings { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid user User @relation(fields: [userId], references: [id], onDelete: Cascade) diff --git a/src/auth.ts b/src/auth.ts index 38c2575..180af79 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -2,7 +2,6 @@ import { betterAuth } from 'better-auth'; import { prismaAdapter } from 'better-auth/adapters/prisma'; import prisma from './prisma'; import { admin, createAuthMiddleware, oneTimeToken } from 'better-auth/plugins'; -import { sso } from '@better-auth/sso'; import { CORS_ORIGIN_STRINGIFIED } from './utils/originConfig'; import { getNameFromEmail } from './helpers/email'; import type { MicrosoftEntraIDProfile } from 'better-auth/social-providers'; @@ -155,7 +154,7 @@ export const auth = betterAuth({ } }) }, - plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] }), sso()], + plugins: [oneTimeToken(), admin({ defaultRole: 'student', adminRoles: ['teacher', 'admin'] })], logger: { level: 'info', log: (level, message, ...args) => { From 9fa718c52b24a11f7da526edeee3bea1144a65b5 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 14 Oct 2025 11:00:11 +0000 Subject: [PATCH 88/89] use prisma config file --- package.json | 13 +++---- prisma.config.ts | 14 ++++++++ prisma/seed-files/users.ts | 7 ++-- yarn.lock | 73 ++++++++++++++++++++------------------ 4 files changed, 61 insertions(+), 46 deletions(-) create mode 100644 prisma.config.ts diff --git a/package.json b/package.json index 11c1b89..f5be2e5 100644 --- a/package.json +++ b/package.json @@ -4,14 +4,14 @@ "main": "server.js", "repository": "https://github.com/GBSL-Informatik/teaching-website-backend.git", "author": "GBSL Informatik", - "license": "CC-BY-SA", + "license": "MIT", "scripts": { "dev": "cross-env NODE_ENV=development nodemon -r tsconfig-paths/register --exec ts-node ./src/server.ts --files", "build": "yarn run prisma generate && tsc --build ./tsconfig.build.json", "start": "cross-env NODE_ENV=production node ./dist/src/server.js", "lint": "eslint . --ignore-pattern node_modules --fix", "format": "prettier --write ./**/*.{ts,json}", - "format:check": "prettier --check .", + "format:check": "prettier --check ./**/*.{ts,json}", "db:migrate": "yarn prisma migrate deploy", "db:migrate:dev": "yarn prisma migrate dev", "db:seed": "yarn prisma db seed", @@ -36,11 +36,6 @@ "socket.io": "^4.8.1", "winston": "^3.13.0" }, - "prisma": { - "schema": "./prisma/schema.prisma", - "seed": "dotenv -- ts-node prisma/seed.ts", - "reset": "dotenv -- ts-node prisma/reset.ts" - }, "devDependencies": { "@mermaid-js/mermaid-cli": "^10.9.1", "@types/cors": "^2.8.17", @@ -55,7 +50,7 @@ "eslint-plugin-prettier": "^5.5.4", "nodemon": "^3.1.10", "prettier": "^3.6.2", - "prisma": "^6.16.2", + "prisma": "^6.17.1", "prisma-dbml-generator": "^0.12.0", "prisma-docs-generator": "^0.8.0", "prisma-erd-generator": "^2.1.0", @@ -68,4 +63,4 @@ "engines": { "node": "^22.15.0" } -} +} \ No newline at end of file diff --git a/prisma.config.ts b/prisma.config.ts new file mode 100644 index 0000000..bb95c42 --- /dev/null +++ b/prisma.config.ts @@ -0,0 +1,14 @@ +import 'dotenv/config'; +import path from 'node:path'; + +import type { PrismaConfig } from 'prisma'; + +export default { + experimental: { + adapter: true + }, + migrations: { + seed: 'dotenv -- ts-node prisma/seed.ts' + } + // now you can use process.env variables +} satisfies PrismaConfig; diff --git a/prisma/seed-files/users.ts b/prisma/seed-files/users.ts index 240a5e6..a72c39e 100644 --- a/prisma/seed-files/users.ts +++ b/prisma/seed-files/users.ts @@ -6,8 +6,8 @@ export const TEST_USER_ID = '4b6d8b5d-3b6c-4c8b-8d3c-6f2c3f6e2b4b'; const { USER_EMAIL, USER_ID } = process.env; const users: Prisma.UserCreateInput[] = [ - { email: 'foo@bar.ch', id: FOO_BAR_ID, firstName: 'Foo', lastName: 'Bar' }, - { email: 'test@user.ch', id: TEST_USER_ID, firstName: 'Test', lastName: 'User' } + { email: 'foo@bar.ch', id: FOO_BAR_ID, firstName: 'Foo', lastName: 'Bar', name: 'Foo Bar' }, + { email: 'test@user.ch', id: TEST_USER_ID, firstName: 'Test', lastName: 'User', name: 'Test User' } ]; // Add admin user from .env-file. @@ -18,7 +18,8 @@ if (USER_EMAIL && USER_ID) { id: USER_ID, firstName: name.split('.')[0], lastName: name.split('.')[1] || name, - role: 'admin' + role: 'admin', + name: name.split('.').join(' ') }); } diff --git a/yarn.lock b/yarn.lock index 67461c3..5e069be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -876,10 +876,10 @@ resolved "https://registry.yarnpkg.com/@prisma/client/-/client-6.16.3.tgz#6c3a9b749a8155f3dfea1358068a6b1e41080182" integrity sha512-JfNfAtXG+/lIopsvoZlZiH2k5yNx87mcTS4t9/S5oufM1nKdXYxOvpDC1XoTCFBa5cQh7uXnbMPsmZrwZY80xw== -"@prisma/config@6.16.3": - version "6.16.3" - resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.16.3.tgz#ac21ce44017393e86bec19f51a4074298787666c" - integrity sha512-VlsLnG4oOuKGGMToEeVaRhoTBZu5H3q51jTQXb/diRags3WV0+BQK5MolJTtP6G7COlzoXmWeS11rNBtvg+qFQ== +"@prisma/config@6.17.1": + version "6.17.1" + resolved "https://registry.yarnpkg.com/@prisma/config/-/config-6.17.1.tgz#ac01e7006fb56117a77e0314054f6dcdf42531c0" + integrity sha512-fs8wY6DsvOCzuiyWVckrVs1LOcbY4LZNz8ki4uUIQ28jCCzojTGqdLhN2Jl5lDnC1yI8/gNIKpsWDM8pLhOdwA== dependencies: c12 "3.1.0" deepmerge-ts "7.1.5" @@ -909,6 +909,11 @@ resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.16.3.tgz#a4892e41ada976fe209e405adcacee02cc34f969" integrity sha512-89DdqWtdKd7qoc9/qJCKLTazj3W3zPEiz0hc7HfZdpjzm21c7orOUB5oHWJsG+4KbV4cWU5pefq3CuDVYF9vgA== +"@prisma/debug@6.17.1": + version "6.17.1" + resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-6.17.1.tgz#b1c0b2787e1e04f08cfc7b39cee02a81c4897ea8" + integrity sha512-Vf7Tt5Wh9XcndpbmeotuqOMLWPTjEKCsgojxXP2oxE1/xYe7PtnP76hsouG9vis6fctX+TxgmwxTuYi/+xc7dQ== + "@prisma/dmmf@6.16.3": version "6.16.3" resolved "https://registry.yarnpkg.com/@prisma/dmmf/-/dmmf-6.16.3.tgz#f5ee854466f6517b81e929f3fef5f031b67ad2cb" @@ -921,10 +926,10 @@ dependencies: "@prisma/debug" "6.16.3" -"@prisma/engines-version@6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a": - version "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" - resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a.tgz#695d03994f428ea2d7a9658b4bb84d57e8ef499d" - integrity sha512-fftRmosBex48Ph1v2ll1FrPpirwtPZpNkE5CDCY1Lw2SD2ctyrLlVlHiuxDAAlALwWBOkPbAll4+EaqdGuMhJw== +"@prisma/engines-version@6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac": + version "6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac" + resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac.tgz#18a7f842cdb5ef57b1c5ffc74d177df1e0be3212" + integrity sha512-17140E3huOuD9lMdJ9+SF/juOf3WR3sTJMVyyenzqUPbuH+89nPhSWcrY+Mf7tmSs6HvaO+7S+HkELinn6bhdg== "@prisma/engines@4.16.2": version "4.16.2" @@ -936,15 +941,15 @@ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.0.0.tgz#5249650eabe77c458c90f2be97d8210353c2e22e" integrity sha512-kyT/8fd0OpWmhAU5YnY7eP31brW1q1YrTGoblWrhQJDiN/1K+Z8S1kylcmtjqx5wsUGcP1HBWutayA/jtyt+sg== -"@prisma/engines@6.16.3": - version "6.16.3" - resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.16.3.tgz#6ae2082961692ace7ec7e4b744abf6f47076520f" - integrity sha512-b+Rl4nzQDcoqe6RIpSHv8f5lLnwdDGvXhHjGDiokObguAAv/O1KaX1Oc69mBW/GFWKQpCkOraobLjU6s1h8HGg== +"@prisma/engines@6.17.1": + version "6.17.1" + resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-6.17.1.tgz#65b6f87773390505af3aa782891ae07a82e95d9c" + integrity sha512-D95Ik3GYZkqZ8lSR4EyFOJ/tR33FcYRP8kK61o+WMsyD10UfJwd7+YielflHfKwiGodcqKqoraWw8ElAgMDbPw== dependencies: - "@prisma/debug" "6.16.3" - "@prisma/engines-version" "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" - "@prisma/fetch-engine" "6.16.3" - "@prisma/get-platform" "6.16.3" + "@prisma/debug" "6.17.1" + "@prisma/engines-version" "6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac" + "@prisma/fetch-engine" "6.17.1" + "@prisma/get-platform" "6.17.1" "@prisma/fetch-engine@4.16.2": version "4.16.2" @@ -992,14 +997,14 @@ temp-dir "2.0.0" tempy "1.0.1" -"@prisma/fetch-engine@6.16.3": - version "6.16.3" - resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.16.3.tgz#72d26421d4793bb6d99218b7e9d571cd6bcb1d3a" - integrity sha512-bUoRIkVaI+CCaVGrSfcKev0/Mk4ateubqWqGZvQ9uCqFv2ENwWIR3OeNuGin96nZn5+SkebcD7RGgKr/+mJelw== +"@prisma/fetch-engine@6.17.1": + version "6.17.1" + resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-6.17.1.tgz#e2c77ab58aee077c3eb8e86f63ff98068d173b69" + integrity sha512-AYZiHOs184qkDMiTeshyJCtyL4yERkjfTkJiSJdYuSfc24m94lTNL5+GFinZ6vVz+ktX4NJzHKn1zIFzGTWrWg== dependencies: - "@prisma/debug" "6.16.3" - "@prisma/engines-version" "6.16.1-1.bb420e667c1820a8c05a38023385f6cc7ef8e83a" - "@prisma/get-platform" "6.16.3" + "@prisma/debug" "6.17.1" + "@prisma/engines-version" "6.17.1-1.272a37d34178c2894197e17273bf937f25acdeac" + "@prisma/get-platform" "6.17.1" "@prisma/generator-helper@4.16.2", "@prisma/generator-helper@^4.14.0": version "4.16.2" @@ -1067,12 +1072,12 @@ terminal-link "2.1.1" ts-pattern "4.3.0" -"@prisma/get-platform@6.16.3": - version "6.16.3" - resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.16.3.tgz#54704555f1eb652a7dd893c816307f016dba4d18" - integrity sha512-X1LxiFXinJ4iQehrodGp0f66Dv6cDL0GbRlcCoLtSu6f4Wi+hgo7eND/afIs5029GQLgNWKZ46vn8hjyXTsHLA== +"@prisma/get-platform@6.17.1": + version "6.17.1" + resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-6.17.1.tgz#376669bfa67adf78eb0d3bdc1b9fe921af32ea19" + integrity sha512-AKEn6fsfz0r482S5KRDFlIGEaq9wLNcgalD1adL+fPcFFblIKs1sD81kY/utrHdqKuVC6E1XSRpegDK3ZLL4Qg== dependencies: - "@prisma/debug" "6.16.3" + "@prisma/debug" "6.17.1" "@prisma/instrumentation@6.15.0": version "6.15.0" @@ -5903,13 +5908,13 @@ prisma-erd-generator@^2.1.0: "@prisma/generator-helper" "^6.15.0" dotenv "^16.6.1" -prisma@^6.16.2: - version "6.16.3" - resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.16.3.tgz#33a7934bfdfdb191dbf91042c5d510de490b3dc8" - integrity sha512-4tJq3KB9WRshH5+QmzOLV54YMkNlKOtLKaSdvraI5kC/axF47HuOw6zDM8xrxJ6s9o2WodY654On4XKkrobQdQ== +prisma@^6.17.1: + version "6.17.1" + resolved "https://registry.yarnpkg.com/prisma/-/prisma-6.17.1.tgz#e3ed9373f84ddde708718053e73c8e18c2110197" + integrity sha512-ac6h0sM1Tg3zu8NInY+qhP/S9KhENVaw9n1BrGKQVFu05JT5yT5Qqqmb8tMRIE3ZXvVj4xcRA5yfrsy4X7Yy5g== dependencies: - "@prisma/config" "6.16.3" - "@prisma/engines" "6.16.3" + "@prisma/config" "6.17.1" + "@prisma/engines" "6.17.1" prismjs@^1.29.0: version "1.30.0" From ddfd15f9e2469dae3f03885b37b1d27fcbde3905 Mon Sep 17 00:00:00 2001 From: bh0fer Date: Tue, 14 Oct 2025 11:02:01 +0000 Subject: [PATCH 89/89] update workflow --- .github/workflows/prettier-check.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prettier-check.yml b/.github/workflows/prettier-check.yml index 49067bc..412e236 100644 --- a/.github/workflows/prettier-check.yml +++ b/.github/workflows/prettier-check.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@v4 with: - node-version: '>=22.11' + node-version: '>=22.15' - name: Install dependencies run: yarn install