pure-orm 4.0.1 → 4.0.3

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.
Files changed (211) hide show
  1. package/.eslintrc.json +20 -10
  2. package/babel.config.js +1 -4
  3. package/coverage/clover.xml +478 -399
  4. package/coverage/coverage-final.json +10 -4
  5. package/coverage/lcov-report/dist/src/core.js.html +152 -131
  6. package/coverage/lcov-report/dist/src/driver-integrations/index.html +1 -1
  7. package/coverage/lcov-report/dist/src/driver-integrations/pgp.js.html +1 -1
  8. package/coverage/lcov-report/dist/src/index.html +18 -18
  9. package/coverage/lcov-report/dist/src/index.js.html +1 -1
  10. package/coverage/lcov-report/dist/src/orm.js.html +1 -1
  11. package/coverage/lcov-report/dist/test-utils/blog/entities.js.html +1 -1
  12. package/coverage/lcov-report/dist/test-utils/blog/index.html +1 -1
  13. package/coverage/lcov-report/dist/test-utils/blog/models/article.js.html +1 -1
  14. package/coverage/lcov-report/dist/test-utils/blog/models/article_tag.js.html +1 -1
  15. package/coverage/lcov-report/dist/test-utils/blog/models/index.html +1 -1
  16. package/coverage/lcov-report/dist/test-utils/blog/models/person.js.html +1 -1
  17. package/coverage/lcov-report/dist/test-utils/blog/models/tag.js.html +1 -1
  18. package/coverage/lcov-report/dist/test-utils/five/entities.js.html +1 -1
  19. package/coverage/lcov-report/dist/test-utils/five/index.html +1 -1
  20. package/coverage/lcov-report/dist/test-utils/five/models/index.html +1 -1
  21. package/coverage/lcov-report/dist/test-utils/five/models/line-item.js.html +1 -1
  22. package/coverage/lcov-report/dist/test-utils/five/models/order.js.html +1 -1
  23. package/coverage/lcov-report/dist/test-utils/five/models/parcel-event.js.html +1 -1
  24. package/coverage/lcov-report/dist/test-utils/five/models/parcel-line-item.js.html +1 -1
  25. package/coverage/lcov-report/dist/test-utils/five/models/parcel.js.html +1 -1
  26. package/coverage/lcov-report/dist/test-utils/fourteen/entities.js.html +87 -0
  27. package/coverage/lcov-report/dist/test-utils/fourteen/index.html +97 -0
  28. package/coverage/lcov-report/dist/test-utils/fourteen/models/customer.js.html +159 -0
  29. package/coverage/lcov-report/dist/test-utils/fourteen/models/index.html +110 -0
  30. package/coverage/lcov-report/dist/test-utils/fourteen/models/person.js.html +138 -0
  31. package/coverage/lcov-report/dist/test-utils/nine/entities.js.html +1 -1
  32. package/coverage/lcov-report/dist/test-utils/nine/index.html +1 -1
  33. package/coverage/lcov-report/dist/test-utils/nine/models/feature-switch.js.html +1 -1
  34. package/coverage/lcov-report/dist/test-utils/nine/models/index.html +1 -1
  35. package/coverage/lcov-report/dist/test-utils/order/entities.js.html +1 -1
  36. package/coverage/lcov-report/dist/test-utils/order/index.html +1 -1
  37. package/coverage/lcov-report/dist/test-utils/order/models/index.html +1 -1
  38. package/coverage/lcov-report/dist/test-utils/order/models/line-item.js.html +1 -1
  39. package/coverage/lcov-report/dist/test-utils/order/models/order.js.html +1 -1
  40. package/coverage/lcov-report/dist/test-utils/order/models/product-variant.js.html +1 -1
  41. package/coverage/lcov-report/dist/test-utils/order/models/product.js.html +1 -1
  42. package/coverage/lcov-report/dist/test-utils/order/models/utm-source.js.html +1 -1
  43. package/coverage/lcov-report/dist/test-utils/order-more/entities.js.html +1 -1
  44. package/coverage/lcov-report/dist/test-utils/order-more/index.html +1 -1
  45. package/coverage/lcov-report/dist/test-utils/order-more/models/actual-product-variant.js.html +1 -1
  46. package/coverage/lcov-report/dist/test-utils/order-more/models/color.js.html +1 -1
  47. package/coverage/lcov-report/dist/test-utils/order-more/models/customer.js.html +1 -1
  48. package/coverage/lcov-report/dist/test-utils/order-more/models/gender.js.html +1 -1
  49. package/coverage/lcov-report/dist/test-utils/order-more/models/index.html +1 -1
  50. package/coverage/lcov-report/dist/test-utils/order-more/models/inventory-level.js.html +1 -1
  51. package/coverage/lcov-report/dist/test-utils/order-more/models/line-item.js.html +1 -1
  52. package/coverage/lcov-report/dist/test-utils/order-more/models/order.js.html +1 -1
  53. package/coverage/lcov-report/dist/test-utils/order-more/models/parcel-event.js.html +1 -1
  54. package/coverage/lcov-report/dist/test-utils/order-more/models/parcel-line-item.js.html +1 -1
  55. package/coverage/lcov-report/dist/test-utils/order-more/models/parcel.js.html +1 -1
  56. package/coverage/lcov-report/dist/test-utils/order-more/models/physical-address.js.html +1 -1
  57. package/coverage/lcov-report/dist/test-utils/order-more/models/product-variant-image.js.html +1 -1
  58. package/coverage/lcov-report/dist/test-utils/order-more/models/product-variant.js.html +1 -1
  59. package/coverage/lcov-report/dist/test-utils/order-more/models/product.js.html +1 -1
  60. package/coverage/lcov-report/dist/test-utils/order-more/models/refund.js.html +1 -1
  61. package/coverage/lcov-report/dist/test-utils/order-more/models/shipment-actual-product-variant.js.html +1 -1
  62. package/coverage/lcov-report/dist/test-utils/order-more/models/shipment.js.html +1 -1
  63. package/coverage/lcov-report/dist/test-utils/order-more/models/size.js.html +1 -1
  64. package/coverage/lcov-report/dist/test-utils/order-more/models/utm-medium.js.html +1 -1
  65. package/coverage/lcov-report/dist/test-utils/order-more/models/utm-source.js.html +1 -1
  66. package/coverage/lcov-report/dist/test-utils/six/entities.js.html +1 -1
  67. package/coverage/lcov-report/dist/test-utils/six/index.html +1 -1
  68. package/coverage/lcov-report/dist/test-utils/six/models/customer.js.html +1 -1
  69. package/coverage/lcov-report/dist/test-utils/six/models/index.html +1 -1
  70. package/coverage/lcov-report/dist/test-utils/six/models/line-item.js.html +1 -1
  71. package/coverage/lcov-report/dist/test-utils/six/models/order.js.html +1 -1
  72. package/coverage/lcov-report/dist/test-utils/six/models/parcel-line-item.js.html +1 -1
  73. package/coverage/lcov-report/dist/test-utils/six/models/parcel.js.html +1 -1
  74. package/coverage/lcov-report/dist/test-utils/thirteen/entities.js.html +1 -1
  75. package/coverage/lcov-report/dist/test-utils/thirteen/index.html +1 -1
  76. package/coverage/lcov-report/dist/test-utils/thirteen/models/audience.js.html +1 -1
  77. package/coverage/lcov-report/dist/test-utils/thirteen/models/brand.js.html +1 -1
  78. package/coverage/lcov-report/dist/test-utils/thirteen/models/category.js.html +1 -1
  79. package/coverage/lcov-report/dist/test-utils/thirteen/models/index.html +1 -1
  80. package/coverage/lcov-report/dist/test-utils/thirteen/models/member.js.html +1 -1
  81. package/coverage/lcov-report/dist/test-utils/thirteen/models/passion.js.html +1 -1
  82. package/coverage/lcov-report/dist/test-utils/thirteen/models/product.js.html +1 -1
  83. package/coverage/lcov-report/dist/test-utils/thirteen/models/recommendation-audience.js.html +1 -1
  84. package/coverage/lcov-report/dist/test-utils/thirteen/models/recommendation.js.html +1 -1
  85. package/coverage/lcov-report/dist/test-utils/three/index.html +1 -1
  86. package/coverage/lcov-report/dist/test-utils/three/results.js.html +1 -1
  87. package/coverage/lcov-report/dist/test-utils/twelve/entities.js.html +1 -1
  88. package/coverage/lcov-report/dist/test-utils/twelve/index.html +1 -1
  89. package/coverage/lcov-report/dist/test-utils/twelve/models/index.html +1 -1
  90. package/coverage/lcov-report/dist/test-utils/twelve/models/member.js.html +1 -1
  91. package/coverage/lcov-report/dist/test-utils/twelve/models/prompt.js.html +1 -1
  92. package/coverage/lcov-report/dist/test-utils/two/index.html +1 -1
  93. package/coverage/lcov-report/dist/test-utils/two/results.js.html +1 -1
  94. package/coverage/lcov-report/index.html +77 -25
  95. package/coverage/lcov-report/src/core.ts.html +162 -141
  96. package/coverage/lcov-report/src/driver-integrations/index.html +1 -1
  97. package/coverage/lcov-report/src/driver-integrations/pgp.ts.html +6 -6
  98. package/coverage/lcov-report/src/index.html +18 -18
  99. package/coverage/lcov-report/src/index.ts.html +1 -1
  100. package/coverage/lcov-report/src/orm.ts.html +45 -18
  101. package/coverage/lcov-report/test-utils/blog/entities.ts.html +1 -1
  102. package/coverage/lcov-report/test-utils/blog/index.html +1 -1
  103. package/coverage/lcov-report/test-utils/blog/models/article.ts.html +1 -1
  104. package/coverage/lcov-report/test-utils/blog/models/article_tag.ts.html +1 -1
  105. package/coverage/lcov-report/test-utils/blog/models/index.html +1 -1
  106. package/coverage/lcov-report/test-utils/blog/models/person.ts.html +1 -1
  107. package/coverage/lcov-report/test-utils/blog/models/tag.ts.html +1 -1
  108. package/coverage/lcov-report/test-utils/five/entities.ts.html +1 -1
  109. package/coverage/lcov-report/test-utils/five/index.html +1 -1
  110. package/coverage/lcov-report/test-utils/five/models/index.html +1 -1
  111. package/coverage/lcov-report/test-utils/five/models/line-item.ts.html +1 -1
  112. package/coverage/lcov-report/test-utils/five/models/order.ts.html +1 -1
  113. package/coverage/lcov-report/test-utils/five/models/parcel-event.ts.html +1 -1
  114. package/coverage/lcov-report/test-utils/five/models/parcel-line-item.ts.html +1 -1
  115. package/coverage/lcov-report/test-utils/five/models/parcel.ts.html +1 -1
  116. package/coverage/lcov-report/test-utils/fourteen/entities.ts.html +78 -0
  117. package/coverage/lcov-report/test-utils/fourteen/index.html +97 -0
  118. package/coverage/lcov-report/test-utils/fourteen/models/customer.ts.html +177 -0
  119. package/coverage/lcov-report/test-utils/fourteen/models/index.html +110 -0
  120. package/coverage/lcov-report/test-utils/fourteen/models/person.ts.html +150 -0
  121. package/coverage/lcov-report/test-utils/nine/entities.ts.html +1 -1
  122. package/coverage/lcov-report/test-utils/nine/index.html +1 -1
  123. package/coverage/lcov-report/test-utils/nine/models/feature-switch.ts.html +1 -1
  124. package/coverage/lcov-report/test-utils/nine/models/index.html +1 -1
  125. package/coverage/lcov-report/test-utils/order/entities.ts.html +1 -1
  126. package/coverage/lcov-report/test-utils/order/index.html +1 -1
  127. package/coverage/lcov-report/test-utils/order/models/index.html +1 -1
  128. package/coverage/lcov-report/test-utils/order/models/line-item.ts.html +1 -1
  129. package/coverage/lcov-report/test-utils/order/models/order.ts.html +1 -1
  130. package/coverage/lcov-report/test-utils/order/models/product-variant.ts.html +1 -1
  131. package/coverage/lcov-report/test-utils/order/models/product.ts.html +1 -1
  132. package/coverage/lcov-report/test-utils/order/models/utm-source.ts.html +1 -1
  133. package/coverage/lcov-report/test-utils/order-more/entities.ts.html +1 -1
  134. package/coverage/lcov-report/test-utils/order-more/index.html +1 -1
  135. package/coverage/lcov-report/test-utils/order-more/models/actual-product-variant.ts.html +1 -1
  136. package/coverage/lcov-report/test-utils/order-more/models/color.ts.html +1 -1
  137. package/coverage/lcov-report/test-utils/order-more/models/customer.ts.html +1 -1
  138. package/coverage/lcov-report/test-utils/order-more/models/gender.ts.html +1 -1
  139. package/coverage/lcov-report/test-utils/order-more/models/index.html +1 -1
  140. package/coverage/lcov-report/test-utils/order-more/models/inventory-level.ts.html +1 -1
  141. package/coverage/lcov-report/test-utils/order-more/models/line-item.ts.html +1 -1
  142. package/coverage/lcov-report/test-utils/order-more/models/order.ts.html +1 -1
  143. package/coverage/lcov-report/test-utils/order-more/models/parcel-event.ts.html +1 -1
  144. package/coverage/lcov-report/test-utils/order-more/models/parcel-line-item.ts.html +1 -1
  145. package/coverage/lcov-report/test-utils/order-more/models/parcel.ts.html +1 -1
  146. package/coverage/lcov-report/test-utils/order-more/models/physical-address.ts.html +1 -1
  147. package/coverage/lcov-report/test-utils/order-more/models/product-variant-image.ts.html +1 -1
  148. package/coverage/lcov-report/test-utils/order-more/models/product-variant.ts.html +1 -1
  149. package/coverage/lcov-report/test-utils/order-more/models/product.ts.html +1 -1
  150. package/coverage/lcov-report/test-utils/order-more/models/refund.ts.html +1 -1
  151. package/coverage/lcov-report/test-utils/order-more/models/shipment-actual-product-variant.ts.html +1 -1
  152. package/coverage/lcov-report/test-utils/order-more/models/shipment.ts.html +1 -1
  153. package/coverage/lcov-report/test-utils/order-more/models/size.ts.html +1 -1
  154. package/coverage/lcov-report/test-utils/order-more/models/utm-medium.ts.html +1 -1
  155. package/coverage/lcov-report/test-utils/order-more/models/utm-source.ts.html +1 -1
  156. package/coverage/lcov-report/test-utils/six/entities.ts.html +1 -1
  157. package/coverage/lcov-report/test-utils/six/index.html +1 -1
  158. package/coverage/lcov-report/test-utils/six/models/customer.ts.html +1 -1
  159. package/coverage/lcov-report/test-utils/six/models/index.html +1 -1
  160. package/coverage/lcov-report/test-utils/six/models/line-item.ts.html +1 -1
  161. package/coverage/lcov-report/test-utils/six/models/order.ts.html +1 -1
  162. package/coverage/lcov-report/test-utils/six/models/parcel-line-item.ts.html +1 -1
  163. package/coverage/lcov-report/test-utils/six/models/parcel.ts.html +1 -1
  164. package/coverage/lcov-report/test-utils/thirteen/entities.ts.html +1 -1
  165. package/coverage/lcov-report/test-utils/thirteen/index.html +1 -1
  166. package/coverage/lcov-report/test-utils/thirteen/models/audience.ts.html +1 -1
  167. package/coverage/lcov-report/test-utils/thirteen/models/brand.ts.html +1 -1
  168. package/coverage/lcov-report/test-utils/thirteen/models/category.ts.html +1 -1
  169. package/coverage/lcov-report/test-utils/thirteen/models/index.html +1 -1
  170. package/coverage/lcov-report/test-utils/thirteen/models/member.ts.html +1 -1
  171. package/coverage/lcov-report/test-utils/thirteen/models/passion.ts.html +1 -1
  172. package/coverage/lcov-report/test-utils/thirteen/models/product.ts.html +1 -1
  173. package/coverage/lcov-report/test-utils/thirteen/models/recommendation-audience.ts.html +1 -1
  174. package/coverage/lcov-report/test-utils/thirteen/models/recommendation.ts.html +1 -1
  175. package/coverage/lcov-report/test-utils/three/index.html +1 -1
  176. package/coverage/lcov-report/test-utils/three/results.js.html +1 -1
  177. package/coverage/lcov-report/test-utils/twelve/entities.ts.html +1 -1
  178. package/coverage/lcov-report/test-utils/twelve/index.html +1 -1
  179. package/coverage/lcov-report/test-utils/twelve/models/index.html +1 -1
  180. package/coverage/lcov-report/test-utils/twelve/models/member.ts.html +1 -1
  181. package/coverage/lcov-report/test-utils/twelve/models/prompt.ts.html +1 -1
  182. package/coverage/lcov-report/test-utils/two/index.html +1 -1
  183. package/coverage/lcov-report/test-utils/two/results.js.html +1 -1
  184. package/coverage/lcov.info +882 -747
  185. package/dist/example/data-access/person.d.ts +1 -1
  186. package/dist/src/core.d.ts +7 -7
  187. package/dist/src/core.js +11 -4
  188. package/dist/src/core.spec.js +15 -0
  189. package/dist/src/driver-integrations/index.d.ts +5 -5
  190. package/dist/src/orm.d.ts +8 -8
  191. package/dist/test-utils/fourteen/entities.d.ts +6 -0
  192. package/dist/test-utils/fourteen/entities.js +6 -0
  193. package/dist/test-utils/fourteen/entities.ts +3 -0
  194. package/dist/test-utils/fourteen/models/customer.d.ts +19 -0
  195. package/dist/test-utils/fourteen/models/customer.js +30 -0
  196. package/dist/test-utils/fourteen/models/customer.ts +36 -0
  197. package/dist/test-utils/fourteen/models/person.d.ts +17 -0
  198. package/dist/test-utils/fourteen/models/person.js +23 -0
  199. package/dist/test-utils/fourteen/models/person.ts +27 -0
  200. package/dist/test-utils/fourteen/results.json +8 -0
  201. package/example/data-access/person.ts +1 -1
  202. package/package.json +5 -4
  203. package/src/core.spec.ts +15 -0
  204. package/src/core.ts +15 -8
  205. package/src/driver-integrations/index.ts +5 -5
  206. package/src/driver-integrations/pgp.ts +5 -5
  207. package/src/orm.ts +25 -16
  208. package/test-utils/fourteen/entities.ts +3 -0
  209. package/test-utils/fourteen/models/customer.ts +36 -0
  210. package/test-utils/fourteen/models/person.ts +27 -0
  211. package/test-utils/fourteen/results.json +8 -0
