notherbase-fs 3.1.5 → 3.1.6

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 CHANGED
@@ -1,4 +1,6 @@
1
1
  # notherbase-fs
2
- Functions to help one develope a base.
2
+ A package to help one develop a base.
3
3
 
4
- Visit www.notherbase.com/docs to for documentation on notherbase-fs and notherbase.
4
+ A base is an Express.js server that will render EJS web pages with automatic route creation. It also has a spirit world, a MongoDB-connected API to provide those pages with dynamic data and multiplayer interaction. A little bit of socket.io is sprinkled for good measure.
5
+
6
+ Visit www.notherbase.com/docs for documentation on notherbase-fs.
@@ -1,20 +1,27 @@
1
1
  import express from "express";
2
2
  import fs from 'fs';
3
3
 
4
+ /**
5
+ * Creation is all the renedered pages in a base.
6
+ */
4
7
  export default class Creation {
5
8
  constructor() {
6
9
  this.router = express.Router();
7
10
 
8
11
  //home
9
12
  this.router.get("/", function(req, res) { res.redirect("/the-front"); });
13
+
10
14
  //the-front
11
15
  this.router.get(`/the-front`, this.front, this.explore);
12
16
  this.router.get(`/the-front/:frontDetail`, this.frontDetail, this.explore);
17
+
13
18
  //pages
14
19
  this.router.get(`/:page`, this.page, this.explore);
20
+
15
21
  //explorer
16
22
  this.router.get(`/:region/:area/:poi`, this.lock, this.poi, this.explore);
17
23
  this.router.get(`/:region/:area/:poi/:detail`, this.lock, this.detail, this.explore);
24
+
18
25
  //void
19
26
  this.router.use(function(req, res) {
20
27
  console.log(req.path);
@@ -22,11 +29,23 @@ export default class Creation {
22
29
  });
23
30
  }
24
31
 
32
+ /**
33
+ * This middleware requires a user to login to access affected routes.
34
+ * @param {Object} req An Express.js request.
35
+ * @param {Object} res An Express.js response.
36
+ * @param {Function} next next()
37
+ */
25
38
  lock = (req, res, next) => {
26
39
  req.lock = true;
27
40
  next();
28
41
  }
29
42
 
43
+ /**
44
+ * This route renders a page and sends it to the client.
45
+ * @param {Object} req An Express.js request.
46
+ * @param {Object} res An Express.js response.
47
+ * @param {Function} next next()
48
+ */
30
49
  explore = async (req, res, next) => {
31
50
  try {
32
51
  if (fs.existsSync(req.main + ".ejs")) {
@@ -57,10 +76,16 @@ export default class Creation {
57
76
  }
58
77
  catch(err) {
59
78
  console.log(err);
60
- res.status(500).end();
79
+ res.status(500).send("Server Error");
61
80
  }
62
81
  }
63
82
 
83
+ /**
84
+ * This middleware directs exploration to the front.
85
+ * @param {Object} req An Express.js request.
86
+ * @param {Object} res An Express.js response.
87
+ * @param {Function} next next()
88
+ */
64
89
  front = async (req, res, next) => {
65
90
  req.main = req.contentPath + "/the-front/index";
66
91
  req.siteTitle = "NotherBase - The Front";
@@ -68,6 +93,12 @@ export default class Creation {
68
93
  next();
69
94
  }
70
95
 
96
+ /**
97
+ * This middleware directs exploration to a detail in the front.
98
+ * @param {Object} req An Express.js request.
99
+ * @param {Object} res An Express.js response.
100
+ * @param {Function} next next()
101
+ */
71
102
  frontDetail = async (req, res, next) => {
72
103
  req.main = `${req.contentPath}/the-front/${req.params.frontDetail}/index`;
73
104
  req.siteTitle = `NotherBase - ${req.params.frontDetail}`;
@@ -75,6 +106,12 @@ export default class Creation {
75
106
  next();
76
107
  }
77
108
 
109
+ /**
110
+ * This middleware directs exploration to a point of interest.
111
+ * @param {Object} req An Express.js request.
112
+ * @param {Object} res An Express.js response.
113
+ * @param {Function} next next()
114
+ */
78
115
  poi = async (req, res, next) => {
79
116
  req.main = `${req.contentPath}/${req.params.region}/${req.params.area}/${req.params.poi}/index`;
80
117
  req.siteTitle = `NotherBase - ${req.params.poi}`;
@@ -82,6 +119,12 @@ export default class Creation {
82
119
  next();
83
120
  }
84
121
 
122
+ /**
123
+ * This middleware directs exploration to a detail.
124
+ * @param {Object} req An Express.js request.
125
+ * @param {Object} res An Express.js response.
126
+ * @param {Function} next next()
127
+ */
85
128
  detail = async (req, res, next) => {
86
129
  req.main = `${req.contentPath}/${req.params.region}/${req.params.area}/${req.params.poi}/${req.params.detail}/index`;
87
130
  req.siteTitle = `NotherBase - ${req.params.detail}`;
@@ -89,6 +132,12 @@ export default class Creation {
89
132
  next();
90
133
  }
91
134
 
135
+ /**
136
+ * This middleware directs exploration to a one-off page.
137
+ * @param {Object} req An Express.js request.
138
+ * @param {Object} res An Express.js response.
139
+ * @param {Function} next next()
140
+ */
92
141
  page = async (req, res, next) => {
93
142
  req.main = `${req.contentPath}/pages/${req.params.page}/index`;
94
143
  req.siteTitle = `${req.params.page}`;
@@ -1,18 +1,43 @@
1
1
  import express from "express";
2
2
  import { stripHtml } from "string-strip-html";
3
- import { success, fail } from "./spirits/util.js";
4
- import User from "./spirits/user.js";
3
+ import { success, fail } from "./util.js";
4
+ import User from "./user.js";
5
5
  import fs from 'fs';
6
6
 
7
+ /**
8
+ * The spirit world is the API of a base.
9
+ */
7
10
  export default class SpiritWorld {
11
+ /**
12
+ * Sets up socket.io for instant messaging and etc.
13
+ * @param {*} socket
14
+ */
8
15
  #setupChat = (socket) => {
9
16
  socket.join(socket.handshake.query.room);
17
+ if (this.rooms[socket.handshake.query.room]) this.rooms[socket.handshake.query.room].users.push(socket.handshake.query.name);
18
+ else {
19
+ this.rooms[socket.handshake.query.room] = {
20
+ users: [
21
+ socket.handshake.query.name
22
+ ]
23
+ }
24
+ }
25
+
26
+ console.log(this.rooms[socket.handshake.query.room]);
10
27
 
11
28
  this.io.to(socket.handshake.query.room).emit("chat message", {
12
29
  name: "Server",
13
30
  time: Date.now(),
14
31
  text: `${socket.handshake.query.name} has joined the room.`
15
32
  });
33
+
34
+ this.io.to(socket.handshake.query.room).emit("chat info", {
35
+ name: socket.handshake.query.room,
36
+ time: Date.now(),
37
+ data: {
38
+ users: this.rooms[socket.handshake.query.room].users
39
+ }
40
+ });
16
41
 
17
42
  socket.on("chat message", (msg) => {
18
43
  this.io.to(socket.handshake.query.room).emit("chat message", {
@@ -23,16 +48,34 @@ export default class SpiritWorld {
23
48
  });
24
49
 
25
50
  socket.on('disconnect', () => {
51
+ this.rooms[socket.handshake.query.room].users.splice(this.rooms[socket.handshake.query.room].users.indexOf(socket.handshake.query.name));
52
+
26
53
  this.io.to(socket.handshake.query.room).emit("chat message", {
27
54
  name: "Server",
28
55
  time: Date.now(),
29
56
  text: `${socket.handshake.query.name} has left the room.`
30
57
  });
58
+
59
+ this.io.to(socket.handshake.query.room).emit("chat info", {
60
+ name: socket.handshake.query.room,
61
+ time: Date.now(),
62
+ data: {
63
+ users: this.rooms[socket.handshake.query.room].users
64
+ }
65
+ });
66
+
67
+ if (this.rooms[socket.handshake.query.room].users.length < 1) delete this.rooms[socket.handshake.query.room];
31
68
  });
32
69
  }
33
70
 
71
+ /**
72
+ * Sets up the spirit world.
73
+ * @param {Server} io
74
+ */
34
75
  constructor(io) {
35
76
  this.io = io;
77
+ this.rooms = {};
78
+
36
79
  this.router = express.Router();
37
80
  this.user = new User();
38
81
 
@@ -43,21 +86,35 @@ export default class SpiritWorld {
43
86
  this.io.on('connection', this.#setupChat);
44
87
  }
45
88
 
89
+ /**
90
+ * This API route requests a spirit from the database.
91
+ * @param {Object} req
92
+ * @param {Object} res
93
+ */
46
94
  load = async (req, res) => {
47
- let parent = null;
48
-
49
- if (req.body.scope === "local") {
50
- let user = await req.db.User.recallOne(req.session.currentUser);
51
- parent = user.id;
52
- }
95
+ try {
96
+ let parent = null;
53
97
 
54
- let spirit = await req.db.Spirit.recallOne(req.body.service, parent);
98
+ if (req.body.scope === "local") {
99
+ let user = await req.db.User.recallOne(req.session.currentUser);
100
+ if (user?.id) parent = user.id;
101
+ else throw new Error("User had no id on load(): ", user);
102
+ }
55
103
 
56
- if (!spirit.memory.data) spirit.memory.data = {};
104
+ let spirit = await req.db.Spirit.recallOne(req.body.service, parent);
57
105
 
58
- res.send(spirit.memory.data);
106
+ res.send(spirit.memory.data ? spirit.memory.data : {});
107
+ } catch (error) {
108
+ console.log(error);
109
+ fail(res, "Server error");
110
+ }
59
111
  }
60
112
 
113
+ /**
114
+ * This API route runs a script on the server. Responds with the result.
115
+ * @param {Object} req
116
+ * @param {Object} res
117
+ */
61
118
  serve = async (req, res) => {
62
119
  try {
63
120
  let scriptPath = `${req.contentPath}${req.body.route}/${req.body.script}.js`;
@@ -2,6 +2,9 @@ import express from "express";
2
2
  import bcrypt from "bcrypt";
3
3
  import { check, success, fail, loginCheck } from "./util.js";
4
4
 
5
+ /**
6
+ * API routes for user functions.
7
+ */
5
8
  export default class User {
6
9
  constructor() {
7
10
  this.router = express.Router();
@@ -19,12 +22,22 @@ export default class User {
19
22
  this.router.post("/getInfo", this.getInfo);
20
23
  }
21
24
 
25
+ /**
26
+ * Logs the user out.
27
+ * @param {Object} req An Express.js request.
28
+ * @param {Object} res An Express.js response.
29
+ */
22
30
  logout = async (req, res) => {
23
31
  await req.session.destroy();
24
32
 
25
33
  success(res, "Logged out.");
26
34
  }
27
35
 
36
+ /**
37
+ * Sends an email with a password reset code.
38
+ * @param {Object} req An Express.js request.
39
+ * @param {Object} res An Express.js response.
40
+ */
28
41
  sendPasswordReset = async (req, res) => {
29
42
  let spirit = await req.db.User.recallOne(req.body.email);
30
43
 
@@ -44,6 +57,11 @@ export default class User {
44
57
  else fail(res, "User not found.");
45
58
  }
46
59
 
60
+ /**
61
+ * Change a user's password.
62
+ * @param {Object} req An Express.js request.
63
+ * @param {Object} res An Express.js response.
64
+ */
47
65
  changePassword = async (req, res) => {
48
66
  if (check(res, req.body.token, "No token provided!")){
49
67
  let spirit = await req.db.User.recallOne(req.body.email);
@@ -66,6 +84,11 @@ export default class User {
66
84
  }
67
85
  }
68
86
 
87
+ /**
88
+ * Register a new user account.
89
+ * @param {Object} req An Express.js request.
90
+ * @param {Object} res An Express.js response.
91
+ */
69
92
  register = async (req, res) => {
70
93
  if (check(res, req.body.password.length > 7, "Password too short.") &&
71
94
  check(res, req.body.email.length > 7, "Email too short.") &&
@@ -81,6 +104,11 @@ export default class User {
81
104
  }
82
105
  }
83
106
 
107
+ /**
108
+ * Logs a user in.
109
+ * @param {Object} req An Express.js request.
110
+ * @param {Object} res An Express.js response.
111
+ */
84
112
  login = async (req, res) => {
85
113
  let spirit = await req.db.User.recallOne(req.body.email);
86
114
 
@@ -95,6 +123,11 @@ export default class User {
95
123
  }
96
124
  }
97
125
 
126
+ /**
127
+ * Changes a user's email address on file.
128
+ * @param {Object} req An Express.js request.
129
+ * @param {Object} res An Express.js response.
130
+ */
98
131
  changeEmail = async (req, res) => {
99
132
  if (loginCheck(req, res)) {
100
133
  let spirit = await req.db.User.recallOne(req.body.email);
@@ -112,6 +145,11 @@ export default class User {
112
145
  }
113
146
  }
114
147
 
148
+ /**
149
+ * Changes a user's display name.
150
+ * @param {Object} req An Express.js request.
151
+ * @param {Object} res An Express.js response.
152
+ */
115
153
  changeUsername = async (req, res) => {
116
154
  if (loginCheck(req, res)) {
117
155
  let spirit = await req.db.User.recallOne(null, req.body.username);
@@ -127,6 +165,11 @@ export default class User {
127
165
  }
128
166
  }
129
167
 
168
+ /**
169
+ * Deletes a user account premanently.
170
+ * @param {Object} req An Express.js request.
171
+ * @param {Object} res An Express.js response.
172
+ */
130
173
  deletePermanently = async (req, res) => {
131
174
  if (loginCheck(req, res)) {
132
175
  let deleted = await req.db.User.delete(req.session.currentUser);
@@ -139,40 +182,59 @@ export default class User {
139
182
  }
140
183
  }
141
184
 
185
+ /**
186
+ * Gets a user's inventory.
187
+ * @param {Object} req An Express.js request.
188
+ * @param {Object} res An Express.js response.
189
+ */
142
190
  getInventory = async (req, res) => {
143
191
  if (loginCheck(req, res)) {
144
192
  let spirit = await req.db.User.recallOne(req.session.currentUser);
145
- if (spirit.memory._lastUpdate > req.body._lastUpdate) {
146
- let inv = spirit.memory.data.inventory;
147
-
148
- success(res, "Inventory found", inv, spirit.memory._lastUpdate);
193
+
194
+ if (check(res, spirit, "Account not found!")) {
195
+ if (check(res, spirit.memory._lastUpdate > req.body._lastUpdate, "Inventory up to date.")) {
196
+ let inv = spirit.memory.data.inventory;
197
+
198
+ success(res, "Inventory found", inv, spirit.memory._lastUpdate);
199
+ }
149
200
  }
150
- else fail(res, "Inventory up to date.");
151
201
  }
152
202
  }
153
203
 
204
+ /**
205
+ * Gets a user attributes.
206
+ * @param {Object} req An Express.js request.
207
+ * @param {Object} res An Express.js response.
208
+ */
154
209
  getAttributes = async (req, res) => {
155
210
  if (loginCheck(req, res)) {
156
211
  let user = await req.db.User.recallOne(req.session.currentUser);
157
212
 
158
- if (user.memory._lastUpdate > req.body._lastUpdate) {
159
- success(res, "Attributes found", user.memory.data.attributes);
213
+ if(check(res, user, "Account not found!")) {
214
+ if (check(res, user.memory._lastUpdate > req.body._lastUpdate, "Attributes up to date.")) {
215
+ success(res, "Attributes found", user.memory.data.attributes);
216
+ }
160
217
  }
161
- else fail(res, "Attributes up to date.");
162
218
  }
163
219
  }
164
220
 
221
+ /**
222
+ * Gets basic account information.
223
+ * @param {Object} req An Express.js request.
224
+ * @param {Object} res An Express.js response.
225
+ */
165
226
  getInfo = async (req, res) => {
166
227
  if (loginCheck(req, res)) {
167
228
  let user = await req.db.User.recallOne(req.session.currentUser);
168
229
 
169
- if (user.memory._lastUpdate > req.body._lastUpdate) {
170
- success(res, "Info found", {
171
- email: user.memory.data.email,
172
- username: user.memory.data.username
173
- });
230
+ if (check(res, user, "Account not found!")) {
231
+ if (check(res, user.memory._lastUpdate > req.body._lastUpdate, "Info up to date.")) {
232
+ success(res, "Info found", {
233
+ email: user.memory.data.email,
234
+ username: user.memory.data.username
235
+ });
236
+ }
174
237
  }
175
- else fail(res, "Info up to date.");
176
238
  }
177
239
  }
178
240
  }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Check if something is true. Respond with a fail otherwise.
3
+ * @param {Object} res An Express.js response.
4
+ * @param {*} checkee What to check against.
5
+ * @param {String} failMsg Message to send in a potential failure response.
6
+ * @returns True or false.
7
+ */
8
+ export const check = (res, checkee, failMsg = "Failed!") => {
9
+ if (!checkee) {
10
+ fail(res, failMsg);
11
+ return false;
12
+ }
13
+ else {
14
+ return true;
15
+ }
16
+ };
17
+
18
+ /**
19
+ * Respond to the client with success.
20
+ * @param {Object} res An Express.js response.
21
+ * @param {String} msg A message describing the success.
22
+ * @param {Object} data Data to send with the response.
23
+ * @param {Number} lastUpdate A number date for synchronization.
24
+ */
25
+ export const success = (res, msg = "Success!", data = null, lastUpdate = 0) => {
26
+ res.send({
27
+ status: "success",
28
+ message: msg,
29
+ lastUpdate: lastUpdate,
30
+ data: data
31
+ });
32
+ };
33
+
34
+ /**
35
+ * Respond to the client with failure.
36
+ * @param {Object} res An Express.js response.
37
+ * @param {String} msg A message describing the failure.
38
+ */
39
+ export const fail = (res, msg = "Failed!") => {
40
+ res.send({
41
+ status: "failed",
42
+ message: msg,
43
+ lastUpdate: 0,
44
+ data: null
45
+ });
46
+ };
47
+
48
+ /**
49
+ * Check if a user is logged in.
50
+ * @param {Object} req An Express.js request.
51
+ * @param {Object} res An Express.js response.
52
+ * @returns True if a user is logged in, else false.
53
+ */
54
+ export const loginCheck = (req, res) => {
55
+ return check(res, req.session.currentUser, "Please login first.");
56
+ }
package/models/item.js CHANGED
@@ -1,6 +1,13 @@
1
1
  import Spirit from "./spirit.js";
2
2
 
3
3
  export default class Item extends Spirit {
4
+ /**
5
+ * Creates an item in the database.
6
+ * @param {String} name The item name.
7
+ * @param {String} short A short descrption.
8
+ * @param {String} long A long description.
9
+ * @returns The item created.
10
+ */
4
11
  static create = async (name, short, long) => {
5
12
  let spirit = new Item(name);
6
13
 
@@ -18,8 +25,12 @@ export default class Item extends Spirit {
18
25
  return spirit;
19
26
  }
20
27
 
28
+ /**
29
+ * Recalls all items.
30
+ * @returns The items found or null.
31
+ */
21
32
  static recallAll = async () => {
22
- let spirit = new Item();
33
+ let items = new Item();
23
34
 
24
35
  let found = await Spirit.db.find({
25
36
  service: "items",
@@ -27,13 +38,18 @@ export default class Item extends Spirit {
27
38
  });
28
39
 
29
40
  if (found) {
30
- spirit.memory = found;
41
+ items.memory = found;
31
42
 
32
- return spirit;
43
+ return items;
33
44
  }
34
45
  else return null;
35
46
  }
36
47
 
48
+ /**
49
+ * Recalls one item by name.
50
+ * @param {String} name The item name.
51
+ * @returns The item found or null.
52
+ */
37
53
  static recallOne = async (name) => {
38
54
  let spirit = new Item(name);
39
55
 
@@ -49,6 +65,11 @@ export default class Item extends Spirit {
49
65
  else return null;
50
66
  }
51
67
 
68
+ /**
69
+ * Deletes items by name.
70
+ * @param {String} name The item name.
71
+ * @returns Number of documents deleted.
72
+ */
52
73
  static delete = async (name) => {
53
74
  let found = await Spirit.db.findAndDelete(Spirit.buildQuery("items", { name }));
54
75
 
@@ -1,5 +1,10 @@
1
1
  import nodemailer from "nodemailer";
2
2
 
3
+ /**
4
+ * Sends an email with a password reset code. WIP
5
+ * @param {String} toEmail Email address to send to.
6
+ * @param {Number} resetToken Token to reset by.
7
+ */
3
8
  const passwordReset = async (toEmail, resetToken) => {
4
9
  var transporter = nodemailer.createTransport({
5
10
  service: 'gmail',
@@ -21,9 +26,14 @@ const passwordReset = async (toEmail, resetToken) => {
21
26
  });
22
27
  };
23
28
 
29
+ /**
30
+ * Sends an email. WIP
31
+ * @param {String} toEmail Email Address to send to.
32
+ * @param {String} subject Subject of the email.
33
+ * @param {String} html Body of the email.
34
+ * @returns
35
+ */
24
36
  const send = async (toEmail, subject, html) => {
25
- console.log("dfhd");
26
-
27
37
  var transporter = nodemailer.createTransport({
28
38
  service: 'gmail',
29
39
  auth: {
@@ -44,5 +54,4 @@ const send = async (toEmail, subject, html) => {
44
54
  });
45
55
  }
46
56
 
47
-
48
57
  export default { passwordReset, send };