Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8d1609dd52 | ||
|
|
f3380f302d | ||
|
|
3dba9c7ee1 | ||
|
|
e0e4f7a9d6 | ||
|
|
48293dc579 | ||
|
|
38ac6243a0 | ||
|
|
bd2f58e2a5 | ||
|
|
808e47c6b9 |
@@ -26,6 +26,8 @@ NEXT_PUBLIC_SOCKET_URL="http://localhost:3318"
|
|||||||
NEXTAUTH_SECRET="your_secret"
|
NEXTAUTH_SECRET="your_secret"
|
||||||
NEXTAUTH_URL="http://localhost:3000"
|
NEXTAUTH_URL="http://localhost:3000"
|
||||||
|
|
||||||
|
NEXT_PUBLIC_HOST="http://localhost:3000"
|
||||||
|
|
||||||
# Next Auth Github Provider
|
# Next Auth Github Provider
|
||||||
GITHUB_CLIENT_ID="your_client_id"
|
GITHUB_CLIENT_ID="your_client_id"
|
||||||
GITHUB_CLIENT_SECRET="your_secret"
|
GITHUB_CLIENT_SECRET="your_secret"
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ FROM base as builder
|
|||||||
# Include all NEXT_PUBLIC_* env vars here
|
# Include all NEXT_PUBLIC_* env vars here
|
||||||
ARG NEXT_PUBLIC_POSTHOG_KEY
|
ARG NEXT_PUBLIC_POSTHOG_KEY
|
||||||
ARG NEXT_PUBLIC_SOCKET_URL
|
ARG NEXT_PUBLIC_SOCKET_URL
|
||||||
|
ARG NEXT_PUBLIC_HOST
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=deps /app/node_modules ./node_modules
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
|||||||
@@ -21,6 +21,13 @@ const config = {
|
|||||||
defaultLocale: "en",
|
defaultLocale: "en",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
rewrites: async () => [
|
||||||
|
{
|
||||||
|
source: "/ingest/:path*",
|
||||||
|
destination: "https://app.posthog.com/:path*",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
webpack: (config) => {
|
webpack: (config) => {
|
||||||
config.module.rules.push({
|
config.module.rules.push({
|
||||||
test: /\.txt$/,
|
test: /\.txt$/,
|
||||||
|
|||||||
@@ -67,7 +67,8 @@
|
|||||||
"nextjs-routes": "^2.0.1",
|
"nextjs-routes": "^2.0.1",
|
||||||
"openai": "4.0.0-beta.7",
|
"openai": "4.0.0-beta.7",
|
||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"posthog-js": "^1.68.4",
|
"posthog-js": "^1.75.3",
|
||||||
|
"posthog-node": "^3.1.1",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"prismjs": "^1.29.0",
|
"prismjs": "^1.29.0",
|
||||||
"react": "18.2.0",
|
"react": "18.2.0",
|
||||||
|
|||||||
108
pnpm-lock.yaml
generated
108
pnpm-lock.yaml
generated
@@ -1,4 +1,4 @@
|
|||||||
lockfileVersion: '6.1'
|
lockfileVersion: '6.0'
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
@@ -144,8 +144,11 @@ dependencies:
|
|||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0
|
version: 8.0.0
|
||||||
posthog-js:
|
posthog-js:
|
||||||
specifier: ^1.68.4
|
specifier: ^1.75.3
|
||||||
version: 1.68.4
|
version: 1.75.3
|
||||||
|
posthog-node:
|
||||||
|
specifier: ^3.1.1
|
||||||
|
version: 3.1.1
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
@@ -2896,7 +2899,7 @@ packages:
|
|||||||
/@types/eslint-scope@3.7.4:
|
/@types/eslint-scope@3.7.4:
|
||||||
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
|
resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint': 8.37.0
|
'@types/eslint': 8.44.1
|
||||||
'@types/estree': 1.0.1
|
'@types/estree': 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -2907,6 +2910,13 @@ packages:
|
|||||||
'@types/json-schema': 7.0.12
|
'@types/json-schema': 7.0.12
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/eslint@8.44.1:
|
||||||
|
resolution: {integrity: sha512-XpNDc4Z5Tb4x+SW1MriMVeIsMoONHCkWFMkR/aPJbzEsxqHy+4Glu/BqTdPrApfDeMaXbtNh6bseNgl5KaWrSg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/estree': 1.0.1
|
||||||
|
'@types/json-schema': 7.0.12
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/estree@1.0.1:
|
/@types/estree@1.0.1:
|
||||||
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3000,6 +3010,10 @@ packages:
|
|||||||
/@types/node@18.16.0:
|
/@types/node@18.16.0:
|
||||||
resolution: {integrity: sha512-BsAaKhB+7X+H4GnSjGhJG9Qi8Tw+inU9nJDwmD5CgOmBLEI6ArdhikpLX7DjbjDRDTbqZzU2LSQNZg8WGPiSZQ==}
|
resolution: {integrity: sha512-BsAaKhB+7X+H4GnSjGhJG9Qi8Tw+inU9nJDwmD5CgOmBLEI6ArdhikpLX7DjbjDRDTbqZzU2LSQNZg8WGPiSZQ==}
|
||||||
|
|
||||||
|
/@types/node@18.17.1:
|
||||||
|
resolution: {integrity: sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/node@20.4.2:
|
/@types/node@20.4.2:
|
||||||
resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==}
|
resolution: {integrity: sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3630,6 +3644,15 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/axios@0.27.2:
|
||||||
|
resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
|
||||||
|
dependencies:
|
||||||
|
follow-redirects: 1.15.2
|
||||||
|
form-data: 4.0.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
/axobject-query@3.2.1:
|
/axobject-query@3.2.1:
|
||||||
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
|
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3750,6 +3773,17 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range: 7.0.1
|
fill-range: 7.0.1
|
||||||
|
|
||||||
|
/browserslist@4.21.10:
|
||||||
|
resolution: {integrity: sha512-bipEBdZfVH5/pwrvqc+Ub0kUPVfGUhlKxbvfD+z1BDnPEO/X98ruXGA1WP5ASpAFKan7Qr6j736IacbZQuAlKQ==}
|
||||||
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
|
hasBin: true
|
||||||
|
dependencies:
|
||||||
|
caniuse-lite: 1.0.30001519
|
||||||
|
electron-to-chromium: 1.4.482
|
||||||
|
node-releases: 2.0.13
|
||||||
|
update-browserslist-db: 1.0.11(browserslist@4.21.10)
|
||||||
|
dev: true
|
||||||
|
|
||||||
/browserslist@4.21.9:
|
/browserslist@4.21.9:
|
||||||
resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==}
|
resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==}
|
||||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||||
@@ -3816,6 +3850,10 @@ packages:
|
|||||||
/caniuse-lite@1.0.30001517:
|
/caniuse-lite@1.0.30001517:
|
||||||
resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==}
|
resolution: {integrity: sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==}
|
||||||
|
|
||||||
|
/caniuse-lite@1.0.30001519:
|
||||||
|
resolution: {integrity: sha512-0QHgqR+Jv4bxHMp8kZ1Kn8CH55OikjKJ6JmKkZYP1F3D7w+lnFXF70nG5eNfsZS89jadi5Ywy5UCSKLAglIRkg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/chai@4.3.7:
|
/chai@4.3.7:
|
||||||
resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
|
resolution: {integrity: sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
@@ -4326,6 +4364,10 @@ packages:
|
|||||||
/electron-to-chromium@1.4.465:
|
/electron-to-chromium@1.4.465:
|
||||||
resolution: {integrity: sha512-XQcuHvEJRMU97UJ75e170mgcITZoz0lIyiaVjk6R+NMTJ8KBIvUHYd1779swgOppUlzxR+JsLpq59PumaXS1jQ==}
|
resolution: {integrity: sha512-XQcuHvEJRMU97UJ75e170mgcITZoz0lIyiaVjk6R+NMTJ8KBIvUHYd1779swgOppUlzxR+JsLpq59PumaXS1jQ==}
|
||||||
|
|
||||||
|
/electron-to-chromium@1.4.482:
|
||||||
|
resolution: {integrity: sha512-h+UqpfmEr1Qkk0zp7ej/jid7CXoq4m4QzW6wNTb0ELJ/BZCpA4wgUylBIMGCe621tnr4l5VmoHjdoSx2lbnNJA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/emoji-regex@10.2.1:
|
/emoji-regex@10.2.1:
|
||||||
resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==}
|
resolution: {integrity: sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -5108,6 +5150,16 @@ packages:
|
|||||||
tslib: 2.6.0
|
tslib: 2.6.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/follow-redirects@1.15.2:
|
||||||
|
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||||
|
engines: {node: '>=4.0'}
|
||||||
|
peerDependencies:
|
||||||
|
debug: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
debug:
|
||||||
|
optional: true
|
||||||
|
dev: false
|
||||||
|
|
||||||
/for-each@0.3.3:
|
/for-each@0.3.3:
|
||||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -5126,6 +5178,15 @@ packages:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/form-data@4.0.0:
|
||||||
|
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||||
|
engines: {node: '>= 6'}
|
||||||
|
dependencies:
|
||||||
|
asynckit: 0.4.0
|
||||||
|
combined-stream: 1.0.8
|
||||||
|
mime-types: 2.1.35
|
||||||
|
dev: false
|
||||||
|
|
||||||
/format@0.2.2:
|
/format@0.2.2:
|
||||||
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
|
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
|
||||||
engines: {node: '>=0.4.x'}
|
engines: {node: '>=0.4.x'}
|
||||||
@@ -5795,7 +5856,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
|
resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==}
|
||||||
engines: {node: '>= 10.13.0'}
|
engines: {node: '>= 10.13.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 18.16.0
|
'@types/node': 18.17.1
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
dev: true
|
dev: true
|
||||||
@@ -6778,12 +6839,22 @@ packages:
|
|||||||
resolution: {integrity: sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==}
|
resolution: {integrity: sha512-VdlZoocy5lCP0c/t66xAfclglEapXPCIVhqqJRncYpvbCgImF0w67aPKfbqUMr72tO2k5q0TdTZwCLjPTI6C9g==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/posthog-js@1.68.4:
|
/posthog-js@1.75.3:
|
||||||
resolution: {integrity: sha512-rHk4uk99nvWiDTU7P2mFdEfzFR6km0hvOpCR3tm/+F7kCJKs7QDkMblOZZHZultxM4wSNyB4neeohmnHjKYUhQ==}
|
resolution: {integrity: sha512-q5xP4R/Tx8E6H0goZQjY+URMLATFiYXc2raHA+31aNvpBs118fPTmExa4RK6MgRZDFhBiMUBZNT6aj7dM3SyUQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
fflate: 0.4.8
|
fflate: 0.4.8
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/posthog-node@3.1.1:
|
||||||
|
resolution: {integrity: sha512-OUSYcnLHbzvY/dxNsbUGoYuTZz5XNx48BkfiCkOIJZMFvot5VPQ0KWEjX+kzYxEwHeXbjW9plqsOVcYCYfidgg==}
|
||||||
|
engines: {node: '>=15.0.0'}
|
||||||
|
dependencies:
|
||||||
|
axios: 0.27.2
|
||||||
|
rusha: 0.8.14
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- debug
|
||||||
|
dev: false
|
||||||
|
|
||||||
/preact-render-to-string@5.2.6(preact@10.16.0):
|
/preact-render-to-string@5.2.6(preact@10.16.0):
|
||||||
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
|
resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -7280,6 +7351,10 @@ packages:
|
|||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/rusha@0.8.14:
|
||||||
|
resolution: {integrity: sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/rxjs@7.8.1:
|
/rxjs@7.8.1:
|
||||||
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7737,12 +7812,12 @@ packages:
|
|||||||
jest-worker: 27.5.1
|
jest-worker: 27.5.1
|
||||||
schema-utils: 3.3.0
|
schema-utils: 3.3.0
|
||||||
serialize-javascript: 6.0.1
|
serialize-javascript: 6.0.1
|
||||||
terser: 5.19.1
|
terser: 5.19.2
|
||||||
webpack: 5.88.2
|
webpack: 5.88.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/terser@5.19.1:
|
/terser@5.19.2:
|
||||||
resolution: {integrity: sha512-27hxBUVdV6GoNg1pKQ7Z5cbR6V9txPVyBA+FQw3BaZ1Wuzvztce5p156DaP0NVZNrMZZ+6iG9Syf7WgMNKDg2Q==}
|
resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8021,6 +8096,17 @@ packages:
|
|||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/update-browserslist-db@1.0.11(browserslist@4.21.10):
|
||||||
|
resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
|
||||||
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
browserslist: '>= 4.21.0'
|
||||||
|
dependencies:
|
||||||
|
browserslist: 4.21.10
|
||||||
|
escalade: 3.1.1
|
||||||
|
picocolors: 1.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/update-browserslist-db@1.0.11(browserslist@4.21.9):
|
/update-browserslist-db@1.0.11(browserslist@4.21.9):
|
||||||
resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
|
resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -8341,7 +8427,7 @@ packages:
|
|||||||
'@webassemblyjs/wasm-parser': 1.11.6
|
'@webassemblyjs/wasm-parser': 1.11.6
|
||||||
acorn: 8.10.0
|
acorn: 8.10.0
|
||||||
acorn-import-assertions: 1.9.0(acorn@8.10.0)
|
acorn-import-assertions: 1.9.0(acorn@8.10.0)
|
||||||
browserslist: 4.21.9
|
browserslist: 4.21.10
|
||||||
chrome-trace-event: 1.0.3
|
chrome-trace-event: 1.0.3
|
||||||
enhanced-resolve: 5.15.0
|
enhanced-resolve: 5.15.0
|
||||||
es-module-lexer: 1.3.0
|
es-module-lexer: 1.3.0
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- CreateEnum
|
||||||
|
CREATE TYPE "UserRole" AS ENUM ('ADMIN', 'USER');
|
||||||
|
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "User" ADD COLUMN "role" "UserRole" NOT NULL DEFAULT 'USER';
|
||||||
@@ -249,12 +249,20 @@ model Session {
|
|||||||
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum UserRole {
|
||||||
|
ADMIN
|
||||||
|
USER
|
||||||
|
}
|
||||||
|
|
||||||
model User {
|
model User {
|
||||||
id String @id @default(uuid()) @db.Uuid
|
id String @id @default(uuid()) @db.Uuid
|
||||||
name String?
|
name String?
|
||||||
email String? @unique
|
email String? @unique
|
||||||
emailVerified DateTime?
|
emailVerified DateTime?
|
||||||
image String?
|
image String?
|
||||||
|
|
||||||
|
role UserRole @default(USER)
|
||||||
|
|
||||||
accounts Account[]
|
accounts Account[]
|
||||||
sessions Session[]
|
sessions Session[]
|
||||||
organizationUsers OrganizationUser[]
|
organizationUsers OrganizationUser[]
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ export default function OutputCell({
|
|||||||
)}
|
)}
|
||||||
</VStack>
|
</VStack>
|
||||||
),
|
),
|
||||||
[hardRefetching, hardRefetch, mostRecentResponse, scenario],
|
[hardRefetching, hardRefetch, mostRecentResponse, scenario, cell],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!vars) return null;
|
if (!vars) return null;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ export const env = createEnv({
|
|||||||
client: {
|
client: {
|
||||||
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),
|
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(),
|
||||||
NEXT_PUBLIC_SOCKET_URL: z.string().url().default("http://localhost:3318"),
|
NEXT_PUBLIC_SOCKET_URL: z.string().url().default("http://localhost:3318"),
|
||||||
|
NEXT_PUBLIC_HOST: z.string().url().default("http://localhost:3000"),
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +43,7 @@ export const env = createEnv({
|
|||||||
RESTRICT_PRISMA_LOGS: process.env.RESTRICT_PRISMA_LOGS,
|
RESTRICT_PRISMA_LOGS: process.env.RESTRICT_PRISMA_LOGS,
|
||||||
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
NEXT_PUBLIC_POSTHOG_KEY: process.env.NEXT_PUBLIC_POSTHOG_KEY,
|
||||||
NEXT_PUBLIC_SOCKET_URL: process.env.NEXT_PUBLIC_SOCKET_URL,
|
NEXT_PUBLIC_SOCKET_URL: process.env.NEXT_PUBLIC_SOCKET_URL,
|
||||||
|
NEXT_PUBLIC_HOST: process.env.NEXT_PUBLIC_HOST,
|
||||||
GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
|
GITHUB_CLIENT_ID: process.env.GITHUB_CLIENT_ID,
|
||||||
GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
|
GITHUB_CLIENT_SECRET: process.env.GITHUB_CLIENT_SECRET,
|
||||||
REPLICATE_API_TOKEN: process.env.REPLICATE_API_TOKEN,
|
REPLICATE_API_TOKEN: process.env.REPLICATE_API_TOKEN,
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ import { SessionProvider } from "next-auth/react";
|
|||||||
import { type AppType } from "next/app";
|
import { type AppType } from "next/app";
|
||||||
import { api } from "~/utils/api";
|
import { api } from "~/utils/api";
|
||||||
import Favicon from "~/components/Favicon";
|
import Favicon from "~/components/Favicon";
|
||||||
import "~/utils/analytics";
|
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { ChakraThemeProvider } from "~/theme/ChakraThemeProvider";
|
import { ChakraThemeProvider } from "~/theme/ChakraThemeProvider";
|
||||||
import { SyncAppStore } from "~/state/sync";
|
import { SyncAppStore } from "~/state/sync";
|
||||||
import NextAdapterApp from "next-query-params/app";
|
import NextAdapterApp from "next-query-params/app";
|
||||||
import { QueryParamProvider } from "use-query-params";
|
import { QueryParamProvider } from "use-query-params";
|
||||||
|
import { SessionIdentifier } from "~/utils/analytics/clientAnalytics";
|
||||||
|
|
||||||
const MyApp: AppType<{ session: Session | null }> = ({
|
const MyApp: AppType<{ session: Session | null }> = ({
|
||||||
Component,
|
Component,
|
||||||
@@ -36,6 +36,7 @@ const MyApp: AppType<{ session: Session | null }> = ({
|
|||||||
<SessionProvider session={session}>
|
<SessionProvider session={session}>
|
||||||
<SyncAppStore />
|
<SyncAppStore />
|
||||||
<Favicon />
|
<Favicon />
|
||||||
|
<SessionIdentifier />
|
||||||
<ChakraThemeProvider>
|
<ChakraThemeProvider>
|
||||||
<QueryParamProvider adapter={NextAdapterApp}>
|
<QueryParamProvider adapter={NextAdapterApp}>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
VStack,
|
VStack,
|
||||||
useInterval,
|
useInterval,
|
||||||
Image,
|
Image,
|
||||||
|
Flex,
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { signIn, useSession } from "next-auth/react";
|
import { signIn, useSession } from "next-auth/react";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
@@ -124,8 +125,16 @@ function ApplicationStatus(props: BoxProps) {
|
|||||||
} else if (user) {
|
} else if (user) {
|
||||||
return (
|
return (
|
||||||
<Wrapper>
|
<Wrapper>
|
||||||
<HStack spacing={8}>
|
<Flex flexDirection={{ base: "column", md: "row" }} alignItems="center">
|
||||||
<UserMenu user={user} borderRadius={2} borderColor={"gray.700"} borderWidth={1} pr={6} />
|
<UserMenu
|
||||||
|
user={user}
|
||||||
|
borderRadius={2}
|
||||||
|
borderColor={"gray.700"}
|
||||||
|
borderWidth={1}
|
||||||
|
pr={6}
|
||||||
|
mr={{ base: 0, md: 8 }}
|
||||||
|
mb={{ base: 8, md: 0 }}
|
||||||
|
/>
|
||||||
<Box flex={1}>
|
<Box flex={1}>
|
||||||
{entrant?.approved ? (
|
{entrant?.approved ? (
|
||||||
<Text fontSize="sm">
|
<Text fontSize="sm">
|
||||||
@@ -145,7 +154,7 @@ function ApplicationStatus(props: BoxProps) {
|
|||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
</HStack>
|
</Flex>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -192,7 +201,14 @@ export default function Signup() {
|
|||||||
Event Details
|
Event Details
|
||||||
</Heading>
|
</Heading>
|
||||||
<Table variant="simple">
|
<Table variant="simple">
|
||||||
<Tbody>
|
<Tbody
|
||||||
|
sx={{
|
||||||
|
th: {
|
||||||
|
base: { px: 0 },
|
||||||
|
md: { px: 6 },
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Tr>
|
<Tr>
|
||||||
<Th>Kickoff</Th>
|
<Th>Kickoff</Th>
|
||||||
<Td>August 14</Td>
|
<Td>August 14</Td>
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import superjson from "superjson";
|
|||||||
import { ZodError } from "zod";
|
import { ZodError } from "zod";
|
||||||
import { getServerAuthSession } from "~/server/auth";
|
import { getServerAuthSession } from "~/server/auth";
|
||||||
import { prisma } from "~/server/db";
|
import { prisma } from "~/server/db";
|
||||||
|
import { capturePath } from "~/utils/analytics/serverAnalytics";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 1. CONTEXT
|
* 1. CONTEXT
|
||||||
@@ -112,7 +113,7 @@ export const createTRPCRouter = t.router;
|
|||||||
export const publicProcedure = t.procedure;
|
export const publicProcedure = t.procedure;
|
||||||
|
|
||||||
/** Reusable middleware that enforces users are logged in before running the procedure. */
|
/** Reusable middleware that enforces users are logged in before running the procedure. */
|
||||||
const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
|
const enforceUserIsAuthed = t.middleware(async ({ ctx, next, path }) => {
|
||||||
if (!ctx.session || !ctx.session.user) {
|
if (!ctx.session || !ctx.session.user) {
|
||||||
throw new TRPCError({ code: "UNAUTHORIZED" });
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
||||||
}
|
}
|
||||||
@@ -134,6 +135,8 @@ const enforceUserIsAuthed = t.middleware(async ({ ctx, next }) => {
|
|||||||
"Protected routes must perform access control checks then explicitly invoke the `ctx.markAccessControlRun()` function to ensure we don't forget access control on a route.",
|
"Protected routes must perform access control checks then explicitly invoke the `ctx.markAccessControlRun()` function to ensure we don't forget access control on a route.",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
capturePath(ctx.session, path);
|
||||||
|
|
||||||
return resp;
|
return resp;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,14 @@ import { TRPCError } from "@trpc/server";
|
|||||||
import { type TRPCContext } from "~/server/api/trpc";
|
import { type TRPCContext } from "~/server/api/trpc";
|
||||||
import { prisma } from "~/server/db";
|
import { prisma } from "~/server/db";
|
||||||
|
|
||||||
|
const isAdmin = async (userId: string) => {
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where: { id: userId, role: "ADMIN" },
|
||||||
|
});
|
||||||
|
|
||||||
|
return !!user;
|
||||||
|
};
|
||||||
|
|
||||||
// No-op method for protected routes that really should be accessible to anyone.
|
// No-op method for protected routes that really should be accessible to anyone.
|
||||||
export const requireNothing = (ctx: TRPCContext) => {
|
export const requireNothing = (ctx: TRPCContext) => {
|
||||||
ctx.markAccessControlRun();
|
ctx.markAccessControlRun();
|
||||||
@@ -18,7 +26,9 @@ export const requireCanViewExperiment = async (experimentId: string, ctx: TRPCCo
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const canModifyExperiment = async (experimentId: string, userId: string) => {
|
export const canModifyExperiment = async (experimentId: string, userId: string) => {
|
||||||
const experiment = await prisma.experiment.findFirst({
|
const [adminUser, experiment] = await Promise.all([
|
||||||
|
isAdmin(userId),
|
||||||
|
prisma.experiment.findFirst({
|
||||||
where: {
|
where: {
|
||||||
id: experimentId,
|
id: experimentId,
|
||||||
organization: {
|
organization: {
|
||||||
@@ -30,9 +40,10 @@ export const canModifyExperiment = async (experimentId: string, userId: string)
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
}),
|
||||||
|
]);
|
||||||
|
|
||||||
return !!experiment;
|
return adminUser || !!experiment;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const requireCanModifyExperiment = async (experimentId: string, ctx: TRPCContext) => {
|
export const requireCanModifyExperiment = async (experimentId: string, ctx: TRPCContext) => {
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
// Make sure we're in the browser
|
|
||||||
import posthog from "posthog-js";
|
|
||||||
import { env } from "~/env.mjs";
|
|
||||||
|
|
||||||
const enableAnalytics = typeof window !== "undefined";
|
|
||||||
|
|
||||||
if (enableAnalytics) {
|
|
||||||
if (env.NEXT_PUBLIC_POSTHOG_KEY) {
|
|
||||||
posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, {
|
|
||||||
api_host: "https://app.posthog.com",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
src/utils/analytics/clientAnalytics.ts
Normal file
31
src/utils/analytics/clientAnalytics.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { type Session } from "next-auth";
|
||||||
|
import { useSession } from "next-auth/react";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
|
||||||
|
import posthog from "posthog-js";
|
||||||
|
import { env } from "~/env.mjs";
|
||||||
|
|
||||||
|
// Make sure we're in the browser
|
||||||
|
const enableBrowserAnalytics = typeof window !== "undefined";
|
||||||
|
|
||||||
|
if (env.NEXT_PUBLIC_POSTHOG_KEY && enableBrowserAnalytics) {
|
||||||
|
posthog.init(env.NEXT_PUBLIC_POSTHOG_KEY, {
|
||||||
|
api_host: `${env.NEXT_PUBLIC_HOST}/ingest`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const identifySession = (session: Session) => {
|
||||||
|
if (!session.user) return;
|
||||||
|
posthog.identify(session.user.id, {
|
||||||
|
name: session.user.name,
|
||||||
|
email: session.user.email,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SessionIdentifier = () => {
|
||||||
|
const session = useSession().data;
|
||||||
|
useEffect(() => {
|
||||||
|
if (session && enableBrowserAnalytics) identifySession(session);
|
||||||
|
}, [session]);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
14
src/utils/analytics/serverAnalytics.ts
Normal file
14
src/utils/analytics/serverAnalytics.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { type Session } from "next-auth";
|
||||||
|
import { PostHog } from "posthog-node";
|
||||||
|
import { env } from "~/env.mjs";
|
||||||
|
|
||||||
|
export const posthogServerClient = env.NEXT_PUBLIC_POSTHOG_KEY
|
||||||
|
? new PostHog(env.NEXT_PUBLIC_POSTHOG_KEY, {
|
||||||
|
host: "https://app.posthog.com",
|
||||||
|
})
|
||||||
|
: null;
|
||||||
|
|
||||||
|
export const capturePath = (session: Session, path: string) => {
|
||||||
|
if (!session.user || !posthogServerClient) return;
|
||||||
|
posthogServerClient?.capture({ distinctId: session.user.id, event: path });
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user