feat(dashboard): more type safety
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { DEFAULT_TIMEZONE } from "@basango/domain/constants";
|
||||
import {
|
||||
Article,
|
||||
Distribution,
|
||||
Distributions,
|
||||
ID,
|
||||
@@ -143,7 +144,7 @@ export async function getArticles(db: Database, params: GetArticlesParams) {
|
||||
.orderBy(desc(articles.publishedAt), desc(articles.id))
|
||||
.limit(pagination.limit + 1);
|
||||
|
||||
return buildPaginatedResult(rows, pagination, {
|
||||
return buildPaginatedResult<Article>(rows, pagination, {
|
||||
date: "publishedAt",
|
||||
id: "id",
|
||||
});
|
||||
@@ -154,7 +155,7 @@ export async function getArticlesPublicationGraph(
|
||||
params: GetPublicationsParams,
|
||||
): Promise<Publications> {
|
||||
const [startDate, endDate] = buildDateRange(params.range);
|
||||
const [previousRangeStart, previousRangeEnd] = buildPreviousRange([startDate, endDate]);
|
||||
const [previousStart, previousEnd] = buildPreviousRange([startDate, endDate]);
|
||||
|
||||
const data = await db.execute<Publication>(sql`
|
||||
WITH bounds AS (
|
||||
@@ -193,8 +194,8 @@ export async function getArticlesPublicationGraph(
|
||||
sql`
|
||||
SELECT COALESCE(COUNT(*)::int, 0) AS count
|
||||
FROM article a
|
||||
WHERE a.published_at >= timezone(${DEFAULT_TIMEZONE}, ${previousRangeStart})
|
||||
AND a.published_at <= timezone(${DEFAULT_TIMEZONE}, ${previousRangeEnd})
|
||||
WHERE a.published_at >= timezone(${DEFAULT_TIMEZONE}, ${previousStart})
|
||||
AND a.published_at <= timezone(${DEFAULT_TIMEZONE}, ${previousEnd})
|
||||
`,
|
||||
)
|
||||
.then((res) => res.rows);
|
||||
|
||||
@@ -24,7 +24,7 @@ export async function getSources(db: Database) {
|
||||
rows.map(async (row) => ({
|
||||
...row,
|
||||
articles: await countArticlesBySourceId(db, row.id),
|
||||
publicationGraph: await getSourcePublicationGraph(db, { id: row.id }),
|
||||
publications: await getSourcePublicationGraph(db, { id: row.id }),
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"#db/*": ["./src/*"],
|
||||
"#domain/*": ["../domain/src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@basango/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
|
||||
@@ -2,6 +2,8 @@ import { z } from "@hono/zod-openapi";
|
||||
|
||||
import { idSchema, sentimentSchema } from "#domain/models/shared";
|
||||
|
||||
import { sourceSchema } from "./sources";
|
||||
|
||||
// schemas
|
||||
export const articleMetadataSchema = z.object({
|
||||
author: z.string().optional().openapi({
|
||||
@@ -70,11 +72,19 @@ export const articleSchema = z.object({
|
||||
description: "The date and time when the article was created in the system.",
|
||||
example: "2023-01-01T12:00:00Z",
|
||||
}),
|
||||
excerpt: z.string().optional().openapi({
|
||||
description: "A brief excerpt or summary of the article.",
|
||||
example: "This article discusses the latest advancements in AI technology.",
|
||||
}),
|
||||
hash: z.string().min(1).openapi({
|
||||
description: "The unique hash of the article link.",
|
||||
example: "d41d8cd98f00b204e9800998ecf8427e",
|
||||
}),
|
||||
id: idSchema,
|
||||
image: z.url().optional().openapi({
|
||||
description: "The URL of the main image associated with the article.",
|
||||
example: "https://example.com/image.jpg",
|
||||
}),
|
||||
link: z.string().url().openapi({
|
||||
description: "The URL of the article.",
|
||||
example: "https://example.com/article",
|
||||
@@ -84,6 +94,11 @@ export const articleSchema = z.object({
|
||||
description: "The publication date of the article as a Date object.",
|
||||
example: "2023-01-01T00:00:00Z",
|
||||
}),
|
||||
readingTime: z.number().int().min(1).openapi({
|
||||
description: "Estimated reading time of the article in minutes.",
|
||||
example: 5,
|
||||
}),
|
||||
source: sourceSchema.optional(),
|
||||
sourceId: z.union([z.uuid(), z.string().min(1)]).openapi({
|
||||
description: "The unique identifier of the source from which the article was crawled.",
|
||||
example: "b3e1c8f4-5d6a-4c9e-8f1e-2d3c4b5a6f7g",
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"#domain/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@basango/tsconfig/base.json",
|
||||
"include": ["src"]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"exclude": ["node_modules"],
|
||||
"extends": "@basango/tsconfig/base.json",
|
||||
"include": ["src/**/*"]
|
||||
"include": ["src"]
|
||||
}
|
||||
|
||||
@@ -11,13 +11,6 @@
|
||||
"moduleDetection": "force",
|
||||
"moduleResolution": "Bundler",
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"paths": {
|
||||
"#api/*": ["../../apps/api/src/*"],
|
||||
"#crawler/*": ["../../apps/crawler/src/*"],
|
||||
"#dashboard/*": ["../../apps/dashboard/src/*"],
|
||||
"#db/*": ["../db/src/*"],
|
||||
"#domain/*": ["../domain/src/*"]
|
||||
},
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
|
||||
Reference in New Issue
Block a user