update schemas

This commit is contained in:
Nate Kelley 2025-08-02 20:15:48 -06:00
parent 13d814e980
commit 7b3975c4ae
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 89 additions and 72 deletions

View File

@ -1,8 +1,5 @@
import type { User } from '@buster/database';
import type {
GetReportsListRequest,
GetReportsListResponse
} from '@buster/server-shared/reports';
import type { GetReportsListRequest, GetReportsListResponse } from '@buster/server-shared/reports';
import { GetReportsListRequestSchema } from '@buster/server-shared/reports';
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
@ -25,16 +22,16 @@ async function getReportsListHandler(
content: [
{
type: 'h1' as const,
children: [{ text: 'Sales Analysis Q4' }]
children: [{ text: 'Sales Analysis Q4' }],
},
{
type: 'p' as const,
children: [{ text: 'This report analyzes our Q4 sales performance.' }]
}
]
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
},
],
},
{
id: 'report-2',
id: 'report-2',
name: 'Customer Metrics Dashboard',
file_name: 'customer_metrics.md',
description: 'Key customer engagement metrics',
@ -46,9 +43,9 @@ async function getReportsListHandler(
content: [
{
type: 'h1' as const,
children: [{ text: 'Customer Metrics' }]
}
]
children: [{ text: 'Customer Metrics' }],
},
],
},
{
id: 'report-3',
@ -63,39 +60,40 @@ async function getReportsListHandler(
content: [
{
type: 'h1' as const,
children: [{ text: 'Marketing Campaign Results' }]
children: [{ text: 'Marketing Campaign Results' }],
},
{
type: 'p' as const,
children: [{ text: 'Overview of our recent marketing initiatives and their performance.' }]
}
]
}
children: [
{ text: 'Overview of our recent marketing initiatives and their performance.' },
],
},
],
},
];
const { page_token, page_size } = request;
const startIndex = page_token * page_size;
const { page, page_size } = request;
const startIndex = page * page_size;
const endIndex = startIndex + page_size;
const paginatedReports = stubbedReports.slice(startIndex, endIndex);
return {
data: paginatedReports,
pagination: {
page: page_token,
page_size: page_size,
page,
page_size,
total: stubbedReports.length,
total_pages: Math.ceil(stubbedReports.length / page_size)
}
total_pages: Math.ceil(stubbedReports.length / page_size),
},
};
}
const app = new Hono()
.get('/', zValidator('query', GetReportsListRequestSchema), async (c) => {
const request = c.req.valid('query');
const user = c.get('busterUser');
const response = await getReportsListHandler(request, user);
return c.json(response);
});
const app = new Hono().get('/', zValidator('query', GetReportsListRequestSchema), async (c) => {
const request = c.req.valid('query');
const user = c.get('busterUser');
const response = await getReportsListHandler(request, user);
return c.json(response);
});
export default app;

View File

