notherbase-fs 3.3.0 → 3.3.2

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.
@@ -5,11 +5,12 @@ import fs from 'fs';
5
5
  * Creation is all the renedered pages in a base.
6
6
  */
7
7
  export default class Creation {
8
- constructor() {
8
+ constructor(siteTitle = "Base") {
9
+ this.siteTitle = siteTitle;
9
10
  this.router = express.Router();
10
11
 
11
12
  //home
12
- this.router.get("/", function(req, res) { res.redirect("/the-front"); });
13
+ this.router.get("/", this.front, this.explore);
13
14
 
14
15
  //the-front
15
16
  this.router.get(`/the-front`, this.front, this.explore);
@@ -18,13 +19,15 @@ export default class Creation {
18
19
  //pages
19
20
  this.router.get(`/:page`, this.page, this.explore);
20
21
 
22
+ //the-front optional shortcuts
23
+ this.router.get(`/:frontDetail`, this.frontDetail, this.explore);
24
+
21
25
  //explorer
22
26
  this.router.get(`/:region/:area/:poi`, this.lock, this.poi, this.explore);
23
27
  this.router.get(`/:region/:area/:poi/:detail`, this.lock, this.detail, this.explore);
24
28
 
25
29
  //void
26
- this.router.use(function(req, res) {
27
- console.log(req.path);
30
+ this.router.use(function(req, res) {
28
31
  res.redirect("/void");
29
32
  });
30
33
  }
@@ -88,7 +91,7 @@ export default class Creation {
88
91
  */
89
92
  front = async (req, res, next) => {
90
93
  req.main = req.contentPath + "/the-front/index";
91
- req.siteTitle = "NotherBase - The Front";
94
+ req.siteTitle = this.siteTitle;
92
95
  req.toRender = "explorer";
93
96
  next();
94
97
  }
@@ -101,7 +104,7 @@ export default class Creation {
101
104
  */
102
105
  frontDetail = async (req, res, next) => {
103
106
  req.main = `${req.contentPath}/the-front/${req.params.frontDetail}/index`;
104
- req.siteTitle = `NotherBase - ${req.params.frontDetail}`;
107
+ req.siteTitle = `${this.siteTitle} - ${req.params.frontDetail}`;
105
108
  req.toRender = "explorer";
106
109
  next();
107
110
  }
@@ -114,7 +117,7 @@ export default class Creation {
114
117
  */
115
118
  poi = async (req, res, next) => {
116
119
  req.main = `${req.contentPath}/${req.params.region}/${req.params.area}/${req.params.poi}/index`;
117
- req.siteTitle = `NotherBase - ${req.params.poi}`;
120
+ req.siteTitle = `${this.siteTitle} - ${req.params.poi}`;
118
121
  req.toRender = "explorer";
119
122
  next();
120
123
  }
@@ -127,7 +130,7 @@ export default class Creation {
127
130
  */
128
131
  detail = async (req, res, next) => {
129
132
  req.main = `${req.contentPath}/${req.params.region}/${req.params.area}/${req.params.poi}/${req.params.detail}/index`;
130
- req.siteTitle = `NotherBase - ${req.params.detail}`;
133
+ req.siteTitle = `${this.siteTitle} - ${req.params.detail}`;
131
134
  req.toRender = "explorer";
132
135
  next();
133
136
  }
@@ -19,7 +19,7 @@ export default class SpiritWorld {
19
19
  this.router = express.Router();
20
20
  this.user = new User();
21
21
 
22
- this.router.post("/load", this.load);
22
+ this.router.post("/loadAll", this.loadAll);
23
23
  this.router.post("/serve", this.serve);
24
24
  this.router.use("/user", this.user.router);
25
25
 
@@ -100,7 +100,10 @@ export default class SpiritWorld {
100
100
  if (req.body.scope === "local") {
101
101
  let user = await req.db.User.recallOne(req.session.currentUser);
102
102
  if (user?.id) parent = user.id;
103
- else throw new Error("User had no id on load(): ", user);
103
+ else {
104
+ fail(res, "User had no id on load()");
105
+ return;
106
+ }
104
107
  }
105
108
 
106
109
  // recall all spirits with the given service name and parent
@@ -20,6 +20,8 @@ export default class User {
20
20
  this.router.post("/getInventory", this.getInventory);
21
21
  this.router.post("/getAttributes", this.getAttributes);
22
22
  this.router.post("/getInfo", this.getInfo);
23
+ this.router.post("/getView", this.getView);
24
+ this.router.post("/setView", this.setView);
23
25
  }
24
26
 
25
27
  /**
@@ -122,14 +124,6 @@ export default class User {
122
124
  }
123
125
  }
124
126
 
125
- /**
126
- * Checks if a user is logged in.
127
- */
128
- loggedIn = () => {
129
- if (this.id) return true;
130
- else return false;
131
- }
132
-
133
127
  /**
134
128
  * Changes a user's email address on file.
135
129
  * @param {Object} req An Express.js request.
@@ -244,4 +238,33 @@ export default class User {
244
238
  }
245
239
  }
246
240
  }
241
+
242
+ /**
243
+ * Gets a user's saved view state.
244
+ */
245
+ getView = async (req, res) => {
246
+ if (loginCheck(req, res)) {
247
+ let user = await req.db.User.recallOne(req.session.currentUser);
248
+
249
+ if (check(res, user, "Account not found!")) {
250
+ success(res, "View found", user.memory.data.view);
251
+ }
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Sets a user's view state.
257
+ */
258
+ setView = async (req, res) => {
259
+ if (loginCheck(req, res)) {
260
+ let user = await req.db.User.recallOne(req.session.currentUser);
261
+
262
+ if (check(res, user, "Account not found!")) {
263
+ user.memory.data.view = req.body.view;
264
+ await user.commit();
265
+
266
+ success(res, "View set");
267
+ }
268
+ }
269
+ }
247
270
  }
package/models/index.js CHANGED
@@ -6,6 +6,8 @@ import Item from "./item.js";
6
6
  import User from "./user.js";
7
7
  import SendMail from "./send-mail.js";
8
8
 
9
+ mongoose.set('strictQuery', true);
10
+
9
11
  mongoose.connection.on('connected', (err) => {
10
12
  console.log(`Mongoose connected to db`);
11
13
  });
package/models/spirit.js CHANGED
@@ -127,7 +127,7 @@ export default class Spirit {
127
127
  * @returns The number of documents deleted.
128
128
  */
129
129
  static delete = async (service, data = {}, parent = null, id = null) => {
130
- let found = await Spirit.db.deleteMany(Spirit.buildQuery(service, data, id));
130
+ let found = await Spirit.db.deleteMany(Spirit.buildQuery(service, data, parent, id));
131
131
 
132
132
  return found.deletedCount;
133
133
  }
@@ -143,12 +143,25 @@ export default class Spirit {
143
143
  * @param {Object} data Data to save.
144
144
  * @returns Updated
145
145
  */
146
- commit = async (data = this.memory.data) => {
146
+ commit = async (data = this.memory.data, which = -1) => {
147
147
  this.memory._lastUpdate = Date.now();
148
148
 
149
- this.memory.data = data;
150
- this.memory.markModified("data");
151
- await this.memory.save();
149
+ if (!Array.isArray(this.memory)) {
150
+ this.memory.data = data;
151
+ this.memory.markModified("data");
152
+ await this.memory.save();
153
+ }
154
+ else {
155
+ for (let i = 0; i < this.memory.length; i++) {
156
+ if (data) {
157
+ if (which < 0) this.memory[i].data = data;
158
+ else if (which === i) this.memory[i].data = data;
159
+ }
160
+
161
+ this.memory[i].markModified("data");
162
+ await this.memory[i].save();
163
+ }
164
+ }
152
165
 
153
166
  return "Updated";
154
167
  }
package/models/user.js CHANGED
@@ -103,96 +103,11 @@ export default class User extends Spirit {
103
103
  }
104
104
 
105
105
  /**
106
- * Attempts to offset the user's inventory of a certain item.
107
- * @param {String} name The item's name.
108
- * @param {Number} offset The amount to offset by.
109
- * @returns True if successful.
106
+ * Checks if a user is logged in.
110
107
  */
111
- offsetItem = async (name, offset) => {
112
- let item = await Item.recallOne(name);
113
-
114
- if (!item) return false;
115
-
116
- let inv = this.memory.data.inventory;
117
-
118
- for (let j = 0; j < inv.length; j++) {
119
- if (inv[j].name === name) {
120
- if (inv[j].amount >= -Math.floor(offset)) {
121
- inv[j].amount += Math.floor(offset);
122
-
123
- if (inv[j].amount === 0) {
124
- let empty = inv[j];
125
-
126
- inv.splice(j, 1);
127
- }
128
-
129
- this.memory._lastUpdate = Date.now();
130
- await this.commit();
131
- return true;
132
- }
133
- else return false;
134
- }
135
- }
136
-
137
- if (offset > 0) {
138
- inv.push({
139
- name: name,
140
- amount: offset
141
- });
142
-
143
- this.memory._lastUpdate = Date.now();
144
-
145
- await this.commit();
146
-
147
- return true;
148
- }
108
+ loggedIn = () => {
109
+ if (this.id) return true;
149
110
  else return false;
150
111
  }
151
-
152
- /**
153
- * Tests if an attribute meets a requirement.
154
- * @param {String} check The attribute to check.
155
- * @param {Number} against The number to meet.
156
- * @returns
157
- */
158
- checkAttribute = async (check, against) => {
159
- let att = this.memory.data.attributes;
160
-
161
- return att[check] >= against;
162
- }
163
-
164
- /**
165
- * Sets a user's attribute score.
166
- * @param {String} change The attribute to change.
167
- * @param {Number} to The number to set it to.
168
- * @returns Attributes set
169
- */
170
- setAttribute = async (change, to) => {
171
- let att = this.memory.data.attributes;
172
-
173
- att[change] = to;
174
- this.memory._lastUpdate = Date.now();
175
- await this.commit();
176
-
177
- return "Attributes set.";
178
- }
179
-
180
- /**
181
- * Increments a user's attribute by one.
182
- * @param {String} change The attribute to increment.
183
- * @param {Number} max The ceiling.
184
- * @returns The resulting attribute score.
185
- */
186
- incrementAttribute = async (change, max) => {
187
- let att = this.memory.data.attributes;
188
-
189
- if (att[change] < max) {
190
- att[change]++;
191
- this.memory._lastUpdate = Date.now();
192
- await this.commit();
193
- }
194
-
195
- return att[change];
196
- }
197
112
  }
198
113
 
package/notherbase-fs.js CHANGED
@@ -17,11 +17,16 @@ import SpiritWorld from "./controllers/spirit-world.js";
17
17
  * The engine that runs a nother base.
18
18
  */
19
19
  class NotherBaseFS {
20
- constructor(contentPath) {
20
+ constructor(contentPath, globals = null, settings = {}) {
21
+ this.settings = {
22
+ siteTitle: "NotherBase",
23
+ favicon: null,
24
+ ...settings
25
+ }
21
26
  this.app = express();
22
27
  this.server = http.createServer(this.app);
23
28
  this.io = new Server(this.server);
24
- this.creation = new Creation();
29
+ this.creation = new Creation(this.settings.siteTitle);
25
30
  this.spiritWorld = new SpiritWorld(this.io);
26
31
 
27
32
  //set views path
@@ -44,7 +49,8 @@ class NotherBaseFS {
44
49
  this.app.use(express.static(`${__dirname}/public`));
45
50
 
46
51
  // sets the favicon image
47
- this.app.use(favicon(__dirname + '/public/img/logo.png'));
52
+ if (this.settings.favicon) this.app.use(favicon(this.settings.favicon));
53
+ else this.app.use(favicon(__dirname + '/public/img/logo.png'));
48
54
 
49
55
  //enable cookies
50
56
  this.app.use(session({
@@ -56,6 +62,7 @@ class NotherBaseFS {
56
62
 
57
63
  //provide database access and etc to use in routes
58
64
  this.app.use((req, res, next) => {
65
+ req.globals = globals;
59
66
  req.db = Models;
60
67
  req.contentPath = contentPath;
61
68
  req.lock = false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "notherbase-fs",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "description": "Functions to help make developing for NotherBase easier.",
5
5
  "exports": "./notherbase-fs.js",
6
6
  "scripts": {
package/public/js/base.js CHANGED
@@ -13,108 +13,6 @@ class Base {
13
13
  return response;
14
14
  }
15
15
 
16
- /**
17
- * The player's inventory.
18
- */
19
- #Inventory = class Inventory {
20
- constructor() {
21
- this.items = [];
22
- this.lastUpdate = 0;
23
-
24
- this.refresh();
25
- }
26
-
27
- /**
28
- * Reloads the inventory.
29
- */
30
- async refresh() {
31
- let $list = $(".inventory .item-list");
32
-
33
- let response = await Base.commune("getInventory", { _lastUpdate: this.lastUpdate });
34
-
35
- if (response.status === "success") {
36
- this.items = response.data;
37
- this.lastUpdate = response.lastUpdate;
38
- $list.empty();
39
-
40
- for (let i = 0; i < this.items.length; i++) {
41
- let $new = $list.append(
42
- `<div class="item-card">
43
- <h5>${this.items[i].name}</h5>
44
- <button id="${i}">X</button>
45
- <hr>
46
- <p>${this.items[i].amount}</p>
47
- </div>`
48
- ).children().last();
49
-
50
- $new.find("button").on("click", this.reduceItem);
51
- }
52
-
53
- this.clearError();
54
- }
55
- }
56
-
57
- /**
58
- * Clears the error on screen.
59
- */
60
- clearError() {
61
- let $error = $("#inventory #error");
62
-
63
- $error.addClass("invisible");
64
- }
65
-
66
- /**
67
- * Shows an error on screen.
68
- * @param {String} text The error message.
69
- */
70
- setError(text) {
71
- let $error = $("#inventory #error");
72
-
73
- $error.text(text);
74
- $error.removeClass("invisible");
75
- }
76
- }
77
-
78
- /**
79
- * The player's attributes.
80
- */
81
- #PlayerAttributes = class PlayerAttributes {
82
- constructor() {
83
- this.attributes = [];
84
- this.lastUpdate = 0;
85
-
86
- this.refresh();
87
- }
88
-
89
- /**
90
- * Reloads the player's attributes.
91
- */
92
- async refresh() {
93
- let response = await Base.commune("getAttributes", { _lastUpdate: this.lastUpdate });
94
- if (response.status === "success") {
95
- this.lastUpdate = response.lastUpdate;
96
- this.attributes = response.data;
97
-
98
- this.render();
99
- }
100
- }
101
-
102
- /**
103
- * Renders the attributes.
104
- */
105
- render() {
106
- let $content = $(".menu .content#player");
107
-
108
- $content.empty();
109
-
110
- if (this.attributes) {
111
- for (const [key, value] of Object.entries(this.attributes)) {
112
- $content.append(`<h3 id="${key}">${key}: ${value}</h3>`);
113
- }
114
- }
115
- }
116
- }
117
-
118
16
  /**
119
17
  * Services for the player's account.
120
18
  */
@@ -123,58 +21,6 @@ class Base {
123
21
  this.username = "";
124
22
  this.email = "";
125
23
  this.lastUpdate = 0;
126
-
127
- this.refresh();
128
- }
129
-
130
- /**
131
- * Reloads the player's basic info.
132
- */
133
- async refresh() {
134
- let response = await Base.commune("getInfo", { _lastUpdate: this.lastUpdate });
135
- if (response.status === "success") {
136
- this.lastUpdate = response.lastUpdate;
137
- this.email = response.data.email;
138
- this.username = response.data.username;
139
- }
140
-
141
- let $email = $(".content#account .setting#email p");
142
- let $emailInput = $(".content#account .edit#email input");
143
- let $username = $(".content#account .setting#username p");
144
- let $usernameInput = $(".content#account .edit#username input");
145
-
146
- $email.text(this.email);
147
- $emailInput.val(this.email);
148
- $username.text(this.username);
149
- $usernameInput.val(this.username);
150
-
151
- $(".content#account .settings").removeClass("invisible");
152
- $(".content#account #please-login").addClass("invisible");
153
- }
154
-
155
- /**
156
- * Initiates email editing.
157
- */
158
- editEmail() {
159
- let $emailSetting = $(".content#account .setting#email");
160
- let $emailEdit = $(".content#account .edit#email");
161
-
162
- $emailSetting.addClass("invisible");
163
- $emailEdit.removeClass("invisible");
164
- }
165
-
166
- /**
167
- * Cancels editing the email.
168
- */
169
- cancelEmail() {
170
- let $email = $(".content#account .setting#email p");
171
- let $emailSetting = $(".content#account .setting#email");
172
- let $emailEdit = $(".content#account .edit#email");
173
- let $emailInput = $(".content#account .edit#email input");
174
-
175
- $emailSetting.removeClass("invisible");
176
- $emailEdit.addClass("invisible");
177
- $emailInput.val($email.text());
178
24
  }
179
25
 
180
26
  /**
@@ -198,31 +44,6 @@ class Base {
198
44
  this.cancelEmail();
199
45
  }
200
46
 
201
- /**
202
- * Initiates username editing.
203
- */
204
- editUsername() {
205
- let $usernameSetting = $(".content#account .setting#username");
206
- let $usernameEdit = $(".content#account .edit#username");
207
-
208
- $usernameSetting.addClass("invisible");
209
- $usernameEdit.removeClass("invisible");
210
- }
211
-
212
- /**
213
- * Cancels username editing.
214
- */
215
- cancelUsername() {
216
- let $usernameSetting = $(".content#account .setting#username");
217
- let $usernameEdit = $(".content#account .edit#username");
218
- let $usernameInput = $(".content#account .edit#username input");
219
- let $username = $(".content#account .setting#username p");
220
-
221
- $usernameSetting.removeClass("invisible");
222
- $usernameEdit.addClass("invisible");
223
- $usernameInput.val($username.text());
224
- }
225
-
226
47
  /**
227
48
  * Confirms and submits a username edit.
228
49
  */
@@ -246,56 +67,9 @@ class Base {
246
67
  }
247
68
 
248
69
  constructor() {
249
- this.playerInventory = new this.#Inventory();
250
- this.playerAttributes = new this.#PlayerAttributes();
251
70
  this.playerAccount = new this.#AccountServices();
252
- this.menuClosing = false;
253
-
254
- this.switchTab("inventory");
255
- }
256
-
257
- /**
258
- * Closes the menu.
259
- */
260
- closeMenu = () => {
261
- let $menu = $(".ui .menu");
262
- let $fade = $(".ui .fade");
263
-
264
- if (!this.menuClosing) {
265
- this.menuClosing = true;
266
- $fade.addClass("camo");
267
-
268
- setTimeout(() => {
269
- $menu.addClass("invisible");
270
- $fade.addClass("invisible");
271
- this.menuClosing = false;
272
- }, 100);
273
- }
274
- }
275
-
276
- /**
277
- * Opens the menu.
278
- */
279
- openMenu = () => {
280
- let $menu = $(".ui .menu");
281
- let $fade = $(".ui .fade");
282
-
283
- $menu.removeClass("invisible");
284
- $fade.removeClass("camo");
285
- $fade.removeClass("invisible");
286
71
  }
287
72
 
288
- /**
289
- * Switches tabs in the menu.
290
- * @param {String} id The name of the tab to switch to.
291
- */
292
- switchTab = function switchTab(id) {
293
- $("#content-window .content").addClass("invisible");
294
- $(".menu .tabs button").removeClass("selected");
295
- $(`#content-window #${id}`).removeClass("invisible");
296
- $(`.menu .tabs #${id}`).addClass("selected");
297
- }
298
-
299
73
  /**
300
74
  * Communes to logout.
301
75
  * @returns Communion response.
@@ -303,7 +77,8 @@ class Base {
303
77
  logout = async () => {
304
78
  let response = await Base.commune("logout");
305
79
 
306
- return response;
80
+ location.reload();
81
+ //return response;
307
82
  }
308
83
 
309
84
  /**
@@ -334,11 +109,8 @@ class Base {
334
109
  });
335
110
 
336
111
  if (response.status === "success") {
337
- this.playerInventory.refresh();
338
112
  this.playerAccount.username = response.data;
339
113
  this.playerAccount.email = email;
340
- this.playerAccount.refresh();
341
- this.playerAttributes.refresh();
342
114
  }
343
115
 
344
116
  return response;
@@ -384,9 +156,6 @@ class Base {
384
156
  }));
385
157
 
386
158
  if (response.status != "success") console.log(`${window.location.pathname} - ${response.message}`);
387
-
388
- this.playerInventory.refresh();
389
- this.playerAttributes.refresh();
390
159
 
391
160
  return response;
392
161
  }
@@ -402,4 +171,30 @@ class Base {
402
171
 
403
172
  return response;
404
173
  }
174
+
175
+ createToggleViewButton = async () => {
176
+ Base.commune("getView").then((res) => {
177
+ // add a button to the footer for toggling between compact and full view
178
+ this.$viewToggle = $("<button>").addClass("view-toggle").text(">");
179
+ this.$viewToggle.on("click", () => {
180
+ this.toggleView();
181
+ });
182
+ $("footer").append(this.$viewToggle);
183
+
184
+ if (res.data === "full") this.toggleView(false);
185
+ });
186
+ }
187
+
188
+ toggleView = async (save = true) => {
189
+ if (this.$viewToggle.text() === ">") {
190
+ this.$viewToggle.text("<");
191
+ $("main").addClass("full-view");
192
+ if (save) Base.commune("setView", { view: "full" });
193
+ }
194
+ else {
195
+ this.$viewToggle.text(">");
196
+ $("main").removeClass("full-view");
197
+ if (save) Base.commune("setView", { view: "compact" });
198
+ }
199
+ }
405
200
  }
@@ -3,6 +3,7 @@
3
3
  */
4
4
  class ChatBox {
5
5
  constructor(username, room) {
6
+ ChatBox.attemptStyle();
6
7
  this.socket = null;
7
8
  this.username = username;
8
9
  this.room = room;
@@ -23,6 +24,18 @@ class ChatBox {
23
24
  this.render();
24
25
  }
25
26
 
27
+ static styled = false;
28
+
29
+ /**
30
+ * Adds the chat box styles if needed.
31
+ */
32
+ static attemptStyle() {
33
+ if (!ChatBox.styled) {
34
+ $("head").append(`<link href='/styles/chat.css' rel='stylesheet' />`);
35
+ ChatBox.styled = true;
36
+ }
37
+ }
38
+
26
39
  /**
27
40
  * Renders a new message in the chat.
28
41
  * @param {Object} msg An object including the text to render.