fix news api

This commit is contained in:
ItsMalma
2025-12-12 12:14:57 +07:00
parent 5e8cf20253
commit e17bbe1549
5 changed files with 37 additions and 20 deletions

View File

@@ -1,7 +1,6 @@
import { Controller } from "@/common/controller"; import { Controller } from "@/common/controller";
import { createOrmContextMiddleware } from "@/common/middlewares/create-orm-context.middleware"; import { createOrmContextMiddleware } from "@/common/middlewares/create-orm-context.middleware";
import { isAdminMiddleware } from "@/common/middlewares/is-admin.middleware"; import { isAdminMiddleware } from "@/common/middlewares/is-admin.middleware";
import { paginationQuerySchema } from "@/common/schemas";
import type { AbstractFileStorage } from "@/common/services/file-storage/abstract.file-storage"; import type { AbstractFileStorage } from "@/common/services/file-storage/abstract.file-storage";
import type { AbstractJwtService } from "@/common/services/jwt-service/abstract.jwt-service"; import type { AbstractJwtService } from "@/common/services/jwt-service/abstract.jwt-service";
import type { import type {
@@ -16,9 +15,11 @@ import { orm } from "@/database/orm";
import type { ArticleMapper } from "@/modules/article/article.mapper"; import type { ArticleMapper } from "@/modules/article/article.mapper";
import { import {
articleParamsSchema, articleParamsSchema,
articleQuerySchema,
articleRequestSchema, articleRequestSchema,
} from "@/modules/article/article.schemas"; } from "@/modules/article/article.schemas";
import type { ArticleResponse } from "@/modules/article/article.types"; import type { ArticleResponse } from "@/modules/article/article.types";
import type { FilterQuery } from "@mikro-orm/core";
import { Router, type Request, type Response } from "express"; import { Router, type Request, type Response } from "express";
import slugify from "slugify"; import slugify from "slugify";
import { ulid } from "ulid"; import { ulid } from "ulid";
@@ -83,7 +84,7 @@ export class ArticleController extends Controller {
} }
async list(req: Request, res: Response) { async list(req: Request, res: Response) {
const parseQueryResult = paginationQuerySchema.safeParse(req.query); const parseQueryResult = articleQuerySchema.safeParse(req.query);
if (!parseQueryResult.success) { if (!parseQueryResult.success) {
return this.handleZodError(parseQueryResult.error, res, "query"); return this.handleZodError(parseQueryResult.error, res, "query");
} }
@@ -91,15 +92,16 @@ export class ArticleController extends Controller {
const count = await orm.em.count(Article); const count = await orm.em.count(Article);
const articles = await orm.em.find( const filter: FilterQuery<Article> = {};
Article, if (query.tag_slug) {
{}, filter.tags = { slug: query.tag_slug };
{ }
limit: query.per_page,
offset: (query.page - 1) * query.per_page, const articles = await orm.em.find(Article, filter, {
orderBy: { createdAt: "DESC" }, limit: query.per_page,
}, offset: (query.page - 1) * query.per_page,
); orderBy: { createdAt: "DESC" },
});
return res.status(200).json({ return res.status(200).json({
data: articles.map(this.mapper.mapEntityToResponse.bind(this.mapper)), data: articles.map(this.mapper.mapEntityToResponse.bind(this.mapper)),

View File

@@ -1,3 +1,4 @@
import { paginationQuerySchema } from "@/common/schemas";
import z from "zod"; import z from "zod";
export const articleRequestSchema = z.object({ export const articleRequestSchema = z.object({
@@ -21,6 +22,17 @@ export const articleRequestSchema = z.object({
.max(100, "Max 100 characters."), .max(100, "Max 100 characters."),
}); });
export const articleQuerySchema = z.intersection(
paginationQuerySchema,
z.object({
tag_slug: z
.string("Must be string.")
.nonempty("Must not empty.")
.max(100, "Max 100 characters.")
.optional(),
}),
);
export const articleParamsSchema = z.object({ export const articleParamsSchema = z.object({
slug: z slug: z
.string("Must be string.") .string("Must be string.")

View File

@@ -1,5 +1,6 @@
import type { import type {
articleParamsSchema, articleParamsSchema,
articleQuerySchema,
articleRequestSchema, articleRequestSchema,
} from "@/modules/article/article.schemas"; } from "@/modules/article/article.schemas";
import type { TagResponse } from "@/modules/tag/tag.types"; import type { TagResponse } from "@/modules/tag/tag.types";
@@ -7,6 +8,8 @@ import z from "zod";
export type ArticleRequest = z.infer<typeof articleRequestSchema>; export type ArticleRequest = z.infer<typeof articleRequestSchema>;
export type ArticleQuery = z.infer<typeof articleQuerySchema>;
export type ArticleParams = z.infer<typeof articleParamsSchema>; export type ArticleParams = z.infer<typeof articleParamsSchema>;
export type ArticleResponse = { export type ArticleResponse = {

View File

@@ -87,13 +87,13 @@ export class TagController extends Controller {
} }
const params = parseParamsResult.data; const params = parseParamsResult.data;
const tag = await orm.em.findOne(Tag, { id: params.id }); const tag = await orm.em.findOne(Tag, { slug: params.slug });
if (!tag) { if (!tag) {
return res.status(404).json({ return res.status(404).json({
data: null, data: null,
errors: [ errors: [
{ {
path: "id", path: "slug",
location: "params", location: "params",
message: "Tag not found.", message: "Tag not found.",
}, },
@@ -120,13 +120,13 @@ export class TagController extends Controller {
} }
const body = parseBodyResult.data; const body = parseBodyResult.data;
const tag = await orm.em.findOne(Tag, { id: params.id }); const tag = await orm.em.findOne(Tag, { slug: params.slug });
if (!tag) { if (!tag) {
return res.status(404).json({ return res.status(404).json({
data: null, data: null,
errors: [ errors: [
{ {
path: "id", path: "slug",
location: "params", location: "params",
message: "Tag not found.", message: "Tag not found.",
}, },
@@ -155,7 +155,7 @@ export class TagController extends Controller {
const tag = await orm.em.findOne( const tag = await orm.em.findOne(
Tag, Tag,
{ id: params.id }, { slug: params.slug },
{ {
populate: ["*"], populate: ["*"],
}, },
@@ -165,7 +165,7 @@ export class TagController extends Controller {
data: null, data: null,
errors: [ errors: [
{ {
path: "id", path: "slug",
location: "params", location: "params",
message: "Tag not found.", message: "Tag not found.",
}, },

View File

@@ -8,8 +8,8 @@ export const tagRequestSchema = z.object({
}); });
export const tagParamsSchema = z.object({ export const tagParamsSchema = z.object({
id: z slug: z
.ulid("Must be ulid string.") .string("Must be string.")
.nonempty("Must not empty.") .nonempty("Must not empty.")
.max(30, "Max 30 characters."), .max(100, "Max 100 characters."),
}); });