|
1 | 1 | import { json } from "@remix-run/server-runtime"; |
2 | | -import { ReportFormatSchema, ReportPeriodSchema } from "@trigger.dev/core/v3/schemas"; |
3 | | -import { z } from "zod"; |
4 | 2 | import { ReportPresenter } from "~/presenters/v3/reports/ReportPresenter.server"; |
| 3 | +import { isReportKey, REPORT_KEYS } from "~/presenters/v3/reports/report-registry"; |
5 | 4 | import { |
6 | | - isReportKey, |
7 | | - REPORT_KEYS, |
8 | | - reportQueryTables, |
9 | | -} from "~/presenters/v3/reports/report-registry"; |
10 | | -import { renderReportAnsi, renderReportMarkdown } from "~/presenters/v3/reports/renderMarkdown"; |
11 | | -import { type ReportViewModel } from "~/presenters/v3/reports/report-view-model"; |
| 5 | + ReportParamsSchema, |
| 6 | + ReportSearchParamsSchema, |
| 7 | + reportAuthResource, |
| 8 | + reportResponse, |
| 9 | +} from "~/presenters/v3/reports/reportsApi.server"; |
12 | 10 | import { logger } from "~/services/logger.server"; |
13 | | -import { createLoaderApiRoute, everyResource } from "~/services/routeBuilders/apiBuilder.server"; |
14 | | - |
15 | | -export const ReportParamsSchema = z.object({ |
16 | | - key: z.string(), |
17 | | -}); |
18 | | - |
19 | | -/** |
20 | | - * `period` and `format` come from `@trigger.dev/core/v3/schemas` — the same definitions the API |
21 | | - * clients and the CLI use, so the accepted grammar can't drift between them. Note `period` |
22 | | - * rejects seconds: reports bucket by whole minutes. |
23 | | - */ |
24 | | -export const ReportSearchParamsSchema = z.object({ |
25 | | - period: ReportPeriodSchema.optional(), |
26 | | - // markdown (default) for CLI/MCP · json (the raw VM) for web · ansi for a colour terminal. |
27 | | - format: ReportFormatSchema.default("markdown"), |
28 | | -}); |
29 | | - |
30 | | -export type ReportFormatParam = z.infer<typeof ReportFormatSchema>; |
31 | | - |
32 | | -/** Render the view model in the requested encoding, with the matching content type. */ |
33 | | -export function reportResponse(vm: ReportViewModel, format: ReportFormatParam): Response { |
34 | | - switch (format) { |
35 | | - case "json": |
36 | | - return json(vm, { status: 200 }); |
37 | | - case "ansi": |
38 | | - return new Response(renderReportAnsi(vm), { |
39 | | - status: 200, |
40 | | - headers: { "Content-Type": "text/plain; charset=utf-8" }, |
41 | | - }); |
42 | | - case "markdown": |
43 | | - return new Response(renderReportMarkdown(vm), { |
44 | | - status: 200, |
45 | | - headers: { "Content-Type": "text/markdown; charset=utf-8" }, |
46 | | - }); |
47 | | - } |
48 | | -} |
49 | | - |
50 | | -/** |
51 | | - * Authorize per-table (like api.v1.query.ts) rather than the permissive |
52 | | - * `{ type: "query", id: "all" }`: a JWT must be scoped to every table the *selected* report |
53 | | - * reads, so a token scoped to only some tables can't fetch a report that reads others. The |
54 | | - * tables come from the registry entry, so a narrower report gets a narrower check for free. |
55 | | - */ |
56 | | -export function reportAuthResource(key: string) { |
57 | | - return everyResource(reportQueryTables(key).map((id) => ({ type: "query", id }))); |
58 | | -} |
| 11 | +import { createLoaderApiRoute } from "~/services/routeBuilders/apiBuilder.server"; |
59 | 12 |
|
| 13 | +// Only `loader` may be exported here: the route's schemas and helpers live in |
| 14 | +// reportsApi.server.ts, or the vite build flags server code reachable from a |
| 15 | +// non-loader export. |
60 | 16 | export const loader = createLoaderApiRoute( |
61 | 17 | { |
62 | 18 | params: ReportParamsSchema, |
|
0 commit comments