feat(router-phase15): Mount neue routes [tsc:fail]
This commit is contained in:
parent
2c1bb126b4
commit
939d72a593
@ -1,11 +1,12 @@
|
|||||||
{
|
{
|
||||||
"completed_features": [],
|
"completed_features": [],
|
||||||
"current_feature": "api-client-phase15",
|
"current_feature": "router-phase15",
|
||||||
"started_at": "2026-05-23T06:57:51.069062",
|
"started_at": "2026-05-23T06:57:51.069062",
|
||||||
"attempted_features": [
|
"attempted_features": [
|
||||||
"saved-views",
|
"saved-views",
|
||||||
"webhook-trigger-events",
|
"webhook-trigger-events",
|
||||||
"password-reset",
|
"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.
|
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>'.
|
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
|
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 { FastifyInstance } from "fastify"
|
||||||
import argon2 from "argon2"
|
import argon2 from "argon2"
|
||||||
import { db } from "../db"
|
import { db } from "../db"
|
||||||
import { users, passwordResets } from "../db/schema"
|
import { users, passwordResetTokens } from "../db/schema"
|
||||||
import { eq, and, gt } from "drizzle-orm"
|
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 { emailService } from "../services/email"
|
||||||
import { randomBytes } from "crypto"
|
import { randomBytes } from "crypto"
|
||||||
|
|
||||||
@ -91,7 +94,7 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
|||||||
const tokenHash = await argon2.hash(token)
|
const tokenHash = await argon2.hash(token)
|
||||||
const expiresAt = new Date(Date.now() + 60 * 60 * 1000)
|
const expiresAt = new Date(Date.now() + 60 * 60 * 1000)
|
||||||
|
|
||||||
await db.insert(passwordResets).values({
|
await db.insert(passwordResetTokens).values({
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
tokenHash,
|
tokenHash,
|
||||||
expiresAt
|
expiresAt
|
||||||
@ -108,11 +111,11 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
|||||||
|
|
||||||
const resets = await db
|
const resets = await db
|
||||||
.select()
|
.select()
|
||||||
.from(passwordResets)
|
.from(passwordResetTokens)
|
||||||
.where(
|
.where(
|
||||||
and(
|
and(
|
||||||
gt(passwordResets.expiresAt, new Date()),
|
gt(passwordResetTokens.expiresAt, new Date()),
|
||||||
eq(passwordResets.used, false)
|
eq(passwordResetTokens.used, false)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -140,9 +143,9 @@ export default async function authRoutes(fastify: FastifyInstance) {
|
|||||||
.where(eq(users.id, matchedReset.userId))
|
.where(eq(users.id, matchedReset.userId))
|
||||||
|
|
||||||
await tx
|
await tx
|
||||||
.update(passwordResets)
|
.update(passwordResetTokens)
|
||||||
.set({ used: true })
|
.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" })
|
return reply.code(200).send({ message: "Password has been reset successfully" })
|
||||||
|
|||||||
@ -12,6 +12,8 @@ import searchRoutes from "./search"
|
|||||||
import webhookRoutes from "./webhooks"
|
import webhookRoutes from "./webhooks"
|
||||||
import reportsRoutes from "./reports"
|
import reportsRoutes from "./reports"
|
||||||
import invoiceRoutes from "./invoices"
|
import invoiceRoutes from "./invoices"
|
||||||
|
import savedViewRoutes from "./saved-views"
|
||||||
|
import notificationRoutes from "./notifications"
|
||||||
|
|
||||||
export async function setupRoutes(server: FastifyInstance) {
|
export async function setupRoutes(server: FastifyInstance) {
|
||||||
server.register(authRoutes, { prefix: "/api/auth" })
|
server.register(authRoutes, { prefix: "/api/auth" })
|
||||||
@ -27,4 +29,6 @@ export async function setupRoutes(server: FastifyInstance) {
|
|||||||
server.register(webhookRoutes, { prefix: "/api/webhooks" })
|
server.register(webhookRoutes, { prefix: "/api/webhooks" })
|
||||||
server.register(reportsRoutes, { prefix: "/api/reports" })
|
server.register(reportsRoutes, { prefix: "/api/reports" })
|
||||||
server.register(invoiceRoutes, { prefix: "/api/invoices" })
|
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 { createRootRoute, createRoute, createRouter, RouterProvider, Outlet, redirect } from "@tanstack/react-router"
|
||||||
import Dashboard from "./pages/Dashboard"
|
import Dashboard from "./pages/Dashboard"
|
||||||
import Login from "./pages/Login"
|
import Login from "./pages/Login"
|
||||||
|
import ForgotPassword from "./pages/ForgotPassword"
|
||||||
|
import ResetPassword from "./pages/ResetPassword"
|
||||||
import TimeEntries from "./pages/TimeEntries"
|
import TimeEntries from "./pages/TimeEntries"
|
||||||
import Customers from "./pages/Customers"
|
import Customers from "./pages/Customers"
|
||||||
import CustomerDetail from "./pages/CustomerDetail"
|
import CustomerDetail from "./pages/CustomerDetail"
|
||||||
@ -54,6 +56,18 @@ const loginRoute = createRoute({
|
|||||||
component: Login
|
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 () => {
|
const authCheck = async () => {
|
||||||
try {
|
try {
|
||||||
await api.getMe()
|
await api.getMe()
|
||||||
@ -152,18 +166,11 @@ const profileRoute = createRoute({
|
|||||||
|
|
||||||
const twoFactorRoute = createRoute({
|
const twoFactorRoute = createRoute({
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
path: "/2fa",
|
path: "/two-factor",
|
||||||
beforeLoad: authCheck,
|
beforeLoad: authCheck,
|
||||||
component: TwoFactorAuth
|
component: TwoFactorAuth
|
||||||
})
|
})
|
||||||
|
|
||||||
const adminUsersRoute = createRoute({
|
|
||||||
getParentRoute: () => rootRoute,
|
|
||||||
path: "/admin/users",
|
|
||||||
beforeLoad: adminCheck,
|
|
||||||
component: AdminUsers
|
|
||||||
})
|
|
||||||
|
|
||||||
const settingsRoute = createRoute({
|
const settingsRoute = createRoute({
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
path: "/settings",
|
path: "/settings",
|
||||||
@ -171,6 +178,34 @@ const settingsRoute = createRoute({
|
|||||||
component: Settings
|
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({
|
const auditLogRoute = createRoute({
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
path: "/admin/audit-log",
|
path: "/admin/audit-log",
|
||||||
@ -180,35 +215,16 @@ const auditLogRoute = createRoute({
|
|||||||
|
|
||||||
const webhooksRoute = createRoute({
|
const webhooksRoute = createRoute({
|
||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
path: "/settings/webhooks",
|
path: "/admin/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",
|
|
||||||
beforeLoad: adminCheck,
|
beforeLoad: adminCheck,
|
||||||
component: ProjectTemplates
|
component: Webhooks
|
||||||
})
|
})
|
||||||
|
|
||||||
const routeTree = [
|
const routeTree = [
|
||||||
indexRoute,
|
indexRoute,
|
||||||
loginRoute,
|
loginRoute,
|
||||||
|
forgotPasswordRoute,
|
||||||
|
resetPasswordRoute,
|
||||||
timeEntriesRoute,
|
timeEntriesRoute,
|
||||||
calendarRoute,
|
calendarRoute,
|
||||||
customersRoute,
|
customersRoute,
|
||||||
@ -219,16 +235,19 @@ const routeTree = [
|
|||||||
invoicesRoute,
|
invoicesRoute,
|
||||||
profileRoute,
|
profileRoute,
|
||||||
twoFactorRoute,
|
twoFactorRoute,
|
||||||
adminUsersRoute,
|
|
||||||
settingsRoute,
|
settingsRoute,
|
||||||
auditLogRoute,
|
|
||||||
webhooksRoute,
|
|
||||||
billingRoute,
|
billingRoute,
|
||||||
integrationsRoute,
|
integrationsRoute,
|
||||||
projectTemplatesRoute
|
projectTemplatesRoute,
|
||||||
|
adminUsersRoute,
|
||||||
|
auditLogRoute,
|
||||||
|
webhooksRoute,
|
||||||
]
|
]
|
||||||
|
|
||||||
const router = createRouter({ routeTree })
|
const router = createRouter({
|
||||||
|
routeTree,
|
||||||
|
defaultCatcher: (error) => <ErrorBoundary error={error} />
|
||||||
|
})
|
||||||
|
|
||||||
declare module "@tanstack/react-router" {
|
declare module "@tanstack/react-router" {
|
||||||
interface Register {
|
interface Register {
|
||||||
@ -237,7 +256,5 @@ declare module "@tanstack/react-router" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
return (
|
return <RouterProvider router={router} />
|
||||||
<RouterProvider router={router} />
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { useNavigate } from "@tanstack/react-router"
|
import { useNavigate, Link } from "@tanstack/react-router"
|
||||||
import { api } from "../lib/api"
|
import { api } from "../lib/api"
|
||||||
|
|
||||||
export default function Login() {
|
export default function Login() {
|
||||||
@ -47,9 +47,17 @@ export default function Login() {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-sm font-medium text-slate-700 mb-1">
|
<div className="flex justify-between items-center mb-1">
|
||||||
|
<label className="block text-sm font-medium text-slate-700">
|
||||||
Password
|
Password
|
||||||
</label>
|
</label>
|
||||||
|
<Link
|
||||||
|
to="/forgot-password"
|
||||||
|
className="text-xs text-indigo-600 hover:text-indigo-500 hover:underline transition-all"
|
||||||
|
>
|
||||||
|
Forgot password?
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
<input
|
<input
|
||||||
type="password"
|
type="password"
|
||||||
value={password}
|
value={password}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user