@@ -1,2 +1,2 @@
1
1
  import { Person } from '../models/person';
2
- export declare const getPerson: (id: number) => Person;
2
+ export declare const getPerson: (id: number) => Promise<Person>;
@@ -4,20 +4,20 @@ export interface IColumnData {
4
4
  references?: IModelClass;
5
5
  primaryKey?: boolean;
6
6
  }
7
- export declare type IColumn = IColumnData | string;
8
- export declare type IColumns = Array<IColumn> | (() => Array<IColumn>);
7
+ export type IColumn = IColumnData | string;
8
+ export type IColumns = Array<IColumn> | (() => Array<IColumn>);
9
9
  export interface IColumnInternalData {
10
10
  column: string;
11
11
  property: string;
12
12
  references?: IModelClass;
13
13
  primaryKey: boolean;
14
14
  }
15
- export declare type IColumnInternal = IColumnInternalData;
16
- export declare type IColumnsInternal = Array<IColumnInternal>;
15
+ export type IColumnInternal = IColumnInternalData;
16
+ export type IColumnsInternal = Array<IColumnInternal>;
17
17
  export interface IModel {
18
18
  [key: string]: any;
19
19
  }
20
- export declare type IModelClass = new (props: any) => IModel;
20
+ export type IModelClass = new (props: any) => IModel;
21
21
  export interface ICollection<T extends IModel> {
22
22
  models: Array<T>;
23
23
  }
