pure-orm 2.1.0 → 2.2.0

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
@@ -76,7 +76,7 @@ class PersonDAO extends BaseDAO {
76
76
  And use it like this:
77
77
 
78
78
  ```javascript
79
- const person = personDAO.get(55);
79
+ const person = await personDAO.get({ id: 55 });
80
80
  console.log(person);
81
81
  ```
82
82
 
@@ -100,7 +100,7 @@ Person {
100
100
  Job {
101
101
  id: 278,
102
102
  personId: 55,
103
- employerId: 26
103
+ employerId: 26,
104
104
  startDate: '2021-01-01',
105
105
  endDate: '2021-12-31',
106
106
  employer: Employer {
@@ -115,11 +115,37 @@ Person {
115
115
 
116
116
  > This is a quick showcase. To see how to wire up this code, see the full [Practical Example](#practical-example) below.
117
117
 
118
- Things to note:
118
+ ### Things to Note:
119
119
 
120
- - Our DAO returns a single Person business object which is properly structured from the relational row records!
120
+ - Our DAO returns a single Person business object which is properly structured from the many relational row records!
121
121
  - Our query is executed with a `one` method. The DAO methods for `one`, `oneOrNone`, `many`, `any` ensure their count against the number of generated top level business objects - not the number of relational row records the sql expression returns!
122
- - Rather than manually specifying our columns in the sql select expression, we use the business object's `getSQLSelectClause`. This is purely a convenience method which namespaces each column with the table name prefix to ensure column names don't collide. (You are welcome to do this by hand if you don't mind the tedium.)
122
+ - Rather than manually specifying our columns in the sql select expression, we use the business object's `getSQLSelectClause`. This is purely a convenience method which namespaces each column with the table name prefix to ensure column names don't collide (for example, the person, job, and employer `id`s would collide if not namespaced, as would person and employer `name`s). You are welcome to do this by hand instead of using the convenience methods (as were used above), if you don't mind the tedium:
123
+ ```javascript
124
+ class PersonDAO extends BaseDAO {
125
+ get({ id }) {
126
+ // Example showing you can manually specific the select expression fields
127
+ // instead of using a business object's `getSQLSelectClause` convenience
128
+ // method. Note: you must namespace the field with table name and hashtag.
129
+ const query = `
130
+ SELECT
131
+ person.id as "person#id",
132
+ person.name as "person#name",
133
+ job.id as "job#id",
134
+ job.person_id: "job#person_id",
135
+ job.employer_id: "job#employer_id",
136
+ job.start_date: "job#start_date",
137
+ job.end_date: "job#end_date",
138
+ employer.id as "employer#id",
139
+ employer.name as "employer#name"
140
+ FROM person
141
+ JOIN job on person.id = job.person_id
142
+ JOIN employer on job.employer_id = employer.id
143
+ WHERE id = $(id)
144
+ `;
145
+ return this.one(query, { id });
146
+ }
147
+ }
148
+ ```
123
149
 
124
150
  ## Usage
125
151
 
@@ -160,18 +186,18 @@ const renderProfile = (req, res) => {
160
186
  endDate: '2020-12-31',
161
187
  employer: {
162
188
  id: 17,
163
- name: 'Good Corp',
189
+ name: 'Good Corp'
164
190
  }
165
191
  },
166
192
  {
167
193
  id: 278,
168
194
  personId: 55,
169
- employerId: 26
195
+ employerId: 26,
170
196
  startDate: '2021-01-01',
171
197
  endDate: '2021-12-31',
172
198
  employer: {
173
199
  id: 26,
174
- name: 'Better Corp',
200
+ name: 'Better Corp'
175
201
  }
176
202
  }
177
203
  ]
@@ -233,7 +259,7 @@ const renderProfile = (req, res) => {
233
259
  - {
234
260
  - id: 278,
235
261
  - personId: 55,
236
- - employerId: 26
262
+ - employerId: 26,
237
263
  - startDate: '2021-01-01',
238
264
  - endDate: '2021-12-31',
239
265
  - employer: {
@@ -244,8 +270,7 @@ const renderProfile = (req, res) => {
244
270
  - ]
245
271
  - }
246
272
  - };
247
- + const personId = req.params.id;
248
- + const person = personDAO.get({personId});
273
+ + const person = personDAO.get({ id: req.params.id });
249
274
  res.render('profile.html', person);
250
275
  ```
251
276
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pure-orm",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "main": "src/index.js",
5
5
  "engines": {
6
6
  "node": ">=6"
package/src/bo/base-bo.js CHANGED
@@ -156,14 +156,19 @@ module.exports = ({ getBusinessObjects }) =>
156
156
  const bo = nodeAlreadySeen || _bo;
157
157
  const isNodeAlreadySeen = !!nodeAlreadySeen;
158
158
  const nodePointingToIt = nodes.find(node => {
159
- const index = Object.values(node.constructor.references).indexOf(
160
- bo.constructor
161
- );
162
- if (index === -1) {
159
+ const indexes = Object.values(node.constructor.references)
160
+ .map((x, i) => (x === bo.constructor ? i : null))
161
+ .filter(x => x != null);
162
+ if (!indexes.length) {
163
163
  return false;
164
164
  }
165
- const property = Object.keys(node.constructor.references)[index];
166
- return node[property] === bo.id;
165
+ for (const index of indexes) {
166
+ const property = Object.keys(node.constructor.references)[index];
167
+ if (node[property] === bo.id) {
168
+ return true;
169
+ }
170
+ }
171
+ return false;
167
172
  });
168
173
  // For first obj type which is has an instance in nodes array,
169
174
  // get its index in nodes array
@@ -18,6 +18,8 @@ const eight = require('../../test-utils/eight/results.json');
18
18
  const nine = require('../../test-utils/nine/results.json');
19
19
  const ten = require('../../test-utils/ten/results.json');
20
20
  const eleven = require('../../test-utils/eleven/results.json');
21
+ const twelve = require('../../test-utils/twelve/results.json');
22
+ const Prompt = require('../../test-utils/twelve/bo/prompt');
21
23
 
22
24
  test('Bo#parseFromDatabase where multiple rows reduce to one nested object (with all one-to-one or one-to-many tables)', () => {
23
25
  const order = Order.createOneFromDatabase(one);
@@ -528,3 +530,18 @@ test('Bo#parseFromDatabase 11', () => {
528
530
  // I'm insecure about the lack of tests so just going at it cause I can.
529
531
  // TODO add more later
530
532
  });
533
+
534
+ // Issue occcurs in nestClump
535
+ // Problem when a table references another model twice (two columns)
536
+ test('Bo#parseFromDatabase 12', () => {
537
+ let prompt;
538
+ try {
539
+ // This failed when the bug was present
540
+ prompt = Prompt.createFromDatabase(twelve);
541
+ } catch (e) {
542
+ expect(e).not.toBeDefined();
543
+ }
544
+ expect(prompt).toBeDefined();
545
+ // Ideally the below should work
546
+ // expect(prompt.fromMember.id).toEqual(1);
547
+ });
@@ -0,0 +1,5 @@
1
+ const { createBaseBO } = require('pure-orm');
2
+ const getBusinessObjects = require('../business-objects');
3
+
4
+ const constructor = createBaseBO({ getBusinessObjects });
5
+ module.exports = constructor;
@@ -0,0 +1,16 @@
1
+ const Base = require('./base');
2
+ const Members = require('./members');
3
+
4
+ class Member extends Base {
5
+ get BoCollection() {
6
+ return Members;
7
+ }
8
+ static get tableName() {
9
+ return 'member';
10
+ }
11
+
12
+ static get sqlColumnsData() {
13
+ return ['id'];
14
+ }
15
+ }
16
+ module.exports = Member;
@@ -0,0 +1,9 @@
1
+ const { BaseBoCollection } = require('../../../src/index');
2
+
3
+ class Members extends BaseBoCollection {
4
+ static get Bo() {
5
+ return require('./member'); // eslint-disable-line
6
+ }
7
+ }
8
+
9
+ module.exports = Members;
@@ -0,0 +1,20 @@
1
+ const Base = require('./base');
2
+ const Prompts = require('./prompts');
3
+ const Member = require('./member');
4
+
5
+ class Prompt extends Base {
6
+ get BoCollection() {
7
+ return Prompts;
8
+ }
9
+ static get tableName() {
10
+ return 'prompt';
11
+ }
12
+ static get sqlColumnsData() {
13
+ return [
14
+ 'id',
15
+ { column: 'for_member_id', references: Member },
16
+ { column: 'from_member_id', references: Member }
17
+ ];
18
+ }
19
+ }
20
+ module.exports = Prompt;
@@ -0,0 +1,9 @@
1
+ const { BaseBoCollection } = require('../../../src/index');
2
+
3
+ class Prompts extends BaseBoCollection {
4
+ static get Bo() {
5
+ return require('./prompt'); // eslint-disable-line
6
+ }
7
+ }
8
+
9
+ module.exports = Prompts;
@@ -0,0 +1,8 @@
1
+ /* eslint-disable global-require */
2
+ const getBusinessObjects = () => [
3
+ // These need to be imported here to get around circular dependencies
4
+ require('./bo/prompt'),
5
+ require('./bo/member')
6
+ ];
7
+
8
+ module.exports = getBusinessObjects;
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "prompt#id": 13,
4
+ "prompt#for_member_id": 336,
5
+ "prompt#from_member_id": 1,
6
+ "member#id": 1
7
+ }
8
+ ]