Skip to content

Commit d36c8bc

Browse files
committed
First commit. Publish package:)
0 parents  commit d36c8bc

File tree

6 files changed

+455
-0
lines changed

6 files changed

+455
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
package-lock.json

README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
### Next API Validation
2+
3+
This is basically the same as [serverless-request-validator](https://www.npmjs.com/package/serverless-request-validator) ready be used in Next.js
4+
5+
### How to use it:
6+
7+
It is nice to be able to programmatically define what you want your API endpoint(s) to do deppending on the request method used.
8+
9+
In express it's something like:
10+
11+
```js
12+
app.get((req,res)=>{
13+
res.send("Something");
14+
})
15+
```
16+
> That will work only when using a `GET` request
17+
18+
In Next.js (and Vercel) apps, your api are files in a specific order in the project directory, each file with a default export being the actual handler that will handle that request.
19+
20+
First, install the module:
21+
22+
```sh
23+
npm install next-api-validation
24+
```
25+
Or
26+
```sh
27+
yarn add next-api-validation
28+
```
29+
30+
Using it in any of your API routes in Next.js:
31+
32+
```js
33+
import validation from "next-api-validation";
34+
35+
export default validation.get((req,res)=>{
36+
res.send("This only accepts GET request")
37+
})
38+
```
39+
> As you can see, using the `get` method in the `validation` object prevents the handler from being executed if a different request method is used.
40+
41+
And so with other methods:
42+
43+
44+
```js
45+
// api/index.js or api/index.ts
46+
import validation from "next-api-validation";
47+
48+
export default validation.post((req,res)=>{
49+
res.send("You just sent a POST request")
50+
})
51+
```
52+
> This handler a POST request
53+
54+
**What if an endpoint should handle requests using more than one or two methods?**
55+
56+
Creating a default export of the function should solve that:
57+
58+
```js
59+
// api/index.js or api/index.ts
60+
import validate from "next-api-validation"
61+
62+
export default validate({
63+
get(req,res){
64+
res.send("A get request")
65+
},
66+
post(req,res){
67+
res.send("I only handle post requests"))
68+
},
69+
put(req,res){
70+
res.send("Did you put something?")
71+
}
72+
})
73+
```
74+
75+
The previous code handles requests that use three different methods, and calls only the necessary handler. An example of how it can be used:
76+
77+
```js
78+
// CRUD of a MongoDB Document model
79+
80+
import { Post } from "src/Models";
81+
import { connectToDatabase } from "src/utils";
82+
import validate from "next-api-validation";
83+
84+
connectToDatabase();
85+
86+
export default validate({
87+
get: async (req, res) => {
88+
const posts = await Post.find();
89+
res.send(posts);
90+
},
91+
post: async (req, res) => {
92+
const newPost = new Post(req.body);
93+
const saved = await newPost.save();
94+
res.send(saved);
95+
},
96+
put: async (req, res) => {
97+
const editedPost = await Post.findByIdAndUpdate(req.body._id, req.body);
98+
res.send(editedPost);
99+
},
100+
delete: async (req, res) => {
101+
const deletedPost = await Post.findByIdAndDelete(req.body._id);
102+
res.send(deletedPost);
103+
},
104+
});
105+
```
106+
> Async handlers work too:), but this is thanks to Next.js itself, not me:P
107+
108+
That's it!
109+
110+
You can follow me on Github as [Danybeltran](https://github.com/danybeltran), I sometimes works on other stuff. Check a similar package made for Vercel APIs: [serverless-request-validator](https://www.npmjs.com/package/serverless-request-validator), also by me. Thanks!

index.d.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { VercelRequest, VercelResponse } from "@vercel/node";
2+
interface ValidateRequest extends VercelRequest {
3+
}
4+
interface ValidateResponse<T> extends VercelResponse {
5+
sendStatus?: (code: number, message?: string) => void;
6+
sendFile?: (url?: string) => void;
7+
}
8+
/** Request handler */
9+
declare type RequestValidatorHandlerType = (
10+
/** Request object */
11+
Req: ValidateRequest,
12+
/** Response object */
13+
Res: ValidateResponse<any>) => void;
14+
interface IValidatorProps {
15+
/** Handles a GET request */
16+
get?: RequestValidatorHandlerType;
17+
/** Handles a POST request */
18+
post?: RequestValidatorHandlerType;
19+
/** Handles a PUT request */
20+
put?: RequestValidatorHandlerType;
21+
/** Handles a DELETE request */
22+
delete?: RequestValidatorHandlerType;
23+
/** Handles a HEAD request */
24+
head?: RequestValidatorHandlerType;
25+
/** Handles a CONNECT request */
26+
connect?: RequestValidatorHandlerType;
27+
/** Handles an OPTIONS request */
28+
options?: RequestValidatorHandlerType;
29+
/** Handles a TRACE request */
30+
trace?: RequestValidatorHandlerType;
31+
/** Handles a PATCH request */
32+
patch?: RequestValidatorHandlerType;
33+
}
34+
/** Specify callbacks for different methods made to an endpoint */
35+
declare type ValidateType = (handlers: IValidatorProps) => Function;
36+
interface IValidate extends IValidatorProps, ValidateType {
37+
}
38+
declare const Validate: IValidate;
39+
export default Validate;

index.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
"use strict";
2+
var __assign =
3+
(this && this.__assign) ||
4+
function () {
5+
__assign =
6+
Object.assign ||
7+
function (t) {
8+
for (var s, i = 1, n = arguments.length; i < n; i++) {
9+
s = arguments[i];
10+
for (var p in s)
11+
if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
12+
}
13+
return t;
14+
};
15+
return __assign.apply(this, arguments);
16+
};
17+
exports.__esModule = true;
18+
var mime_types_1 = require("mime-types");
19+
var fs = require("fs");
20+
var RequestMethods = [
21+
"get",
22+
"post",
23+
"put",
24+
"delete",
25+
"head",
26+
"connect",
27+
"options",
28+
"trace",
29+
"patch",
30+
];
31+
var Validate = function (handlers) {
32+
var validateResponseCallback = function (req, res) {
33+
var _handlers = __assign({}, handlers);
34+
var vResponse = __assign(__assign({}, res), {
35+
sendStatus: function (code, message) {
36+
if (message === void 0) {
37+
message = "";
38+
}
39+
res.status(code).send(message);
40+
},
41+
sendFile: function (url) {
42+
if (url === void 0) {
43+
url = "";
44+
}
45+
try {
46+
var fileHeadType = mime_types_1.lookup(url);
47+
if (typeof fileHeadType === "string") {
48+
res.writeHead(200, {
49+
"Content-Type": fileHeadType.toString(),
50+
});
51+
var rs = fs.createReadStream(url);
52+
rs.pipe(res);
53+
} else {
54+
res.status(404).send("File not found");
55+
}
56+
} catch (err) {
57+
throw err;
58+
}
59+
},
60+
});
61+
try {
62+
RequestMethods.forEach(function (requestMethod) {
63+
if (!handlers[requestMethod]) {
64+
var invalidMethodCb = function (req, res) {
65+
res
66+
.status(405)
67+
.send("Cannot " + requestMethod.toUpperCase() + " " + req.url);
68+
};
69+
_handlers[requestMethod] = invalidMethodCb;
70+
}
71+
});
72+
return _handlers[req.method.toLowerCase()](req, vResponse);
73+
} catch (err) {
74+
res.send("An error ocurred");
75+
throw err;
76+
}
77+
};
78+
return validateResponseCallback;
79+
};
80+
RequestMethods.forEach(function (requestMethod) {
81+
Validate[requestMethod] = function (handler) {
82+
var responseCb = function (req, res) {
83+
var method = req.method;
84+
var vResponse = __assign(__assign({}, res), {
85+
sendStatus: function (code, message) {
86+
if (message === void 0) {
87+
message = "";
88+
}
89+
res.status(code).send(message);
90+
},
91+
sendFile: function (url) {
92+
if (url === void 0) {
93+
url = "";
94+
}
95+
try {
96+
var fileHeadType = mime_types_1.lookup(url);
97+
if (typeof fileHeadType === "string") {
98+
res.writeHead(200, {
99+
"Content-Type": fileHeadType.toString(),
100+
});
101+
var rs = fs.createReadStream(url);
102+
rs.pipe(res);
103+
} else {
104+
res.status(404).send("File not found");
105+
}
106+
} catch (err) {
107+
throw err;
108+
}
109+
},
110+
});
111+
if (method.toLowerCase() === requestMethod) {
112+
handler(req, vResponse);
113+
} else {
114+
vResponse.sendStatus(405, "Cannot " + method + " " + req.url);
115+
}
116+
};
117+
return responseCb;
118+
};
119+
});
120+
exports["default"] = Validate;

0 commit comments

Comments
 (0)