mirror of
https://github.com/polaroi8d/cactoide.git
synced 2026-03-22 14:15:28 +00:00
Compare commits
15 Commits
feat/invit
...
fix/edit-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7692f9d503 | ||
|
|
baf3fcd923 | ||
|
|
5468bc7cb2 | ||
|
|
0afe331cab | ||
|
|
fa9a79192c | ||
|
|
7275084ab9 | ||
|
|
02975a0abd | ||
|
|
aebe477f90 | ||
|
|
325237d414 | ||
|
|
24e9d8b626 | ||
|
|
05556eefdb | ||
|
|
2273ae50a4 | ||
|
|
e75c7e40dc | ||
|
|
2a96d3762c | ||
|
|
935042dd06 |
2
.github/workflows/build-and-push.yml
vendored
2
.github/workflows/build-and-push.yml
vendored
@@ -62,6 +62,8 @@ jobs:
|
|||||||
file: ./Dockerfile
|
file: ./Dockerfile
|
||||||
build-args: |
|
build-args: |
|
||||||
PUBLIC_LANDING_INFO=${{ vars.PUBLIC_LANDING_INFO }}
|
PUBLIC_LANDING_INFO=${{ vars.PUBLIC_LANDING_INFO }}
|
||||||
|
LOG_PRETTY=${{ vars.LOG_PRETTY }}
|
||||||
|
LOG_LEVEL=${{ vars.LOG_LEVEL }}
|
||||||
push: true
|
push: true
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
cache-from: type=gha
|
cache-from: type=gha
|
||||||
|
|||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -30,6 +30,8 @@ jobs:
|
|||||||
run: npm run build
|
run: npm run build
|
||||||
env:
|
env:
|
||||||
PUBLIC_LANDING_INFO: ${{ vars.PUBLIC_LANDING_INFO }}
|
PUBLIC_LANDING_INFO: ${{ vars.PUBLIC_LANDING_INFO }}
|
||||||
|
LOG_PRETTY: ${{ vars.LOG_PRETTY }}
|
||||||
|
LOG_LEVEL: ${{ vars.LOG_LEVEL }}
|
||||||
|
|
||||||
- name: Test build output
|
- name: Test build output
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -7,6 +7,12 @@ RUN npm ci
|
|||||||
ARG PUBLIC_LANDING_INFO
|
ARG PUBLIC_LANDING_INFO
|
||||||
ENV PUBLIC_LANDING_INFO=$PUBLIC_LANDING_INFO
|
ENV PUBLIC_LANDING_INFO=$PUBLIC_LANDING_INFO
|
||||||
|
|
||||||
|
ARG LOG_PRETTY
|
||||||
|
ENV LOG_PRETTY=$LOG_PRETTY
|
||||||
|
|
||||||
|
ARG LOG_LEVEL
|
||||||
|
ENV LOG_LEVEL=$LOG_LEVEL
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|||||||
296
package-lock.json
generated
296
package-lock.json
generated
@@ -11,6 +11,8 @@
|
|||||||
"@sveltejs/adapter-node": "^5.3.1",
|
"@sveltejs/adapter-node": "^5.3.1",
|
||||||
"drizzle-orm": "^0.44.5",
|
"drizzle-orm": "^0.44.5",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
|
"pino": "^10.1.0",
|
||||||
|
"pino-pretty": "^13.1.2",
|
||||||
"postgres": "^3.4.7"
|
"postgres": "^3.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -22,7 +24,12 @@
|
|||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
|
<<<<<<< HEAD
|
||||||
"drizzle-kit": "^0.31.5",
|
"drizzle-kit": "^0.31.5",
|
||||||
|
=======
|
||||||
|
"@types/node": "^24.9.1",
|
||||||
|
"drizzle-kit": "^0.31.4",
|
||||||
|
>>>>>>> 222c2ee (feat: add pino logger for serverside)
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"eslint-plugin-svelte": "^3.0.0",
|
"eslint-plugin-svelte": "^3.0.0",
|
||||||
@@ -1231,6 +1238,12 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@pinojs/redact": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
|
||||||
|
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@polka/url": {
|
"node_modules/@polka/url": {
|
||||||
"version": "1.0.0-next.29",
|
"version": "1.0.0-next.29",
|
||||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
|
||||||
@@ -2095,6 +2108,20 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "24.9.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz",
|
||||||
|
"integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==",
|
||||||
|
"devOptional": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"undici-types": "~7.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
>>>>>>> 222c2ee (feat: add pino logger for serverside)
|
||||||
"node_modules/@types/resolve": {
|
"node_modules/@types/resolve": {
|
||||||
"version": "1.20.2",
|
"version": "1.20.2",
|
||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||||
@@ -2432,6 +2459,15 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/atomic-sleep": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/axobject-query": {
|
"node_modules/axobject-query": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
|
||||||
@@ -2561,6 +2597,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/colorette": {
|
||||||
|
"version": "2.0.20",
|
||||||
|
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||||
|
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/commondir": {
|
"node_modules/commondir": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
|
||||||
@@ -2611,6 +2653,15 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/dateformat": {
|
||||||
|
"version": "4.6.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
|
||||||
|
"integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
|
||||||
@@ -2801,6 +2852,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/end-of-stream": {
|
||||||
|
"version": "1.4.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||||
|
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"once": "^1.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/enhanced-resolve": {
|
"node_modules/enhanced-resolve": {
|
||||||
"version": "5.18.3",
|
"version": "5.18.3",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz",
|
||||||
@@ -3110,6 +3170,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-copy": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/fast-deep-equal": {
|
"node_modules/fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
@@ -3161,6 +3227,12 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-safe-stringify": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.19.1",
|
"version": "1.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
|
||||||
@@ -3359,6 +3431,12 @@
|
|||||||
"node": ">= 0.4"
|
"node": ">= 0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/help-me": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ignore": {
|
"node_modules/ignore": {
|
||||||
"version": "5.3.2",
|
"version": "5.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||||
@@ -3476,6 +3554,15 @@
|
|||||||
"jiti": "lib/jiti-cli.mjs"
|
"jiti": "lib/jiti-cli.mjs"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/joycon": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/js-yaml": {
|
"node_modules/js-yaml": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||||
@@ -3901,6 +3988,15 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/minimist": {
|
||||||
|
"version": "1.2.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
|
||||||
|
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/minipass": {
|
"node_modules/minipass": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
@@ -3989,6 +4085,24 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/on-exit-leak-free": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"wrappy": "1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/optionator": {
|
"node_modules/optionator": {
|
||||||
"version": "0.9.4",
|
"version": "0.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
|
||||||
@@ -4096,6 +4210,79 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pino": {
|
||||||
|
"version": "10.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino/-/pino-10.1.0.tgz",
|
||||||
|
"integrity": "sha512-0zZC2ygfdqvqK8zJIr1e+wT1T/L+LF6qvqvbzEQ6tiMAoTqEVK9a1K3YRu8HEUvGEvNqZyPJTtb2sNIoTkB83w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@pinojs/redact": "^0.4.0",
|
||||||
|
"atomic-sleep": "^1.0.0",
|
||||||
|
"on-exit-leak-free": "^2.1.0",
|
||||||
|
"pino-abstract-transport": "^2.0.0",
|
||||||
|
"pino-std-serializers": "^7.0.0",
|
||||||
|
"process-warning": "^5.0.0",
|
||||||
|
"quick-format-unescaped": "^4.0.3",
|
||||||
|
"real-require": "^0.2.0",
|
||||||
|
"safe-stable-stringify": "^2.3.1",
|
||||||
|
"sonic-boom": "^4.0.1",
|
||||||
|
"thread-stream": "^3.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"pino": "bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pino-abstract-transport": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"split2": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pino-pretty": {
|
||||||
|
"version": "13.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.2.tgz",
|
||||||
|
"integrity": "sha512-3cN0tCakkT4f3zo9RXDIhy6GTvtYD6bK4CRBLN9j3E/ePqN1tugAXD5rGVfoChW6s0hiek+eyYlLNqc/BG7vBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"colorette": "^2.0.7",
|
||||||
|
"dateformat": "^4.6.3",
|
||||||
|
"fast-copy": "^3.0.2",
|
||||||
|
"fast-safe-stringify": "^2.1.1",
|
||||||
|
"help-me": "^5.0.0",
|
||||||
|
"joycon": "^3.1.1",
|
||||||
|
"minimist": "^1.2.6",
|
||||||
|
"on-exit-leak-free": "^2.1.0",
|
||||||
|
"pino-abstract-transport": "^2.0.0",
|
||||||
|
"pump": "^3.0.0",
|
||||||
|
"secure-json-parse": "^4.0.0",
|
||||||
|
"sonic-boom": "^4.0.1",
|
||||||
|
"strip-json-comments": "^5.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"pino-pretty": "bin.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pino-pretty/node_modules/strip-json-comments": {
|
||||||
|
"version": "5.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz",
|
||||||
|
"integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pino-std-serializers": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
@@ -4373,6 +4560,32 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process-warning": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/pump": {
|
||||||
|
"version": "3.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||||
|
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"end-of-stream": "^1.1.0",
|
||||||
|
"once": "^1.3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
@@ -4404,6 +4617,12 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/quick-format-unescaped": {
|
||||||
|
"version": "4.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||||
|
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "4.1.2",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz",
|
||||||
@@ -4418,6 +4637,15 @@
|
|||||||
"url": "https://paulmillr.com/funding/"
|
"url": "https://paulmillr.com/funding/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/real-require": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/resolve": {
|
"node_modules/resolve": {
|
||||||
"version": "1.22.10",
|
"version": "1.22.10",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
|
||||||
@@ -4545,6 +4773,31 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/safe-stable-stringify": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/secure-json-parse": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fastify"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/fastify"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "BSD-3-Clause"
|
||||||
|
},
|
||||||
"node_modules/semver": {
|
"node_modules/semver": {
|
||||||
"version": "7.7.2",
|
"version": "7.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||||
@@ -4601,6 +4854,15 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sonic-boom": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"atomic-sleep": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/source-map": {
|
"node_modules/source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
@@ -4631,6 +4893,15 @@
|
|||||||
"source-map": "^0.6.0"
|
"source-map": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/split2": {
|
||||||
|
"version": "4.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
||||||
|
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strip-json-comments": {
|
"node_modules/strip-json-comments": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
|
||||||
@@ -4798,6 +5069,15 @@
|
|||||||
"node": ">=18"
|
"node": ">=18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/thread-stream": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"real-require": "^0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tinyglobby": {
|
"node_modules/tinyglobby": {
|
||||||
"version": "0.2.15",
|
"version": "0.2.15",
|
||||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||||
@@ -4902,11 +5182,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "7.10.0",
|
"version": "7.16.0",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
|
||||||
"integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==",
|
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
|
||||||
"license": "MIT",
|
"devOptional": true,
|
||||||
"optional": true
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/uri-js": {
|
"node_modules/uri-js": {
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
@@ -5045,6 +5325,12 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/yallist": {
|
"node_modules/yallist": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
|
||||||
|
|||||||
@@ -22,7 +22,8 @@
|
|||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.9",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.15",
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
"drizzle-kit": "^0.31.5",
|
"@types/node": "^24.9.1",
|
||||||
|
"drizzle-kit": "^0.31.4",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"eslint-plugin-svelte": "^3.0.0",
|
"eslint-plugin-svelte": "^3.0.0",
|
||||||
@@ -41,6 +42,8 @@
|
|||||||
"@sveltejs/adapter-node": "^5.3.1",
|
"@sveltejs/adapter-node": "^5.3.1",
|
||||||
"drizzle-orm": "^0.44.5",
|
"drizzle-orm": "^0.44.5",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
|
"pino": "^10.1.0",
|
||||||
|
"pino-pretty": "^13.1.2",
|
||||||
"postgres": "^3.4.7"
|
"postgres": "^3.4.7"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import type { Handle } from '@sveltejs/kit';
|
import type { Handle } from '@sveltejs/kit';
|
||||||
import { generateUserId } from '$lib/generateUserId.js';
|
import { generateUserId } from '$lib/generateUserId.js';
|
||||||
import { ensureDatabaseConnection } from '$lib/database/healthCheck';
|
import { ensureDatabaseConnection } from '$lib/database/healthCheck';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
// Global flag to track if database health check has been performed
|
// Global flag to track if database health check has been performed
|
||||||
let dbHealthCheckPerformed = false;
|
let dbHealthCheckPerformed = false;
|
||||||
@@ -18,7 +19,7 @@ export const handle: Handle = async ({ event, resolve }) => {
|
|||||||
});
|
});
|
||||||
dbHealthCheckPerformed = true;
|
dbHealthCheckPerformed = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Database health check failed:', error);
|
logger.error({ error }, 'Database health check failed');
|
||||||
// The ensureDatabaseConnection function will exit the process
|
// The ensureDatabaseConnection function will exit the process
|
||||||
// if the database is unavailable, so this catch is just for safety
|
// if the database is unavailable, so this catch is just for safety
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
@@ -33,11 +34,10 @@ export const handle: Handle = async ({ event, resolve }) => {
|
|||||||
const PATH = '/';
|
const PATH = '/';
|
||||||
|
|
||||||
if (!cactoideUserId) {
|
if (!cactoideUserId) {
|
||||||
console.debug(`There is no cactoideUserId cookie, generating new one...`);
|
logger.debug({ userId }, 'No cactoideUserId cookie found, generating new one');
|
||||||
event.cookies.set('cactoideUserId', userId, { path: PATH, maxAge: MAX_AGE });
|
event.cookies.set('cactoideUserId', userId, { path: PATH, maxAge: MAX_AGE });
|
||||||
} else {
|
} else {
|
||||||
console.debug(`cactoideUserId: ${cactoideUserId}`);
|
logger.debug({ cactoideUserId }, 'cactoideUserId cookie found, using existing one');
|
||||||
console.debug(`cactoideUserId cookie found, using existing one...`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(event);
|
return resolve(event);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import postgres from 'postgres';
|
import postgres from 'postgres';
|
||||||
import { env } from '$env/dynamic/private';
|
import { env } from '$env/dynamic/private';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
interface HealthCheckOptions {
|
interface HealthCheckOptions {
|
||||||
maxRetries?: number;
|
maxRetries?: number;
|
||||||
@@ -29,7 +30,7 @@ export async function checkDatabaseHealth(
|
|||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
if (!env.DATABASE_URL) {
|
if (!env.DATABASE_URL) {
|
||||||
console.error('DATABASE_URL environment variable is not set');
|
logger.error('DATABASE_URL environment variable is not set');
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
error: 'DATABASE_URL environment variable is not set',
|
error: 'DATABASE_URL environment variable is not set',
|
||||||
@@ -39,10 +40,10 @@ export async function checkDatabaseHealth(
|
|||||||
|
|
||||||
let lastError: Error | null = null;
|
let lastError: Error | null = null;
|
||||||
|
|
||||||
console.log(`Starting database health check (max retries: ${maxRetries})`);
|
logger.info({ maxRetries }, 'Starting database health check');
|
||||||
|
|
||||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||||
console.log(`Attempt ${attempt}/${maxRetries} - Testing database connection`);
|
logger.debug({ attempt, maxRetries }, 'Testing database connection');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Create a new connection for the health check
|
// Create a new connection for the health check
|
||||||
@@ -57,7 +58,7 @@ export async function checkDatabaseHealth(
|
|||||||
await client`SELECT 1 as health_check`;
|
await client`SELECT 1 as health_check`;
|
||||||
await client.end();
|
await client.end();
|
||||||
|
|
||||||
console.log(`Database connection successful on attempt ${attempt}.`);
|
logger.info({ attempt }, 'Database connection successful');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -66,12 +67,12 @@ export async function checkDatabaseHealth(
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
lastError = error as Error;
|
lastError = error as Error;
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
console.error(`Connection failed on attempt ${attempt}: ${errorMessage}`);
|
logger.warn({ attempt, error: errorMessage }, 'Database connection failed');
|
||||||
|
|
||||||
// Don't wait after the last attempt
|
// Don't wait after the last attempt
|
||||||
if (attempt < maxRetries) {
|
if (attempt < maxRetries) {
|
||||||
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
const delay = Math.min(baseDelay * Math.pow(2, attempt - 1), maxDelay);
|
||||||
console.log(`Waiting ${delay}ms before retry...`);
|
logger.debug({ delay }, 'Waiting before retry');
|
||||||
await new Promise((resolve) => setTimeout(resolve, delay));
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +80,10 @@ export async function checkDatabaseHealth(
|
|||||||
|
|
||||||
const finalError = lastError?.message || 'Unknown database connection error';
|
const finalError = lastError?.message || 'Unknown database connection error';
|
||||||
|
|
||||||
console.error(`All ${maxRetries} attempts failed. Final error: ${finalError}`);
|
logger.error(
|
||||||
|
{ attempts: maxRetries, error: finalError },
|
||||||
|
'All database connection attempts failed'
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
@@ -95,10 +99,10 @@ export async function ensureDatabaseConnection(options?: HealthCheckOptions): Pr
|
|||||||
const result = await checkDatabaseHealth(options);
|
const result = await checkDatabaseHealth(options);
|
||||||
|
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
console.error('Database connection failed after all retry attempts');
|
logger.fatal(
|
||||||
console.error(`Error: ${result.error}`);
|
{ error: result.error, attempts: result.attempts },
|
||||||
console.error(`Attempts made: ${result.attempts}`);
|
'Database connection failed after all retry attempts. Exiting application'
|
||||||
console.error('Exiting application...');
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
"public": "Public",
|
"public": "Public",
|
||||||
"private": "Private",
|
"private": "Private",
|
||||||
"inviteOnly": "Invite Only",
|
"inviteOnly": "Invite Only",
|
||||||
|
"invite-only": "Invite Only",
|
||||||
"limited": "Limited",
|
"limited": "Limited",
|
||||||
"unlimited": "Unlimited",
|
"unlimited": "Unlimited",
|
||||||
"capacity": "Capacity",
|
"capacity": "Capacity",
|
||||||
@@ -267,7 +268,7 @@
|
|||||||
"layout": {
|
"layout": {
|
||||||
"defaultTitle": "Cactoide -",
|
"defaultTitle": "Cactoide -",
|
||||||
"defaultDescription": "Create and manage event RSVPs",
|
"defaultDescription": "Create and manage event RSVPs",
|
||||||
"userIdCookieText": "Your UserID storated as a cookie:",
|
"userIdCookieText": "Your UserID stored as a cookie:",
|
||||||
"firstTimeVisiting": "First time visiting. Generating new UserID...",
|
"firstTimeVisiting": "First time visiting. Generating new UserID...",
|
||||||
"copyright": "© 2025 Cactoide"
|
"copyright": "© 2025 Cactoide"
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/lib/logger.ts
Normal file
22
src/lib/logger.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import pino from 'pino';
|
||||||
|
import { LOG_PRETTY, LOG_LEVEL } from '$env/static/private';
|
||||||
|
|
||||||
|
const USE_PRETTY_LOGS = LOG_PRETTY === 'true';
|
||||||
|
|
||||||
|
const transport = USE_PRETTY_LOGS
|
||||||
|
? {
|
||||||
|
target: 'pino-pretty',
|
||||||
|
options: {
|
||||||
|
colorize: true,
|
||||||
|
translateTime: 'SYS:standard',
|
||||||
|
ignore: 'pid,hostname'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
export const logger = pino({
|
||||||
|
level: LOG_LEVEL,
|
||||||
|
transport
|
||||||
|
});
|
||||||
|
|
||||||
|
export type Logger = typeof logger;
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<!-- Error Content -->
|
<!-- Error Content -->
|
||||||
<div class="container mx-auto flex-1 px-4 py-8">
|
<div class="container mx-auto flex-1 px-4 py-8">
|
||||||
<div class="mx-auto max-w-md text-center">
|
<div class="mx-auto max-w-md text-center">
|
||||||
<div class="rounded-sm border border-red-500/30 bg-red-900/20 p-8">
|
<div class="rounded-sm border border-red-500/30 bg-red-900 p-8">
|
||||||
<div class="mb-4 text-6xl text-red-400">🚨</div>
|
<div class="mb-4 text-6xl text-red-400">🚨</div>
|
||||||
<h2 class="mb-4 text-2xl font-bold text-red-400">{t('errors.errorTitle')}</h2>
|
<h2 class="mb-4 text-2xl font-bold text-red-400">{t('errors.errorTitle')}</h2>
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { events, inviteTokens } from '$lib/database/schema';
|
|||||||
import { fail, redirect } from '@sveltejs/kit';
|
import { fail, redirect } from '@sveltejs/kit';
|
||||||
import type { Actions } from './$types';
|
import type { Actions } from './$types';
|
||||||
import { generateInviteToken, calculateTokenExpiration } from '$lib/inviteTokenHelpers.js';
|
import { generateInviteToken, calculateTokenExpiration } from '$lib/inviteTokenHelpers.js';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
// Generate a random URL-friendly ID
|
// Generate a random URL-friendly ID
|
||||||
function generateEventId(): string {
|
function generateEventId(): string {
|
||||||
@@ -116,7 +117,7 @@ export const actions: Actions = {
|
|||||||
userId: userId!
|
userId: userId!
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Unexpected error', error);
|
logger.error({ error, eventId, userId }, 'Unexpected error creating event');
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { database } from '$lib/database/db';
|
|||||||
import { desc, inArray } from 'drizzle-orm';
|
import { desc, inArray } from 'drizzle-orm';
|
||||||
import type { PageServerLoad } from './$types';
|
import type { PageServerLoad } from './$types';
|
||||||
import { events } from '$lib/database/schema';
|
import { events } from '$lib/database/schema';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
export const load: PageServerLoad = async () => {
|
export const load: PageServerLoad = async () => {
|
||||||
try {
|
try {
|
||||||
@@ -33,7 +34,7 @@ export const load: PageServerLoad = async () => {
|
|||||||
events: transformedEvents
|
events: transformedEvents
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading public events:', error);
|
logger.error({ error }, 'Error loading public events');
|
||||||
|
|
||||||
// Return empty array on error to prevent page crash
|
// Return empty array on error to prevent page crash
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { events } from '$lib/database/schema';
|
|||||||
import { fail } from '@sveltejs/kit';
|
import { fail } from '@sveltejs/kit';
|
||||||
import { eq, desc } from 'drizzle-orm';
|
import { eq, desc } from 'drizzle-orm';
|
||||||
import type { Actions } from './$types';
|
import type { Actions } from './$types';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
export const load = async ({ cookies }) => {
|
export const load = async ({ cookies }) => {
|
||||||
const userId = cookies.get('cactoideUserId');
|
const userId = cookies.get('cactoideUserId');
|
||||||
@@ -36,7 +37,7 @@ export const load = async ({ cookies }) => {
|
|||||||
|
|
||||||
return { events: transformedEvents };
|
return { events: transformedEvents };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading user events:', error);
|
logger.error({ error, userId }, 'Error loading user events');
|
||||||
return { events: [] };
|
return { events: [] };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -68,7 +69,7 @@ export const actions: Actions = {
|
|||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error deleting event:', error);
|
logger.error({ error, eventId, userId }, 'Error deleting event');
|
||||||
return fail(500, { error: 'Failed to delete event' });
|
return fail(500, { error: 'Failed to delete event' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,8 @@
|
|||||||
? 'border-green-300 text-green-400'
|
? 'border-green-300 text-green-400'
|
||||||
: 'border-orange-300 text-orange-400'}"
|
: 'border-orange-300 text-orange-400'}"
|
||||||
>
|
>
|
||||||
{event.visibility === 'public' ? t('common.public') : t('common.private')}
|
<!-- TODO(polaroi8d): replace with something better solution; message.json using this, beacuse of common.invite-only works here -->
|
||||||
|
{t(`common.${event.visibility}`)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center space-x-2"></div>
|
<div class="flex items-center space-x-2"></div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { events, rsvps } from '$lib/database/schema';
|
|||||||
import { eq, asc } from 'drizzle-orm';
|
import { eq, asc } from 'drizzle-orm';
|
||||||
import { error, fail } from '@sveltejs/kit';
|
import { error, fail } from '@sveltejs/kit';
|
||||||
import type { PageServerLoad, Actions } from './$types';
|
import type { PageServerLoad, Actions } from './$types';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, cookies }) => {
|
export const load: PageServerLoad = async ({ params, cookies }) => {
|
||||||
const eventId = params.id;
|
const eventId = params.id;
|
||||||
@@ -70,7 +71,7 @@ export const load: PageServerLoad = async ({ params, cookies }) => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof Response) throw err; // This is the 404 error
|
if (err instanceof Response) throw err; // This is the 404 error
|
||||||
|
|
||||||
console.error('Error loading event:', err);
|
logger.error({ error: err, eventId }, 'Error loading event');
|
||||||
throw error(500, 'Failed to load event');
|
throw error(500, 'Failed to load event');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -145,7 +146,7 @@ export const actions: Actions = {
|
|||||||
|
|
||||||
return { success: true, type: 'add' };
|
return { success: true, type: 'add' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error adding RSVP:', err);
|
logger.error({ error: err, eventId, userId, name }, 'Error adding RSVP');
|
||||||
return fail(500, { error: 'Failed to add RSVP' });
|
return fail(500, { error: 'Failed to add RSVP' });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -163,7 +164,7 @@ export const actions: Actions = {
|
|||||||
await database.delete(rsvps).where(eq(rsvps.id, rsvpId));
|
await database.delete(rsvps).where(eq(rsvps.id, rsvpId));
|
||||||
return { success: true, type: 'remove' };
|
return { success: true, type: 'remove' };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error removing RSVP:', err);
|
logger.error({ error: err, rsvpId }, 'Error removing RSVP');
|
||||||
return fail(500, { error: 'Failed to remove RSVP' });
|
return fail(500, { error: 'Failed to remove RSVP' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -485,19 +485,19 @@
|
|||||||
{#if success}
|
{#if success}
|
||||||
{#if typeToShow === 'add'}
|
{#if typeToShow === 'add'}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-green-500/30 bg-green-900/20 p-4 text-green-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-green-500/30 bg-green-900 p-4 text-green-400"
|
||||||
>
|
>
|
||||||
{success}
|
{success}
|
||||||
</div>
|
</div>
|
||||||
{:else if typeToShow === 'remove'}
|
{:else if typeToShow === 'remove'}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900/20 p-4 text-yellow-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900 p-4 text-yellow-400"
|
||||||
>
|
>
|
||||||
{t('event.removedRsvpSuccessfully')}
|
{t('event.removedRsvpSuccessfully')}
|
||||||
</div>
|
</div>
|
||||||
{:else if typeToShow === 'copy'}
|
{:else if typeToShow === 'copy'}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900/20 p-4 text-yellow-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900 p-4 text-yellow-400"
|
||||||
>
|
>
|
||||||
{t('event.eventLinkCopied')}
|
{t('event.eventLinkCopied')}
|
||||||
</div>
|
</div>
|
||||||
@@ -508,7 +508,7 @@
|
|||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-red-500/30 bg-red-900/20 p-4 text-red-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-red-500/30 bg-red-900 p-4 text-red-400"
|
||||||
>
|
>
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { events, inviteTokens } from '$lib/database/schema';
|
|||||||
import { eq, and } from 'drizzle-orm';
|
import { eq, and } from 'drizzle-orm';
|
||||||
import { fail, redirect } from '@sveltejs/kit';
|
import { fail, redirect } from '@sveltejs/kit';
|
||||||
import type { Actions, PageServerLoad } from './$types';
|
import type { Actions, PageServerLoad } from './$types';
|
||||||
|
import { logger } from '$lib/logger';
|
||||||
|
|
||||||
export const load: PageServerLoad = async ({ params, cookies }) => {
|
export const load: PageServerLoad = async ({ params, cookies }) => {
|
||||||
const eventId = params.id;
|
const eventId = params.id;
|
||||||
@@ -75,7 +76,7 @@ export const actions: Actions = {
|
|||||||
const date = formData.get('date') as string;
|
const date = formData.get('date') as string;
|
||||||
const time = formData.get('time') as string;
|
const time = formData.get('time') as string;
|
||||||
const location = formData.get('location') as string;
|
const location = formData.get('location') as string;
|
||||||
const locationType = formData.get('location_type') as 'none' | 'text' | 'maps';
|
const locationType = formData.get('locationType') as string;
|
||||||
const locationUrl = formData.get('location_url') as string;
|
const locationUrl = formData.get('location_url') as string;
|
||||||
const type = formData.get('type') as 'limited' | 'unlimited';
|
const type = formData.get('type') as 'limited' | 'unlimited';
|
||||||
const attendeeLimit = formData.get('attendee_limit') as string;
|
const attendeeLimit = formData.get('attendee_limit') as string;
|
||||||
@@ -108,7 +109,7 @@ export const actions: Actions = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if date is in the past using local timezone (but allow editing past events for corrections)
|
// Check if date is in the past using local timezone
|
||||||
const [year, month, day] = date.split('-').map(Number);
|
const [year, month, day] = date.split('-').map(Number);
|
||||||
const eventDate = new Date(year, month - 1, day);
|
const eventDate = new Date(year, month - 1, day);
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
@@ -147,7 +148,6 @@ export const actions: Actions = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the event
|
// Update the event
|
||||||
await database
|
await database
|
||||||
.update(events)
|
.update(events)
|
||||||
@@ -156,7 +156,7 @@ export const actions: Actions = {
|
|||||||
date: date,
|
date: date,
|
||||||
time: time,
|
time: time,
|
||||||
location: location?.trim() || '',
|
location: location?.trim() || '',
|
||||||
locationType: locationType,
|
locationType: locationType as 'none' | 'text' | 'maps',
|
||||||
locationUrl: locationType === 'maps' ? locationUrl?.trim() : null,
|
locationUrl: locationType === 'maps' ? locationUrl?.trim() : null,
|
||||||
type: type,
|
type: type,
|
||||||
attendeeLimit: type === 'limited' ? parseInt(attendeeLimit) : null,
|
attendeeLimit: type === 'limited' ? parseInt(attendeeLimit) : null,
|
||||||
@@ -165,7 +165,7 @@ export const actions: Actions = {
|
|||||||
})
|
})
|
||||||
.where(and(eq(events.id, eventId), eq(events.userId, userId)))
|
.where(and(eq(events.id, eventId), eq(events.userId, userId)))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error('Unexpected error updating event', error);
|
logger.error({ error, eventId, userId }, 'Unexpected error updating event');
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { EventType, LocationType } from '$lib/types';
|
import type { CreateEventData, EventType, LocationType } from '$lib/types';
|
||||||
import { enhance } from '$app/forms';
|
import { enhance } from '$app/forms';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { t } from '$lib/i18n/i18n.js';
|
import { t } from '$lib/i18n/i18n.js';
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
export let data;
|
export let data;
|
||||||
export let form;
|
export let form;
|
||||||
|
|
||||||
let eventData = {
|
let eventData: CreateEventData = {
|
||||||
name: data.event.name,
|
name: data.event.name,
|
||||||
date: data.event.date,
|
date: data.event.date,
|
||||||
time: data.event.time,
|
time: data.event.time,
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
location_type: data.event.locationType || 'none',
|
location_type: data.event.locationType || 'none',
|
||||||
location_url: data.event.locationUrl || '',
|
location_url: data.event.locationUrl || '',
|
||||||
type: data.event.type,
|
type: data.event.type,
|
||||||
attendee_limit: data.event.attendeeLimit,
|
attendee_limit: data.event.attendeeLimit || undefined,
|
||||||
visibility: data.event.visibility
|
visibility: data.event.visibility
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,14 +44,14 @@
|
|||||||
attendee_limit: (values as any).attendee_limit
|
attendee_limit: (values as any).attendee_limit
|
||||||
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
parseInt(String((values as any).attendee_limit))
|
parseInt(String((values as any).attendee_limit))
|
||||||
: null
|
: undefined
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleTypeChange = (type: EventType) => {
|
const handleTypeChange = (type: EventType) => {
|
||||||
eventData.type = type;
|
eventData.type = type;
|
||||||
if (type === 'unlimited') {
|
if (type === 'unlimited') {
|
||||||
eventData.attendee_limit = null;
|
eventData.attendee_limit = undefined;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -189,6 +189,9 @@
|
|||||||
|
|
||||||
<!-- Location Type -->
|
<!-- Location Type -->
|
||||||
<div>
|
<div>
|
||||||
|
<!-- Hidden input to submit locationType value -->
|
||||||
|
<input type="hidden" name="locationType" bind:value={eventData.location_type} />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
||||||
{t('create.locationTypeLabel')}
|
{t('create.locationTypeLabel')}
|
||||||
@@ -279,6 +282,9 @@
|
|||||||
|
|
||||||
<!-- Event Type -->
|
<!-- Event Type -->
|
||||||
<div>
|
<div>
|
||||||
|
<!-- Hidden input to submit type value -->
|
||||||
|
<input type="hidden" name="type" bind:value={eventData.type} />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
||||||
{t('common.type')} <span class="text-red-400">{t('common.required')}</span>
|
{t('common.type')} <span class="text-red-400">{t('common.required')}</span>
|
||||||
@@ -333,6 +339,9 @@
|
|||||||
|
|
||||||
<!-- Event Visibility -->
|
<!-- Event Visibility -->
|
||||||
<div>
|
<div>
|
||||||
|
<!-- Hidden input to submit visibility value -->
|
||||||
|
<input type="hidden" name="visibility" bind:value={eventData.visibility} />
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
<legend class="text-dark-800 mb-3 block text-sm font-semibold">
|
||||||
{t('common.visibility')} <span class="text-red-400">{t('common.required')}</span>
|
{t('common.visibility')} <span class="text-red-400">{t('common.required')}</span>
|
||||||
@@ -444,7 +453,7 @@
|
|||||||
<!-- Invite Link Toast -->
|
<!-- Invite Link Toast -->
|
||||||
{#if showInviteLinkToast}
|
{#if showInviteLinkToast}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900/20 p-4 text-yellow-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900 p-4 text-yellow-400"
|
||||||
>
|
>
|
||||||
{t('event.inviteLinkCopied')}
|
{t('event.inviteLinkCopied')}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -450,13 +450,13 @@
|
|||||||
{#if success}
|
{#if success}
|
||||||
{#if form?.type === 'add'}
|
{#if form?.type === 'add'}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-green-500/30 bg-green-900/20 p-4 text-green-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-green-500 bg-green-900 p-4 text-green-400"
|
||||||
>
|
>
|
||||||
{success}
|
{success}
|
||||||
</div>
|
</div>
|
||||||
{:else if form?.type === 'remove'}
|
{:else if form?.type === 'remove'}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500/30 bg-yellow-900/20 p-4 text-yellow-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-yellow-500 bg-yellow-900 p-4 text-yellow-400"
|
||||||
>
|
>
|
||||||
{t('event.removedRsvpSuccessfully')}
|
{t('event.removedRsvpSuccessfully')}
|
||||||
</div>
|
</div>
|
||||||
@@ -465,7 +465,7 @@
|
|||||||
|
|
||||||
{#if error}
|
{#if error}
|
||||||
<div
|
<div
|
||||||
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-red-500/30 bg-red-900/20 p-4 text-red-400"
|
class="fixed right-4 bottom-4 z-40 w-128 rounded-sm border border-red-500 bg-red-900 p-4 text-red-400"
|
||||||
>
|
>
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"moduleResolution": "bundler"
|
"moduleResolution": "bundler",
|
||||||
|
"types": ["node"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user