nodester 0.6.4 → 0.6.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.
@@ -0,0 +1,23 @@
1
+ const Enum = require('nodester/enum');
2
+
3
+
4
+ module.exports = new Enum({
5
+ and: Symbol.for('and'),
6
+ between: Symbol.for('between'),
7
+ contains: Symbol.for('contains'),
8
+ eq: Symbol.for('eq'),
9
+ ne: Symbol.for('ne'),
10
+ gte: Symbol.for('gte'),
11
+ gt: Symbol.for('gt'),
12
+ lte: Symbol.for('lte'),
13
+ lt: Symbol.for('lt'),
14
+ not: Symbol.for('not'),
15
+ is: Symbol.for('is'),
16
+ in: Symbol.for('in'),
17
+ notIn: Symbol.for('notIn'),
18
+ like: Symbol.for('like'),
19
+ notLike: Symbol.for('notLike'),
20
+ notBetween: Symbol.for('notBetween'),
21
+ or: Symbol.for('or'),
22
+ xor: Symbol.for('xor'),
23
+ });
@@ -0,0 +1,38 @@
1
+ /**
2
+ * nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const {
9
+ HTTP_CODE_NOT_FOUND
10
+ } = require('nodester/http/codes');
11
+
12
+ const { createErrorResponse } = require('nodester/factories/responses/rest');
13
+
14
+
15
+ /**
16
+ * Initialize `404` middleware.
17
+ *
18
+ * @param {Object} [options]
19
+ *
20
+ * @return {Function}
21
+ *
22
+ * @access public
23
+ */
24
+ module.exports = function init404Middleware(options={}) {
25
+ const context = {
26
+ options
27
+ }
28
+ return handle.bind(context);
29
+ }
30
+
31
+ function handle(req, res, next) {
32
+ const err = new Error('Route not found');
33
+
34
+ return createErrorResponse(res, {
35
+ error: err,
36
+ status: HTTP_CODE_NOT_FOUND
37
+ });
38
+ }
@@ -0,0 +1,81 @@
1
+ /**
2
+ * nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+ const calculate = require('etag');
9
+ const Stream = require('stream');
10
+
11
+ // Utils:
12
+ const promisify = require('util').promisify;
13
+ const fs = require('fs');
14
+ const getFileStats = promisify(fs.stat);
15
+
16
+
17
+ module.exports = initETagMiddleware;
18
+
19
+ /**
20
+ * Initialize `etag` middleware.
21
+ *
22
+ * @param {Object} [options]
23
+ * @param {boolean} options.weak
24
+ *
25
+ * @return {Function}
26
+ *
27
+ * @access public
28
+ */
29
+ function initETagMiddleware(options) {
30
+ const context = {
31
+ options
32
+ }
33
+ return handle.bind(context);
34
+ }
35
+
36
+ /**
37
+ * Add ETag header field.
38
+ */
39
+ function handle(req, res, next) {
40
+ // console.log('e', req.headers);
41
+ return next();
42
+ }
43
+
44
+ async function _getResponseEntity(res) {
45
+ // If body is not defined:
46
+ const { body } = res;
47
+ if (!body || res.get('etag'))
48
+ return;
49
+
50
+ // Status code.
51
+ const status = res.statusCode / 100 | 0;
52
+
53
+ console.log('getResponseEntity', status, { tag: res.get('etag') });
54
+
55
+ // 2xx
56
+ if (status !== 2)
57
+ return;
58
+
59
+ if (body instanceof Stream) {
60
+ if (!body.path)
61
+ return;
62
+
63
+ const stats = await getFileStats(body.path);
64
+ return stats;
65
+ }
66
+ else if (typeof body === 'string' || Buffer.isBuffer(body)) {
67
+ return body;
68
+ }
69
+ else {
70
+ return JSON.stringify(body);
71
+ }
72
+ }
73
+
74
+ function _setEtag(res, entity, options) {
75
+ console.log('setEtag', typeof res, entity);
76
+
77
+ if (!entity)
78
+ return;
79
+
80
+ res.etag = calculate(entity, options);
81
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * nodester
3
+ * MIT Licensed
4
+ */
5
+
6
+ 'use strict';
7
+
8
+
9
+ module.exports = function initRenderMiddleware() {
10
+ return handle;
11
+ }
12
+
13
+
14
+ function handle(req, res, next) {
15
+ const context = { req, res, next };
16
+ res.render = _render.bind(context);
17
+ next();
18
+ }
19
+
20
+
21
+ /**
22
+ * Render `view` with the given `options` and optional callback `fn`.
23
+ * When a callback function is given a response will _not_ be made
24
+ * automatically, otherwise a response of _200_ and _text/html_ is given.
25
+ *
26
+ * Options:
27
+ *
28
+ * - `cache` boolean hinting to the engine it should cache
29
+ * - `filename` filename of the view being rendered
30
+ *
31
+ * @alias render
32
+ * @access public
33
+ */
34
+ function _render(view, options, callback) {
35
+ const app = this.req.app;
36
+ let done = callback;
37
+ let opts = options || {};
38
+
39
+ const req = this.req;
40
+ const res = this.res;
41
+ const next = this.next;
42
+
43
+ // support callback function as second arg
44
+ if (typeof options === 'function') {
45
+ done = options;
46
+ opts = {};
47
+ }
48
+
49
+ // merge res.locals
50
+ opts._locals = res.locals;
51
+
52
+ // default callback to respond
53
+ done = done || function (err, str) {
54
+ if (err)
55
+ return next(err);
56
+
57
+ res.send(str);
58
+ };
59
+
60
+ // render
61
+ app.render(view, opts, done);
62
+ };
@@ -212,10 +212,8 @@ async function _updateOne(
212
212
 
213
213
  // Will contain data from parent instance and associations.
214
214
  const fullInstanceData = instance.toJSON();
215
+ const parentData = { ...data };
215
216
 
216
- const parentData = {
217
- ...data
218
- }
219
217
  for (let includeConfig of include) {
220
218
  const { association } = includeConfig;
221
219
 
@@ -223,6 +221,7 @@ async function _updateOne(
223
221
  continue;
224
222
  }
225
223
 
224
+ // Remove association from parentData (handled separately)
226
225
  delete parentData[association];
227
226
 
228
227
  const associationDefinition = this.associations[association];
@@ -246,6 +245,15 @@ async function _updateOne(
246
245
  // If association type is HasMany or HasOne (We don't work with any other):
247
246
  switch(associationType) {
248
247
  case 'HasMany': {
248
+ // Handle empty array (remove all old associations):
249
+ if (Array.isArray(includeData) && includeData.length === 0) {
250
+ const where = {
251
+ [foreignKey]: instance.id
252
+ }
253
+ await associatedModel.destroy({ where });
254
+ fullInstanceData[association] = [];
255
+ }
256
+
249
257
  const promises = includeData.map(singleData => {
250
258
  // Note: for now we are only able to work with a model with single PrimaryKey:
251
259
  const where = {
@@ -263,16 +271,25 @@ async function _updateOne(
263
271
  }
264
272
 
265
273
  case 'HasOne': {
266
- // Note: for now we are only able to work with a model with single PrimaryKey:
267
- const where = {
268
- [pkField]: includeData[pkField]
274
+ // Handle null case (remove old association)
275
+ if (includeData === null) {
276
+ const where = {
277
+ [foreignKey]: instance.id
278
+ }
279
+ await associatedModel.destroy({ where });
280
+ fullInstanceData[association] = null;
281
+ }
282
+ else {
283
+ // Note: for now we are only able to work with a model with single PrimaryKey:
284
+ const where = {
285
+ [pkField]: includeData[pkField]
286
+ }
287
+ fullInstanceData[association] = await associatedModel.updateOne(
288
+ where,
289
+ includeData,
290
+ associationUpdateOpts
291
+ );
269
292
  }
270
- fullInstanceData[association] = await associatedModel.updateOne(
271
- where,
272
- includeData,
273
- associationUpdateOpts
274
- );
275
-
276
293
  continue;
277
294
  }
278
295
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodester",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "A versatile REST framework for Node.js",
5
5
  "directories": {
6
6
  "docs": "docs",
@@ -89,8 +89,8 @@
89
89
  "http-errors": "^2.0.0",
90
90
  "inflection": "^2.0.1",
91
91
  "mime": "^3.0.0",
92
- "mysql2": "^3.6.0",
93
- "pg": "^8.11.3",
92
+ "mysql2": "^3.14.4",
93
+ "pg": "^8.16.3",
94
94
  "pg-hstore": "^2.3.4",
95
95
  "qs": "^6.11.0",
96
96
  "sequelize": "^6.6.5"
package/tests/ast.js ADDED
@@ -0,0 +1,18 @@
1
+ const { ModelsTree } = require('../lib/middlewares/ql/sequelize/interpreter/ModelsTree');
2
+ const { AST_ModelsTree } = require('../lib/tools/nql.tool');
3
+
4
+ const tree = new ModelsTree();
5
+ tree.node.addWhere({ id: ['1000'] });
6
+ tree.include('comments').use('comments');
7
+ tree.node.order = 'desc';
8
+ tree.up();
9
+ tree.include('users');
10
+ tree.include('likes') && tree.use('likes');
11
+ tree.node.order = 'rand';
12
+ tree.up();
13
+ tree.include('reposts');
14
+
15
+ console.debug(
16
+ AST_ModelsTree(tree)
17
+ );
18
+