mirror of
https://github.com/BradNut/musicle-svelte
synced 2025-09-08 17:40:21 +00:00
Adding timespan, token service, fixing ui for password form.
This commit is contained in:
parent
744e5dad89
commit
5497fb75a7
8 changed files with 220 additions and 66 deletions
|
|
@ -38,7 +38,7 @@
|
|||
"@storybook/test": "^8.4.7",
|
||||
"@sveltejs/adapter-node": "^5.2.9",
|
||||
"@sveltejs/enhanced-img": "^0.4.4",
|
||||
"@sveltejs/kit": "^2.9.0",
|
||||
"@sveltejs/kit": "^2.15.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^5.0.3",
|
||||
"@tanstack/svelte-query": "^5.62.9",
|
||||
"@tanstack/svelte-query-devtools": "^5.62.9",
|
||||
|
|
@ -95,7 +95,7 @@
|
|||
"dotenv": "^16.4.7",
|
||||
"drizzle-orm": "^0.38.3",
|
||||
"drizzle-zod": "^0.6.1",
|
||||
"hono": "^4.6.14",
|
||||
"hono": "^4.6.15",
|
||||
"hono-pino": "^0.7.0",
|
||||
"hono-rate-limiter": "^0.4.2",
|
||||
"hono-zod-openapi": "^0.5.0",
|
||||
|
|
|
|||
104
pnpm-lock.yaml
104
pnpm-lock.yaml
|
|
@ -10,16 +10,16 @@ importers:
|
|||
dependencies:
|
||||
'@hono/swagger-ui':
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0(hono@4.6.14)
|
||||
version: 0.5.0(hono@4.6.15)
|
||||
'@hono/zod-openapi':
|
||||
specifier: ^0.18.3
|
||||
version: 0.18.3(hono@4.6.14)(zod@3.24.1)
|
||||
version: 0.18.3(hono@4.6.15)(zod@3.24.1)
|
||||
'@hono/zod-validator':
|
||||
specifier: ^0.4.2
|
||||
version: 0.4.2(hono@4.6.14)(zod@3.24.1)
|
||||
version: 0.4.2(hono@4.6.15)(zod@3.24.1)
|
||||
'@inlang/paraglide-sveltekit':
|
||||
specifier: ^0.15.0
|
||||
version: 0.15.0(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))
|
||||
version: 0.15.0(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))
|
||||
'@needle-di/core':
|
||||
specifier: ^0.8.4
|
||||
version: 0.8.4
|
||||
|
|
@ -46,7 +46,7 @@ importers:
|
|||
version: 1.0.0
|
||||
'@scalar/hono-api-reference':
|
||||
specifier: ^0.5.162
|
||||
version: 0.5.165(hono@4.6.14)
|
||||
version: 0.5.165(hono@4.6.15)
|
||||
'@tailwindcss/container-queries':
|
||||
specifier: ^0.1.1
|
||||
version: 0.1.1(tailwindcss@3.4.17)
|
||||
|
|
@ -75,17 +75,17 @@ importers:
|
|||
specifier: ^0.6.1
|
||||
version: 0.6.1(drizzle-orm@0.38.3(@types/pg@8.11.10)(@types/react@19.0.2)(pg@8.13.1)(postgres@3.4.5)(react@18.3.1))(zod@3.24.1)
|
||||
hono:
|
||||
specifier: ^4.6.14
|
||||
version: 4.6.14
|
||||
specifier: ^4.6.15
|
||||
version: 4.6.15
|
||||
hono-pino:
|
||||
specifier: ^0.7.0
|
||||
version: 0.7.0(hono@4.6.14)(pino@9.6.0)
|
||||
version: 0.7.0(hono@4.6.15)(pino@9.6.0)
|
||||
hono-rate-limiter:
|
||||
specifier: ^0.4.2
|
||||
version: 0.4.2(hono@4.6.14)
|
||||
version: 0.4.2(hono@4.6.15)
|
||||
hono-zod-openapi:
|
||||
specifier: ^0.5.0
|
||||
version: 0.5.0(hono@4.6.14)(zod@3.24.1)
|
||||
version: 0.5.0(hono@4.6.15)(zod@3.24.1)
|
||||
ioredis:
|
||||
specifier: ^5.4.2
|
||||
version: 5.4.2
|
||||
|
|
@ -121,7 +121,7 @@ importers:
|
|||
version: 0.33.5
|
||||
stoker:
|
||||
specifier: ^1.4.2
|
||||
version: 1.4.2(@asteasolutions/zod-to-openapi@7.3.0(zod@3.24.1))(@hono/zod-openapi@0.18.3(hono@4.6.14)(zod@3.24.1))(hono@4.6.14)(openapi3-ts@4.4.0)
|
||||
version: 1.4.2(@asteasolutions/zod-to-openapi@7.3.0(zod@3.24.1))(@hono/zod-openapi@0.18.3(hono@4.6.15)(zod@3.24.1))(hono@4.6.15)(openapi3-ts@4.4.0)
|
||||
devDependencies:
|
||||
'@biomejs/biome':
|
||||
specifier: ^1.9.4
|
||||
|
|
@ -167,13 +167,13 @@ importers:
|
|||
version: 8.4.7(storybook@8.4.7)
|
||||
'@sveltejs/adapter-node':
|
||||
specifier: ^5.2.9
|
||||
version: 5.2.11(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))
|
||||
version: 5.2.11(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))
|
||||
'@sveltejs/enhanced-img':
|
||||
specifier: ^0.4.4
|
||||
version: 0.4.4(rollup@4.29.1)(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/kit':
|
||||
specifier: ^2.9.0
|
||||
version: 2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
specifier: ^2.15.1
|
||||
version: 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/vite-plugin-svelte':
|
||||
specifier: ^5.0.3
|
||||
version: 5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
|
|
@ -212,7 +212,7 @@ importers:
|
|||
version: 0.30.1
|
||||
formsnap:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(svelte@5.16.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2))
|
||||
version: 2.0.0(svelte@5.16.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2))
|
||||
lucide-svelte:
|
||||
specifier: ^0.469.0
|
||||
version: 0.469.0(svelte@5.16.0)
|
||||
|
|
@ -239,10 +239,10 @@ importers:
|
|||
version: 0.3.28(svelte@5.16.0)
|
||||
sveltekit-flash-message:
|
||||
specifier: ^2.4.4
|
||||
version: 2.4.4(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)
|
||||
version: 2.4.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)
|
||||
sveltekit-superforms:
|
||||
specifier: ^2.22.1
|
||||
version: 2.22.1(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)
|
||||
version: 2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)
|
||||
tailwind-merge:
|
||||
specifier: ^2.6.0
|
||||
version: 2.6.0
|
||||
|
|
@ -2160,8 +2160,8 @@ packages:
|
|||
svelte: ^5.0.0
|
||||
vite: '>= 5.0.0'
|
||||
|
||||
'@sveltejs/kit@2.15.0':
|
||||
resolution: {integrity: sha512-FI1bhfhFNGI2sKg+BhiRyM4eaOvX+KZqRYSQqL5PK3ZZREX2xufZ6MzZAw79N846OnIxYNqcz/3VOUq+FPDd3w==}
|
||||
'@sveltejs/kit@2.15.1':
|
||||
resolution: {integrity: sha512-8t7D3hQHbUDMiaQ2RVnjJJ/+Ur4Fn/tkeySJCsHtX346Q9cp3LAnav8xXdfuqYNJwpUGX0x3BqF1uvbmXQw93A==}
|
||||
engines: {node: '>=18.13'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
|
|
@ -3411,8 +3411,8 @@ packages:
|
|||
hono: ^4.6.10
|
||||
zod: ^3.21.4
|
||||
|
||||
hono@4.6.14:
|
||||
resolution: {integrity: sha512-j4VkyUp2xazGJ8eCCLN1Vm/bxdvm/j5ZuU9AIjLu9vapn2M44p9L3Ktr9Vnb2RN2QtcR/wVjZVMlT5k7GJQgPw==}
|
||||
hono@4.6.15:
|
||||
resolution: {integrity: sha512-OiQwvAOAaI2JrABBH69z5rsctHDzFzIKJge0nYXgtzGJ0KftwLWcBXm1upJC23/omNRtnqM0gjRMbtXshPdqhQ==}
|
||||
engines: {node: '>=16.9.0'}
|
||||
|
||||
hookable@5.5.3:
|
||||
|
|
@ -5724,20 +5724,20 @@ snapshots:
|
|||
'@hapi/hoek': 9.3.0
|
||||
optional: true
|
||||
|
||||
'@hono/swagger-ui@0.5.0(hono@4.6.14)':
|
||||
'@hono/swagger-ui@0.5.0(hono@4.6.15)':
|
||||
dependencies:
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
|
||||
'@hono/zod-openapi@0.18.3(hono@4.6.14)(zod@3.24.1)':
|
||||
'@hono/zod-openapi@0.18.3(hono@4.6.15)(zod@3.24.1)':
|
||||
dependencies:
|
||||
'@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.1)
|
||||
'@hono/zod-validator': 0.4.2(hono@4.6.14)(zod@3.24.1)
|
||||
hono: 4.6.14
|
||||
'@hono/zod-validator': 0.4.2(hono@4.6.15)(zod@3.24.1)
|
||||
hono: 4.6.15
|
||||
zod: 3.24.1
|
||||
|
||||
'@hono/zod-validator@0.4.2(hono@4.6.14)(zod@3.24.1)':
|
||||
'@hono/zod-validator@0.4.2(hono@4.6.15)(zod@3.24.1)':
|
||||
dependencies:
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
zod: 3.24.1
|
||||
|
||||
'@humanwhocodes/config-array@0.9.5':
|
||||
|
|
@ -5869,12 +5869,12 @@ snapshots:
|
|||
- babel-plugin-macros
|
||||
- debug
|
||||
|
||||
'@inlang/paraglide-sveltekit@0.15.0(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))':
|
||||
'@inlang/paraglide-sveltekit@0.15.0(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))':
|
||||
dependencies:
|
||||
'@inlang/paraglide-js': 1.11.3
|
||||
'@inlang/paraglide-vite': 1.3.0
|
||||
'@lix-js/client': 2.2.1
|
||||
'@sveltejs/kit': 2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
commander: 12.1.0
|
||||
dedent: 1.5.1
|
||||
devalue: 4.3.3
|
||||
|
|
@ -6388,10 +6388,10 @@ snapshots:
|
|||
'@rollup/rollup-win32-x64-msvc@4.29.1':
|
||||
optional: true
|
||||
|
||||
'@scalar/hono-api-reference@0.5.165(hono@4.6.14)':
|
||||
'@scalar/hono-api-reference@0.5.165(hono@4.6.15)':
|
||||
dependencies:
|
||||
'@scalar/types': 0.0.25
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
|
||||
'@scalar/openapi-types@0.1.5': {}
|
||||
|
||||
|
|
@ -6690,12 +6690,12 @@ snapshots:
|
|||
dependencies:
|
||||
storybook: 8.4.7
|
||||
|
||||
'@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))':
|
||||
'@sveltejs/adapter-node@5.2.11(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))':
|
||||
dependencies:
|
||||
'@rollup/plugin-commonjs': 28.0.2(rollup@4.29.1)
|
||||
'@rollup/plugin-json': 6.1.0(rollup@4.29.1)
|
||||
'@rollup/plugin-node-resolve': 16.0.0(rollup@4.29.1)
|
||||
'@sveltejs/kit': 2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
rollup: 4.29.1
|
||||
|
||||
'@sveltejs/enhanced-img@0.4.4(rollup@4.29.1)(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))':
|
||||
|
|
@ -6710,7 +6710,7 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- rollup
|
||||
|
||||
'@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))':
|
||||
'@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))':
|
||||
dependencies:
|
||||
'@sveltejs/vite-plugin-svelte': 5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@types/cookie': 0.6.0
|
||||
|
|
@ -7897,11 +7897,11 @@ snapshots:
|
|||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
|
||||
formsnap@2.0.0(svelte@5.16.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)):
|
||||
formsnap@2.0.0(svelte@5.16.0)(sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)):
|
||||
dependencies:
|
||||
svelte: 5.16.0
|
||||
svelte-toolbelt: 0.5.0(svelte@5.16.0)
|
||||
sveltekit-superforms: 2.22.1(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)
|
||||
sveltekit-superforms: 2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2)
|
||||
|
||||
forwarded@0.2.0: {}
|
||||
|
||||
|
|
@ -7998,24 +7998,24 @@ snapshots:
|
|||
|
||||
help-me@5.0.0: {}
|
||||
|
||||
hono-pino@0.7.0(hono@4.6.14)(pino@9.6.0):
|
||||
hono-pino@0.7.0(hono@4.6.15)(pino@9.6.0):
|
||||
dependencies:
|
||||
defu: 6.1.4
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
pino: 9.6.0
|
||||
|
||||
hono-rate-limiter@0.4.2(hono@4.6.14):
|
||||
hono-rate-limiter@0.4.2(hono@4.6.15):
|
||||
dependencies:
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
|
||||
hono-zod-openapi@0.5.0(hono@4.6.14)(zod@3.24.1):
|
||||
hono-zod-openapi@0.5.0(hono@4.6.15)(zod@3.24.1):
|
||||
dependencies:
|
||||
'@hono/zod-validator': 0.4.2(hono@4.6.14)(zod@3.24.1)
|
||||
hono: 4.6.14
|
||||
'@hono/zod-validator': 0.4.2(hono@4.6.15)(zod@3.24.1)
|
||||
hono: 4.6.15
|
||||
zod: 3.24.1
|
||||
zod-openapi: 4.2.1(zod@3.24.1)
|
||||
|
||||
hono@4.6.14: {}
|
||||
hono@4.6.15: {}
|
||||
|
||||
hookable@5.5.3: {}
|
||||
|
||||
|
|
@ -9024,13 +9024,13 @@ snapshots:
|
|||
|
||||
std-env@3.8.0: {}
|
||||
|
||||
stoker@1.4.2(@asteasolutions/zod-to-openapi@7.3.0(zod@3.24.1))(@hono/zod-openapi@0.18.3(hono@4.6.14)(zod@3.24.1))(hono@4.6.14)(openapi3-ts@4.4.0):
|
||||
stoker@1.4.2(@asteasolutions/zod-to-openapi@7.3.0(zod@3.24.1))(@hono/zod-openapi@0.18.3(hono@4.6.15)(zod@3.24.1))(hono@4.6.15)(openapi3-ts@4.4.0):
|
||||
dependencies:
|
||||
'@asteasolutions/zod-to-openapi': 7.3.0(zod@3.24.1)
|
||||
hono: 4.6.14
|
||||
hono: 4.6.15
|
||||
openapi3-ts: 4.4.0
|
||||
optionalDependencies:
|
||||
'@hono/zod-openapi': 0.18.3(hono@4.6.14)(zod@3.24.1)
|
||||
'@hono/zod-openapi': 0.18.3(hono@4.6.15)(zod@3.24.1)
|
||||
|
||||
storybook@8.4.7:
|
||||
dependencies:
|
||||
|
|
@ -9223,14 +9223,14 @@ snapshots:
|
|||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
sveltekit-flash-message@2.4.4(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0):
|
||||
sveltekit-flash-message@2.4.4(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0):
|
||||
dependencies:
|
||||
'@sveltejs/kit': 2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
svelte: 5.16.0
|
||||
|
||||
sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2):
|
||||
sveltekit-superforms@2.22.1(@sveltejs/kit@2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(@types/json-schema@7.0.15)(svelte@5.16.0)(typescript@5.7.2):
|
||||
dependencies:
|
||||
'@sveltejs/kit': 2.15.0(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
'@sveltejs/kit': 2.15.1(@sveltejs/vite-plugin-svelte@5.0.3(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1)))(svelte@5.16.0)(vite@6.0.6(@types/node@22.10.2)(jiti@1.21.7)(tsx@4.19.2)(yaml@2.6.1))
|
||||
devalue: 5.1.1
|
||||
memoize-weak: 1.0.2
|
||||
svelte: 5.16.0
|
||||
|
|
|
|||
7
src/lib/components/ui/separator/index.ts
Normal file
7
src/lib/components/ui/separator/index.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
import Root from "./separator.svelte";
|
||||
|
||||
export {
|
||||
Root,
|
||||
//
|
||||
Root as Separator,
|
||||
};
|
||||
22
src/lib/components/ui/separator/separator.svelte
Normal file
22
src/lib/components/ui/separator/separator.svelte
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<script lang="ts">
|
||||
import { Separator as SeparatorPrimitive } from "bits-ui";
|
||||
import { cn } from "$lib/utils.js";
|
||||
|
||||
let {
|
||||
ref = $bindable(null),
|
||||
class: className,
|
||||
orientation = "horizontal",
|
||||
...restProps
|
||||
}: SeparatorPrimitive.RootProps = $props();
|
||||
</script>
|
||||
|
||||
<SeparatorPrimitive.Root
|
||||
bind:ref
|
||||
class={cn(
|
||||
"bg-border shrink-0",
|
||||
orientation === "horizontal" ? "h-[1px] w-full" : "min-h-full w-[1px]",
|
||||
className
|
||||
)}
|
||||
{orientation}
|
||||
{...restProps}
|
||||
/>
|
||||
44
src/lib/server/api/common/services/tokens.service.ts
Normal file
44
src/lib/server/api/common/services/tokens.service.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { inject, injectable } from '@needle-di/core';
|
||||
import { generateRandomString, type RandomReader } from "@oslojs/crypto/random";
|
||||
import { HashingService } from './hashing.service';
|
||||
import { createDate, TimeSpan, type TimeSpanUnit } from '@/utils/timespan';
|
||||
|
||||
@injectable()
|
||||
export class TokensService {
|
||||
constructor(private hashingService = inject(HashingService)) {}
|
||||
|
||||
generateToken() {
|
||||
const alphabet = '23456789ACDEFGHJKLMNPQRSTUVWXYZ'; // alphabet with removed look-alike characters (0, 1, O, I)
|
||||
const random: RandomReader = {
|
||||
read(bytes) {
|
||||
crypto.getRandomValues(bytes);
|
||||
}
|
||||
}
|
||||
return generateRandomString(random, alphabet, 10);
|
||||
}
|
||||
|
||||
generateTokenWithExpiry(number: number, lifespan: TimeSpanUnit) {
|
||||
return {
|
||||
token: this.generateToken(),
|
||||
expiry: createDate(new TimeSpan(number, lifespan)),
|
||||
};
|
||||
}
|
||||
|
||||
async generateTokenWithExpiryAndHash(number: number, lifespan: TimeSpanUnit) {
|
||||
const token = this.generateToken();
|
||||
const hashedToken = await this.hashingService.hash(token);
|
||||
return {
|
||||
token,
|
||||
hashedToken,
|
||||
expiry: createDate(new TimeSpan(number, lifespan)),
|
||||
};
|
||||
}
|
||||
|
||||
async createHashedToken(token: string) {
|
||||
return this.hashingService.hash(token);
|
||||
}
|
||||
|
||||
async verifyHashedToken(hashedToken: string, token: string) {
|
||||
return this.hashingService.compare(hashedToken, token);
|
||||
}
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ import { UsersRepository } from '../../users/users.repository';
|
|||
import { VerificationCodesService } from '../../common/services/verification-codes.service';
|
||||
import type { LoginRequestDto } from './dtos/login-request.dto';
|
||||
import { CredentialsRepository } from '../../users/credentials.repository';
|
||||
import { TokensService } from '../../common/services/tokens.service';
|
||||
|
||||
@injectable()
|
||||
export class LoginRequestsService {
|
||||
|
|
@ -22,6 +23,7 @@ export class LoginRequestsService {
|
|||
private verificationCodesService = inject(VerificationCodesService),
|
||||
private usersService = inject(UsersService),
|
||||
private sessionsService = inject(SessionsService),
|
||||
private tokensService = inject(TokensService),
|
||||
private mailer = inject(MailerService),
|
||||
) {}
|
||||
|
||||
|
|
@ -38,7 +40,7 @@ export class LoginRequestsService {
|
|||
throw BadRequest('Invalid credentials');
|
||||
}
|
||||
|
||||
if (!(await this.tokensService.verifyHashedToken(credential.secret_data, data.password))) {
|
||||
if (!(await this.tokensService.verifyHashedToken(credential.secret_data, password))) {
|
||||
throw BadRequest('Invalid credentials');
|
||||
}
|
||||
|
||||
|
|
|
|||
58
src/lib/utils/timespan.ts
Normal file
58
src/lib/utils/timespan.ts
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
export type TimeSpanUnit = "ms" | "s" | "m" | "h" | "d" | "w";
|
||||
|
||||
export class TimeSpan {
|
||||
constructor(value: number, unit: TimeSpanUnit) {
|
||||
this.value = value;
|
||||
this.unit = unit;
|
||||
}
|
||||
|
||||
public value: number;
|
||||
public unit: TimeSpanUnit;
|
||||
|
||||
public milliseconds(): number {
|
||||
if (this.unit === "ms") {
|
||||
return this.value;
|
||||
}
|
||||
if (this.unit === "s") {
|
||||
return this.value * 1000;
|
||||
}
|
||||
if (this.unit === "m") {
|
||||
return this.value * 1000 * 60;
|
||||
}
|
||||
if (this.unit === "h") {
|
||||
return this.value * 1000 * 60 * 60;
|
||||
}
|
||||
if (this.unit === "d") {
|
||||
return this.value * 1000 * 60 * 60 * 24;
|
||||
}
|
||||
return this.value * 1000 * 60 * 60 * 24 * 7;
|
||||
}
|
||||
|
||||
public seconds(): number {
|
||||
return this.milliseconds() / 1000;
|
||||
}
|
||||
|
||||
public transform(x: number): TimeSpan {
|
||||
return new TimeSpan(Math.round(this.milliseconds() * x), "ms");
|
||||
}
|
||||
}
|
||||
|
||||
export function isWithinExpirationDate(date: Date): boolean {
|
||||
return Date.now() < date.getTime();
|
||||
}
|
||||
|
||||
export function createDate(timeSpan: TimeSpan): Date {
|
||||
return new Date(Date.now() + timeSpan.milliseconds());
|
||||
}
|
||||
|
||||
export type TypedArray =
|
||||
| Uint8Array
|
||||
| Int8Array
|
||||
| Uint16Array
|
||||
| Int16Array
|
||||
| Uint32Array
|
||||
| Int32Array
|
||||
| Float32Array
|
||||
| Float64Array
|
||||
| BigInt64Array
|
||||
| BigUint64Array;
|
||||
|
|
@ -28,11 +28,12 @@
|
|||
import ChevronLeftIcon from 'lucide-svelte/icons/chevron-left';
|
||||
import { queryHandler } from '$lib/tanstack-query';
|
||||
import * as InputOTP from '$lib/components/ui/input-otp/index.js';
|
||||
import Separator from '@/components/ui/separator/separator.svelte';
|
||||
|
||||
const RESEND_VERIFICATION_CODE_COOLDOWN = 60;
|
||||
|
||||
let queryClient = useQueryClient();
|
||||
let step = $state<'login' | 'request' | 'verify'>('request');
|
||||
let step = $state<'login' | 'totp' | 'request' | 'verify'>('request');
|
||||
let countdownTimer = $state(RESEND_VERIFICATION_CODE_COOLDOWN);
|
||||
let resendVerificationCodeOnCooldown = $derived(
|
||||
countdownTimer != RESEND_VERIFICATION_CODE_COOLDOWN
|
||||
|
|
@ -42,9 +43,12 @@
|
|||
const requestUsernamePasswordLoginMutation = createMutation({
|
||||
...queryHandler().iam.requestUsernamePasswordLogin(),
|
||||
onSuccess(_data, variables, _context) {
|
||||
step = 'verify';
|
||||
$verifyForm.email = variables.json.email;
|
||||
$verifyForm.
|
||||
step = 'totp';
|
||||
$loginPasswordForm.email = variables.json.email;
|
||||
$loginPasswordForm.password = variables.json.password;
|
||||
},
|
||||
onError(error) {
|
||||
loginPasswordErrors.set({ email: [error.message] });
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -71,17 +75,30 @@
|
|||
}
|
||||
});
|
||||
|
||||
/* ------------------------------- Login Form ------------------------------- */
|
||||
/* ------------------------------- Login Password Form ------------------------------- */
|
||||
const sf_login_username_password = superForm(defaults(zod(loginPasswordSchema)), {
|
||||
resetForm: false,
|
||||
SPA: true,
|
||||
validators: zod(loginPasswordSchema),
|
||||
async onUpdated(event) {
|
||||
if (!event.form.valid) return;
|
||||
await $requestUsernamePasswordLogin.mutateAsync({ json: event.form.data });
|
||||
if (!event.form.valid) {
|
||||
return;
|
||||
}
|
||||
await $requestUsernamePasswordLoginMutation.mutateAsync({ json: event.form.data });
|
||||
|
||||
if ($requestUsernamePasswordLoginMutation.error) {
|
||||
return setError(event.form, 'email', $requestUsernamePasswordLoginMutation.error.message);
|
||||
}
|
||||
|
||||
step = 'totp';
|
||||
$loginPasswordForm.email = event.form.data.email;
|
||||
}
|
||||
})
|
||||
|
||||
const { form: loginPasswordForm, enhance: loginPasswordEnhance, errors: loginPasswordErrors } = sf_login_username_password;
|
||||
|
||||
/* ------------------------------- Login Form ------------------------------- */
|
||||
|
||||
const sf_login = superForm(defaults(zod(loginSchema)), {
|
||||
resetForm: false,
|
||||
SPA: true,
|
||||
|
|
@ -95,14 +112,14 @@
|
|||
}
|
||||
});
|
||||
|
||||
if ($requestMutation.error)
|
||||
if ($requestMutation.error) {
|
||||
return setError(event.form, 'email', $requestMutation.error.message);
|
||||
}
|
||||
|
||||
step = 'verify';
|
||||
$verifyForm.email = event.form.data.email;
|
||||
}
|
||||
});
|
||||
const { form: loginPasswordForm, enhance: loginPasswordEnhance, errors: loginPasswordErrors } = sf_login_username_password;
|
||||
|
||||
const { form: loginForm, enhance: loginEnhance, errors: requestErrors } = sf_login;
|
||||
|
||||
|
|
@ -161,7 +178,7 @@
|
|||
<Card.Description>Enter your email below to login to your account</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<form use:loginEnhance method="POST" class="grid gap-4">
|
||||
<form use:loginPasswordEnhance method="POST" class="grid gap-4">
|
||||
<Form.Field form={sf_login_username_password} name="email">
|
||||
<Form.Control>
|
||||
{#snippet children({ props })}
|
||||
|
|
@ -182,7 +199,9 @@
|
|||
<Form.Description />
|
||||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
<Button type="submit" class="w-full">Continue with Email</Button>
|
||||
<Button type="submit" class="w-full">Submit</Button>
|
||||
<Separator class="my-4" />
|
||||
<Button type="button" onclick={() => (step = 'request')}>Login with Email</Button>
|
||||
</form>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
|
|
@ -207,6 +226,8 @@
|
|||
<Form.FieldErrors />
|
||||
</Form.Field>
|
||||
<Button type="submit" class="w-full">Continue with Email</Button>
|
||||
<Separator class="my-4" />
|
||||
<Button type="button" onclick={() => (step = 'login')}>Login with Username & Password</Button>
|
||||
</form>
|
||||
</Card.Content>
|
||||
</Card.Root>
|
||||
|
|
|
|||
Loading…
Reference in a new issue