pvanand commited on
Commit
59b2e56
·
verified ·
1 Parent(s): 1e12f0a

Delete app

Browse files
app/app.js DELETED
@@ -1,44 +0,0 @@
1
- // npm packages
2
- const dotenv = require("dotenv");
3
- const express = require("express");
4
-
5
- // app imports
6
- const { connectToDatabase, globalResponseHeaders } = require("./config");
7
- const { errorHandler } = require("./handlers");
8
- const { thingsRouter } = require("./routers");
9
-
10
- // global constants
11
- dotenv.config();
12
- const app = express();
13
- const {
14
- bodyParserHandler,
15
- globalErrorHandler,
16
- fourOhFourHandler,
17
- fourOhFiveHandler,
18
- } = errorHandler;
19
-
20
- // database
21
- connectToDatabase();
22
-
23
- // body parser setup
24
- app.use(express.urlencoded({ extended: true }));
25
- app.use(express.json({ type: "*/*" }));
26
- app.use(bodyParserHandler); // error handling specific to body parser only
27
-
28
- // response headers setup; CORS
29
- app.use(globalResponseHeaders);
30
-
31
- app.use("/things", thingsRouter);
32
-
33
- // catch-all for 404 "Not Found" errors
34
- app.get("*", fourOhFourHandler);
35
- // catch-all for 405 "Method Not Allowed" errors
36
- app.all("*", fourOhFiveHandler);
37
-
38
- app.use(globalErrorHandler);
39
-
40
- /**
41
- * This file does NOT run the app. It merely builds and configures it then exports it.config
42
- * This is for integration tests with supertest (see __tests__).
43
- */
44
- module.exports = app;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/config.js DELETED
@@ -1,56 +0,0 @@
1
- const mongoose = require("mongoose");
2
-
3
- const APP_NAME = "Boilerplate API";
4
- const ENV = process.env.NODE_ENV;
5
- const PORT = process.env.PORT || 8080;
6
-
7
- /**
8
- * Connect to mongoose asynchronously or bail out if it fails
9
- */
10
- async function connectToDatabase() {
11
- const MONGODB_URI =
12
- process.env.MONGODB_URI || "mongodb://mongodb/boilerplate";
13
-
14
- mongoose.Promise = Promise;
15
- if (ENV === "development" || ENV === "test") {
16
- mongoose.set("debug", true);
17
- }
18
-
19
- try {
20
- await mongoose.connect(MONGODB_URI, {
21
- autoIndex: false,
22
- useNewUrlParser: true,
23
- useUnifiedTopology: true,
24
- });
25
- console.log(`${APP_NAME} successfully connected to database.`);
26
- } catch (error) {
27
- console.log(error);
28
- process.exit(1);
29
- }
30
- }
31
-
32
- /**
33
- * Configuration middleware to enable cors and set some other allowed headers.
34
- * You can also just use the 'cors' package.
35
- */
36
- function globalResponseHeaders(request, response, next) {
37
- response.header("Access-Control-Allow-Origin", "*");
38
- response.header(
39
- "Access-Control-Allow-Headers",
40
- "Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Authorization"
41
- );
42
- response.header(
43
- "Access-Control-Allow-Methods",
44
- "POST,GET,PATCH,DELETE,OPTIONS"
45
- );
46
- response.header("Content-Type", "application/json");
47
- return next();
48
- }
49
-
50
- module.exports = {
51
- APP_NAME,
52
- ENV,
53
- PORT,
54
- connectToDatabase,
55
- globalResponseHeaders,
56
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/handlers/error.js DELETED
@@ -1,45 +0,0 @@
1
- const { APP_NAME } = require("../config");
2
- const { APIError } = require("../helpers");
3
-
4
- function bodyParserHandler(error, request, response, next) {
5
- if (error instanceof SyntaxError || error instanceof TypeError) {
6
- // console.error(error);
7
- return next(new APIError(400, "Bad Request", "Malformed JSON."));
8
- }
9
- }
10
-
11
- function fourOhFourHandler(request, response, next) {
12
- return next(
13
- new APIError(
14
- 404,
15
- "Resource Not Found",
16
- `${request.path} is not valid path to a ${APP_NAME} resource.`
17
- )
18
- );
19
- }
20
-
21
- function fourOhFiveHandler(request, response, next) {
22
- return next(
23
- new APIError(
24
- 405,
25
- "Method Not Allowed",
26
- `${request.method} method is not supported at ${request.path}.`
27
- )
28
- );
29
- }
30
-
31
- function globalErrorHandler(error, request, response, next) {
32
- let err = error;
33
- if (!(error instanceof APIError)) {
34
- err = new APIError(500, error.type, error.message);
35
- }
36
-
37
- return response.status(err.status).json(err);
38
- }
39
-
40
- module.exports = {
41
- bodyParserHandler,
42
- fourOhFourHandler,
43
- fourOhFiveHandler,
44
- globalErrorHandler
45
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/handlers/index.js DELETED
@@ -1,3 +0,0 @@
1
- exports.errorHandler = require("./error");
2
- exports.thingHandler = require("./thing");
3
- exports.thingsHandler = require("./things");
 
 
 
 
app/handlers/thing.js DELETED
@@ -1,91 +0,0 @@
1
- // npm packages
2
- const { validate } = require("jsonschema");
3
-
4
- // app imports
5
- const { Thing } = require("../models");
6
- const { APIError } = require("../helpers");
7
- const { thingNewSchema, thingUpdateSchema } = require("../schemas");
8
-
9
- /**
10
- * Validate the POST request body and create a new Thing
11
- */
12
- async function createThing(request, response, next) {
13
- const validation = validate(request.body, thingNewSchema);
14
- if (!validation.valid) {
15
- return next(
16
- new APIError(
17
- 400,
18
- "Bad Request",
19
- validation.errors.map(e => e.stack).join(". ")
20
- )
21
- );
22
- }
23
-
24
- try {
25
- const newThing = await Thing.createThing(new Thing(request.body));
26
- return response.status(201).json(newThing);
27
- } catch (err) {
28
- return next(err);
29
- }
30
- }
31
-
32
- /**
33
- * Get a single thing
34
- * @param {String} name - the name of the Thing to retrieve
35
- */
36
- async function readThing(request, response, next) {
37
- const { name } = request.params;
38
- try {
39
- const thing = await Thing.readThing(name);
40
- return response.json(thing);
41
- } catch (err) {
42
- return next(err);
43
- }
44
- }
45
-
46
- /**
47
- * Update a single thing
48
- * @param {String} name - the name of the Thing to update
49
- */
50
- async function updateThing(request, response, next) {
51
- const { name } = request.params;
52
-
53
- const validation = validate(request.body, thingUpdateSchema);
54
- if (!validation.valid) {
55
- return next(
56
- new APIError(
57
- 400,
58
- "Bad Request",
59
- validation.errors.map(e => e.stack).join(". ")
60
- )
61
- );
62
- }
63
-
64
- try {
65
- const thing = await Thing.updateThing(name, request.body);
66
- return response.json(thing);
67
- } catch (err) {
68
- return next(err);
69
- }
70
- }
71
-
72
- /**
73
- * Remove a single thing
74
- * @param {String} name - the name of the Thing to remove
75
- */
76
- async function deleteThing(request, response, next) {
77
- const { name } = request.params;
78
- try {
79
- const deleteMsg = await Thing.deleteThing(name);
80
- return response.json(deleteMsg);
81
- } catch (err) {
82
- return next(err);
83
- }
84
- }
85
-
86
- module.exports = {
87
- createThing,
88
- readThing,
89
- updateThing,
90
- deleteThing
91
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/handlers/things.js DELETED
@@ -1,28 +0,0 @@
1
- // app imports
2
- const { Thing } = require("../models");
3
- const { APIError, parseSkipLimit } = require("../helpers");
4
-
5
- /**
6
- * List all the things. Query params ?skip=0&limit=1000 by default
7
- */
8
- async function readThings(request, response, next) {
9
- /* pagination validation */
10
- let skip = parseSkipLimit(request.query.skip) || 0;
11
- let limit = parseSkipLimit(request.query.limit, 1000) || 1000;
12
- if (skip instanceof APIError) {
13
- return next(skip);
14
- } else if (limit instanceof APIError) {
15
- return next(limit);
16
- }
17
-
18
- try {
19
- const things = await Thing.readThings({}, {}, skip, limit);
20
- return response.json(things);
21
- } catch (err) {
22
- return next(err);
23
- }
24
- }
25
-
26
- module.exports = {
27
- readThings
28
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/helpers/APIError.js DELETED
@@ -1,31 +0,0 @@
1
- /** Class representing an API Error Response with a related HTTP Status Code **/
2
- class APIError extends Error {
3
- /**
4
- * Create an Error Object
5
- * @param {Number} status - The HTTP Status Code (e.g. 404)
6
- * @param {String} title - The title corresponding to the Status Code (e.g. Bad Request)
7
- * @param {String} message - Specific information about what caused the error
8
- */
9
- constructor(
10
- status = 500,
11
- title = "Internal Server Error",
12
- message = "An unknown server error occurred."
13
- ) {
14
- super(message);
15
- this.status = status;
16
- this.title = title;
17
- this.message = message;
18
- }
19
- toJSON() {
20
- const { status, title, message } = this;
21
- return {
22
- error: {
23
- status,
24
- title,
25
- message
26
- }
27
- };
28
- }
29
- }
30
-
31
- module.exports = APIError;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/helpers/index.js DELETED
@@ -1,2 +0,0 @@
1
- exports.APIError = require("./APIError");
2
- exports.parseSkipLimit = require("./parseSkipLimit");
 
 
 
app/helpers/parseSkipLimit.js DELETED
@@ -1,33 +0,0 @@
1
- const APIError = require("./APIError");
2
- /**
3
- * Validate the 'limit' and `skip` query params
4
- * @param {String} val - limit or skip param
5
- * @param {Number} max - the max value (default 1000)
6
- * @param {String} type - what we're validating (skip or limit, default limit)
7
- * @return {Number} numerical form of the val
8
- */
9
- function parseSkipLimit(val, max = 1000, type = "limit") {
10
- if (!val) {
11
- return null;
12
- }
13
- const min = type === "skip" ? 0 : 1;
14
- const num = +val;
15
-
16
- if (!Number.isInteger(num)) {
17
- return new APIError(
18
- 400,
19
- "Bad Request",
20
- `Invalid ${type}: '${val}', ${type} needs to be an integer.`
21
- );
22
- } else if (num < min || (max && num > max)) {
23
- return new APIError(
24
- 400,
25
- "Bad Request",
26
- `${num} is out of range for ${type} -- it should be between ${min} and ${max}.`
27
- );
28
- }
29
-
30
- return num;
31
- }
32
-
33
- module.exports = parseSkipLimit;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/models/Thing.js DELETED
@@ -1,108 +0,0 @@
1
- // npm packages
2
- const mongoose = require("mongoose");
3
-
4
- // app imports
5
- const { APIError } = require("../helpers");
6
-
7
- // globals
8
- const Schema = mongoose.Schema;
9
-
10
- const thingSchema = new Schema({
11
- name: String,
12
- number: Number,
13
- stuff: [String],
14
- url: String
15
- });
16
-
17
- thingSchema.statics = {
18
- /**
19
- * Create a Single New Thing
20
- * @param {object} newThing - an instance of Thing
21
- * @returns {Promise<Thing, APIError>}
22
- */
23
- async createThing(newThing) {
24
- const duplicate = await this.findOne({ name: newThing.name });
25
- if (duplicate) {
26
- throw new APIError(
27
- 409,
28
- "Thing Already Exists",
29
- `There is already a thing with name '${newThing.name}'.`
30
- );
31
- }
32
- const thing = await newThing.save();
33
- return thing.toObject();
34
- },
35
- /**
36
- * Delete a single Thing
37
- * @param {String} name - the Thing's name
38
- * @returns {Promise<Thing, APIError>}
39
- */
40
- async deleteThing(name) {
41
- const deleted = await this.findOneAndRemove({ name });
42
- if (!deleted) {
43
- throw new APIError(404, "Thing Not Found", `No thing '${name}' found.`);
44
- }
45
- return deleted.toObject();
46
- },
47
- /**
48
- * Get a single Thing by name
49
- * @param {String} name - the Thing's name
50
- * @returns {Promise<Thing, APIError>}
51
- */
52
- async readThing(name) {
53
- const thing = await this.findOne({ name });
54
-
55
- if (!thing) {
56
- throw new APIError(404, "Thing Not Found", `No thing '${name}' found.`);
57
- }
58
- return thing.toObject();
59
- },
60
- /**
61
- * Get a list of Things
62
- * @param {Object} query - pre-formatted query to retrieve things.
63
- * @param {Object} fields - a list of fields to select or not in object form
64
- * @param {String} skip - number of docs to skip (for pagination)
65
- * @param {String} limit - number of docs to limit by (for pagination)
66
- * @returns {Promise<Things, APIError>}
67
- */
68
- async readThings(query, fields, skip, limit) {
69
- const things = await this.find(query, fields)
70
- .skip(skip)
71
- .limit(limit)
72
- .sort({ name: 1 })
73
- .exec();
74
- if (!things.length) {
75
- return [];
76
- }
77
- return things.map(thing => thing.toObject());
78
- },
79
- /**
80
- * Patch/Update a single Thing
81
- * @param {String} name - the Thing's name
82
- * @param {Object} thingUpdate - the json containing the Thing attributes
83
- * @returns {Promise<Thing, APIError>}
84
- */
85
- async updateThing(name, thingUpdate) {
86
- const thing = await this.findOneAndUpdate({ name }, thingUpdate, {
87
- new: true
88
- });
89
- if (!thing) {
90
- throw new APIError(404, "Thing Not Found", `No thing '${name}' found.`);
91
- }
92
- return thing.toObject();
93
- }
94
- };
95
-
96
- /* Transform with .toObject to remove __v and _id from response */
97
- if (!thingSchema.options.toObject) thingSchema.options.toObject = {};
98
- thingSchema.options.toObject.transform = (doc, ret) => {
99
- const transformed = ret;
100
- delete transformed._id;
101
- delete transformed.__v;
102
- return transformed;
103
- };
104
-
105
- /** Ensure MongoDB Indices **/
106
- thingSchema.index({ name: 1, number: 1 }, { unique: true }); // example compound idx
107
-
108
- module.exports = mongoose.model("Thing", thingSchema);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/models/index.js DELETED
@@ -1 +0,0 @@
1
- exports.Thing = require("./Thing");
 
 
app/routers/index.js DELETED
@@ -1 +0,0 @@
1
- exports.thingsRouter = require("./things");
 
 
app/routers/things.js DELETED
@@ -1,25 +0,0 @@
1
- // npm packages
2
- const express = require("express");
3
-
4
- // app imports
5
- const { thingHandler, thingsHandler } = require("../handlers");
6
-
7
- // globals
8
- const router = new express.Router();
9
- const { readThings } = thingsHandler;
10
- const { createThing, readThing, updateThing, deleteThing } = thingHandler;
11
-
12
- /* All the Things Route */
13
- router
14
- .route("")
15
- .get(readThings)
16
- .post(createThing);
17
-
18
- /* Single Thing by Name Route */
19
- router
20
- .route("/:name")
21
- .get(readThing)
22
- .patch(updateThing)
23
- .delete(deleteThing);
24
-
25
- module.exports = router;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/schemas/index.js DELETED
@@ -1,2 +0,0 @@
1
- exports.thingNewSchema = require('./thingNew');
2
- exports.thingUpdateSchema = require('./thingUpdate');
 
 
 
app/schemas/thingNew.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-04/schema#",
3
- "type": "object",
4
- "additionalProperties": false,
5
- "properties": {
6
- "name": {
7
- "type": "string"
8
- },
9
- "number": {
10
- "type": "integer",
11
- "minimum": 0
12
- },
13
- "stuff": {
14
- "type": "array",
15
- "uniqueItems": true,
16
- "minItems": 1,
17
- "items": {
18
- "type": "string"
19
- }
20
- },
21
- "url": {
22
- "type": "string",
23
- "format": "uri"
24
- }
25
- },
26
- "required": ["name"]
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/schemas/thingUpdate.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/draft-04/schema#",
3
- "type": "object",
4
- "additionalProperties": false,
5
- "properties": {
6
- "name": {
7
- "type": "string"
8
- },
9
- "number": {
10
- "type": "integer",
11
- "minimum": 0
12
- },
13
- "stuff": {
14
- "type": "array",
15
- "uniqueItems": true,
16
- "minItems": 1,
17
- "items": {
18
- "type": "string"
19
- }
20
- },
21
- "url": {
22
- "type": "string",
23
- "format": "uri"
24
- }
25
- },
26
- "required": ["name"]
27
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app/server.js DELETED
@@ -1,6 +0,0 @@
1
- const { APP_NAME, PORT } = require("./config");
2
- const app = require("./app");
3
-
4
- app.listen(PORT, () => {
5
- console.log(`${APP_NAME} is listening on port ${PORT}...`);
6
- });