From 2ef478e4b1367685f0d5d853e9c5f1d6ebe963e2 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:04:40 +0000 Subject: [PATCH 01/10] feat(#65): Add winston and axiom logging --- package.json | 4 +- pnpm-lock.yaml | 207 +++++++++++++++++++++++++++++++++ src/lib/utils/logger/logger.ts | 40 +++++++ 3 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 src/lib/utils/logger/logger.ts diff --git a/package.json b/package.json index 6dd387c..d706928 100644 --- a/package.json +++ b/package.json @@ -47,10 +47,12 @@ }, "type": "module", "dependencies": { + "@axiomhq/winston": "^1.2.0", "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.44.2", "stripe": "^15.4.0", - "ts-debounce": "^4.0.0" + "ts-debounce": "^4.0.0", + "winston": "^3.15.0" }, "engines": { "node": ">=18.13.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 437f249..a4ac133 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,6 +8,9 @@ importers: .: dependencies: + '@axiomhq/winston': + specifier: ^1.2.0 + version: 1.2.0 '@supabase/ssr': specifier: ^0.4.0 version: 0.4.1(@supabase/supabase-js@2.45.4) @@ -20,6 +23,9 @@ importers: ts-debounce: specifier: ^4.0.0 version: 4.0.0 + winston: + specifier: ^3.15.0 + version: 3.15.0 devDependencies: '@sveltejs/adapter-auto': specifier: ^3.0.0 @@ -134,6 +140,14 @@ packages: peerDependencies: ajv: '>=8' + '@axiomhq/js@1.2.0': + resolution: {integrity: sha512-ALvNo8YeDwE7EHWr9TGijdfo/gbmgTB5XHHBcIcu6Ra+A9+2ltBO5UvTzvSSGPaxn4neEyh+8ESzEBJVEjNAnA==} + engines: {node: '>=16'} + + '@axiomhq/winston@1.2.0': + resolution: {integrity: sha512-PE3dy49MZj9lrgTLcADu9iw8xeLxIA6Vcdc35JwgDDKDpvxy68+rz7LKWvhtnNi5T5Xpc5QMVjO3OGGDD35HrQ==} + engines: {node: '>=16'} + '@babel/code-frame@7.24.7': resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} engines: {node: '>=6.9.0'} @@ -709,6 +723,13 @@ packages: '@canvas/image-data@1.0.0': resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} @@ -1187,6 +1208,9 @@ packages: '@types/resolve@1.20.2': resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -1270,6 +1294,10 @@ packages: '@vite-pwa/assets-generator': optional: true + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -1436,6 +1464,9 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + builtin-modules@3.3.0: resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} engines: {node: '>=6'} @@ -1505,6 +1536,9 @@ packages: color-string@1.9.1: resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -1512,6 +1546,9 @@ packages: colorette@2.0.20: resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + commander@12.1.0: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} @@ -1683,6 +1720,9 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -1801,6 +1841,14 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -1838,10 +1886,16 @@ packages: picomatch: optional: true + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + fetch-blob@3.2.0: resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} engines: {node: ^12.20 || >= 14.13} + fetch-retry@6.0.0: + resolution: {integrity: sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -1864,6 +1918,9 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -2229,6 +2286,9 @@ packages: kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} @@ -2273,6 +2333,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.6.1: + resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} + engines: {node: '>= 12.0.0'} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -2420,6 +2484,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2606,6 +2673,10 @@ packages: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} + process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + pump@3.0.2: resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} @@ -2648,6 +2719,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2735,6 +2810,10 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + sander@0.5.1: resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} @@ -2827,6 +2906,9 @@ packages: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} deprecated: Please use @jridgewell/sourcemap-codec instead + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + streamx@2.20.1: resolution: {integrity: sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==} @@ -3010,6 +3092,9 @@ packages: text-decoder@1.2.0: resolution: {integrity: sha512-n1yg1mOj9DNpk3NeZOx7T6jchTbyJS3i3cucbNN6FcdPriMZx7NsgrGpWWdWZZGxD7ES1XB+3uoqHMgOKaN+fg==} + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -3048,6 +3133,10 @@ packages: tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -3148,6 +3237,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + vite-plugin-pwa@0.20.5: resolution: {integrity: sha512-aweuI/6G6n4C5Inn0vwHumElU/UEpNuO+9iZzwPZGTCH87TeZ6YFMrEY6ZUBQdIHHlhTsbMDryFARcSuOdsz9Q==} engines: {node: '>=16.0.0'} @@ -3233,6 +3326,14 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-transport@4.8.0: + resolution: {integrity: sha512-qxSTKswC6llEMZKgCQdaWgDuMJQnhuvF5f2Nk3SNXc4byfQ+voo2mX1Px9dkNOuR8p0KAjfPG29PuYUSIb+vSA==} + engines: {node: '>= 12.0.0'} + + winston@3.15.0: + resolution: {integrity: sha512-RhruH2Cj0bV0WgNL+lOfoUBI4DVfdUNjVnJGVovWZmrcKtrFTTRzgXYK2O9cymSGjrERCtaAeHwMNnUWXlwZow==} + engines: {node: '>= 12.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -3351,6 +3452,16 @@ snapshots: jsonpointer: 5.0.1 leven: 3.1.0 + '@axiomhq/js@1.2.0': + dependencies: + fetch-retry: 6.0.0 + uuid: 8.3.2 + + '@axiomhq/winston@1.2.0': + dependencies: + '@axiomhq/js': 1.2.0 + winston-transport: 4.8.0 + '@babel/code-frame@7.24.7': dependencies: '@babel/highlight': 7.24.7 @@ -4114,6 +4225,14 @@ snapshots: '@canvas/image-data@1.0.0': {} + '@colors/colors@1.6.0': {} + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@esbuild/aix-ppc64@0.21.5': optional: true @@ -4562,6 +4681,8 @@ snapshots: '@types/resolve@1.20.2': {} + '@types/triple-beam@1.3.5': {} + '@types/trusted-types@2.0.7': {} '@types/ws@8.5.12': @@ -4668,6 +4789,10 @@ snapshots: optionalDependencies: '@vite-pwa/assets-generator': 0.2.6 + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: acorn: 8.12.1 @@ -4857,6 +4982,11 @@ snapshots: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + builtin-modules@3.3.0: {} cac@6.7.14: {} @@ -4931,6 +5061,11 @@ snapshots: color-name: 1.1.4 simple-swizzle: 0.2.2 + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + color@4.2.3: dependencies: color-convert: 2.0.1 @@ -4938,6 +5073,11 @@ snapshots: colorette@2.0.20: {} + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + commander@12.1.0: {} commander@2.20.3: {} @@ -5086,6 +5226,8 @@ snapshots: emoji-regex@9.2.2: {} + enabled@2.0.0: {} + end-of-stream@1.4.4: dependencies: once: 1.4.0 @@ -5303,6 +5445,10 @@ snapshots: esutils@2.0.3: {} + event-target-shim@5.0.1: {} + + events@3.3.0: {} + expand-template@2.0.3: {} fast-deep-equal@3.1.3: {} @@ -5333,11 +5479,15 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fecha@4.2.3: {} + fetch-blob@3.2.0: dependencies: node-domexception: 1.0.0 web-streams-polyfill: 3.3.3 + fetch-retry@6.0.0: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -5363,6 +5513,8 @@ snapshots: flatted@3.3.1: {} + fn.name@1.1.0: {} + for-each@0.3.3: dependencies: is-callable: 1.2.7 @@ -5706,6 +5858,8 @@ snapshots: kolorist@1.8.0: {} + kuler@2.0.0: {} + leven@3.1.0: {} levn@0.4.1: @@ -5737,6 +5891,15 @@ snapshots: lodash@4.17.21: {} + logform@2.6.1: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -5854,6 +6017,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -6012,6 +6179,8 @@ snapshots: pretty-bytes@6.1.1: {} + process@0.11.10: {} + pump@3.0.2: dependencies: end-of-stream: 1.4.4 @@ -6062,6 +6231,14 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readable-stream@4.5.2: + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -6171,6 +6348,8 @@ snapshots: es-errors: 1.3.0 is-regex: 1.1.4 + safe-stable-stringify@2.5.0: {} + sander@0.5.1: dependencies: es6-promise: 3.3.1 @@ -6280,6 +6459,8 @@ snapshots: sourcemap-codec@1.4.8: {} + stack-trace@0.0.10: {} + streamx@2.20.1: dependencies: fast-fifo: 1.3.2 @@ -6546,6 +6727,8 @@ snapshots: dependencies: b4a: 1.6.6 + text-hex@1.0.0: {} + text-table@0.2.0: {} thenify-all@1.6.0: @@ -6582,6 +6765,8 @@ snapshots: dependencies: punycode: 2.3.1 + triple-beam@1.4.1: {} + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: typescript: 5.6.2 @@ -6684,6 +6869,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@8.3.2: {} + vite-plugin-pwa@0.20.5(@vite-pwa/assets-generator@0.2.6)(vite@5.4.6(@types/node@22.5.5)(terser@5.33.0))(workbox-build@7.1.1)(workbox-window@7.1.0): dependencies: debug: 4.3.7 @@ -6758,6 +6945,26 @@ snapshots: dependencies: isexe: 2.0.0 + winston-transport@4.8.0: + dependencies: + logform: 2.6.1 + readable-stream: 4.5.2 + triple-beam: 1.4.1 + + winston@3.15.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.6.1 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.8.0 + word-wrap@1.2.5: {} workbox-background-sync@7.1.0: diff --git a/src/lib/utils/logger/logger.ts b/src/lib/utils/logger/logger.ts new file mode 100644 index 0000000..dcc7d34 --- /dev/null +++ b/src/lib/utils/logger/logger.ts @@ -0,0 +1,40 @@ +import { createLogger, transports, format } from 'winston'; +import { WinstonTransport as AxiomTransport } from '@axiomhq/winston'; +import { VITE_AXIOM_DATASET, VITE_AXIOM_TOKEN } from '$env/static/private'; + +const axiomTransport = new AxiomTransport({ + dataset: VITE_AXIOM_DATASET, + token: VITE_AXIOM_TOKEN +}); + +const logger = createLogger({ + level: 'info', + defaultMeta: { service: 'example-site' }, // Change this so you can identify your website if you have multiple logging into Axiom + format: format.combine( + format.errors({ stack: true }), // Captures error stack traces + format.timestamp(), + format.json() // Formats logs as JSON for structured logging + ), + transports: [ + new transports.Console({ + format: format.combine( + format.colorize(), + format.printf(({ timestamp, level, message, stack }) => { + // Stack traces will be included in error messages automatically + return `${timestamp} [${level.toUpperCase()}]: ${message}${stack ? `\n${stack}` : ''}`; + }) + ) + }), + axiomTransport + ], + exceptionHandlers: [axiomTransport], // Logs uncaught exceptions + rejectionHandlers: [axiomTransport] // Logs unhandled promise rejections +}); + +// Uncomment this for testing your initial logging setup +logger.log({ + level: 'info', + message: 'Logger successfully setup' +}); + +export default logger; From 3d89222eecbf9542da335db1209f3aa868ea89d3 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:06:12 +0000 Subject: [PATCH 02/10] feat(#65): Replace existing console logs --- src/lib/utils/supabase/admin.ts | 25 +++++++++++---------- src/routes/account/+page.server.ts | 16 ++++++++----- src/routes/api/checkout/+server.ts | 3 ++- src/routes/api/subscribe/+server.ts | 3 ++- src/routes/api/webhook/stripe/+server.ts | 5 +++-- src/routes/checkout/success/+page.server.ts | 5 +++-- src/routes/products/+server.ts | 3 ++- 7 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/lib/utils/supabase/admin.ts b/src/lib/utils/supabase/admin.ts index 4052695..b2d2f03 100644 --- a/src/lib/utils/supabase/admin.ts +++ b/src/lib/utils/supabase/admin.ts @@ -4,6 +4,7 @@ import type { Database, Tables, TablesInsert } from '$lib/types/supabase'; import { PUBLIC_SUPABASE_URL } from '$env/static/public'; import { SUPABASE_SERVICE_ROLE_KEY } from '$env/static/private'; import { stripe as stripeClient } from '$lib/utils/stripe'; +import logger from '$lib/utils/logger/logger'; const toDateTime = (secs: number) => { const t = new Date(+0); // Unix epoch start. @@ -39,7 +40,7 @@ const upsertProductRecord = async (product: stripe.Product) => { const { error: upsertError } = await supabaseAdmin.from('products').upsert([productData]); if (upsertError) throw new Error(`Product insert/update failed: ${upsertError.message}`); - console.log(`Product inserted/updated: ${product.id}`); + logger.info(`Product inserted/updated: ${product.id}`); }; const upsertPriceRecord = async (price: stripe.Price, retryCount = 0, maxRetries = 3) => { @@ -61,7 +62,7 @@ const upsertPriceRecord = async (price: stripe.Price, retryCount = 0, maxRetries if (upsertError?.message.includes('foreign key constraint')) { if (retryCount < maxRetries) { - console.log(`Retry attempt ${retryCount + 1} for price ID: ${price.id}`); + logger.info(`Retry attempt ${retryCount + 1} for price ID: ${price.id}`); await new Promise((resolve) => setTimeout(resolve, 2000)); await upsertPriceRecord(price, retryCount + 1, maxRetries); } else { @@ -72,7 +73,7 @@ const upsertPriceRecord = async (price: stripe.Price, retryCount = 0, maxRetries } else if (upsertError) { throw new Error(`Price insert/update failed: ${upsertError.message}`); } else { - console.log(`Price inserted/updated: ${price.id}`); + logger.info(`Price inserted/updated: ${price.id}`); } }; @@ -82,13 +83,13 @@ const deleteProductRecord = async (product: stripe.Product) => { .delete() .eq('id', product.id); if (deletionError) throw new Error(`Product deletion failed: ${deletionError.message}`); - console.log(`Product deleted: ${product.id}`); + logger.info(`Product deleted: ${product.id}`); }; const deletePriceRecord = async (price: stripe.Price) => { const { error: deletionError } = await supabaseAdmin.from('prices').delete().eq('id', price.id); if (deletionError) throw new Error(`Price deletion failed: ${deletionError.message}`); - console.log(`Price deleted: ${price.id}`); + logger.info(`Price deleted: ${price.id}`); }; const upsertCustomerToSupabase = async (uuid: string, customerId: string) => { @@ -258,7 +259,7 @@ const manageSubscriptionStatusChange = async ( .from('subscriptions') .upsert([subscriptionData]); if (upsertError) throw new Error(`Subscription insert/update failed: ${upsertError.message}`); - console.log(`Inserted/updated subscription [${subscription.id}] for user [${uuid}]`); + logger.info(`Inserted/updated subscription [${subscription.id}] for user [${uuid}]`); // // For a new subscription copy the billing details to the customer object. // // NOTE: This is a costly operation and should happen at the very end. @@ -271,7 +272,7 @@ const manageSubscriptionStatusChange = async ( }; const recordProductPurchase = async (userId: string, productId: string, priceId: string) => { - console.log( + logger.info( `Recording product purchase for user [${userId}] and product [${productId}] with price [${priceId}]` ); @@ -284,10 +285,10 @@ const recordProductPurchase = async (userId: string, productId: string, priceId: throw new Error(`Failed to record product purchase: ${error.message}`); } } catch (error) { - console.error(error); + logger.error(error); } - console.log(`Product purchased recorded for user [${userId}] and product [${productId}]`); + logger.info(`Product purchased recorded for user [${userId}] and product [${productId}]`); }; const hasProductAccess = async (userId: string, productId: string) => { @@ -381,7 +382,7 @@ const updateUserCredits = async (userId: string, creditsChange: number, descript await logCreditTransaction(userId, creditsChange, description); - console.log( + logger.info( `${creditsChange > 0 ? 'Added' : 'Deducted'} ${Math.abs(creditsChange)} credits to user [${userId}]` ); }; @@ -390,7 +391,7 @@ const addCredits = async (userId: string, creditsToAdd: number, description: str try { await updateUserCredits(userId, creditsToAdd, description); } catch (error) { - console.error(error); + logger.error(error); } }; @@ -398,7 +399,7 @@ const deductCredits = async (userId: string, creditsToDeduct: number, descriptio try { await updateUserCredits(userId, -creditsToDeduct, description); } catch (error) { - console.error(error); + logger.error(error); } }; diff --git a/src/routes/account/+page.server.ts b/src/routes/account/+page.server.ts index d839775..6ae0f5e 100644 --- a/src/routes/account/+page.server.ts +++ b/src/routes/account/+page.server.ts @@ -1,5 +1,6 @@ import { fail, redirect } from '@sveltejs/kit'; import type { Actions, PageServerLoad } from './$types'; +import logger from '$lib/utils/logger/logger'; export const load: PageServerLoad = async ({ locals: { supabase, safeGetSession } }) => { const { session } = await safeGetSession(); @@ -27,20 +28,23 @@ export const actions: Actions = { if (!session) { return fail(401, { name }); } - const { error } = await supabase.from('users').update({ - name: name, - }).eq('id', session?.user.id); + const { error } = await supabase + .from('users') + .update({ + name: name + }) + .eq('id', session?.user.id); - console.error(error); + logger.error(error); if (error) { return fail(500, { - name, + name }); } return { - name, + name }; }, signout: async ({ locals: { supabase, safeGetSession } }) => { diff --git a/src/routes/api/checkout/+server.ts b/src/routes/api/checkout/+server.ts index 05d3272..884ab64 100644 --- a/src/routes/api/checkout/+server.ts +++ b/src/routes/api/checkout/+server.ts @@ -2,6 +2,7 @@ import { type RequestHandler, redirect } from '@sveltejs/kit'; import { stripe as stripeClient } from '$lib/utils/stripe'; import { getStripeCustomerId } from '$lib/utils/supabase/admin'; import type Stripe from 'stripe'; +import logger from '$lib/utils/logger/logger'; // Create a checkout session export const POST: RequestHandler = async ({ request, cookies, locals: { safeGetSession } }) => { @@ -34,7 +35,7 @@ export const POST: RequestHandler = async ({ request, cookies, locals: { safeGet try { stripeCustomerId = await getStripeCustomerId(userEmail!, userId); } catch (error) { - console.error('Error fetching Stripe customer ID:', error); + logger.error('Error fetching Stripe customer ID:', error); } const stripeCheckoutSessionObject = { diff --git a/src/routes/api/subscribe/+server.ts b/src/routes/api/subscribe/+server.ts index bcd7168..5c1df56 100644 --- a/src/routes/api/subscribe/+server.ts +++ b/src/routes/api/subscribe/+server.ts @@ -2,6 +2,7 @@ import { type RequestHandler, redirect } from '@sveltejs/kit'; import { stripe as stripeClient } from '$lib/utils/stripe'; import { getStripeCustomerId } from '$lib/utils/supabase/admin'; import type Stripe from 'stripe'; +import logger from '$lib/utils/logger/logger'; // Create a subscription checkout session export const POST: RequestHandler = async ({ request, cookies, locals: { safeGetSession } }) => { @@ -29,7 +30,7 @@ export const POST: RequestHandler = async ({ request, cookies, locals: { safeGet try { stripeCustomerId = await getStripeCustomerId(userEmail!, userId); } catch (error) { - console.error('Error fetching Stripe customer ID:', error); + logger.error('Error fetching Stripe customer ID:', error); } const stripeCheckoutSessionObject = { diff --git a/src/routes/api/webhook/stripe/+server.ts b/src/routes/api/webhook/stripe/+server.ts index b05992d..7291df1 100644 --- a/src/routes/api/webhook/stripe/+server.ts +++ b/src/routes/api/webhook/stripe/+server.ts @@ -10,6 +10,7 @@ import { recordProductPurchase } from '$lib/utils/supabase/admin'; import { stripe as stripeClient } from '$lib/utils/stripe'; +import logger from '$lib/utils/logger/logger'; export const POST: RequestHandler = async ({ request }) => { const body = await request.text(); @@ -26,7 +27,7 @@ export const POST: RequestHandler = async ({ request }) => { try { event = stripeClient.webhooks.constructEvent(body, signature, STRIPE_ENDPOINT_SECRET); } catch (err) { - console.error(`⚠️ Webhook signature verification failed.`, err.message); + logger.error(`⚠️ Webhook signature verification failed.`, err.message); return { status: 400, body: {} @@ -104,7 +105,7 @@ export const POST: RequestHandler = async ({ request }) => { break; } default: - console.log(`Unhandled event type ${event.type}`); + logger.info(`Unhandled event type ${event.type}`); } } catch (err) { const message = err instanceof Error ? err.message : 'An unknown error has occurred'; diff --git a/src/routes/checkout/success/+page.server.ts b/src/routes/checkout/success/+page.server.ts index b29cba2..11500c1 100644 --- a/src/routes/checkout/success/+page.server.ts +++ b/src/routes/checkout/success/+page.server.ts @@ -1,13 +1,14 @@ import { redirect } from '@sveltejs/kit'; import Stripe from 'stripe'; import { getProductById, upsertCustomerToSupabase } from '$lib/utils/supabase/admin'; +import logger from '$lib/utils/logger/logger'; export const load = async ({ fetch, locals: { safeGetSession } }) => { const { session } = await safeGetSession(); const response = await fetch('/api/checkout/status'); if (!response.ok) { - console.error('Failed to fetch checkout status'); + logger.error('Failed to fetch checkout status'); return; } @@ -30,7 +31,7 @@ export const load = async ({ fetch, locals: { safeGetSession } }) => { const stripeCustomerId = checkoutSession.customer as string; await upsertCustomerToSupabase(session.user.id, stripeCustomerId); } else { - console.error('User ID is undefined'); + logger.error('User ID is undefined'); } return { diff --git a/src/routes/products/+server.ts b/src/routes/products/+server.ts index f3e2530..4b2168b 100644 --- a/src/routes/products/+server.ts +++ b/src/routes/products/+server.ts @@ -1,5 +1,6 @@ import { json } from '@sveltejs/kit'; import { getActiveProductsWithPrices } from '$lib/utils/supabase/admin'; +import logger from '$lib/utils/logger/logger'; export const GET = async ({ url }) => { try { @@ -13,7 +14,7 @@ export const GET = async ({ url }) => { return json({ products, count }); } catch (error) { - console.error(error); + logger.error(error); return json({ error: error.message }, { status: 500 }); } }; From ddac66e3a932112ebdd4bd96d974de5a50d1792f Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:06:20 +0000 Subject: [PATCH 03/10] feat(#65): Update example env --- .env.example | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.example b/.env.example index 6d0104e..c7e4a6b 100644 --- a/.env.example +++ b/.env.example @@ -3,4 +3,6 @@ PUBLIC_SUPABASE_ANON_KEY="" SUPABASE_SERVICE_ROLE_KEY="" STRIPE_SECRET_KEY="" STRIPE_ENDPOINT_SECRET="" -VITE_PRODUCT_ID_EXAMPLEPRODUCT="" \ No newline at end of file +VITE_PRODUCT_ID_EXAMPLEPRODUCT="" +VITE_AXIOM_DATASET="" +VITE_AXIOM_TOKEN="" \ No newline at end of file From 9253926c7d4b16d4458c77af5f049d554915e627 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:06:28 +0000 Subject: [PATCH 04/10] chore(*): Remove unused components --- src/lib/components/SignIn.svelte | 126 ------------------------------- src/lib/components/SignUp.svelte | 68 ----------------- 2 files changed, 194 deletions(-) delete mode 100644 src/lib/components/SignIn.svelte delete mode 100644 src/lib/components/SignUp.svelte diff --git a/src/lib/components/SignIn.svelte b/src/lib/components/SignIn.svelte deleted file mode 100644 index 8ad7d36..0000000 --- a/src/lib/components/SignIn.svelte +++ /dev/null @@ -1,126 +0,0 @@ - - -
-
-
- -
-
- -
-
- -
-
- -
-
-
diff --git a/src/lib/components/SignUp.svelte b/src/lib/components/SignUp.svelte deleted file mode 100644 index dbb92f1..0000000 --- a/src/lib/components/SignUp.svelte +++ /dev/null @@ -1,68 +0,0 @@ - - -
-
- -
-
- -
-
- -
-
From fe1f49090cf738a85ec38bc6d5f083dcd4924fd6 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:08:20 +0000 Subject: [PATCH 05/10] chore(#65): Comment out test code --- src/lib/utils/logger/logger.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/utils/logger/logger.ts b/src/lib/utils/logger/logger.ts index dcc7d34..b56c756 100644 --- a/src/lib/utils/logger/logger.ts +++ b/src/lib/utils/logger/logger.ts @@ -32,9 +32,9 @@ const logger = createLogger({ }); // Uncomment this for testing your initial logging setup -logger.log({ - level: 'info', - message: 'Logger successfully setup' -}); +// logger.log({ +// level: 'info', +// message: 'Logger successfully setup' +// }); export default logger; From 8a251f775a8f2a9560573e0941eb15bf890aa373 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:10:18 +0000 Subject: [PATCH 06/10] refactor(#65): Enhance error logging with request context --- src/routes/products/+server.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/routes/products/+server.ts b/src/routes/products/+server.ts index 4b2168b..a60e5f6 100644 --- a/src/routes/products/+server.ts +++ b/src/routes/products/+server.ts @@ -14,7 +14,14 @@ export const GET = async ({ url }) => { return json({ products, count }); } catch (error) { - logger.error(error); + logger.error('Failed to fetch products', { + error: error.message, + stack: error.stack, + params: { + limit: limitParam, + offset: offsetParam + } + }); return json({ error: error.message }, { status: 500 }); } }; From 86ced6e7f9c1da295f4682620afee1a54eb9766e Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:12:27 +0000 Subject: [PATCH 07/10] refactor(#65): Enhance error logging with context --- src/routes/account/+page.server.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/routes/account/+page.server.ts b/src/routes/account/+page.server.ts index 6ae0f5e..fe47e93 100644 --- a/src/routes/account/+page.server.ts +++ b/src/routes/account/+page.server.ts @@ -35,7 +35,12 @@ export const actions: Actions = { }) .eq('id', session?.user.id); - logger.error(error); + if (error) { + logger.error('Failed to update user name', { + userId: session?.user.id, + error + }); + } if (error) { return fail(500, { From d329989230504cd221a4b70d0aac31c3e3757b7a Mon Sep 17 00:00:00 2001 From: OllyNicholass Date: Tue, 5 Nov 2024 21:44:48 +0000 Subject: [PATCH 08/10] refactor(#65): move scope of logged params Type defs added where relevent --- src/routes/products/+server.ts | 36 ++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/src/routes/products/+server.ts b/src/routes/products/+server.ts index a60e5f6..02fe9d3 100644 --- a/src/routes/products/+server.ts +++ b/src/routes/products/+server.ts @@ -3,25 +3,35 @@ import { getActiveProductsWithPrices } from '$lib/utils/supabase/admin'; import logger from '$lib/utils/logger/logger'; export const GET = async ({ url }) => { + const limitParam = url.searchParams.get('limit'); + const offsetParam = url.searchParams.get('offset'); try { - const limitParam = url.searchParams.get('limit'); - const offsetParam = url.searchParams.get('offset'); - const limit = limitParam ? parseInt(limitParam, 10) : 10; const offset = offsetParam ? parseInt(offsetParam, 10) : 0; const { products, count } = await getActiveProductsWithPrices(limit, offset); return json({ products, count }); - } catch (error) { - logger.error('Failed to fetch products', { - error: error.message, - stack: error.stack, - params: { - limit: limitParam, - offset: offsetParam - } - }); - return json({ error: error.message }, { status: 500 }); + } catch (error: unknown) { + if (error instanceof Error) { + logger.error('Failed to fetch products', { + error: error.message, + stack: error.stack, + params: { + limit: limitParam, + offset: offsetParam + } + }); + return json({ error: error.message }, { status: 500 }); + } else { + logger.error('Failed to fetch products', { + error, + params: { + limit: limitParam, + offset: offsetParam + } + }); + return json({ error }, { status: 500 }); + } } }; From 3cd3200d1e4979ee0be34c89bfc3b9c69a3157c2 Mon Sep 17 00:00:00 2001 From: OllyNicholass Date: Tue, 5 Nov 2024 22:06:36 +0000 Subject: [PATCH 09/10] refactor(#65): add additional error handling & logs --- src/lib/utils/supabase/admin.ts | 65 ++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/lib/utils/supabase/admin.ts b/src/lib/utils/supabase/admin.ts index cc27934..b7eb4f8 100644 --- a/src/lib/utils/supabase/admin.ts +++ b/src/lib/utils/supabase/admin.ts @@ -255,10 +255,17 @@ const manageSubscriptionStatusChange = async ( trial_end: subscription.trial_end ? toDateTime(subscription.trial_end).toISOString() : null }; - const { error: upsertError } = await supabaseAdmin - .from('subscriptions') - .upsert([subscriptionData]); - if (upsertError) throw new Error(`Subscription insert/update failed: ${upsertError.message}`); + try { + const { error: upsertError } = await supabaseAdmin + .from('subscriptions') + .upsert([subscriptionData]); + if (upsertError) { + throw new Error(`Subscription insert/update failed: ${upsertError.message}`); + } + } catch (error) { + logger.error(error); + } + logger.info(`Inserted/updated subscription [${subscription.id}] for user [${uuid}]`); // // For a new subscription copy the billing details to the customer object. @@ -293,32 +300,40 @@ const recordProductPurchase = async (userId: string, productId: string, priceId: const hasProductAccess = async (userId: string, productId: string) => { // Check if user has purchased the product - const { data: purchases, error: purchaseError } = await supabaseAdmin - .from('purchases') - .select('*') - .eq('user_id', userId) - .eq('product_id', productId); + try { + const { data: purchases, error: purchaseError } = await supabaseAdmin + .from('purchases') + .select('*') + .eq('user_id', userId) + .eq('product_id', productId); - if (purchaseError) throw new Error(purchaseError.message); + if (purchaseError) throw new Error(purchaseError.message); - if (purchases && purchases.length > 0) { - // User has purchased the product - return true; + if (purchases && purchases.length > 0) { + // User has purchased the product + return true; + } + } catch (error) { + logger.error(error); } // Check if user has an active subscription for the product - const { data: subscriptions, error: subError } = await supabaseAdmin - .from('subscriptions') - .select('*') - .eq('user_id', userId) - .eq('product_id', productId) - .in('status', ['active', 'trialing']); + try { + const { data: subscriptions, error: subError } = await supabaseAdmin + .from('subscriptions') + .select('*') + .eq('user_id', userId) + .eq('product_id', productId) + .in('status', ['active', 'trialing']); - if (subError) throw new Error(subError.message); + if (subError) throw new Error(subError.message); - if (subscriptions && subscriptions.length > 0) { - // User has an active subscription - return true; + if (subscriptions && subscriptions.length > 0) { + // User has an active subscription + return true; + } + } catch (error) { + logger.error(error); } return false; @@ -490,7 +505,7 @@ const getUserSubscriptions = async (userId: string) => { .eq('user_id', userId); if (error) { - console.error('Error retrieving subscriptions:', error.message); + logger.error('Error retrieving subscriptions:', error.message); throw new Error('Failed to fetch subscriptions'); } @@ -521,7 +536,7 @@ const getUserSubscriptions = async (userId: string) => { return subscriptionDetails; } catch (error) { - console.error('An error occurred while retrieving subscription details:', error); + logger.error('An error occurred while retrieving subscription details:', error); throw new Error('Could not retrieve subscription details'); } }; From 57a800ef2c8d5fc7425337debf66d99109466430 Mon Sep 17 00:00:00 2001 From: OllyNicholass Date: Tue, 5 Nov 2024 22:13:20 +0000 Subject: [PATCH 10/10] refactor(#65): add types to products page params --- src/routes/products/+server.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/routes/products/+server.ts b/src/routes/products/+server.ts index 02fe9d3..d76aa1a 100644 --- a/src/routes/products/+server.ts +++ b/src/routes/products/+server.ts @@ -3,11 +3,11 @@ import { getActiveProductsWithPrices } from '$lib/utils/supabase/admin'; import logger from '$lib/utils/logger/logger'; export const GET = async ({ url }) => { - const limitParam = url.searchParams.get('limit'); - const offsetParam = url.searchParams.get('offset'); + const limitParam: string | null = url.searchParams.get('limit'); + const offsetParam: string | null = url.searchParams.get('offset'); try { - const limit = limitParam ? parseInt(limitParam, 10) : 10; - const offset = offsetParam ? parseInt(offsetParam, 10) : 0; + const limit = limitParam ? Number.parseInt(limitParam, 10) : 10; + const offset = offsetParam ? Number.parseInt(offsetParam, 10) : 0; const { products, count } = await getActiveProductsWithPrices(limit, offset);