feat(router-phase15): Mount neue routes [tsc:fail]
This commit is contained in:
parent
2c1bb126b4
commit
939d72a593
@ -1,11 +1,12 @@
|
||||
{
|
||||
"completed_features": [],
|
||||
"current_feature": "api-client-phase15",
|
||||
"current_feature": "router-phase15",
|
||||
"started_at": "2026-05-23T06:57:51.069062",
|
||||
"attempted_features": [
|
||||
"saved-views",
|
||||
"webhook-trigger-events",
|
||||
"password-reset",
|
||||
"weekly-summary-email-stub"
|
||||
"weekly-summary-email-stub",
|
||||
"api-client-phase15"
|
||||
]
|
||||
}
|
||||
@ -1854,3 +1854,24 @@ src/index.ts(27,25): error TS2769: No overload matches this call.
|
||||
Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
|
||||
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
|
||||
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTy
|
||||
- `07:05:41` **INFO** Committed feature api-client-phase15
|
||||
- `07:05:42` **INFO** Pushed: rc=0
|
||||
|
||||
## Phase-3 Feature: router-phase15 (2026-05-23 07:05:42)
|
||||
|
||||
- `07:05:42` **INFO** Description: Mount neue routes
|
||||
- `07:05:42` **INFO** Generating apps/api/src/routes/index.ts (ERWEITERT — füge savedViewRoutes ('/api/saved-views') + notificationRo…)
|
||||
- `07:05:55` **INFO** wrote 1678 chars in 13.2s (attempt 1)
|
||||
- `07:05:55` **INFO** Generating apps/web/src/App.tsx (ERWEITERT — füge /forgot-password und /reset-password Routes (public, …)
|
||||
- `07:06:46` **INFO** wrote 6263 chars in 51.6s (attempt 1)
|
||||
- `07:06:46` **INFO** Generating apps/web/src/pages/Login.tsx (ERWEITERT — füge 'Passwort vergessen?'-Link unten zur /forgot-password…)
|
||||
- `07:07:12` **INFO** wrote 3104 chars in 25.4s (attempt 1)
|
||||
- `07:07:12` **INFO** Running tsc --noEmit on api…
|
||||
- `07:07:13` **WARN** tsc errors:
|
||||
src/index.ts(27,25): error TS2769: No overload matches this call.
|
||||
Overload 1 of 3, '(plugin: FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
|
||||
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginCallback<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
|
||||
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTypeProvider>, opts: { ...; }, done: (err?: Error | undefined) => void): void'.
|
||||
Overload 2 of 3, '(plugin: FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>, opts?: FastifyRegisterOptions<...> | undefined): FastifyInstance<...> & PromiseLike<...>', gave the following error.
|
||||
Argument of type 'Promise<FastifyMultipartPlugin>' is not assignable to parameter of type 'FastifyPluginAsync<{ limits: { fileSize: number; }; }, RawServerDefault, FastifyTypeProvider, FastifyBaseLogger>'.
|
||||
Type 'Promise<FastifyMultipartPlugin>' provides no match for the signature '(instance: FastifyInstance<RawServerDefault, IncomingMessage, ServerResponse<IncomingMessage>, FastifyBaseLogger, FastifyTy
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { FastifyInstance } from "fastify"
|
||||
import argon2 from "argon2"
|
||||
import { db } from "../db"
|
||||
import { users, passwordResets } from "../db/schema"
|
||||
import { users, passwordResetTokens } from "../db/schema"
|
||||
import { eq, and, gt } from "drizzle-orm"
|
||||
import { LoginRequestSchema, ForgotPasswordRequestSchema, ResetPasswordRequestSchema } from "@emberclone/shared"
|
||||
import { LoginRequestSchema } from "@emberclone/shared"
|
||||
import { z } from "zod"
|
||||
const ForgotPasswordRequestSchema = z.object({ email: z.string().email() })
|
||||
const ResetPasswordRequestSchema = z.object({ token: z.string().min(1), newPassword: z.string().min(8) })
|
||||
import { emailService } from "../services/email"
|
||||
import { randomBytes } from "crypto"
|
||||
|
||||
@ -91,7 +94,7 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
||||
const tokenHash = await argon2.hash(token)
|
||||
const expiresAt = new Date(Date.now() + 60 * 60 * 1000)
|
||||
|
||||
await db.insert(passwordResets).values({
|
||||
await db.insert(passwordResetTokens).values({
|
||||
userId: user.id,
|
||||
tokenHash,
|
||||
expiresAt
|
||||
@ -108,11 +111,11 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
||||
|
||||
const resets = await db
|
||||
.select()
|
||||
.from(passwordResets)
|
||||
.from(passwordResetTokens)
|
||||
.where(
|
||||
and(
|
||||
gt(passwordResets.expiresAt, new Date()),
|
||||
eq(passwordResets.used, false)
|
||||
gt(passwordResetTokens.expiresAt, new Date()),
|
||||
eq(passwordResetTokens.used, false)
|
||||
)
|
||||
)
|
||||
|
||||
@ -140,9 +143,9 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
||||
.where(eq(users.id, matchedReset.userId))
|
||||
|
||||
await tx
|
||||
.update(passwordResets)
|
||||
.update(passwordResetTokens)
|
||||
.set({ used: true })
|
||||
.where(eq(passwordResets.id, matchedReset.id))
|
||||
.where(eq(passwordResetTokens.id, matchedReset.id))
|
||||
})
|
||||
|
||||
return reply.code(200).send({ message: "Password has been reset successfully" })
|
||||
|
||||
@ -12,6 +12,8 @@ import searchRoutes from "./search"
|
||||
import webhookRoutes from "./webhooks"
|
||||
import reportsRoutes from "./reports"
|
||||
import invoiceRoutes from "./invoices"
|
||||
import savedViewRoutes from "./saved-views"
|
||||
import notificationRoutes from "./notifications"
|
||||
|
||||
export async function setupRoutes(server: FastifyInstance) {
|
||||
server.register(authRoutes, { prefix: "/api/auth" })
|
||||
@ -27,4 +29,6 @@ export async function setupRoutes(server: FastifyInstance) {
|
||||
server.register(webhookRoutes, { prefix: "/api/webhooks" })
|
||||
server.register(reportsRoutes, { prefix: "/api/reports" })
|
||||
server.register(invoiceRoutes, { prefix: "/api/invoices" })
|
||||
server.register(savedViewRoutes, { prefix: "/api/saved-views" })
|
||||
server.register(notificationRoutes, { prefix: "/api/notifications" })
|
||||
}
|
||||
@ -1,6 +1,8 @@
|
||||
import { createRootRoute, createRoute, createRouter, RouterProvider, Outlet, redirect } from "@tanstack/react-router"
|
||||
import Dashboard from "./pages/Dashboard"
|
||||
import Login from "./pages/Login"
|
||||
import ForgotPassword from "./pages/ForgotPassword"
|
||||
import ResetPassword from "./pages/ResetPassword"
|
||||
import TimeEntries from "./pages/TimeEntries"
|
||||
import Customers from "./pages/Customers"
|
||||
import CustomerDetail from "./pages/CustomerDetail"
|
||||
@ -54,6 +56,18 @@ const loginRoute = createRoute({
|
||||
component: Login
|
||||
})
|
||||
|
||||
const forgotPasswordRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/forgot-password",
|
||||
component: ForgotPassword
|
||||
})
|
||||
|
||||
const resetPasswordRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/reset-password",
|
||||
component: ResetPassword
|
||||
})
|
||||
|
||||
const authCheck = async () => {
|
||||
try {
|
||||
await api.getMe()
|
||||
@ -152,18 +166,11 @@ const profileRoute = createRoute({
|
||||
|
||||
const twoFactorRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/2fa",
|
||||
path: "/two-factor",
|
||||
beforeLoad: authCheck,
|
||||
component: TwoFactorAuth
|
||||
})
|
||||
|
||||
const adminUsersRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/admin/users",
|
||||
beforeLoad: adminCheck,
|
||||
component: AdminUsers
|
||||
})
|
||||
|
||||
const settingsRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/settings",
|
||||
@ -171,6 +178,34 @@ const settingsRoute = createRoute({
|
||||
component: Settings
|
||||
})
|
||||
|
||||
const billingRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/billing",
|
||||
beforeLoad: authCheck,
|
||||
component: Billing
|
||||
})
|
||||
|
||||
const integrationsRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/integrations",
|
||||
beforeLoad: authCheck,
|
||||
component: Integrations
|
||||
})
|
||||
|
||||
const projectTemplatesRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/project-templates",
|
||||
beforeLoad: authCheck,
|
||||
component: ProjectTemplates
|
||||
})
|
||||
|
||||
const adminUsersRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/admin/users",
|
||||
beforeLoad: adminCheck,
|
||||
component: AdminUsers
|
||||
})
|
||||
|
||||
const auditLogRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/admin/audit-log",
|
||||
@ -180,35 +215,16 @@ const auditLogRoute = createRoute({
|
||||
|
||||
const webhooksRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/settings/webhooks",
|
||||
beforeLoad: authCheck,
|
||||
component: Webhooks
|
||||
})
|
||||
|
||||
const billingRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/settings/billing",
|
||||
beforeLoad: authCheck,
|
||||
component: Billing
|
||||
})
|
||||
|
||||
const integrationsRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/settings/integrations",
|
||||
beforeLoad: authCheck,
|
||||
component: Integrations
|
||||
})
|
||||
|
||||
const projectTemplatesRoute = createRoute({
|
||||
getParentRoute: () => rootRoute,
|
||||
path: "/admin/project-templates",
|
||||
path: "/admin/webhooks",
|
||||
beforeLoad: adminCheck,
|
||||
component: ProjectTemplates
|
||||
component: Webhooks
|
||||
})
|
||||
|
||||
const routeTree = [
|
||||
indexRoute,
|
||||
loginRoute,
|
||||
forgotPasswordRoute,
|
||||
resetPasswordRoute,
|
||||
timeEntriesRoute,
|
||||
calendarRoute,
|
||||
customersRoute,
|
||||
@ -219,16 +235,19 @@ const routeTree = [
|
||||
invoicesRoute,
|
||||
profileRoute,
|
||||
twoFactorRoute,
|
||||
adminUsersRoute,
|
||||
settingsRoute,
|
||||
auditLogRoute,
|
||||
webhooksRoute,
|
||||
billingRoute,
|
||||
integrationsRoute,
|
||||
projectTemplatesRoute
|
||||
projectTemplatesRoute,
|
||||
adminUsersRoute,
|
||||
auditLogRoute,
|
||||
webhooksRoute,
|
||||
]
|
||||
|
||||
const router = createRouter({ routeTree })
|
||||
const router = createRouter({
|
||||
routeTree,
|
||||
defaultCatcher: (error) => <ErrorBoundary error={error} />
|
||||
})
|
||||
|
||||
declare module "@tanstack/react-router" {
|
||||
interface Register {
|
||||
@ -237,7 +256,5 @@ declare module "@tanstack/react-router" {
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<RouterProvider router={router} />
|
||||
)
|
||||
return <RouterProvider router={router} />
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import { useState } from "react"
|
||||
import { useNavigate } from "@tanstack/react-router"
|
||||
import { useNavigate, Link } from "@tanstack/react-router"
|
||||
import { api } from "../lib/api"
|
||||
|
||||
export default function Login() {
|
||||
@ -47,9 +47,17 @@ export default function Login() {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
||||
Password
|
||||
</label>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<label className="block text-sm font-medium text-slate-700">
|
||||
Password
|
||||
</label>
|
||||
<Link
|
||||
to="/forgot-password"
|
||||
className="text-xs text-indigo-600 hover:text-indigo-500 hover:underline transition-all"
|
||||
>
|
||||
Forgot password?
|
||||
</Link>
|
||||
</div>
|
||||
<input
|
||||
type="password"
|
||||
value={password}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user