jxp 2.13.0 → 2.13.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.
package/docs/caching.md CHANGED
@@ -6,6 +6,7 @@ Enable caching to speed up your queries. Caching is disabled by default. Enable
6
6
  {
7
7
  "cache": {
8
8
  "enabled": true,
9
+ "debug": false,
9
10
  "ttl": 3600
10
11
  }
11
12
  }
package/libs/cache.js CHANGED
@@ -2,46 +2,81 @@ const NodeCache = require('node-cache');
2
2
  const config = require('config');
3
3
  const cache = new NodeCache({ stdTTL: config.cache?.ttl || 5 * 60 });
4
4
 
5
- const generateKey = (req) => {
6
- const url = req.url
7
- return url
5
+ const generateKey = (req, res) => {
6
+ if (res.jxp_cache_key) return res.jxp_cache_key;
7
+ let key = `${req.modelname}/`;
8
+ if (req.params.item_id) {
9
+ key += `${req.params.item_id}`
10
+ }
11
+ if (req.query) {
12
+ key += `?${JSON.stringify(req.query)}`
13
+ }
14
+ res.jxp_cache_key = key;
15
+ return key;
8
16
  }
9
17
 
10
- const set = (req, res, next) => {
11
- if (!config.cache?.enabled) return next();
12
- const key = generateKey(req)
18
+ const set = async (req, res) => {
19
+ if (!config.cache?.enabled) return;
20
+ const key = generateKey(req, res)
13
21
  cache.set(key, res.result)
14
- next()
22
+ if (config.cache?.debug) {
23
+ console.log('cache set', key)
24
+ }
15
25
  }
16
26
 
17
27
  const get = (req, res, next) => {
18
- if (!config.cache?.enabled) return next();
19
- const key = generateKey(req)
28
+ if (!config.cache?.enabled) return;
29
+ const key = generateKey(req, res)
30
+ res.header('jxp-cache-key', key);
20
31
  const cached = cache.get(key)
21
32
  if (cached) {
33
+ if (config.cache?.debug) {
34
+ console.log('cache hit', key)
35
+ }
22
36
  res.header('jxp-cache', 'hit')
23
37
  res.result = cached
24
38
  return res.send(res.result)
25
39
  }
40
+ if (config.cache?.debug) {
41
+ console.log('cache miss', key)
42
+ }
26
43
  res.header('jxp-cache', 'miss')
27
44
  next()
28
45
  }
29
46
 
30
- const clear = (req, res, next) => {
31
- if (!config.cache?.enabled) return next();
47
+ const clear = async (req, res) => {
48
+ if (!config.cache?.enabled) return;
49
+ const keys = cache.keys()
50
+ keys.forEach(key => {
51
+ if (key.startsWith(`${req.modelname}/`)) {
52
+ if (config.cache?.debug) {
53
+ console.log('cache del', key)
54
+ }
55
+ cache.del(key)
56
+ }
57
+ })
58
+ }
59
+
60
+ const clearAll = async () => {
61
+ if (!config.cache?.enabled) return;
62
+ if (config.cache?.debug) {
63
+ console.log('cache flushAll')
64
+ }
32
65
  cache.flushAll()
33
- next()
34
66
  }
35
67
 
36
- const stats = (req, res, next) => {
37
- if (!config.cache?.enabled) return {};
68
+ const stats = async (req, res) => {
69
+ if (!config.cache?.enabled) {
70
+ res.result = { cache_enabled: false }
71
+ return;
72
+ }
38
73
  res.result = cache.getStats()
39
- next()
40
74
  }
41
75
 
42
76
  module.exports = {
43
77
  set,
44
78
  get,
45
79
  clear,
46
- stats
80
+ clearAll,
81
+ stats,
47
82
  }
package/libs/jxp.js CHANGED
@@ -54,10 +54,9 @@ const middlewareCheckAdmin = (req, res, next) => {
54
54
  };
55
55
 
56
56
  // Outputs whatever is in res.result as JSON
57
- const outputJSON = (req, res, next) => {
57
+ const outputJSON = async (req, res) => {
58
58
  try {
59
59
  res.send(res.result);
60
- next();
61
60
  } catch (err) {
62
61
  console.error(new Date(), err);
63
62
  throw new errors.InternalServerError(err.toString());
@@ -919,7 +918,6 @@ const JXP = function(options) {
919
918
  middlewareModel,
920
919
  security.login,
921
920
  security.auth,
922
- cache.get,
923
921
  config.pre_hooks.getOne,
924
922
  cache.get,
925
923
  actionGetOne,
@@ -934,7 +932,7 @@ const JXP = function(options) {
934
932
  middlewarePasswords,
935
933
  config.pre_hooks.post,
936
934
  actionPost,
937
- cache.clear,
935
+ cache.clearAll,
938
936
  (req, res, next) => {
939
937
  next();
940
938
  },
@@ -948,7 +946,10 @@ const JXP = function(options) {
948
946
  middlewareCheckAdmin,
949
947
  config.pre_hooks.put,
950
948
  actionPut,
951
- cache.clear,
949
+ cache.clearAll,
950
+ (req, res, next) => {
951
+ next();
952
+ },
952
953
  );
953
954
  server.del(
954
955
  "/api/:modelname/:item_id",
@@ -957,7 +958,7 @@ const JXP = function(options) {
957
958
  security.auth,
958
959
  config.pre_hooks.delete,
959
960
  actionDelete,
960
- cache.clear,
961
+ cache.clearAll,
961
962
  );
962
963
 
963
964
  // Count
@@ -967,9 +968,9 @@ const JXP = function(options) {
967
968
  security.login,
968
969
  security.auth,
969
970
  config.pre_hooks.get,
970
- cache.get,
971
+ // cache.get,
971
972
  actionCount,
972
- cache.set,
973
+ // cache.set,
973
974
  outputJSON
974
975
  );
975
976
 
@@ -1021,7 +1022,7 @@ const JXP = function(options) {
1021
1022
  middlewareCheckAdmin,
1022
1023
  config.pre_hooks.update,
1023
1024
  actionUpdate,
1024
- cache.clear,
1025
+ cache.clearAll,
1025
1026
  );
1026
1027
 
1027
1028
  /* Batch routes - ROLLED BACK FOR NOW */
@@ -1034,7 +1035,7 @@ const JXP = function(options) {
1034
1035
  security.login,
1035
1036
  security.auth,
1036
1037
  actionCall,
1037
- cache.clear,
1038
+ cache.clearAll,
1038
1039
  );
1039
1040
  server.post(
1040
1041
  "/call/:modelname/:method_name",
@@ -1042,7 +1043,7 @@ const JXP = function(options) {
1042
1043
  security.login,
1043
1044
  security.auth,
1044
1045
  actionCall,
1045
- cache.clear,
1046
+ cache.clearAll,
1046
1047
  );
1047
1048
  server.get(
1048
1049
  "/call/:modelname/:item_id/:method_name",
@@ -1050,7 +1051,7 @@ const JXP = function(options) {
1050
1051
  security.login,
1051
1052
  security.auth,
1052
1053
  actionCallItem,
1053
- cache.clear,
1054
+ cache.clearAll,
1054
1055
  );
1055
1056
 
1056
1057
  /* Login and authentication */
@@ -1100,7 +1101,7 @@ const JXP = function(options) {
1100
1101
 
1101
1102
  /* Cache */
1102
1103
  server.get("/cache/stats", cache.stats, outputJSON);
1103
- server.get("/cache/clear", cache.clear, outputJSON);
1104
+ server.get("/cache/clear", cache.clearAll, outputJSON);
1104
1105
 
1105
1106
  return server;
1106
1107
  };
package/mkdocs.yml CHANGED
@@ -11,6 +11,7 @@ nav:
11
11
  - Aggregations: aggregations.md
12
12
  - Bulk Writes: bulk_writes.md
13
13
  - Queries: queries.md
14
+ - Caching: caching.md
14
15
  - Websocket: websocket.md
15
16
  - Special Features: special.md
16
17
  - Changelog: changelog.md
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "jxp",
3
3
  "description:": "An opinionated RESTful API library based on Mongoose and Restify. Make an API by just writing Mongoose models.",
4
- "version": "2.13.0",
4
+ "version": "2.13.2",
5
5
  "private": false,
6
6
  "main": "libs/jxp.js",
7
7
  "scripts": {
package/test/init.js CHANGED
@@ -8,6 +8,7 @@ global.JXPSchema = require("../libs/schema");
8
8
  const User = require(path.join(model_dir, "user_model"));
9
9
  const Apikey = require(path.join(model_dir, "apikey_model"));
10
10
  const Test = require(path.join(model_dir, "test_model"));
11
+ const cache = require("../libs/cache");
11
12
 
12
13
  const security = require("../libs/security");
13
14
 
@@ -38,6 +39,7 @@ const admin_password = "SecretPassword";
38
39
 
39
40
  const init = async () => {
40
41
  try {
42
+ await cache.clearAll();
41
43
  await empty_user_collections();
42
44
  await post(User, { name: "Admin User", email: admin_email, password: security.encPassword(admin_password), urlid: "admin-user", admin: true });
43
45
  await post(User, { name: "Test User", email, password: security.encPassword(password), urlid: "test-user" });
package/test/test.js CHANGED
@@ -1142,7 +1142,7 @@ describe('Test', () => {
1142
1142
  chai.request(server)
1143
1143
  .get("/cache/clear")
1144
1144
  .end((err, res) => {
1145
- console.log(res.body);
1145
+ // console.log(res.body);
1146
1146
  res.should.have.status(200);
1147
1147
  done();
1148
1148
  });
@@ -1173,13 +1173,124 @@ describe('Test', () => {
1173
1173
  chai.request(server)
1174
1174
  .get("/cache/stats")
1175
1175
  .end((err, res) => {
1176
- // console.log(res.body);
1177
1176
  res.should.have.status(200);
1178
1177
  res.body.should.have.property("hits");
1179
- res.body.hits.should.equal(1);
1180
- res.body.misses.should.equal(1);
1178
+ res.body.hits.should.be.greaterThan(0);
1179
+ res.body.misses.should.be.greaterThan(0);
1181
1180
  done();
1182
1181
  });
1183
1182
  })
1184
1183
  });
1184
+ describe("Cache invalidating", () => {
1185
+ let test_id;
1186
+ it("should get a test record", done => {
1187
+ chai.request(server)
1188
+ .get(`/api/test?populate=link&limit=1`)
1189
+ .auth(init.email, init.password)
1190
+ .end((err, res) => {
1191
+ // console.log(res.headers)
1192
+ res.should.have.status(200);
1193
+ res.body.data[0].should.have.property("_id");
1194
+ test_id = res.body.data[0]._id;
1195
+ res.body.data[0].should.have.property("link");
1196
+ should.equal(res.body.data[0].link, null);
1197
+ res.headers["jxp-cache"].should.equal("miss");
1198
+ done();
1199
+ });
1200
+ });
1201
+ it("should get a cached test record", done => {
1202
+ chai.request(server)
1203
+ .get(`/api/test?populate=link&limit=1`)
1204
+ .auth(init.email, init.password)
1205
+ .end((err, res) => {
1206
+ // console.log(res.headers)
1207
+ res.should.have.status(200);
1208
+ res.body.data[0].should.have.property("_id");
1209
+ res.headers["jxp-cache"].should.equal("hit");
1210
+ should.equal(res.body.data[0].link, null);
1211
+ done();
1212
+ });
1213
+ });
1214
+ let link_id;
1215
+ it("should add a link record", done => {
1216
+ chai.request(server)
1217
+ .post(`/api/link`)
1218
+ .auth(init.email, init.password)
1219
+ .send({
1220
+ name: "cache_test",
1221
+ val: "YoYoYo"
1222
+ })
1223
+ .end((err, res) => {
1224
+ // console.log(res.body)
1225
+ res.should.have.status(200);
1226
+ res.body.data.should.have.property("_id");
1227
+ link_id = res.body.data._id;
1228
+ done();
1229
+ });
1230
+ });
1231
+ it("should put link_id into test record", done => {
1232
+ chai.request(server)
1233
+ .put(`/api/test/${test_id}`)
1234
+ .auth(init.admin_email, init.admin_password)
1235
+ .send({
1236
+ link_id
1237
+ })
1238
+ .end((err, res) => {
1239
+ // console.log(res.body)
1240
+ res.should.have.status(200);
1241
+ res.body.data.should.have.property("_id");
1242
+ res.body.data.link_id.should.equal(link_id);
1243
+ done();
1244
+ });
1245
+ });
1246
+ it("should get a test record with link", done => {
1247
+ chai.request(server)
1248
+ .get(`/api/test?populate=link&limit=1`)
1249
+ .auth(init.email, init.password)
1250
+ .end((err, res) => {
1251
+ // console.log(res.body)
1252
+ res.should.have.status(200);
1253
+ res.body.data[0].should.have.property("_id");
1254
+ res.body.data[0].should.have.property("link");
1255
+ res.body.data[0].link.should.not.equal(null);
1256
+ res.body.data[0].link._id.should.equal(link_id);
1257
+ res.body.data[0].link.name.should.equal("cache_test");
1258
+ res.body.data[0].link.val.should.equal("YoYoYo");
1259
+ res.headers["jxp-cache"].should.equal("miss");
1260
+ done();
1261
+ });
1262
+ });
1263
+ it("should update link record", done => {
1264
+ chai.request(server)
1265
+ .put(`/api/link/${link_id}`)
1266
+ .auth(init.admin_email, init.admin_password)
1267
+ .send({
1268
+ val: "YoYoYo2"
1269
+ })
1270
+ .end((err, res) => {
1271
+ // console.log(res.body)
1272
+ res.should.have.status(200);
1273
+ res.body.data.should.have.property("_id");
1274
+ res.body.data.val.should.equal("YoYoYo2");
1275
+ done();
1276
+ });
1277
+ });
1278
+ it("should get a test record with updated link", done => {
1279
+ chai.request(server)
1280
+ .get(`/api/test?populate=link&limit=1`)
1281
+ .auth(init.email, init.password)
1282
+ .end((err, res) => {
1283
+ // console.log(res.body.data[0].link)
1284
+ res.should.have.status(200);
1285
+ res.body.data[0].should.have.property("_id");
1286
+ res.body.data[0].should.have.property("link");
1287
+ res.body.data[0].link.should.not.equal(null);
1288
+ res.body.data[0].link._id.should.equal(link_id);
1289
+ res.body.data[0].link.name.should.equal("cache_test");
1290
+ res.body.data[0].link.val.should.equal("YoYoYo2");
1291
+ res.headers["jxp-cache"].should.equal("miss");
1292
+ done();
1293
+ });
1294
+ });
1295
+ })
1185
1296
  });