bootpress 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,96 @@
1
+ <h1 align="center" style="margin-bottom: 0" >bootpress</h1>
2
+ <p align=center>Express but SpringBoot like</p>
3
+
4
+ ## Methods
5
+ ### **RestService**: Converts all methods to Express RequestHandlers
6
+ #### Basic usage:
7
+ ```ts
8
+ const UserServiceImpl = {
9
+ users: [1, 2, 3, 4],
10
+ findAllUsers(): number[] {
11
+ return this.users;
12
+ },
13
+ findUserById(id: number) {
14
+ return this.users.find(user => user == id);
15
+ }
16
+ };
17
+
18
+ const UserService = RestService(UserServiceImpl);
19
+
20
+ app.get("/users", UserService.findAllUsers);
21
+ app.get("/users/:id", (req) => UserService.findUserById(+req.params.id));
22
+ ```
23
+
24
+ #### Advanced usage:
25
+ ```ts
26
+ class PostServiceImpl {
27
+ posts = [1, 2, 3, 4, 5];
28
+ findById(id: number | string) {
29
+ return getOrThrow(
30
+ this.posts.find(p => p == id),
31
+ new HttpError(404, "Post is not found")
32
+ );
33
+ }
34
+ add(id: number) {
35
+ this.posts.push(id);
36
+ return new HttpResponse(201, id);
37
+ }
38
+ delete(id: number) {
39
+ const idx = this.posts.indexOf(id);
40
+ if (idx > -1) {
41
+ this.posts.splice(idx, 1);
42
+ this.#printDeleted(id);
43
+ }
44
+ }
45
+ // use private methods to
46
+ #printDeleted(id: number | string) {
47
+ console.warn(`post ${id} is deleted`)
48
+ }
49
+ }
50
+
51
+ const PostService = RestService(new PostServiceImpl());
52
+
53
+ app.get("/posts/:id", (req) => PostService.findById(req.params.id));
54
+ app.post("/posts/:id", (req) => PostService.add(+req.params.id));
55
+ ```
56
+
57
+ ### **RestMethod**: Converts single method to RequestHandler
58
+ #### Usage:
59
+ ```ts
60
+ class UserService {
61
+ users = [1, 2, 3, 4];
62
+ findAll() {
63
+ return RestMethod(() => {
64
+ return this.users;
65
+ })
66
+ }
67
+ findById(id: number) {
68
+ return RestMethod(() => {
69
+ return getOrThrow(this.users.find(u => u == id), new HttpError(404, "Not Found"));
70
+ })
71
+ }
72
+ }
73
+
74
+ const userService = new UserService();
75
+
76
+ app.get("/users", userService.findAll())
77
+ app.get("/users/:id", (req) => userService.findById(+req.params.id))
78
+ ```
79
+
80
+ ### **Restify**: Decorator to convert a single method to RequestHandler
81
+ #### Note that currently decorators in Typescript doesn't support changing the return type of applied method. So you have to provide RequestHandler as an "or type":
82
+
83
+ ```ts
84
+ class LogServiceImpl {
85
+ logs = ["log1", "log2", "log3"];
86
+
87
+ @Restify
88
+ findAll(): string[] | RequestHandler {
89
+ return this.logs;
90
+ }
91
+ }
92
+
93
+ const LogService = new LogServiceImpl();
94
+
95
+ app.get("/logs", LogService.findAll() as RequestHandler)
96
+ ```
@@ -0,0 +1,3 @@
1
+ import { HttpError } from "..";
2
+
3
+ export function getOrThrow<T, E extends HttpError>(data: T, error: E): T;
@@ -0,0 +1,11 @@
1
+ function getOrThrow(data, error){
2
+ if(data === null || data === undefined){
3
+ throw error;
4
+ }else{
5
+ return data;
6
+ }
7
+ }
8
+
9
+ module.exports = {
10
+ getOrThrow
11
+ }
package/index.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ import { RequestHandler } from "express"
2
+
3
+ declare class HttpError extends Error {
4
+ status: number
5
+ message: string
6
+ constructor(status: number, message: string)
7
+ }
8
+
9
+ declare class HttpResponse<T> {
10
+ status: number
11
+ data: T
12
+ constructor(status: number, data: T)
13
+ }
14
+
15
+ type RestedService<T extends Record<string, any>> = { [K in keyof T]:
16
+ T[K] extends Function
17
+ ? (...args: Parameters<T[K]>) => ((req: Request, res: Response) => void)
18
+ : T[K]
19
+ }
20
+
21
+ declare function RestService<T extends Record<string, any>>(service: T): RestedService<T>;
22
+ declare function RestMethod<T>(callback: () => T): RequestHandler;
23
+ declare function Restify(target: any, key: string, desc: PropertyDescriptor): PropertyDescriptor;
24
+
25
+ export {
26
+ HttpError,
27
+ HttpResponse,
28
+ RestService,
29
+ RestMethod,
30
+ Restify
31
+ }
package/index.js ADDED
@@ -0,0 +1,76 @@
1
+ class HttpError extends Error {
2
+ constructor(status, message) {
3
+ super(message);
4
+ this.stack += "\n" + message;
5
+ this.message = message;
6
+ this.status = status;
7
+ }
8
+ }
9
+
10
+ class HttpResponse {
11
+ constructor(status, data) {
12
+ this.status = status;
13
+ this.data = data;
14
+ }
15
+ }
16
+
17
+ function RestService(service) {
18
+ return Object.fromEntries(
19
+ Object.entries(service).map(keyvalue => {
20
+ if (typeof keyvalue[1] == "function") {
21
+ return [
22
+ keyvalue[0],
23
+ (...args) =>
24
+ (req, res) => {
25
+ try {
26
+ const result = keyvalue[1](...args);
27
+ res.status(result.status || 200).json(result.data || result);
28
+ } catch (e) {
29
+ res.status(e.status || 500).json(e.message || e);
30
+ }
31
+ }
32
+ ]
33
+ } else {
34
+ return keyvalue;
35
+ }
36
+ })
37
+ );
38
+ }
39
+
40
+ function RestMethod(callback) {
41
+ return (req, res) => {
42
+ try {
43
+ const result = callback();
44
+ res.status(result.status || 200).json(result.data || result);
45
+ return result;
46
+ } catch (e) {
47
+ res.status(e.status || 500).json(e.message || e);
48
+ }
49
+ }
50
+ }
51
+
52
+ function Restify(target, key, desc) {
53
+ const oldFunc = desc.value;
54
+ return {
55
+ ...desc,
56
+ value: (...args) => {
57
+ return (req, res) => {
58
+ try {
59
+ const result = oldFunc(...args);
60
+ res.status(result.status || 200).json(result.data || result);
61
+ return result;
62
+ } catch (e) {
63
+ res.status(e.status || 500).json(e.message || e);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ module.exports = {
71
+ HttpError,
72
+ HttpResponse,
73
+ RestService,
74
+ RestMethod,
75
+ Restify
76
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "bootpress",
3
+ "version": "2.0.0",
4
+ "description": "REST service methods for express",
5
+ "main": "index.js",
6
+ "scripts": {},
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/ufukbakan/bootpress.git"
10
+ },
11
+ "keywords": [
12
+ "bootpress",
13
+ "express",
14
+ "rest",
15
+ "service",
16
+ "methods",
17
+ "spring",
18
+ "boot",
19
+ "like"
20
+ ],
21
+ "author": "Ufuk Bakan",
22
+ "license": "MIT",
23
+ "bugs": {
24
+ "url": "https://github.com/ufukbakan/bootpress/issues"
25
+ },
26
+ "homepage": "https://github.com/ufukbakan/bootpress#readme",
27
+ "devDependencies": {
28
+ "@types/express": "^4.17.17"
29
+ },
30
+ "dependencies": {
31
+ "express": "^4.18.2"
32
+ }
33
+ }