mirror of
https://github.com/complexcaresolutions/cms.c2sgmbh.git
synced 2026-03-17 17:24:12 +00:00
fix: resolve all TypeScript errors in production code
- Add Where type imports and proper type assertions in API routes - Add Locale type definitions for locale validation - Fix email-logs/stats route with proper EmailLog typing - Fix newsletter-service interests type and null checks - Remove invalid contact field from OpenAPI metadata - Fix formSubmissionOverrides type casting in payload.config - Fix vcard route Team type casting All 24 TypeScript errors in src/ are now resolved. Test files have separate type issues that don't affect production. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
2faefdac1e
commit
9016d3c06c
9 changed files with 54 additions and 38 deletions
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import config from '@payload-config'
|
||||
import type { Category, Media, Post } from '@/payload-types'
|
||||
|
||||
type Locale = 'de' | 'en' | 'all'
|
||||
import {
|
||||
searchLimiter,
|
||||
rateLimitHeaders,
|
||||
|
|
@ -49,8 +52,8 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
|||
const includeRelated = searchParams.get('includeRelated') !== 'false' // Default true
|
||||
|
||||
// Validate locale
|
||||
const validLocales = ['de', 'en']
|
||||
const locale = localeParam && validLocales.includes(localeParam) ? localeParam : 'de'
|
||||
const validLocales: Locale[] = ['de', 'en']
|
||||
const locale: Locale = localeParam && validLocales.includes(localeParam as Locale) ? (localeParam as Locale) : 'de'
|
||||
|
||||
// Parse tenant ID - REQUIRED for tenant isolation
|
||||
const tenantId = tenantParam ? parseInt(tenantParam, 10) : undefined
|
||||
|
|
@ -68,7 +71,7 @@ export async function GET(request: NextRequest, { params }: RouteParams) {
|
|||
const payload = await getPayload({ config })
|
||||
|
||||
// Build where clause (tenant is now required)
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
slug: { equals: slug },
|
||||
status: { equals: 'published' },
|
||||
tenant: { equals: tenantId },
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import config from '@payload-config'
|
||||
import type { Category, Media, Post } from '@/payload-types'
|
||||
|
||||
type Locale = 'de' | 'en' | 'all'
|
||||
import {
|
||||
searchLimiter,
|
||||
rateLimitHeaders,
|
||||
|
|
@ -29,7 +32,7 @@ interface NewsQueryParams {
|
|||
search?: string
|
||||
year?: number
|
||||
month?: number
|
||||
locale: string
|
||||
locale: Locale
|
||||
page: number
|
||||
limit: number
|
||||
excludeIds?: number[]
|
||||
|
|
@ -51,7 +54,7 @@ async function getNews(payload: Awaited<ReturnType<typeof getPayload>>, params:
|
|||
} = params
|
||||
|
||||
// Build where clause
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
status: { equals: 'published' },
|
||||
}
|
||||
|
||||
|
|
@ -131,7 +134,7 @@ async function getNews(payload: Awaited<ReturnType<typeof getPayload>>, params:
|
|||
// Execute query
|
||||
return payload.find({
|
||||
collection: 'posts',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: '-publishedAt',
|
||||
page,
|
||||
limit,
|
||||
|
|
@ -144,16 +147,16 @@ async function getNews(payload: Awaited<ReturnType<typeof getPayload>>, params:
|
|||
async function getCategories(
|
||||
payload: Awaited<ReturnType<typeof getPayload>>,
|
||||
tenantId?: number,
|
||||
locale: string = 'de'
|
||||
locale: Locale = 'de'
|
||||
) {
|
||||
const where: Record<string, unknown> = {}
|
||||
const where: Where = {}
|
||||
if (tenantId) {
|
||||
where.tenant = { equals: tenantId }
|
||||
}
|
||||
|
||||
const result = await payload.find({
|
||||
collection: 'categories',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: 'name',
|
||||
limit: 100,
|
||||
locale,
|
||||
|
|
@ -172,7 +175,7 @@ async function getArchive(
|
|||
payload: Awaited<ReturnType<typeof getPayload>>,
|
||||
tenantId: number // Now required
|
||||
) {
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
status: { equals: 'published' },
|
||||
publishedAt: { exists: true },
|
||||
tenant: { equals: tenantId },
|
||||
|
|
@ -187,7 +190,7 @@ async function getArchive(
|
|||
while (hasMore) {
|
||||
const result = await payload.find({
|
||||
collection: 'posts',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: '-publishedAt',
|
||||
page,
|
||||
limit: pageSize,
|
||||
|
|
@ -270,8 +273,8 @@ export async function GET(request: NextRequest) {
|
|||
const includeArchive = searchParams.get('includeArchive') === 'true'
|
||||
|
||||
// Validate locale
|
||||
const validLocales = ['de', 'en']
|
||||
const locale = localeParam && validLocales.includes(localeParam) ? localeParam : 'de'
|
||||
const validLocales: Locale[] = ['de', 'en']
|
||||
const locale: Locale = localeParam && validLocales.includes(localeParam as Locale) ? (localeParam as Locale) : 'de'
|
||||
|
||||
// Validate and parse types
|
||||
let types: NewsType | NewsType[] | undefined
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ export async function GET(
|
|||
}
|
||||
|
||||
// Generate vCard 3.0
|
||||
const vcard = generateVCard(member)
|
||||
const vcard = generateVCard(member as TeamMember)
|
||||
|
||||
// Return as downloadable file
|
||||
const filename = `${member.slug || member.name?.toLowerCase().replace(/\s+/g, '-')}.vcf`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import config from '@payload-config'
|
||||
|
||||
type Locale = 'de' | 'en' | 'all'
|
||||
|
||||
/**
|
||||
* Team API
|
||||
*
|
||||
|
|
@ -44,10 +47,11 @@ export async function GET(request: NextRequest) {
|
|||
const limit = Math.min(parseInt(searchParams.get('limit') || '50'), 100)
|
||||
const page = parseInt(searchParams.get('page') || '1')
|
||||
const sort = searchParams.get('sort') || 'order'
|
||||
const locale = (searchParams.get('locale') as 'de' | 'en') || 'de'
|
||||
const localeParam = searchParams.get('locale')
|
||||
const locale: Locale = (localeParam === 'de' || localeParam === 'en') ? localeParam : 'de'
|
||||
|
||||
// Build where clause
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
tenant: { equals: parseInt(tenantId) },
|
||||
isActive: { equals: true },
|
||||
}
|
||||
|
|
@ -94,7 +98,7 @@ export async function GET(request: NextRequest) {
|
|||
// Query team members
|
||||
const result = await payload.find({
|
||||
collection: 'team',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: sortField,
|
||||
limit,
|
||||
page,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import config from '@payload-config'
|
||||
import type { Media } from '@/payload-types'
|
||||
|
||||
type Locale = 'de' | 'en' | 'all'
|
||||
import {
|
||||
searchLimiter,
|
||||
rateLimitHeaders,
|
||||
|
|
@ -127,8 +130,8 @@ export async function GET(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Validate locale
|
||||
const validLocales = ['de', 'en']
|
||||
const locale = localeParam && validLocales.includes(localeParam) ? localeParam : 'de'
|
||||
const validLocales: Locale[] = ['de', 'en']
|
||||
const locale: Locale = localeParam && validLocales.includes(localeParam as Locale) ? (localeParam as Locale) : 'de'
|
||||
|
||||
// Validate type if provided
|
||||
if (typeParam && !TIMELINE_TYPES.includes(typeParam as TimelineType)) {
|
||||
|
|
@ -139,7 +142,7 @@ export async function GET(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Build where clause
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
status: { equals: 'published' },
|
||||
tenant: { equals: tenantId },
|
||||
}
|
||||
|
|
@ -160,7 +163,7 @@ export async function GET(request: NextRequest) {
|
|||
// Execute query
|
||||
const result = await payload.find({
|
||||
collection: 'timelines',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: '-updatedAt',
|
||||
limit: slugParam ? 1 : 100, // Single or list
|
||||
locale,
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import config from '@payload-config'
|
||||
import type { Media } from '@/payload-types'
|
||||
|
||||
type Locale = 'de' | 'en' | 'all'
|
||||
import {
|
||||
searchLimiter,
|
||||
rateLimitHeaders,
|
||||
|
|
@ -122,8 +125,8 @@ export async function GET(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Validate locale
|
||||
const validLocales = ['de', 'en']
|
||||
const locale = localeParam && validLocales.includes(localeParam) ? localeParam : 'de'
|
||||
const validLocales: Locale[] = ['de', 'en']
|
||||
const locale: Locale = localeParam && validLocales.includes(localeParam as Locale) ? (localeParam as Locale) : 'de'
|
||||
|
||||
// Validate type if provided
|
||||
if (typeParam && !WORKFLOW_TYPES.includes(typeParam as WorkflowType)) {
|
||||
|
|
@ -142,7 +145,7 @@ export async function GET(request: NextRequest) {
|
|||
}
|
||||
|
||||
// Build where clause
|
||||
const where: Record<string, unknown> = {
|
||||
const where: Where = {
|
||||
status: { equals: 'published' },
|
||||
tenant: { equals: tenantId },
|
||||
}
|
||||
|
|
@ -163,7 +166,7 @@ export async function GET(request: NextRequest) {
|
|||
// Execute query
|
||||
const result = await payload.find({
|
||||
collection: 'workflows',
|
||||
where,
|
||||
where: where as Where,
|
||||
sort: '-updatedAt',
|
||||
limit: slugParam ? 1 : 100, // Single or list
|
||||
locale,
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@
|
|||
*/
|
||||
|
||||
import { getPayload } from 'payload'
|
||||
import type { Where } from 'payload'
|
||||
import configPromise from '@payload-config'
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import type { EmailLog } from '@/payload-types'
|
||||
import { logAccessDenied } from '@/lib/audit/audit-service'
|
||||
import { maskSmtpError } from '@/lib/security/data-masking'
|
||||
|
||||
|
|
@ -89,7 +91,7 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|||
const periodDate = getPeriodDate(period)
|
||||
|
||||
// Basis-Where für alle Queries
|
||||
const baseWhere: Record<string, unknown> = {
|
||||
const baseWhere: Where = {
|
||||
createdAt: { greater_than_equal: periodDate.toISOString() },
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +103,7 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|||
// Gesamt
|
||||
payload.count({
|
||||
collection: 'email-logs',
|
||||
where: baseWhere,
|
||||
where: baseWhere as Where,
|
||||
}),
|
||||
// Gesendet
|
||||
payload.count({
|
||||
|
|
@ -161,7 +163,7 @@ export async function GET(req: NextRequest): Promise<NextResponse> {
|
|||
successRate,
|
||||
},
|
||||
bySource: sourceStats,
|
||||
recentFailures: recentFailed.docs.map((doc: Record<string, unknown>) => ({
|
||||
recentFailures: recentFailed.docs.map((doc: EmailLog) => ({
|
||||
id: doc.id,
|
||||
to: doc.to,
|
||||
subject: doc.subject,
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ export class NewsletterService {
|
|||
email: string
|
||||
firstName?: string
|
||||
lastName?: string
|
||||
interests?: string[]
|
||||
interests?: ('general' | 'blog' | 'products' | 'offers' | 'events')[]
|
||||
source?: string
|
||||
ipAddress?: string
|
||||
userAgent?: string
|
||||
|
|
@ -245,12 +245,14 @@ export class NewsletterService {
|
|||
})
|
||||
|
||||
// Tenant-ID ermitteln
|
||||
const tenantId = typeof subscriber.tenant === 'object'
|
||||
const tenantId = typeof subscriber.tenant === 'object' && subscriber.tenant
|
||||
? subscriber.tenant.id
|
||||
: subscriber.tenant
|
||||
|
||||
// Willkommens-E-Mail senden
|
||||
await this.sendWelcomeEmail(tenantId as number, subscriber)
|
||||
if (tenantId) {
|
||||
await this.sendWelcomeEmail(tenantId as number, subscriber)
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
|
@ -308,7 +310,7 @@ export class NewsletterService {
|
|||
}
|
||||
|
||||
// Tenant-ID ermitteln
|
||||
const tenantId = typeof subscriber.tenant === 'object'
|
||||
const tenantId = typeof subscriber.tenant === 'object' && subscriber.tenant
|
||||
? subscriber.tenant.id
|
||||
: subscriber.tenant
|
||||
|
||||
|
|
|
|||
|
|
@ -308,12 +308,12 @@ export default buildConfig({
|
|||
// Fix für TypeScript Types Generation - das Plugin braucht explizite relationTo Angaben
|
||||
redirectRelationships: ['pages'],
|
||||
formSubmissionOverrides: {
|
||||
...formSubmissionOverrides,
|
||||
...(formSubmissionOverrides as Record<string, unknown>),
|
||||
hooks: {
|
||||
beforeChange: [formSubmissionBeforeChange],
|
||||
afterChange: [sendFormNotification],
|
||||
},
|
||||
},
|
||||
} as Parameters<typeof formBuilderPlugin>[0]['formSubmissionOverrides'],
|
||||
}),
|
||||
redirectsPlugin({
|
||||
collections: ['pages'],
|
||||
|
|
@ -330,10 +330,6 @@ export default buildConfig({
|
|||
title: 'Payload CMS API',
|
||||
version: '1.0.0',
|
||||
description: 'Multi-Tenant CMS API für porwoll.de, complexcaresolutions.de, gunshin.de und zweitmein.ng',
|
||||
contact: {
|
||||
name: 'C2S GmbH',
|
||||
url: 'https://complexcaresolutions.de',
|
||||
},
|
||||
},
|
||||
}),
|
||||
// Swagger UI unter /api/docs
|
||||
|
|
|
|||
Loading…
Reference in a new issue