We use cookies to ensure you get the best experience on our website. By continuing, you agree
- to our use of cookies.
+ to our use of cookies. For details, please see our Privacy Policy .
Accept
Date: Wed, 30 Oct 2024 21:04:40 +0000
Subject: [PATCH 04/19] 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 05/19] 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 06/19] 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 07/19] 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 08/19] 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 3189d8932b7235f49f86d8ffefd1188d72409f10 Mon Sep 17 00:00:00 2001
From: Josh Creek <8179928+jcreek@users.noreply.github.com>
Date: Fri, 1 Nov 2024 19:12:34 +0000
Subject: [PATCH 09/19] feat(#59): Add styling to account page
---
src/routes/account/+page.svelte | 159 +++++++++++++++++++++++++-------
1 file changed, 128 insertions(+), 31 deletions(-)
diff --git a/src/routes/account/+page.svelte b/src/routes/account/+page.svelte
index d133724..5435c0d 100644
--- a/src/routes/account/+page.svelte
+++ b/src/routes/account/+page.svelte
@@ -19,41 +19,138 @@
};
};
- const handleSignOut: SubmitFunction = () => {
- loading = true;
- return async ({ update }) => {
- loading = false;
- update();
- };
- };
+ const subscriptions = [
+ { name: 'Premium Plan', nextBillingDate: '12th August 2021' },
+ { name: 'Basic Plan', nextBillingDate: '12th August 2021' }
+ ];
+
+ const billingHistory = [
+ { id: 123, date: '12th August 2021', amount: 9.99, downloadLink: '#' },
+ { id: 122, date: '12th July 2021', amount: 9.99, downloadLink: '#' }
+ ];
-