generated from PluteoJS/pluteojs-template
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(api): implement news submission api (without date min validation)
- Loading branch information
1 parent
ef3cee1
commit b31bcd1
Showing
12 changed files
with
258 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import {NextFunction, Router} from "express"; | ||
|
||
import logger from "@loaders/logger"; | ||
|
||
// import middlewares from "@api/middlewares"; | ||
|
||
import expressUtil from "@util/expressUtil"; | ||
|
||
import {iRequest, iResponse, RouteType} from "@customTypes/expressTypes"; | ||
import {iNewsSubmissionDTO} from "customTypes/appDataTypes/newsTypes"; | ||
import {celebrate, Segments} from "celebrate"; | ||
import {newsSubmissionBodySchema} from "validations/newsRouteSchemas"; | ||
import NewsService from "services/NewsService"; | ||
|
||
const route = Router(); | ||
const newsService = new NewsService(); | ||
|
||
const newsRoute: RouteType = (apiRouter) => { | ||
apiRouter.use("/news", route); | ||
|
||
/* | ||
Registering isAuthorized middleware to the entire /users route | ||
as all the endpoint in this route needs authorization. | ||
*/ | ||
// route.use(middlewares.isAuthorized); | ||
|
||
route.post( | ||
"/", | ||
celebrate({ | ||
[Segments.BODY]: newsSubmissionBodySchema, | ||
}), | ||
async ( | ||
req: iRequest<iNewsSubmissionDTO>, | ||
res: iResponse<{id: string}>, | ||
next: NextFunction | ||
) => { | ||
const uniqueRequestId = expressUtil.parseUniqueRequestId(req); | ||
|
||
logger.debug( | ||
uniqueRequestId, | ||
"Calling POST:/news endpoint with body:", | ||
null, | ||
{ | ||
requestBody: req.body, | ||
} | ||
); | ||
|
||
try { | ||
const {body} = req; | ||
|
||
const result = await newsService.addNews(uniqueRequestId, body); | ||
|
||
logger.debug( | ||
uniqueRequestId, | ||
"POST:/news :: Completed newsService.addNews & sending result to client:", | ||
null, | ||
{ | ||
result, | ||
} | ||
); | ||
|
||
const {httpStatusCode} = result; | ||
|
||
return res.status(httpStatusCode).json(result); | ||
} catch (error) { | ||
logger.error(uniqueRequestId, "Error on POST:/news :", error); | ||
|
||
return next(error); | ||
} | ||
} | ||
); | ||
}; | ||
|
||
export default newsRoute; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import {StringArray} from "customTypes/commonTypes"; | ||
|
||
export interface iNewsSubmissionDTO { | ||
title: string; | ||
content: string; | ||
url: string; | ||
publishedDate: string; | ||
} | ||
|
||
interface iNews { | ||
id: string; | ||
publishedDate: string; | ||
url: string; | ||
title: string; | ||
content: string; | ||
createdAt: string; | ||
} | ||
|
||
type MultiNews = { | ||
ids: StringArray; | ||
|
||
items: { | ||
[key in string]: iNews; | ||
}; | ||
}; | ||
|
||
export type {iNews, MultiNews}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export interface iNewsModel { | ||
id: string; | ||
published_date: string; | ||
url: string; | ||
title: string; | ||
content: string; | ||
created_at: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {IDatabase, IMain} from "pg-promise"; | ||
|
||
import {iNewsModel} from "db/models/news.model"; | ||
|
||
import {news as sql} from "@db/sql"; | ||
|
||
/* | ||
This repository mixes hard-coded and dynamic SQL, just to show how to use both. | ||
*/ | ||
export default class NewsRepository { | ||
/** | ||
* @param db | ||
* Automated database connection context/interface. | ||
* | ||
* If you ever need to access other repositories from this one, | ||
* you will have to replace type 'IDatabase<any>' with 'any'. | ||
* | ||
* @param pgp | ||
* Library's root, if ever needed, like to access 'helpers' | ||
* or other namespaces available from the root. | ||
*/ | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
constructor(private db: IDatabase<any>, private pgp: IMain) { | ||
/* | ||
If your repository needs to use helpers like ColumnSet, | ||
you should create it conditionally, inside the constructor, | ||
i.e. only once, as a singleton. | ||
*/ | ||
} | ||
|
||
/** | ||
* Creates the annotations table. | ||
* | ||
* @returns null | ||
*/ | ||
async create(): Promise<null> { | ||
return this.db.none(sql.create); | ||
} | ||
|
||
// Returns all annotations records; | ||
async all(): Promise<iNewsModel[]> { | ||
return this.db.any("SELECT * FROM news"); | ||
} | ||
|
||
// Adds a new news record, and returns the new object; | ||
async add( | ||
id: string, | ||
publishedDate: string, | ||
url: string, | ||
title: string, | ||
content: string | ||
): Promise<iNewsModel> { | ||
return this.db.one(sql.add, { | ||
id, | ||
publishedDate, | ||
url, | ||
title, | ||
content, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
/* | ||
Inserts a new news record. | ||
*/ | ||
INSERT INTO news(id, published_date, url, title, content, created_at) | ||
VALUES(${id}, ${publishedDate}, ${url}, ${title}, ${content}, CURRENT_TIMESTAMP) | ||
RETURNING * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
Creates table news. | ||
*/ | ||
CREATE TABLE news | ||
( | ||
id UUID PRIMARY KEY, | ||
published_date TIMESTAMPTZ, | ||
url TEXT NOT NULL, | ||
title VARCHAR(225) NOT NULL, | ||
content TEXT NOT NULL, | ||
created_at TIMESTAMPTZ | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import logger from "@loaders/logger"; | ||
|
||
import {db} from "@db/index"; | ||
|
||
import serviceUtil from "@util/serviceUtil"; | ||
|
||
import {iGenericServiceResult} from "@customTypes/commonServiceTypes"; | ||
import {httpStatusCodes} from "@customTypes/networkTypes"; | ||
|
||
import {NullableString} from "@customTypes/commonTypes"; | ||
import {iNewsSubmissionDTO} from "@customTypes/appDataTypes/newsTypes"; | ||
import securityUtil from "util/securityUtil"; | ||
|
||
export default class NewsService { | ||
public async addNews( | ||
uniqueRequestId: NullableString, | ||
news: iNewsSubmissionDTO | ||
): Promise<iGenericServiceResult<{id: string} | null>> { | ||
return db.tx("add-news", async (task) => { | ||
logger.silly("Inserting new news record to news table"); | ||
|
||
const uuid = securityUtil.generateUUID(); | ||
|
||
const newNewsRecord = await task.news.add( | ||
uuid, | ||
news.publishedDate, | ||
news.url, | ||
news.title, | ||
news.content | ||
); | ||
|
||
return serviceUtil.buildResult( | ||
true, | ||
httpStatusCodes.SUCCESS_OK, | ||
uniqueRequestId, | ||
null, | ||
{ | ||
id: newNewsRecord.id, | ||
} | ||
); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import {Joi} from "celebrate"; | ||
|
||
import {uuidv4Schema} from "@validations/genericSchemas"; | ||
|
||
const newsIdSchema = uuidv4Schema.required(); | ||
|
||
const newsSubmissionBodySchema = Joi.object({ | ||
title: Joi.string().min(1).required(), | ||
content: Joi.string().min(1).required(), | ||
url: Joi.string().uri().required(), | ||
date: Joi.string().isoDate().required(), | ||
}); | ||
|
||
export {newsIdSchema, newsSubmissionBodySchema}; |