auth
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -44,3 +44,5 @@ yarn-error.log*
|
||||
|
||||
# idea files
|
||||
.idea
|
||||
# clerk configuration (can include secrets)
|
||||
/.clerk/
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@clerk/nextjs": "^6.14.0",
|
||||
"@neondatabase/serverless": "^1.0.0",
|
||||
"@t3-oss/env-nextjs": "^0.12.0",
|
||||
"drizzle-orm": "^0.41.0",
|
||||
@@ -25,6 +26,7 @@
|
||||
"postgres": "^3.4.4",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"server-only": "^0.0.1",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
201
pnpm-lock.yaml
generated
201
pnpm-lock.yaml
generated
@@ -8,6 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@clerk/nextjs':
|
||||
specifier: ^6.14.0
|
||||
version: 6.14.0(next@15.2.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@neondatabase/serverless':
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0
|
||||
@@ -29,6 +32,9 @@ importers:
|
||||
react-dom:
|
||||
specifier: ^19.0.0
|
||||
version: 19.1.0(react@19.1.0)
|
||||
server-only:
|
||||
specifier: ^0.0.1
|
||||
version: 0.0.1
|
||||
zod:
|
||||
specifier: ^3.24.2
|
||||
version: 3.24.2
|
||||
@@ -120,6 +126,46 @@ packages:
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@clerk/backend@1.27.0':
|
||||
resolution: {integrity: sha512-WqdigkqGyVcU0Y08xCJSor6I8j7WxtlZfMlIbHyw+JM8U06kNVSX9umRmTePFRFN02EwIQmQmqnRXVn0kwMyBQ==}
|
||||
engines: {node: '>=18.17.0'}
|
||||
peerDependencies:
|
||||
svix: ^1.62.0
|
||||
peerDependenciesMeta:
|
||||
svix:
|
||||
optional: true
|
||||
|
||||
'@clerk/clerk-react@5.26.0':
|
||||
resolution: {integrity: sha512-9PQfCSFvpQDtL5fcp/gnQHBKvkMSW/FTuIEHdzhqhcO8xJRcOmcE0z5YjrnhytB3j3P1fx2gdiJgO5/OaU33hg==}
|
||||
engines: {node: '>=18.17.0'}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
|
||||
'@clerk/nextjs@6.14.0':
|
||||
resolution: {integrity: sha512-kSb0yPLbaACyRcvGDB2T0/IyypNYBQMIUP95YhFrZZWJDKR96rUdzw5ptG/OaP+vw7fAyhfz3Q8OeMrn97hxBw==}
|
||||
engines: {node: '>=18.17.0'}
|
||||
peerDependencies:
|
||||
next: ^13.5.7 || ^14.2.25 || ^15.2.3
|
||||
react: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
|
||||
'@clerk/shared@3.4.0':
|
||||
resolution: {integrity: sha512-3ms1JZVNXe/qJXdsFY+QlOYKcocdMKDHXDr/EvpuQV+WsLKkpMcswH2fbWNhsWG2otekL2sIYBVkCy+/0hBlPA==}
|
||||
engines: {node: '>=18.17.0'}
|
||||
peerDependencies:
|
||||
react: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-0
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
react-dom:
|
||||
optional: true
|
||||
|
||||
'@clerk/types@4.51.0':
|
||||
resolution: {integrity: sha512-igUZ5BOe3rOgQSM8v9f6zHCOowX3yV36zWYImMUWD61cpLqUokKtN6qH2x8sHUHrq3B9Dj3AsXItGaQsLNs3mw==}
|
||||
engines: {node: '>=18.17.0'}
|
||||
|
||||
'@drizzle-team/brocli@0.10.2':
|
||||
resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==}
|
||||
|
||||
@@ -721,6 +767,10 @@ packages:
|
||||
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
|
||||
engines: {node: '>=12.5.0'}
|
||||
|
||||
cookie@1.0.2:
|
||||
resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
csstype@3.1.3:
|
||||
resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
|
||||
|
||||
@@ -733,10 +783,17 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
detect-libc@2.0.3:
|
||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
dot-case@3.0.4:
|
||||
resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
|
||||
|
||||
drizzle-kit@0.30.6:
|
||||
resolution: {integrity: sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g==}
|
||||
hasBin: true
|
||||
@@ -861,6 +918,9 @@ packages:
|
||||
get-tsconfig@4.10.0:
|
||||
resolution: {integrity: sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==}
|
||||
|
||||
glob-to-regexp@0.4.1:
|
||||
resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==}
|
||||
|
||||
graceful-fs@4.2.11:
|
||||
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
|
||||
|
||||
@@ -875,6 +935,10 @@ packages:
|
||||
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
|
||||
hasBin: true
|
||||
|
||||
js-cookie@3.0.5:
|
||||
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
lightningcss-darwin-arm64@1.29.2:
|
||||
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
@@ -939,6 +1003,13 @@ packages:
|
||||
resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
|
||||
engines: {node: '>= 12.0.0'}
|
||||
|
||||
lower-case@2.0.2:
|
||||
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
|
||||
|
||||
map-obj@4.3.0:
|
||||
resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
@@ -968,6 +1039,9 @@ packages:
|
||||
sass:
|
||||
optional: true
|
||||
|
||||
no-case@3.0.4:
|
||||
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
|
||||
|
||||
obuf@1.1.2:
|
||||
resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==}
|
||||
|
||||
@@ -1040,6 +1114,9 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
|
||||
server-only@0.0.1:
|
||||
resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==}
|
||||
|
||||
sharp@0.33.5:
|
||||
resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==}
|
||||
engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
|
||||
@@ -1051,6 +1128,13 @@ packages:
|
||||
simple-swizzle@0.2.2:
|
||||
resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
|
||||
|
||||
snake-case@3.0.4:
|
||||
resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==}
|
||||
|
||||
snakecase-keys@8.0.1:
|
||||
resolution: {integrity: sha512-Sj51kE1zC7zh6TDlNNz0/Jn1n5HiHdoQErxO8jLtnyrkJW/M5PrI7x05uDgY3BO7OUQYKCvmeMurW6BPUdwEOw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
source-map-js@1.2.1:
|
||||
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -1062,6 +1146,9 @@ packages:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
std-env@3.9.0:
|
||||
resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
|
||||
|
||||
streamsearch@1.1.0:
|
||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
@@ -1079,6 +1166,11 @@ packages:
|
||||
babel-plugin-macros:
|
||||
optional: true
|
||||
|
||||
swr@2.3.3:
|
||||
resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==}
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
tailwindcss@4.1.3:
|
||||
resolution: {integrity: sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==}
|
||||
|
||||
@@ -1089,6 +1181,10 @@ packages:
|
||||
tslib@2.8.1:
|
||||
resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==}
|
||||
|
||||
type-fest@4.39.1:
|
||||
resolution: {integrity: sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
typescript@5.8.3:
|
||||
resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
|
||||
engines: {node: '>=14.17'}
|
||||
@@ -1100,6 +1196,11 @@ packages:
|
||||
undici-types@6.21.0:
|
||||
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
|
||||
|
||||
use-sync-external-store@1.5.0:
|
||||
resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
which@4.0.0:
|
||||
resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==}
|
||||
engines: {node: ^16.13.0 || >=18.0.0}
|
||||
@@ -1147,6 +1248,55 @@ snapshots:
|
||||
'@biomejs/cli-win32-x64@1.9.4':
|
||||
optional: true
|
||||
|
||||
'@clerk/backend@1.27.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@clerk/shared': 3.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@clerk/types': 4.51.0
|
||||
cookie: 1.0.2
|
||||
snakecase-keys: 8.0.1
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- react
|
||||
- react-dom
|
||||
|
||||
'@clerk/clerk-react@5.26.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@clerk/shared': 3.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@clerk/types': 4.51.0
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
tslib: 2.8.1
|
||||
|
||||
'@clerk/nextjs@6.14.0(next@15.2.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@clerk/backend': 1.27.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@clerk/clerk-react': 5.26.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@clerk/shared': 3.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
'@clerk/types': 4.51.0
|
||||
next: 15.2.4(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
server-only: 0.0.1
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- svix
|
||||
|
||||
'@clerk/shared@3.4.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)':
|
||||
dependencies:
|
||||
'@clerk/types': 4.51.0
|
||||
dequal: 2.0.3
|
||||
glob-to-regexp: 0.4.1
|
||||
js-cookie: 3.0.5
|
||||
std-env: 3.9.0
|
||||
swr: 2.3.3(react@19.1.0)
|
||||
optionalDependencies:
|
||||
react: 19.1.0
|
||||
react-dom: 19.1.0(react@19.1.0)
|
||||
|
||||
'@clerk/types@4.51.0':
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
|
||||
'@drizzle-team/brocli@0.10.2': {}
|
||||
|
||||
'@emnapi/runtime@1.4.0':
|
||||
@@ -1539,14 +1689,23 @@ snapshots:
|
||||
color-string: 1.9.1
|
||||
optional: true
|
||||
|
||||
cookie@1.0.2: {}
|
||||
|
||||
csstype@3.1.3: {}
|
||||
|
||||
debug@4.4.0:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-libc@2.0.3: {}
|
||||
|
||||
dot-case@3.0.4:
|
||||
dependencies:
|
||||
no-case: 3.0.4
|
||||
tslib: 2.8.1
|
||||
|
||||
drizzle-kit@0.30.6:
|
||||
dependencies:
|
||||
'@drizzle-team/brocli': 0.10.2
|
||||
@@ -1644,6 +1803,8 @@ snapshots:
|
||||
dependencies:
|
||||
resolve-pkg-maps: 1.0.0
|
||||
|
||||
glob-to-regexp@0.4.1: {}
|
||||
|
||||
graceful-fs@4.2.11: {}
|
||||
|
||||
is-arrayish@0.3.2:
|
||||
@@ -1653,6 +1814,8 @@ snapshots:
|
||||
|
||||
jiti@2.4.2: {}
|
||||
|
||||
js-cookie@3.0.5: {}
|
||||
|
||||
lightningcss-darwin-arm64@1.29.2:
|
||||
optional: true
|
||||
|
||||
@@ -1698,6 +1861,12 @@ snapshots:
|
||||
lightningcss-win32-arm64-msvc: 1.29.2
|
||||
lightningcss-win32-x64-msvc: 1.29.2
|
||||
|
||||
lower-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
map-obj@4.3.0: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
nanoid@3.3.11: {}
|
||||
@@ -1727,6 +1896,11 @@ snapshots:
|
||||
- '@babel/core'
|
||||
- babel-plugin-macros
|
||||
|
||||
no-case@3.0.4:
|
||||
dependencies:
|
||||
lower-case: 2.0.2
|
||||
tslib: 2.8.1
|
||||
|
||||
obuf@1.1.2: {}
|
||||
|
||||
pg-int8@1.0.1: {}
|
||||
@@ -1786,6 +1960,8 @@ snapshots:
|
||||
|
||||
semver@7.7.1: {}
|
||||
|
||||
server-only@0.0.1: {}
|
||||
|
||||
sharp@0.33.5:
|
||||
dependencies:
|
||||
color: 4.2.3
|
||||
@@ -1820,6 +1996,17 @@ snapshots:
|
||||
is-arrayish: 0.3.2
|
||||
optional: true
|
||||
|
||||
snake-case@3.0.4:
|
||||
dependencies:
|
||||
dot-case: 3.0.4
|
||||
tslib: 2.8.1
|
||||
|
||||
snakecase-keys@8.0.1:
|
||||
dependencies:
|
||||
map-obj: 4.3.0
|
||||
snake-case: 3.0.4
|
||||
type-fest: 4.39.1
|
||||
|
||||
source-map-js@1.2.1: {}
|
||||
|
||||
source-map-support@0.5.21:
|
||||
@@ -1829,6 +2016,8 @@ snapshots:
|
||||
|
||||
source-map@0.6.1: {}
|
||||
|
||||
std-env@3.9.0: {}
|
||||
|
||||
streamsearch@1.1.0: {}
|
||||
|
||||
styled-jsx@5.1.6(react@19.1.0):
|
||||
@@ -1836,18 +2025,30 @@ snapshots:
|
||||
client-only: 0.0.1
|
||||
react: 19.1.0
|
||||
|
||||
swr@2.3.3(react@19.1.0):
|
||||
dependencies:
|
||||
dequal: 2.0.3
|
||||
react: 19.1.0
|
||||
use-sync-external-store: 1.5.0(react@19.1.0)
|
||||
|
||||
tailwindcss@4.1.3: {}
|
||||
|
||||
tapable@2.2.1: {}
|
||||
|
||||
tslib@2.8.1: {}
|
||||
|
||||
type-fest@4.39.1: {}
|
||||
|
||||
typescript@5.8.3: {}
|
||||
|
||||
undici-types@6.19.8: {}
|
||||
|
||||
undici-types@6.21.0: {}
|
||||
|
||||
use-sync-external-store@1.5.0(react@19.1.0):
|
||||
dependencies:
|
||||
react: 19.1.0
|
||||
|
||||
which@4.0.0:
|
||||
dependencies:
|
||||
isexe: 3.1.1
|
||||
|
||||
30
public/GLIcon.svg
Normal file
30
public/GLIcon.svg
Normal file
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="74.193405mm"
|
||||
height="74.232162mm"
|
||||
viewBox="0 0 74.193405 74.232162"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
id="layer1"
|
||||
transform="translate(-24.550957,-64.437925)">
|
||||
<path
|
||||
d="m 61.66652,64.437927 c -20.498425,1.81e-4 -37.115669,16.617653 -37.115564,37.116083 -1.05e-4,20.49842 16.617139,37.1159 37.115564,37.11608 16.081184,-0.0265 30.316081,-10.4061 35.258313,-25.70903 1.144195,-3.51294 1.757471,-7.1771 1.819527,-10.87117 H 87.864404 67.217603 v 10.87117 h 17.977714 c -4.361366,9.03731 -13.494221,14.79672 -23.528797,14.83786 -14.494622,0 -26.244916,-11.75029 -26.244909,-26.24491 -7e-6,-14.494627 11.750287,-26.244918 26.244909,-26.244912 z"
|
||||
style="font-variation-settings:'wght' 600;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.07219;stroke-linejoin:round"
|
||||
id="path10" />
|
||||
<rect
|
||||
style="font-variation-settings:'wght' 600;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.03354;stroke-linejoin:round"
|
||||
id="rect9"
|
||||
width="31.802109"
|
||||
height="11.397169"
|
||||
x="-96.2453"
|
||||
y="67.460899"
|
||||
transform="rotate(-90)" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
15
src/app/admin/page.tsx
Normal file
15
src/app/admin/page.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { SignedIn } from "@clerk/nextjs";
|
||||
|
||||
const AdminPage = async () => {
|
||||
return (
|
||||
<SignedIn>
|
||||
<main className="flex min-h-screen flex-col items-center justify-center bg-black text-white">
|
||||
<div>
|
||||
hello admin
|
||||
</div>
|
||||
</main>
|
||||
</SignedIn>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdminPage;
|
||||
@@ -1,12 +1,15 @@
|
||||
import "~/styles/globals.css";
|
||||
|
||||
import Link from "next/link";
|
||||
import type { Metadata } from "next";
|
||||
import { Geist } from "next/font/google";
|
||||
|
||||
import { ClerkProvider, SignedIn, SignedOut, SignUpButton, UserButton } from "@clerk/nextjs";
|
||||
import { auth } from "@clerk/nextjs/server";
|
||||
import { env } from "~/env";
|
||||
export const metadata: Metadata = {
|
||||
title: "Create T3 App",
|
||||
description: "Generated by create-t3-app",
|
||||
icons: [{ rel: "icon", url: "/favicon.ico" }],
|
||||
title: "Gregor Lohaus",
|
||||
description: "My Personal Website",
|
||||
icons: [{ rel: "icon", url: "/GLIcon.svg" }],
|
||||
};
|
||||
|
||||
const geist = Geist({
|
||||
@@ -14,13 +17,32 @@ const geist = Geist({
|
||||
variable: "--font-geist-sans",
|
||||
});
|
||||
|
||||
const TopNav = () => {
|
||||
const AdminWrap = async ({children,}: Readonly<{ children: React.ReactNode }>) => {
|
||||
const userid = (await auth()).userId
|
||||
const isAdmin = (userid == env.ADMIN_USER_CLERK_ID)
|
||||
if (isAdmin) {
|
||||
return <>{children}</>
|
||||
}
|
||||
return (<></>)
|
||||
}
|
||||
|
||||
const TopNav = async () => {
|
||||
return (
|
||||
<nav className="flex w-full border-b p-4 gap-5 bg-black text-white border-white">
|
||||
<div> Blog </div>
|
||||
<div> CV </div>
|
||||
<div> Projects </div>
|
||||
<div> Fun </div>
|
||||
<nav className="flex flex-wrap items-center w-full border-b px-5 py-5 gap-5 bg-black text-white border-white">
|
||||
<Link className="h-fit" href={"/blog"}> Blog </Link>
|
||||
<Link className="h-fit" href={"/cv"}> CV </Link>
|
||||
<Link className="h-fit" href={"/projects"}> Projects </Link>
|
||||
<Link className="h-fit" href={"/fun"}> Fun </Link>
|
||||
<div className="ml-auto"/>
|
||||
<AdminWrap><Link className="h-fit" href={"/admin"}> Admin </Link></AdminWrap>
|
||||
<div className="h-fit flex">
|
||||
<SignedIn>
|
||||
<UserButton/>
|
||||
</SignedIn>
|
||||
<SignedOut>
|
||||
<SignUpButton/>
|
||||
</SignedOut>
|
||||
</div>
|
||||
</nav>
|
||||
)
|
||||
}
|
||||
@@ -29,11 +51,13 @@ export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{ children: React.ReactNode }>) {
|
||||
return (
|
||||
<ClerkProvider>
|
||||
<html lang="en" className={`${geist.variable}`}>
|
||||
<body className="flex flex-col gap-2 bg-black text-white">
|
||||
<TopNav/>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
</ClerkProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,10 @@
|
||||
import Link from "next/link";
|
||||
import { db } from "~/server/db";
|
||||
export const dynamic = "force-dynamic"
|
||||
|
||||
export default async function HomePage() {
|
||||
const posts = await db.query.posts.findMany()
|
||||
return (
|
||||
<main className="flex min-h-screen flex-col items-center justify-center bg-black text-white">
|
||||
<div>
|
||||
{posts.map((post) => {
|
||||
return (
|
||||
<div key={post.id}>
|
||||
{post.name}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
hello world
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
||||
@@ -8,6 +8,7 @@ export const env = createEnv({
|
||||
*/
|
||||
server: {
|
||||
DATABASE_URL: z.string().url(),
|
||||
ADMIN_USER_CLERK_ID: z.string(),
|
||||
NODE_ENV: z
|
||||
.enum(["development", "test", "production"])
|
||||
.default("development"),
|
||||
@@ -28,6 +29,7 @@ export const env = createEnv({
|
||||
*/
|
||||
runtimeEnv: {
|
||||
DATABASE_URL: process.env.DATABASE_URL,
|
||||
ADMIN_USER_CLERK_ID: process.env.ADMIN_USER_CLERK_ID,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
// NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
|
||||
},
|
||||
|
||||
21
src/middleware.ts
Normal file
21
src/middleware.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { clerkMiddleware, createRouteMatcher, currentUser } from "@clerk/nextjs/server";
|
||||
import { env } from "~/env";
|
||||
|
||||
const isTenantAdminRoute = createRouteMatcher(['/admin(.*)'])
|
||||
export default clerkMiddleware(async (auth,req) => {
|
||||
if (isTenantAdminRoute(req)) {
|
||||
let userid = (await auth()).userId
|
||||
if (userid != env.ADMIN_USER_CLERK_ID) {
|
||||
await auth.protect()
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
// Skip Next.js internals and all static files, unless found in search params
|
||||
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
|
||||
// Always run for API routes
|
||||
'/(api|trpc)(.*)',
|
||||
],
|
||||
};
|
||||
1
src/server/db/query.ts
Normal file
1
src/server/db/query.ts
Normal file
@@ -0,0 +1 @@
|
||||
import "server-only"
|
||||
@@ -1,7 +1,7 @@
|
||||
// Example model schema from the Drizzle docs
|
||||
// https://orm.drizzle.team/docs/sql-schema-declaration
|
||||
|
||||
import { sql } from "drizzle-orm";
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import { index, pgTableCreator } from "drizzle-orm/pg-core";
|
||||
|
||||
/**
|
||||
@@ -12,16 +12,37 @@ import { index, pgTableCreator } from "drizzle-orm/pg-core";
|
||||
*/
|
||||
export const createTable = pgTableCreator((name) => `gregorlohaus.com_${name}`);
|
||||
|
||||
export const posts = createTable(
|
||||
"post",
|
||||
export const cvCategory = createTable(
|
||||
"cv_category",
|
||||
(d) => ({
|
||||
id: d.integer().primaryKey().generatedByDefaultAsIdentity(),
|
||||
name: d.varchar({ length: 256 }),
|
||||
id: d.uuid().primaryKey(),
|
||||
name: d.varchar({length: 50})
|
||||
}),
|
||||
(t) => [index("name_idx").on(t.name)],
|
||||
)
|
||||
|
||||
export const cvCategoryRelations = relations(cvCategory,({many}) => ({
|
||||
cvEntry: many(cvEntry)
|
||||
}))
|
||||
|
||||
export const cvEntry = createTable(
|
||||
"cv_entry",
|
||||
(d) => ({
|
||||
id: d.uuid().primaryKey().notNull(),
|
||||
categoryId: d.uuid('category_id'),
|
||||
fromTime: d.date().notNull(),
|
||||
toTime: d.date().notNull(),
|
||||
createdAt: d
|
||||
.timestamp({ withTimezone: true })
|
||||
.default(sql`CURRENT_TIMESTAMP`)
|
||||
.notNull(),
|
||||
updatedAt: d.timestamp({ withTimezone: true }).$onUpdate(() => new Date()),
|
||||
})
|
||||
)
|
||||
|
||||
export const cvEntryRelations = relations(cvEntry, ({one}) => ({
|
||||
category: one(cvCategory, {
|
||||
fields: [cvEntry.categoryId],
|
||||
references: [cvCategory.id]
|
||||
}),
|
||||
(t) => [index("name_idx").on(t.name)],
|
||||
);
|
||||
}));
|
||||
|
||||
Reference in New Issue
Block a user