@@ -29,7 +29,7 @@ export interface IEntity<T extends IModel> {
29
29
  Model: new (props: any) => T;
30
30
  Collection: new ({ models }: any) => ICollection<T>;
31
31
  }
32
- export declare type IEntities<T extends IModel> = Array<IEntity<T>>;
32
+ export type IEntities<T extends IModel> = Array<IEntity<T>>;
33
33
  export interface IEntityInternal<T extends IModel> {
34
34
  tableName: string;
35
35
  displayName: string;
@@ -45,7 +45,7 @@ export interface IEntityInternal<T extends IModel> {
45
45
  selectColumnsClause: string;
46
46
  getPkId: (model: IModel) => string;
47
47
  }
48
- export declare type IEntitiesInternal<T extends IModel> = Array<IEntityInternal<T>>;
48
+ export type IEntitiesInternal<T extends IModel> = Array<IEntityInternal<T>>;
49
49
  export interface ICreateCoreOptions {
50
50
  entities: IEntities<IModel>;
51
51
  }
package/dist/src/core.js CHANGED
@@ -138,12 +138,19 @@ const createCore = ({ entities: externalEntities }) => {
138
138
  ...nodes.slice(0, indexOfOldestParent + 1).reverse()
139
139
  ];
140
140
  const nodeItPointsTo = parentHeirarchy.find((parent) => {
141
- const index = Object.values(getEntityByModel(model).references).indexOf(parent.constructor);
142
- if (index === -1) {
141
+ const indexes = Object.values(getEntityByModel(model).references)
142
+ .map((x, i) => x === parent.constructor ? i : null)
143
+ .filter((x, i) => x != null);
144
+ if (!indexes.length) {
143
145
  return false;
144
146
  }
145
- const property = Object.keys(getEntityByModel(model).references)[index];
146
- return model[property] === parent.id;
147
+ for (const index of indexes) {
148
+ const property = Object.keys(getEntityByModel(model).references)[index];
149
+ if (model[property] === parent.id) {
150
+ return true;
151
+ }
152
+ }
153
+ return false;
147
154
  });
148
155
  if (isNodeAlreadySeen) {
149
156
  if (nodeItPointsTo && !nodePointingToIt) {
@@ -10,6 +10,7 @@ const entities_5 = require("../test-utils/five/entities");
10
10
  const entities_6 = require("../test-utils/six/entities");
11
11
  const entities_7 = require("../test-utils/twelve/entities");
12
12
  const entities_8 = require("../test-utils/thirteen/entities");
13
+ const entities_9 = require("../test-utils/fourteen/entities");
13
14
  const article_1 = require("../test-utils/blog/models/article");
14
15
  const two = require('../test-utils/two/results');
15
16
  const three = require('../test-utils/three/results');
@@ -24,6 +25,7 @@ const ten = require('../test-utils/ten/results.json');
24
25
  const eleven = require('../test-utils/eleven/results.json');
25
26
  const twelve = require('../test-utils/twelve/results.json');
26
27
  const thirteen = require('../test-utils/thirteen/results.json');
28
+ const fourteen = require('../test-utils/fourteen/results.json');
27
29
  describe('createFromDatabase', () => {
28
30
  test('multiple rows reduce to one nested object (with all one-to-one or one-to-many tables)', () => {
29
31
  const core = (0, core_1.createCore)({ entities: entities_1.entities });
@@ -575,6 +577,19 @@ describe('createFromDatabase', () => {
575
577
  expect(member === null || member === void 0 ? void 0 : member.recommendations.models[3].category.id).toEqual(4);
576
578
  expect(member === null || member === void 0 ? void 0 : member.recommendations.models[3].recommendationAudiences.models[0].audience.id).toEqual(1);
577
579
  });
580
+ // Issue occcurs in nestClump
581
+ // Problem when a table has two columns which reference the same other table
582
+ test('14', () => {
583
+ var _a;
584
+ const core = (0, core_1.createCore)({ entities: entities_9.entities });
585
+ const persons = core.createFromDatabase(fourteen);
586
+ expect(persons === null || persons === void 0 ? void 0 : persons.models.length).toEqual(1);
587
+ expect(persons.models[0].id).toEqual(67);
588
+ // Known issue: A reference always uses the model's name,
589
+ // instead of some version of the column's name
590
+ expect((_a = persons.models[0].customers) === null || _a === void 0 ? void 0 : _a.models.length).toEqual(1);
591
+ expect(persons.models[0].customers.models[0].id).toEqual(4);
592
+ });
578
593
  });
579
594
  describe('createOneFromDatabase', () => {
580
595
  test('reduces to one', () => {
@@ -6,9 +6,9 @@ export interface ICreateForDriverOptions {
6
6
  }
7
7
  export interface ICoreIntegratedDriver extends ICore {
8
8
  db: any;
9
- one: <T extends IModel>(query: string, values?: object, errorHandler?: (err: Error) => never) => T;
10
- oneOrNone: <T extends IModel>(query: string, values?: object, errorHandler?: (err: Error) => never) => T | void;
11
- many: <T extends ICollection<IModel>>(query: string, values?: object, errorHandler?: (err: Error) => never) => T;
12
- any: <T extends ICollection<IModel>>(query: string, values?: object, errorHandler?: (err: Error) => never) => T | void;
13
- none: (query: string, values?: object, errorHandler?: (err: Error) => never) => void;
9
+ one: <T extends IModel>(query: string, values?: object, errorHandler?: (err: Error) => never) => Promise<T>;
10
+ oneOrNone: <T extends IModel>(query: string, values?: object, errorHandler?: (err: Error) => never) => Promise<T | void>;
11
+ many: <T extends ICollection<IModel>>(query: string, values?: object, errorHandler?: (err: Error) => never) => Promise<T>;
12
+ any: <T extends ICollection<IModel>>(query: string, values?: object, errorHandler?: (err: Error) => never) => Promise<T | void>;
13
+ none: (query: string, values?: object, errorHandler?: (err: Error) => never) => Promise<void>;
14
14
  }
package/dist/src/orm.d.ts CHANGED
@@ -6,16 +6,16 @@ export interface ICreateOptions {
6
6
  logError?: (err: Error) => never;
7
7
  }
8
8
  export interface IPureORM extends ICoreIntegratedDriver {
9
- getMatching: <T extends IModel>(model: T) => T;
10
- getOneOrNoneMatching: <T extends IModel>(model: T) => T | void;
11
- getAnyMatching: <T extends ICollection<IModel>>(model: IModel) => T | void;
12
- getAllMatching: <T extends ICollection<IModel>>(model: IModel) => T;
13
- create: <T extends IModel>(model: T) => T;
9
+ getMatching: <T extends IModel>(model: T) => Promise<T>;
10
+ getOneOrNoneMatching: <T extends IModel>(model: T) => Promise<T | void>;
11
+ getAnyMatching: <T extends ICollection<IModel>>(model: IModel) => Promise<T | void>;
12
+ getAllMatching: <T extends ICollection<IModel>>(model: IModel) => Promise<T>;
13
+ create: <T extends IModel>(model: T) => Promise<T>;
14
14
  update: <T extends IModel>(model: T, options: {
15
15
  on: string;
16
- }) => T;
17
- delete: <T extends IModel>(model: T) => void;
18
- deleteMatching: <T extends IModel>(model: T) => void;
16
+ }) => Promise<T>;
17
+ delete: <T extends IModel>(model: T) => Promise<void>;
18
+ deleteMatching: <T extends IModel>(model: T) => Promise<void>;
19
19
  getSqlInsertParts: (model: IModel) => {
20
20
  columns: string;
21
21
  values: Array<string>;
@@ -0,0 +1,6 @@
1
+ export declare const entities: {
2
+ tableName: string;
3
+ columns: import("../../src/core").IColumn[];
4
+ Model: typeof import("./models/person").Person;
5
+ Collection: typeof import("./models/person").Persons;
6
+ }[];
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.entities = void 0;
4
+ const person_1 = require("./models/person");
5
+ const customer_1 = require("./models/customer");
6
+ exports.entities = [person_1.personEntity, customer_1.customerEntity];
@@ -0,0 +1,3 @@
1
+ import { personEntity } from './models/person';
2
+ import { customerEntity } from './models/customer';
3
+ export const entities = [personEntity, customerEntity];
@@ -0,0 +1,19 @@
1
+ import { IModel, ICollection, IColumns } from '../../../src/index';
2
+ export declare const tableName: string;
3
+ export declare const columns: IColumns;
4
+ export declare class Customer implements IModel {
5
+ id: number;
6
+ lockedToAffiliateId: number;
7
+ lockedToSalespersonId: number;
8
+ constructor(props: any);
9
+ }
10
+ export declare class Customers implements ICollection<Customer> {
11
+ models: Array<Customer>;
12
+ constructor({ models }: any);
13
+ }
14
+ export declare const customerEntity: {
15
+ tableName: string;
16
+ columns: import("../../../src/core").IColumn[];
17
+ Model: typeof Customer;
18
+ Collection: typeof Customers;
19
+ };
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.customerEntity = exports.Customers = exports.Customer = exports.columns = exports.tableName = void 0;
4
+ const person_1 = require("./person");
5
+ exports.tableName = 'customer';
6
+ exports.columns = [
7
+ 'id',
8
+ { column: 'locked_to_affiliate_id', references: person_1.Person },
9
+ { column: 'locked_to_salesperson_id', references: person_1.Person }
10
+ ];
11
+ class Customer {
12
+ constructor(props) {
13
+ this.id = props.id;
14
+ this.lockedToAffiliateId = props.lockedToAffiliateId;
15
+ this.lockedToSalespersonId = props.lockedToSalespersonId;
16
+ }
17
+ }
18
+ exports.Customer = Customer;
19
+ class Customers {
20
+ constructor({ models }) {
21
+ this.models = models;
22
+ }
23
+ }
24
+ exports.Customers = Customers;
25
+ exports.customerEntity = {
26
+ tableName: exports.tableName,
27
+ columns: exports.columns,
28
+ Model: Customer,
29
+ Collection: Customers
30
+ };
@@ -0,0 +1,36 @@
1
+ import { IModel, ICollection, IColumns } from '../../../src/index';
2
+ import { Person } from './person';
3
+
4
+ export const tableName: string = 'customer';
5
+
6
+ export const columns: IColumns = [
7
+ 'id',
8
+ { column: 'locked_to_affiliate_id', references: Person },
9
+ { column: 'locked_to_salesperson_id', references: Person }
10
+ ];
11
+
12
+ export class Customer implements IModel {
13
+ id: number;
14
+ lockedToAffiliateId: number;
15
+ lockedToSalespersonId: number;
16
+
17
+ constructor(props: any) {
18
+ this.id = props.id;
19
+ this.lockedToAffiliateId = props.lockedToAffiliateId;
20
+ this.lockedToSalespersonId = props.lockedToSalespersonId;
21
+ }
22
+ }
23
+
24
+ export class Customers implements ICollection<Customer> {
25
+ models: Array<Customer>;
26
+ constructor({ models }: any) {
27
+ this.models = models;
28
+ }
29
+ }
30
+
31
+ export const customerEntity = {
32
+ tableName,
33
+ columns,
34
+ Model: Customer,
35
+ Collection: Customers
36
+ };
@@ -0,0 +1,17 @@
1
+ import { IModel, ICollection, IColumns } from '../../../src/index';
2
+ export declare const tableName: string;
3
+ export declare const columns: IColumns;
4
+ export declare class Person implements IModel {
5
+ id: number;
6
+ constructor(props: any);
7
+ }
8
+ export declare class Persons implements ICollection<Person> {
9
+ models: Array<Person>;
10
+ constructor({ models }: any);
11
+ }
12
+ export declare const personEntity: {
13
+ tableName: string;
14
+ columns: import("../../../src/core").IColumn[];
15
+ Model: typeof Person;
16
+ Collection: typeof Persons;
17
+ };
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.personEntity = exports.Persons = exports.Person = exports.columns = exports.tableName = void 0;
4
+ exports.tableName = 'person';
5
+ exports.columns = ['id'];
6
+ class Person {
7
+ constructor(props) {
8
+ this.id = props.id;
9
+ }
10
+ }
11
+ exports.Person = Person;
12
+ class Persons {
13
+ constructor({ models }) {
14
+ this.models = models;
15
+ }
16
+ }
17
+ exports.Persons = Persons;
18
+ exports.personEntity = {
19
+ tableName: exports.tableName,
20
+ columns: exports.columns,
21
+ Model: Person,
22
+ Collection: Persons
23
+ };
@@ -0,0 +1,27 @@
1
+ import { IModel, ICollection, IColumns } from '../../../src/index';
2
+
3
+ export const tableName: string = 'person';
4
+
5
+ export const columns: IColumns = ['id'];
6
+
7
+ export class Person implements IModel {
8
+ id: number;
9
+
10
+ constructor(props: any) {
11
+ this.id = props.id;
12
+ }
13
+ }
14
+
15
+ export class Persons implements ICollection<Person> {
16
+ models: Array<Person>;
17
+ constructor({ models }: any) {
18
+ this.models = models;
19
+ }
20
+ }
21
+
22
+ export const personEntity = {
23
+ tableName,
24
+ columns,
25
+ Model: Person,
26
+ Collection: Persons
27
+ };
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "person#id": 67,
4
+ "customer#id": 4,
5
+ "customer#locked_to_affiliate_id": null,
6
+ "customer#locked_to_salesperson_id": 67
7
+ }
8
+ ]
@@ -1,7 +1,7 @@
1
1
  import orm from '../factories/orm';
2
2
  import { Person } from '../models/person';
3
3
 
4
- export const getPerson = (id: number): Person => {
4
+ export const getPerson = (id: number): Promise<Person> => {
5
5
  const query = `
6
6
  SELECT
7
7
  ${orm.tables.person.columns},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pure-orm",
3
- "version": "4.0.1",
3
+ "version": "4.0.3",
4
4
  "main": "dist/src/index.js",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "engines": {
@@ -28,13 +28,14 @@
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/express": "^4.17.13",
31
- "eslint": "^2.8.0",
31
+ "eslint": "^8.38.0",
32
+ "@babel/eslint-parser": "^7.21.3",
32
33
  "express": "^4.18.1",
33
34
  "jest": "^24.8.0",
34
- "np": "^5.0.1",
35
+ "np": "^10.2.0",
35
36
  "pg-promise": "^10.11.1",
36
37
  "prettier": "^2.6.2",
37
- "typescript": "^4.6.3"
38
+ "typescript": "^5.8.3"
38
39
  },
39
40
  "jest": {
40
41
  "coverageDirectory": "./coverage/",
package/src/core.spec.ts CHANGED
@@ -8,6 +8,7 @@ import { entities as fiveEntities } from '../test-utils/five/entities';
8
8
  import { entities as sixEntities } from '../test-utils/six/entities';
9
9
  import { entities as twelveEntities } from '../test-utils/twelve/entities';
10
10
  import { entities as thirteenEntities } from '../test-utils/thirteen/entities';
11
+ import { entities as fourteenEntities } from '../test-utils/fourteen/entities';
11
12
  import { Articles } from '../test-utils/blog/models/article';
12
13
  const two = require('../test-utils/two/results');
13
14
  const three = require('../test-utils/three/results');
@@ -22,6 +23,7 @@ const ten = require('../test-utils/ten/results.json');
22
23
  const eleven = require('../test-utils/eleven/results.json');
23
24
  const twelve = require('../test-utils/twelve/results.json');
24
25
  const thirteen = require('../test-utils/thirteen/results.json');
26
+ const fourteen = require('../test-utils/fourteen/results.json');
25
27
 
26
28
  describe('createFromDatabase', () => {
27
29
  test('multiple rows reduce to one nested object (with all one-to-one or one-to-many tables)', () => {
@@ -1066,6 +1068,19 @@ describe('createFromDatabase', () => {
1066
1068
  .audience.id
1067
1069
  ).toEqual(1);
1068
1070
  });
1071
+
1072
+ // Issue occcurs in nestClump
1073
+ // Problem when a table has two columns which reference the same other table
1074
+ test('14', () => {
1075
+ const core = createCore({ entities: fourteenEntities });
1076
+ const persons = core.createFromDatabase(fourteen);
1077
+ expect(persons?.models.length).toEqual(1);
1078
+ expect(persons.models[0].id).toEqual(67);
1079
+ // Known issue: A reference always uses the model's name,
1080
+ // instead of some version of the column's name
1081
+ expect(persons.models[0].customers?.models.length).toEqual(1);
1082
+ expect(persons.models[0].customers.models[0].id).toEqual(4);
1083
+ });
1069
1084
  });
1070
1085
 
1071
1086
  describe('createOneFromDatabase', () => {
package/src/core.ts CHANGED
@@ -292,16 +292,23 @@ export const createCore = ({
292
292
  ...nodes.slice(0, indexOfOldestParent + 1).reverse()
293
293
  ];
294
294
  const nodeItPointsTo = parentHeirarchy.find((parent) => {
295
- const index = Object.values(
296
- getEntityByModel(model).references
297
- ).indexOf(parent.constructor);
298
- if (index === -1) {
295
+ const indexes = Object.values(getEntityByModel(model).references)
296
+ .map((x: IModelClass, i: number) =>
297
+ x === parent.constructor ? i : null
298
+ )
299
+ .filter((x: number | null, i) => x != null) as Array<number>;
300
+ if (!indexes.length) {
299
301
  return false;
300
302
  }
301
- const property = Object.keys(getEntityByModel(model).references)[
302
- index
303
- ];
304
- return model[property as keyof typeof model] === parent.id;
303
+ for (const index of indexes) {
304
+ const property = Object.keys(getEntityByModel(model).references)[
305
+ index
306
+ ];
307
+ if (model[property] === parent.id) {
308
+ return true;
309
+ }
310
+ }
311
+ return false;
305
312
  });
306
313
  if (isNodeAlreadySeen) {
307
314
  if (nodeItPointsTo && !nodePointingToIt) {
@@ -26,33 +26,33 @@ export interface ICoreIntegratedDriver extends ICore {
26
26
  query: string,
27
27
  values?: object,
28
28
  errorHandler?: (err: Error) => never
29
- ) => T;
29
+ ) => Promise<T>;
30
30
 
31
31
  // Execute a query returning either single model or undefined, or throws.
32
32
  oneOrNone: <T extends IModel>(
33
33
  query: string,
34
34
  values?: object,
35
35
  errorHandler?: (err: Error) => never
36
- ) => T | void;
36
+ ) => Promise<T | void>;
37
37
 
38
38
  // Execute a query returning a Collection with at least one model, or throws.
39
39
  many: <T extends ICollection<IModel>>(
40
40
  query: string,
41
41
  values?: object,
42
42
  errorHandler?: (err: Error) => never
43
- ) => T;
43
+ ) => Promise<T>;
44
44
 
45
45
  // Execute a query returning a Collection.
46
46
  any: <T extends ICollection<IModel>>(
47
47
  query: string,
48
48
  values?: object,
49
49
  errorHandler?: (err: Error) => never
50
- ) => T | void;
50
+ ) => Promise<T | void>;
51
51
 
52
52
  // Execute a query returning null.
53
53
  none: (
54
54
  query: string,
55
55
  values?: object,
56
56
  errorHandler?: (err: Error) => never
57
- ) => void;
57
+ ) => Promise<void>;
58
58
  }
@@ -23,7 +23,7 @@ export const createForPGP = ({
23
23
  query: string,
24
24
  values?: object,
25
25
  errorHandler = defaultErrorHandler
26
- ): T => {
26
+ ): Promise<T> => {
27
27
  return db
28
28
  .many(query, values)
29
29
  .then((rows: any) => core.createOneFromDatabase(rows))
@@ -34,7 +34,7 @@ export const createForPGP = ({
34
34
  query: string,
35
35
  values?: object,
36
36
  errorHandler = defaultErrorHandler
37
- ): T | void => {
37
+ ): Promise<T | void> => {
38
38
  return db
39
39
  .any(query, values)
40
40
  .then((rows: any) => core.createOneOrNoneFromDatabase(rows))
@@ -45,7 +45,7 @@ export const createForPGP = ({
45
45
  query: string,
46
46
  values?: object,
47
47
  errorHandler = defaultErrorHandler
48
- ): T => {
48
+ ): Promise<T> => {
49
49
  return db
50
50
  .any(query, values)
51
51
  .then((rows: any) => core.createManyFromDatabase(rows))
@@ -56,7 +56,7 @@ export const createForPGP = ({
56
56
  query: string,
57
57
  values?: object,
58
58
  errorHandler = defaultErrorHandler
59
- ): T | void => {
59
+ ): Promise<T | void> => {
60
60
  return db
61
61
  .result(query, values)
62
62
  .then((result: any) =>
@@ -72,7 +72,7 @@ export const createForPGP = ({
72
72
  query: string,
73
73
  values?: object,
74
74
  errorHandler = defaultErrorHandler
75
- ): void => {
75
+ ): Promise<void> => {
76
76
  return db
77
77
  .none(query, values)
78
78
  .then(() => null)
package/src/orm.ts CHANGED
@@ -20,14 +20,16 @@ export interface IPureORM extends ICoreIntegratedDriver {
20
20
  * if you want to write these in your data access layer yourself.
21
21
  */
22
22
 
23
- getMatching: <T extends IModel>(model: T) => T;
24
- getOneOrNoneMatching: <T extends IModel>(model: T) => T | void;
25
- getAnyMatching: <T extends ICollection<IModel>>(model: IModel) => T | void;
26
- getAllMatching: <T extends ICollection<IModel>>(model: IModel) => T;
27
- create: <T extends IModel>(model: T) => T;
28
- update: <T extends IModel>(model: T, options: { on: string }) => T;
29
- delete: <T extends IModel>(model: T) => void;
30
- deleteMatching: <T extends IModel>(model: T) => void;
23
+ getMatching: <T extends IModel>(model: T) => Promise<T>;
24
+ getOneOrNoneMatching: <T extends IModel>(model: T) => Promise<T | void>;
25
+ getAnyMatching: <T extends ICollection<IModel>>(
26
+ model: IModel
27
+ ) => Promise<T | void>;
28
+ getAllMatching: <T extends ICollection<IModel>>(model: IModel) => Promise<T>;
29
+ create: <T extends IModel>(model: T) => Promise<T>;
30
+ update: <T extends IModel>(model: T, options: { on: string }) => Promise<T>;
31
+ delete: <T extends IModel>(model: T) => Promise<void>;
32
+ deleteMatching: <T extends IModel>(model: T) => Promise<void>;
31
33
 
32
34
  /* ------------------------------------------------------------------------*/
33
35
  /* Helper Utility Functions -----------------------------------------------*/
@@ -230,7 +232,7 @@ export const create = ({
230
232
  /* ------------------------------------------------------------------------*/
231
233
 
232
234
  // Standard create
233
- const create = <T extends IModel>(model: T): T => {
235
+ const create = <T extends IModel>(model: T): Promise<T> => {
234
236
  const { columns, values, valuesVar } = getSqlInsertParts(model);
235
237
  const query = `
236
238
  INSERT INTO "${orm.getEntityByModel(model).tableName}" ( ${columns} )
@@ -241,7 +243,10 @@ export const create = ({
241
243
  };
242
244
 
243
245
  // Standard update
244
- const update = <T extends IModel>(model: T, { on = 'id' } = {}): T => {
246
+ const update = <T extends IModel>(
247
+ model: T,
248
+ { on = 'id' } = {}
249
+ ): Promise<T> => {
245
250
  const { clause, idVar, values } = getSqlUpdateParts(model, on);
246
251
  const query = `
247
252
  UPDATE "${orm.getEntityByModel(model).tableName}"
@@ -255,7 +260,7 @@ export const create = ({
255
260
  };
256
261
 
257
262
  // Standard delete
258
- const _delete = <T extends IModel>(model: T): void => {
263
+ const _delete = <T extends IModel>(model: T): Promise<void> => {
259
264
  const id = (model as any).id;
260
265
  const query = `
261
266
  DELETE FROM "${orm.getEntityByModel(model).tableName}"
@@ -264,7 +269,7 @@ export const create = ({
264
269
  return orm.none(query, { id });
265
270
  };
266
271
 
267
- const deleteMatching = <T extends IModel>(model: T) => {
272
+ const deleteMatching = <T extends IModel>(model: T): Promise<void> => {
268
273
  const { whereClause, values } = getMatchingParts(model);
269
274
  const query = `
270
275
  DELETE FROM "${orm.getEntityByModel(model).tableName}"
@@ -273,7 +278,7 @@ export const create = ({
273
278
  return orm.none(query, values);
274
279
  };
275
280
 
276
- const getMatching = <T extends IModel>(model: T): T => {
281
+ const getMatching = <T extends IModel>(model: T): Promise<T> => {
277
282
  const { whereClause, values } = getMatchingParts(model);
278
283
  const query = `
279
284
  SELECT ${orm.getEntityByModel(model).selectColumnsClause}
@@ -283,7 +288,9 @@ export const create = ({
283
288
  return orm.one<T>(query, values);
284
289
  };
285
290
 
286
- const getOneOrNoneMatching = <T extends IModel>(model: T): T | void => {
291
+ const getOneOrNoneMatching = <T extends IModel>(
292
+ model: T
293
+ ): Promise<T | void> => {
287
294
  const { whereClause, values } = getMatchingParts(model);
288
295
  const query = `
289
296
  SELECT ${orm.getEntityByModel(model).selectColumnsClause}
@@ -295,7 +302,7 @@ export const create = ({
295
302
 
296
303
  const getAnyMatching = <T extends ICollection<IModel>>(
297
304
  model: IModel
298
- ): T | void => {
305
+ ): Promise<T | void> => {
299
306
  const { whereClause, values } = getMatchingParts(model);
300
307
  const query = `
301
308
  SELECT ${orm.getEntityByModel(model).selectColumnsClause}
@@ -305,7 +312,9 @@ export const create = ({
305
312
  return orm.any<T>(query, values);
306
313
  };
307
314
 
308
- const getAllMatching = <T extends ICollection<IModel>>(model: IModel): T => {
315
+ const getAllMatching = <T extends ICollection<IModel>>(
316
+ model: IModel
317
+ ): Promise<T> => {
309
318
  const { whereClause, values } = getMatchingParts(model);
310
319
  const query = `
311
320
  SELECT ${orm.getEntityByModel(model).selectColumnsClause}
@@ -0,0 +1,3 @@
1
+ import { personEntity } from './models/person';
2
+ import { customerEntity } from './models/customer';
3
+ export const entities = [personEntity, customerEntity];