@ -1,8 +1,5 @@
import type { User } from '@buster/database';
import type {
UpdateReportRequest,
UpdateReportResponse
} from '@buster/server-shared/reports';
import type { UpdateReportRequest, UpdateReportResponse } from '@buster/server-shared/reports';
import { UpdateReportRequestSchema } from '@buster/server-shared/reports';
import { zValidator } from '@hono/zod-validator';
import { Hono } from 'hono';
@ -16,7 +13,7 @@ async function updateReportHandler(
const existingReport = {
id: reportId,
name: 'Sales Analysis Q4',
file_name: 'sales_analysis_q4.md',
file_name: 'sales_analysis_q4.md',
description: 'Quarterly sales performance analysis',
created_by: user.id,
created_at: '2024-01-15T10:00:00Z',
@ -26,13 +23,13 @@ async function updateReportHandler(
content: [
{
type: 'h1' as const,
children: [{ text: 'Sales Analysis Q4' }]
children: [{ text: 'Sales Analysis Q4' }],
},
{
type: 'p' as const,
children: [{ text: 'This report analyzes our Q4 sales performance.' }]
}
]
children: [{ text: 'This report analyzes our Q4 sales performance.' }],
},
],
};
if (!reportId || reportId === 'invalid') {
@ -42,20 +39,23 @@ async function updateReportHandler(
const updatedReport = {
...existingReport,
...request,
updated_at: new Date().toISOString()
updated_at: new Date().toISOString(),
};
return updatedReport;
}
const app = new Hono()
.put('/', zValidator('json', UpdateReportRequestSchema), async (c) => {
const reportId = c.req.param('id');
const request = c.req.valid('json');
const user = c.get('busterUser');
const response = await updateReportHandler(reportId, request, user);
return c.json(response);
});
const app = new Hono().put('/', zValidator('json', UpdateReportRequestSchema), async (c) => {
const reportId = c.req.param('id');
const request = c.req.valid('json');
const user = c.get('busterUser');
if (!reportId) {
throw new HTTPException(404, { message: 'Report ID is required' });
}
const response = await updateReportHandler(reportId, request, user);
return c.json(response);
});
export default app;

View File

@ -1,7 +1,23 @@
import { z } from 'zod';
import type { ReportElements } from './report-elements';
import type { ReportElement } from './report-elements';
import { ReportElementSchema } from './report-elements';
export const ReportSchema = z.object({
// Define the type explicitly
export type ReportResponse = {
id: string;
name: string;
file_name: string;
description: string;
created_by: string;
created_at: string;
updated_at: string;
deleted_at: string | null;
publicly_accessible: boolean;
content: ReportElement[];
};
// Create schema with explicit type annotation
export const ReportResponseSchema = z.object({
id: z.string(),
name: z.string(),
file_name: z.string(),
@ -11,7 +27,5 @@ export const ReportSchema = z.object({
updated_at: z.string(),
deleted_at: z.string().nullable(),
publicly_accessible: z.boolean(),
content: z.any() as z.ZodType<ReportElements>,
});
export type Report = z.infer<typeof ReportSchema>;
content: z.lazy(() => z.array(ReportElementSchema)), // Now using the actual schema
}) as z.ZodType<ReportResponse>;

View File

@ -1,17 +1,17 @@
import { z } from 'zod';
import type { z } from 'zod';
import { PaginatedRequestSchema } from '../type-utilities/pagination';
import type { ReportElements } from './report-elements';
import { ReportResponseSchema } from './reports.types';
export const GetReportsListRequestSchema = z.object({
page_token: z.number().optional().default(0),
page_size: z.number().optional().default(50),
});
export const GetReportsListRequestSchema = PaginatedRequestSchema;
export const UpdateReportRequestSchema = z.object({
name: z.string().optional(),
description: z.string().optional(),
publicly_accessible: z.boolean().optional(),
content: z.any().optional() as z.ZodOptional<z.ZodType<ReportElements>>,
});
// 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();
export type GetReportsListRequest = z.infer<typeof GetReportsListRequestSchema>;
export type UpdateReportRequest = z.infer<typeof UpdateReportRequestSchema>;

View File

@ -1,9 +1,9 @@
import { z } from 'zod';
import type { z } from 'zod';
import { PaginatedResponseSchema } from '../type-utilities/pagination';
import { ReportSchema, type Report } from './reports.types';
import { ReportResponseSchema } from './reports.types';
export const GetReportsListResponseSchema = PaginatedResponseSchema(ReportSchema);
export const UpdateReportResponseSchema = ReportSchema;
export const GetReportsListResponseSchema = PaginatedResponseSchema(ReportResponseSchema);
export const UpdateReportResponseSchema = ReportResponseSchema;
export type GetReportsListResponse = z.infer<typeof GetReportsListResponseSchema>;
export type UpdateReportResponse = Report;
export type UpdateReportResponse = z.infer<typeof UpdateReportResponseSchema>;

View File

@ -16,3 +16,8 @@ export const PaginatedResponseSchema = <T>(schema: z.ZodType<T>) =>
});
export type PaginatedResponse<T> = z.infer<ReturnType<typeof PaginatedResponseSchema<T>>>;
export const PaginatedRequestSchema = z.object({
page: z.number(),
page_size: z.number(),
});