nodester 0.2.0 → 0.2.1

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,9 +1,12 @@
1
1
  # nodester
2
- > A robust and flexible boilerplate framework that makes iterative development easy.
3
2
 
4
3
  [![NPM version](https://img.shields.io/npm/v/nodester)](https://www.npmjs.com/package/nodester)
5
4
  [![License](https://img.shields.io/npm/l/nodester)](https://www.npmjs.com/package/nodester)
6
5
 
6
+ > **nodester** is a modern and versatile Node.js framework designed to streamline the development of robust and scalable web applications.
7
+
8
+ **nodester Query Language (NQL):** The main reason of nodester's existence is the [nodester Query Language (NQL)](docs/Queries.md), an extension of standard REST API syntax, it lets you craft complex queries with hierarchical associations.
9
+
7
10
 
8
11
  ## Installation
9
12
 
@@ -18,7 +21,6 @@ npm install -S nodester
18
21
 
19
22
  - [Usage](#usage)
20
23
  - [Documentation](#documentation)
21
- - [Extending App](#extending-application-functionality)
22
24
  - [Philosophy](#philosophy)
23
25
  - [License](#license)
24
26
  - [Copyright](#copyright)
@@ -47,10 +49,11 @@ app.listen(8080, function() {
47
49
  [Core concepts documentation ➡️](docs/CoreConcepts.md)
48
50
 
49
51
 
50
- ### Queries & Querying - Nodester Query Language (NQR)
51
- One of the main power points of nodester is it's query language. It's an extension of a REST API syntaxis for a broader integration with a database SQL. Read more about it in the documentation:
52
+ ### Queries & Querying - Nodester Query Language (NQL)
53
+ The true strength of nodester lies in its query language. Serving as an extension of standard REST API syntax, it brings many aspects of SQL into REST requests, providing developers with a simple yet potent tool for expressive and efficient data querying.
52
54
 
53
- [NQR documentaion ➡️](docs/Queries.md)
55
+ Read more about it in the documentation:
56
+ [NQL documentaion ➡️](docs/Queries.md)
54
57
 
55
58
 
56
59
  ### Database
@@ -70,7 +73,7 @@ The Philosophy of `nodester` is to provide a developer with a tool that can buil
70
73
 
71
74
  ### Goal
72
75
 
73
- The goal of `nodester` is to be a robust and flexible framework that makes development in iteratations easy, and further scale possible.
76
+ The goal of `nodester` is to be a robust and flexible framework that makes development in iteratations easy, while laying the foundation for seamless scalability in the future.
74
77
 
75
78
 
76
79
  ## LICENSE
@@ -134,6 +134,17 @@ module.exports = class NodesterApplication extends Emitter {
134
134
  return this._router.isLocked;
135
135
  }
136
136
 
137
+ /**
138
+ * Indicates whether app is awaiting requests.
139
+ *
140
+ * @return {Boolean} isListening
141
+ *
142
+ * @api public
143
+ */
144
+ get isListening() {
145
+ return this._isListening;
146
+ }
147
+
137
148
  // Getters\
138
149
 
139
150
  /*
@@ -222,6 +222,13 @@ module.exports = class QueryLexer {
222
222
  const model = token;
223
223
  tree.use(model) ?? tree.include(model);
224
224
 
225
+ // Last token (model) was included,
226
+ // now jump to root and proceed to collect next token (model).
227
+ tree.node.resetActiveParam();
228
+ tree.upToRoot();
229
+
230
+ tree.node.activeParam = 'includes';
231
+
225
232
  token = '';
226
233
  continue;
227
234
  }
@@ -403,7 +410,7 @@ module.exports = class QueryLexer {
403
410
  const err = MissingCharError(i+1, ')');
404
411
  throw err;
405
412
  }
406
-
413
+
407
414
  this.setNodeParam(tree.node, token, value);
408
415
 
409
416
  // If end of subquery:
@@ -261,11 +261,12 @@ function traverse(queryNode, filter=null, model=null) {
261
261
 
262
262
 
263
263
  // Includes:
264
- // If requested includes are not available:
264
+ // Validate, if requested includes are available:
265
265
  for (let include of includes) {
266
266
  const includeName = include.model;
267
+
267
268
  if (rootModelAssociations[includeName] === undefined) {
268
- const err = new NQueryError(`No include named '${ includeName }'.`);
269
+ const err = new NQueryError(`No include named '${ includeName }'`);
269
270
  err.status = httpCodes.NOT_ACCEPTABLE;
270
271
  Error.captureStackTrace(err, traverse);
271
272
  throw err;
@@ -300,7 +301,7 @@ function _traverseIncludes(includes, model, filter, resultQuery) {
300
301
 
301
302
  // If no such association:
302
303
  if (!association) {
303
- const err = new NQueryError(`No include named '${ includeName }'.`);
304
+ const err = new NQueryError(`No include named '${ includeName }'`);
304
305
  err.status = httpCodes.NOT_ACCEPTABLE;
305
306
  Error.captureStackTrace(err, _traverseIncludes);
306
307
  throw err;
@@ -97,7 +97,8 @@ module.exports = class NodesterFilter {
97
97
  }
98
98
 
99
99
  // If singular association:
100
- if (['HasMany', 'HasOne'].indexOf(association.associationType) === -1) {
100
+ // Fix of "Only HasMany associations support include.separate"
101
+ if ('HasMany' !== association.associationType) {
101
102
  // Empty bounds.
102
103
  includeFilter.noBounds = true;
103
104
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodester",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "A boilerplate framework for Node.js",
5
5
  "exports": {
6
6
  ".": "./lib/application/index.js",
@@ -27,13 +27,13 @@ describe('nodester application', () => {
27
27
  test('Application start', () => {
28
28
  app.listen(PORT, function() {
29
29
  expect(app.port).toBe(PORT);
30
- expect(app.router._middlewares.isLocked).toBe(true);
31
- expect(app.router._middlewares.length).toBe(2);
30
+ expect(app.isLocked).toBe(true);
31
+ expect(app.isListening).toBe(true);
32
+ expect(app.middlewaresStack.length).toBe(4);
32
33
 
33
34
  app.stop();
34
35
 
35
- expect(app.router._middlewares.length).toBe(0);
36
- expect(app.router._middlewares.isLocked).toBe(false);
36
+ expect(app.isLocked).toBe(false);
37
37
  expect(app.isListening).toBe(false);
38
38
  });
39
39
  });
package/tests/nql.test.js CHANGED
@@ -49,6 +49,9 @@ describe('nodester Query Language', () => {
49
49
 
50
50
  // Like simple.
51
51
  'title=like(some_text)',
52
+
53
+ // Subinclude and isolated Horizontal.
54
+ 'in=comments.user,likes',
52
55
  ];
53
56
 
54
57
  it('query "Simple where"', () => {
@@ -262,7 +265,6 @@ describe('nodester Query Language', () => {
262
265
 
263
266
  expect(result).toMatchObject(expected);
264
267
  });
265
-
266
268
 
267
269
  test('Token "Like" simple', () => {
268
270
  const lexer = new QueryLexer( queryStrings[14] );
@@ -274,4 +276,19 @@ describe('nodester Query Language', () => {
274
276
 
275
277
  expect(result).toMatchObject(expected);
276
278
  });
279
+
280
+ it('query "Subinclude and isolated Horizontal"', () => {
281
+ const lexer = new QueryLexer( queryStrings[15] );
282
+ result = lexer.query;
283
+
284
+ const tree = new ModelsTree();
285
+ tree.include('comments').use('comments');
286
+ tree.include('user');
287
+ tree.up();
288
+ tree.include('likes');
289
+ const expected = tree.root.toObject();
290
+
291
+ expect(result).toMatchObject(expected);
292
+ });
293
+
277
294
  });