diff --git a/apps/server/src/api/v2/reports/GET.ts b/apps/server/src/api/v2/reports/GET.ts index b7df62a32..42ab139b6 100644 --- a/apps/server/src/api/v2/reports/GET.ts +++ b/apps/server/src/api/v2/reports/GET.ts @@ -1,5 +1,9 @@ import type { User } from '@buster/database'; -import type { GetReportsListRequest, GetReportsListResponse } from '@buster/server-shared/reports'; +import type { + GetReportsListRequest, + GetReportsListResponse, + ReportResponse, +} from '@buster/server-shared/reports'; import { GetReportsListRequestSchema } from '@buster/server-shared/reports'; import { zValidator } from '@hono/zod-validator'; import { Hono } from 'hono'; @@ -8,7 +12,7 @@ async function getReportsListHandler( request: GetReportsListRequest, user: User ): Promise { - const stubbedReports = [ + const stubbedReports: ReportResponse[] = [ { id: 'report-1', name: 'Sales Analysis Q4', @@ -77,7 +81,7 @@ async function getReportsListHandler( const endIndex = startIndex + page_size; const paginatedReports = stubbedReports.slice(startIndex, endIndex); - return { + const result: GetReportsListResponse = { data: paginatedReports, pagination: { page, @@ -86,6 +90,8 @@ async function getReportsListHandler( total_pages: Math.ceil(stubbedReports.length / page_size), }, }; + + return result; } const app = new Hono().get('/', zValidator('query', GetReportsListRequestSchema), async (c) => { diff --git a/apps/server/src/api/v2/reports/[id].ts b/apps/server/src/api/v2/reports/[id].ts index e892278f4..e8a4a6674 100644 --- a/apps/server/src/api/v2/reports/[id].ts +++ b/apps/server/src/api/v2/reports/[id].ts @@ -1,5 +1,9 @@ import type { User } from '@buster/database'; -import type { UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports'; +import type { + ReportResponse, + UpdateReportRequest, + UpdateReportResponse, +} from '@buster/server-shared/reports'; import { UpdateReportRequestSchema } from '@buster/server-shared/reports'; import { zValidator } from '@hono/zod-validator'; import { Hono } from 'hono'; diff --git a/packages/server-shared/src/reports/index.ts b/packages/server-shared/src/reports/index.ts index 3b4f7c10c..3663df7df 100644 --- a/packages/server-shared/src/reports/index.ts +++ b/packages/server-shared/src/reports/index.ts @@ -2,3 +2,4 @@ export * from './report-elements'; export * from './reports.types'; export * from './requests'; export * from './responses'; +export * from './reports.types'; diff --git a/packages/server-shared/src/reports/reports.types.ts b/packages/server-shared/src/reports/reports.types.ts index a9106c7c9..1076d36ef 100644 --- a/packages/server-shared/src/reports/reports.types.ts +++ b/packages/server-shared/src/reports/reports.types.ts @@ -1,9 +1,8 @@ import { z } from 'zod'; -import type { ReportElement } from './report-elements'; +import type { ReportElement, ReportElements } from './report-elements'; import { ReportElementSchema } from './report-elements'; -// Define the type explicitly -export type ReportResponse = { +const ReportResponseSchema: z.ZodType<{ id: string; name: string; file_name: string; @@ -14,10 +13,7 @@ export type ReportResponse = { deleted_at: string | null; publicly_accessible: boolean; content: ReportElement[]; -}; - -// Create schema with explicit type annotation -export const ReportResponseSchema = z.object({ +}> = z.object({ id: z.string(), name: z.string(), file_name: z.string(), @@ -27,5 +23,10 @@ export const ReportResponseSchema = z.object({ updated_at: z.string(), deleted_at: z.string().nullable(), publicly_accessible: z.boolean(), - content: z.lazy(() => z.array(ReportElementSchema)), // Now using the actual schema -}) as z.ZodType; + content: z.array(ReportElementSchema) as z.ZodType, +}); + +// Export base schema for operations like .pick() +export { ReportResponseSchema }; + +export type ReportResponse = z.infer; diff --git a/packages/server-shared/src/reports/requests.ts b/packages/server-shared/src/reports/requests.ts index 0a8c47890..7bfa39dc6 100644 --- a/packages/server-shared/src/reports/requests.ts +++ b/packages/server-shared/src/reports/requests.ts @@ -1,17 +1,22 @@ -import type { z } from 'zod'; +import { z } from 'zod'; import { PaginatedRequestSchema } from '../type-utilities/pagination'; -import type { ReportElements } from './report-elements'; +import type { ReportElement, ReportElements } from './report-elements'; +import { ReportElementSchema } from './report-elements'; import { ReportResponseSchema } from './reports.types'; export const GetReportsListRequestSchema = PaginatedRequestSchema; -// UpdateReportRequestSchema uses zod's .pick to select updatable fields from ReportResponseSchema -export const UpdateReportRequestSchema = ReportResponseSchema.pick({ - name: true, - description: true, - publicly_accessible: true, - content: true, -}).partial(); +// Define UpdateReportRequestSchema with explicit type annotation +export const UpdateReportRequestSchema = z + .object({ + name: z.string().optional(), + description: z.string().optional(), + publicly_accessible: z.boolean().optional(), + content: z.lazy(() => z.array(ReportElementSchema)).optional() as z.ZodOptional< + z.ZodType + >, + }) + .partial(); -export type GetReportsListRequest = z.infer; export type UpdateReportRequest = z.infer; +export type GetReportsListRequest = z.infer; diff --git a/packages/server-shared/src/type-utilities/pagination.ts b/packages/server-shared/src/type-utilities/pagination.ts index a3591819c..eb18eb4f6 100644 --- a/packages/server-shared/src/type-utilities/pagination.ts +++ b/packages/server-shared/src/type-utilities/pagination.ts @@ -18,6 +18,6 @@ export const PaginatedResponseSchema = (schema: z.ZodType) => export type PaginatedResponse = z.infer>>; export const PaginatedRequestSchema = z.object({ - page: z.number(), - page_size: z.number(), + page: z.coerce.number().min(1).default(1), + page_size: z.coerce.number().min(1).max(5000).default(250), });