
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Express but Spring Boot like
Recommended tool: create-bootpress-app
Http Response Status will inherit status field of returned value by method or 200 by default.
Http Response Body will be mapped to 'data' field or value itself by default.
If you want to explicitly specify a field named 'data' or 'status' it's recommended to encapsulate your value with HttpResponse class.
import express from "express";
import { HttpError, PassParam, RestService } from "bootpress";
import { as, getOrThrow } from "bootpress/helpers";
const app = express();
app.use(express.json());
const UserServiceImpl = {
users: [1, 2, 3, 4],
findAllUsers(): number[] {
return this.users;
},
findUserById(idInParams: string | undefined) {
const id = as(idInParams, "integer");
return getOrThrow(this.users.find(user => user === id), new HttpError(404, "Not Found"));
}
};
const UserService = RestService(UserServiceImpl);
app.get("/users", UserService.findAllUsers());
app.get("/users/:id", PassParam("id")(UserService.findUserById));
import { HttpError, HttpResponse, PassBody, PassParam, PassQuery, RestService } from "bootpress";
import { as, asStrict, getOrThrow } from "bootpress/helpers";
class PostServiceImpl {
posts = [1, 2, 3, 4, 5];
findById(id: string) {
return getOrThrow(
this.posts.find(p => p === as(id, "integer")),
new HttpError(404, "Post is not found")
);
}
add(body: any) {
let casted = asStrict(body, {
"id": "number"
});
this.posts.push(casted.id);
return new HttpResponse(201, casted.id);
}
delete(deleteInQuery: string | undefined, idInQuery: string | undefined) {
if (deleteInQuery === "yes") {
const id = as(idInQuery, "integer");
const index = this.posts.indexOf(id);
if (index > -1) {
this.#logDeleted(idInQuery!);
return this.posts.splice(index, 1);
} else {
throw new HttpError(404, "Post is not found")
}
}
throw new HttpError(400, "Bad Request");
}
// use private methods to
#logDeleted(id: number | string) {
console.warn(`post ${id} is deleted`)
}
findAll() {
return this.posts;
}
}
const PostService = RestService(PostServiceImpl);
// this is valid too:
// const PostService = RestService(new PostServiceImpl());
app.get("/posts", PostService.findAll())
app.post("/posts", PassBody(PostService.add));
app.delete("/posts", PassQuery("delete")(PassQuery("id")(PostService.delete)));
app.get("/posts/:id", PassParam("id")(PostService.findById));
import { HttpError, RestMethod } from "bootpress";
import { getOrThrow } from "bootpress/helpers";
class UserService {
users = [1, 2, 3, 4];
findAll() {
return RestMethod(() => {
return this.users;
})
}
findById(id: number) {
return RestMethod(() => {
return getOrThrow(this.users.find(u => u == id), new HttpError(404, "Not Found"));
})
}
}
const userService = new UserService();
app.get("/users", userService.findAll())
app.get("/users/:id", (req) => userService.findById(+req.params.id))
import { Restify } from "bootpress";
import { RequestHandler } from "express";
class LogServiceImpl {
logs = ["log1", "log2", "log3"];
@Restify
findAll(): string[] | RequestHandler {
return this.logs;
}
}
const LogService = new LogServiceImpl();
app.get("/logs", LogService.findAll() as RequestHandler)
PassBody(serviceFunction) -> Passes body to service function without any validation
ParseBodyAs(type, config?)(serviceFunction) -> Parses body to specified type then passes it to service function. Config object is optional and has messageTemplate field which represents a string with details placeholder: {0}
PassBodyAs(type, config?)(serviceFunction) -> Validates body with provided type and passes it to service function. Config object is optional and has messageTemplate field which represents a string with details placeholder: {0}
PassAllParams(serviceFunction) -> Passes all path parameters to service function as a Record<string, string> (pure js object that contains key-value pairs)
PassAllQueries(serviceFunction) -> Passes query to service function as Record<string, string>
PassAllCookies(serviceFunction) -> Passes cookies to service function as Record<string, string>
PassParam(pathParam)(serviceFunction) -> Passes specified parameter as arguments to service function
PassQuery(searchQueryName)(serviceFunction) -> Passes specified query as arguments to service function
PassCookie(cookieName)(serviceFunction) -> Passes specified cookie as arguments to service function
PassRequest(serviceFunction) -> Passes express request object to service function
PassResponse(serviceFunction) -> Passes express response object to service function
Argument passers can be chained by passing result of one as serviceFunction parameter to other. e.g.:
// in rest service class:
function serviceFunction(cookies, body){
...
}
// in router:
router.post("/", PassAllCookies( PassBodyAs(yourSchema)(restService.serviceFunction) ));
Returns the value back if it's not null, undefined or empty array.
Returns the value if it's not null or undefined otherwise returns the default value.
Helps you to define a JS Schema.
Tries to parse target value to provided type.
If type of provided type is string then it's a primitive key and valid values are:
"string"
"string[]"
"boolean"
"boolean[]"
"number"
"number[]"
"integer"
"integer[]"
"string?"
"string[]?"
"boolean?"
"boolean[]?"
"number?"
"number[]?"
"integer?"
"integer[]?"
If typeof provided type is object then it's a JS Schema and structure must follow:
{
"property": string | object | Array // Nullable primitives not allowed here instead use question mark end of the property key
"nullableProperty?": string | object | Array
}
If typeof provided type is an array the structure must follow:
[
yourJsSchemaObject
]
There must be only one element in an array schema which defines ArrayOf<Schema>
Config object is optional and structure follows:
{
errorVariableName: string | undefined, // variable name in the error message
messageTemplate: string | undefined // default values is "{0}" where it directly writes error details.
// an messageTemplate example is: "Parse error:\n{0}"
}
Same as 'as' method but doesn't try to parse different types instead throws error.
Please use "as" or "asStrict" instead of these functions. For example:
//const x: string = asString(o); // deprecated
const x: string = as(o, "string");
FAQs
REST service methods for express
The npm package bootpress receives a total of 3 weekly downloads. As such, bootpress popularity was classified as not popular.
We found that bootpress demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.