@abedmurrar/objection 0.0.0-stage → 4.0.0-alpha.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.
Files changed (190) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +69 -2
  3. package/lib/.eslintrc.json +8 -0
  4. package/lib/initialize.js +14 -0
  5. package/lib/model/AjvValidator.js +325 -0
  6. package/lib/model/Model.js +942 -0
  7. package/lib/model/ModifierNotFoundError.js +12 -0
  8. package/lib/model/NotFoundError.js +23 -0
  9. package/lib/model/RelationDoesNotExistError.js +14 -0
  10. package/lib/model/ValidationError.js +54 -0
  11. package/lib/model/Validator.js +26 -0
  12. package/lib/model/getModel.js +9 -0
  13. package/lib/model/graph/ModelGraph.js +80 -0
  14. package/lib/model/graph/ModelGraphBuilder.js +241 -0
  15. package/lib/model/graph/ModelGraphEdge.js +52 -0
  16. package/lib/model/graph/ModelGraphNode.js +240 -0
  17. package/lib/model/inheritModel.js +28 -0
  18. package/lib/model/modelBindKnex.js +83 -0
  19. package/lib/model/modelClone.js +121 -0
  20. package/lib/model/modelColPropMap.js +34 -0
  21. package/lib/model/modelId.js +62 -0
  22. package/lib/model/modelJsonAttributes.js +92 -0
  23. package/lib/model/modelParseRelations.js +82 -0
  24. package/lib/model/modelQueryProps.js +147 -0
  25. package/lib/model/modelSet.js +136 -0
  26. package/lib/model/modelTableMetadata.js +83 -0
  27. package/lib/model/modelToJson.js +187 -0
  28. package/lib/model/modelUtils.js +47 -0
  29. package/lib/model/modelValidate.js +48 -0
  30. package/lib/model/modelValues.js +126 -0
  31. package/lib/model/modelVisitor.js +41 -0
  32. package/lib/objection.js +114 -0
  33. package/lib/queryBuilder/FunctionBuilder.js +339 -0
  34. package/lib/queryBuilder/InternalOptions.js +29 -0
  35. package/lib/queryBuilder/JoinBuilder.js +157 -0
  36. package/lib/queryBuilder/QueryBuilder.js +1398 -0
  37. package/lib/queryBuilder/QueryBuilderBase.js +884 -0
  38. package/lib/queryBuilder/QueryBuilderContext.js +27 -0
  39. package/lib/queryBuilder/QueryBuilderContextBase.js +35 -0
  40. package/lib/queryBuilder/QueryBuilderOperationSupport.js +558 -0
  41. package/lib/queryBuilder/QueryBuilderUserContext.js +31 -0
  42. package/lib/queryBuilder/RawBuilder.js +93 -0
  43. package/lib/queryBuilder/ReferenceBuilder.js +284 -0
  44. package/lib/queryBuilder/RelationExpression.js +431 -0
  45. package/lib/queryBuilder/StaticHookArguments.js +134 -0
  46. package/lib/queryBuilder/ValueBuilder.js +127 -0
  47. package/lib/queryBuilder/expressions.js +151 -0
  48. package/lib/queryBuilder/functions/mysql.js +817 -0
  49. package/lib/queryBuilder/graph/GraphAction.js +69 -0
  50. package/lib/queryBuilder/graph/GraphData.js +14 -0
  51. package/lib/queryBuilder/graph/GraphFetcher.js +191 -0
  52. package/lib/queryBuilder/graph/GraphNodeDbExistence.js +184 -0
  53. package/lib/queryBuilder/graph/GraphOperation.js +27 -0
  54. package/lib/queryBuilder/graph/GraphOptions.js +207 -0
  55. package/lib/queryBuilder/graph/GraphUpsert.js +305 -0
  56. package/lib/queryBuilder/graph/delete/GraphDelete.js +20 -0
  57. package/lib/queryBuilder/graph/delete/GraphDeleteAction.js +74 -0
  58. package/lib/queryBuilder/graph/insert/GraphInsert.js +145 -0
  59. package/lib/queryBuilder/graph/insert/GraphInsertAction.js +225 -0
  60. package/lib/queryBuilder/graph/insert/JoinRowGraphInsertAction.js +92 -0
  61. package/lib/queryBuilder/graph/patch/GraphPatch.js +20 -0
  62. package/lib/queryBuilder/graph/patch/GraphPatchAction.js +258 -0
  63. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsert.js +31 -0
  64. package/lib/queryBuilder/graph/recursiveUpsert/GraphRecursiveUpsertAction.js +126 -0
  65. package/lib/queryBuilder/join/JoinResultColumn.js +23 -0
  66. package/lib/queryBuilder/join/JoinResultParser.js +119 -0
  67. package/lib/queryBuilder/join/RelationJoiner.js +341 -0
  68. package/lib/queryBuilder/join/TableNode.js +163 -0
  69. package/lib/queryBuilder/join/TableTree.js +85 -0
  70. package/lib/queryBuilder/join/utils.js +25 -0
  71. package/lib/queryBuilder/operations/DelegateOperation.js +141 -0
  72. package/lib/queryBuilder/operations/DeleteOperation.js +51 -0
  73. package/lib/queryBuilder/operations/FindByIdOperation.js +37 -0
  74. package/lib/queryBuilder/operations/FindByIdsOperation.js +29 -0
  75. package/lib/queryBuilder/operations/FindOperation.js +164 -0
  76. package/lib/queryBuilder/operations/FirstOperation.js +27 -0
  77. package/lib/queryBuilder/operations/FromOperation.js +110 -0
  78. package/lib/queryBuilder/operations/InsertAndFetchOperation.js +49 -0
  79. package/lib/queryBuilder/operations/InsertGraphAndFetchOperation.js +45 -0
  80. package/lib/queryBuilder/operations/InsertGraphOperation.js +108 -0
  81. package/lib/queryBuilder/operations/InsertOperation.js +206 -0
  82. package/lib/queryBuilder/operations/InstanceDeleteOperation.js +46 -0
  83. package/lib/queryBuilder/operations/InstanceFindOperation.js +21 -0
  84. package/lib/queryBuilder/operations/InstanceInsertOperation.js +24 -0
  85. package/lib/queryBuilder/operations/InstanceUpdateOperation.js +59 -0
  86. package/lib/queryBuilder/operations/JoinRelatedOperation.js +103 -0
  87. package/lib/queryBuilder/operations/KnexOperation.js +14 -0
  88. package/lib/queryBuilder/operations/MergeOperation.js +56 -0
  89. package/lib/queryBuilder/operations/ObjectionToKnexConvertingOperation.js +192 -0
  90. package/lib/queryBuilder/operations/OnBuildKnexOperation.js +29 -0
  91. package/lib/queryBuilder/operations/OnBuildOperation.js +29 -0
  92. package/lib/queryBuilder/operations/OnErrorOperation.js +29 -0
  93. package/lib/queryBuilder/operations/QueryBuilderOperation.js +297 -0
  94. package/lib/queryBuilder/operations/RangeOperation.js +47 -0
  95. package/lib/queryBuilder/operations/RelateOperation.js +27 -0
  96. package/lib/queryBuilder/operations/ReturningOperation.js +30 -0
  97. package/lib/queryBuilder/operations/RunAfterOperation.js +29 -0
  98. package/lib/queryBuilder/operations/RunBeforeOperation.js +29 -0
  99. package/lib/queryBuilder/operations/UnrelateOperation.js +23 -0
  100. package/lib/queryBuilder/operations/UpdateAndFetchOperation.js +80 -0
  101. package/lib/queryBuilder/operations/UpdateOperation.js +155 -0
  102. package/lib/queryBuilder/operations/UpsertGraphAndFetchOperation.js +45 -0
  103. package/lib/queryBuilder/operations/UpsertGraphOperation.js +66 -0
  104. package/lib/queryBuilder/operations/WhereCompositeOperation.js +57 -0
  105. package/lib/queryBuilder/operations/WhereInOperation.js +48 -0
  106. package/lib/queryBuilder/operations/eager/EagerOperation.js +61 -0
  107. package/lib/queryBuilder/operations/eager/JoinEagerOperation.js +51 -0
  108. package/lib/queryBuilder/operations/eager/NaiveEagerOperation.js +13 -0
  109. package/lib/queryBuilder/operations/eager/WhereInEagerOperation.js +285 -0
  110. package/lib/queryBuilder/operations/jsonApi/WhereJsonHasOperation.js +36 -0
  111. package/lib/queryBuilder/operations/jsonApi/WhereJsonNotObjectOperation.js +53 -0
  112. package/lib/queryBuilder/operations/jsonApi/WhereJsonOperation.js +31 -0
  113. package/lib/queryBuilder/operations/jsonApi/WhereJsonOverlapsOperation.js +31 -0
  114. package/lib/queryBuilder/operations/jsonApi/mysqlJsonApi.js +167 -0
  115. package/lib/queryBuilder/operations/jsonApi/postgresJsonApi.js +164 -0
  116. package/lib/queryBuilder/operations/select/SelectOperation.js +66 -0
  117. package/lib/queryBuilder/operations/select/Selection.js +123 -0
  118. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeMsSqlOperation.js +117 -0
  119. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeOperation.js +100 -0
  120. package/lib/queryBuilder/operations/whereInComposite/WhereInCompositeSqliteOperation.js +104 -0
  121. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.js +886 -0
  122. package/lib/queryBuilder/parsers/jsonFieldExpressionParser.pegjs +97 -0
  123. package/lib/queryBuilder/parsers/relationExpressionParser.js +1042 -0
  124. package/lib/queryBuilder/parsers/relationExpressionParser.pegjs +141 -0
  125. package/lib/queryBuilder/transformations/CompositeQueryTransformation.js +22 -0
  126. package/lib/queryBuilder/transformations/QueryTransformation.js +11 -0
  127. package/lib/queryBuilder/transformations/WrapMysqlModifySubqueryTransformation.js +71 -0
  128. package/lib/queryBuilder/transformations/index.js +15 -0
  129. package/lib/queryBuilder/whereScopes.js +227 -0
  130. package/lib/relations/Relation.js +401 -0
  131. package/lib/relations/RelationDeleteOperation.js +29 -0
  132. package/lib/relations/RelationFindOperation.js +149 -0
  133. package/lib/relations/RelationInsertOperation.js +33 -0
  134. package/lib/relations/RelationOwner.js +236 -0
  135. package/lib/relations/RelationProperty.js +247 -0
  136. package/lib/relations/RelationUpdateOperation.js +30 -0
  137. package/lib/relations/belongsToOne/BelongsToOneDeleteOperation.js +23 -0
  138. package/lib/relations/belongsToOne/BelongsToOneInsertOperation.js +44 -0
  139. package/lib/relations/belongsToOne/BelongsToOneRelateOperation.js +50 -0
  140. package/lib/relations/belongsToOne/BelongsToOneRelation.js +53 -0
  141. package/lib/relations/belongsToOne/BelongsToOneUnrelateOperation.js +61 -0
  142. package/lib/relations/hasMany/HasManyInsertOperation.js +61 -0
  143. package/lib/relations/hasMany/HasManyRelateOperation.js +64 -0
  144. package/lib/relations/hasMany/HasManyRelation.js +49 -0
  145. package/lib/relations/hasMany/HasManyUnrelateOperation.js +33 -0
  146. package/lib/relations/hasOne/HasOneRelation.js +13 -0
  147. package/lib/relations/hasOneThrough/HasOneThroughRelation.js +13 -0
  148. package/lib/relations/manyToMany/ManyToManyModifyMixin.js +105 -0
  149. package/lib/relations/manyToMany/ManyToManyRelation.js +507 -0
  150. package/lib/relations/manyToMany/ManyToManySqliteModifyMixin.js +36 -0
  151. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperation.js +10 -0
  152. package/lib/relations/manyToMany/delete/ManyToManyDeleteOperationBase.js +26 -0
  153. package/lib/relations/manyToMany/delete/ManyToManyDeleteSqliteOperation.js +12 -0
  154. package/lib/relations/manyToMany/find/ManyToManyFindOperation.js +105 -0
  155. package/lib/relations/manyToMany/insert/ManyToManyInsertOperation.js +52 -0
  156. package/lib/relations/manyToMany/relate/ManyToManyRelateOperation.js +81 -0
  157. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperation.js +14 -0
  158. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateOperationBase.js +34 -0
  159. package/lib/relations/manyToMany/unrelate/ManyToManyUnrelateSqliteOperation.js +16 -0
  160. package/lib/relations/manyToMany/update/ManyToManyUpdateOperation.js +10 -0
  161. package/lib/relations/manyToMany/update/ManyToManyUpdateOperationBase.js +82 -0
  162. package/lib/relations/manyToMany/update/ManyToManyUpdateSqliteOperation.js +12 -0
  163. package/lib/transaction.js +96 -0
  164. package/lib/utils/assert.js +25 -0
  165. package/lib/utils/buildUtils.js +21 -0
  166. package/lib/utils/classUtils.js +13 -0
  167. package/lib/utils/clone.js +2329 -0
  168. package/lib/utils/createModifier.js +42 -0
  169. package/lib/utils/deprecate.js +15 -0
  170. package/lib/utils/identifierMapping.js +227 -0
  171. package/lib/utils/internalPropUtils.js +11 -0
  172. package/lib/utils/knexUtils.js +76 -0
  173. package/lib/utils/mixin.js +25 -0
  174. package/lib/utils/mysqlJsonPath.js +55 -0
  175. package/lib/utils/normalizeIds.js +144 -0
  176. package/lib/utils/objectUtils.js +416 -0
  177. package/lib/utils/parseFieldExpression.js +51 -0
  178. package/lib/utils/postgresJsonPath.js +110 -0
  179. package/lib/utils/promiseUtils/after.js +17 -0
  180. package/lib/utils/promiseUtils/afterReturn.js +17 -0
  181. package/lib/utils/promiseUtils/index.js +17 -0
  182. package/lib/utils/promiseUtils/isPromise.js +11 -0
  183. package/lib/utils/promiseUtils/map.js +110 -0
  184. package/lib/utils/promiseUtils/mapAfterAllReturn.js +29 -0
  185. package/lib/utils/promiseUtils/try.js +22 -0
  186. package/lib/utils/resolveModel.js +107 -0
  187. package/lib/utils/tmpColumnUtils.js +16 -0
  188. package/package.json +86 -4
  189. package/typings/objection/index.d.ts +4104 -0
  190. package/typings/objection/relation-expression.d.ts +237 -0
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ class ModifierNotFoundError extends Error {
4
+ constructor(modifierName) {
5
+ super(`Unable to determine modify function from provided value: "${modifierName}".`);
6
+ this.modifierName = modifierName;
7
+ }
8
+ }
9
+
10
+ module.exports = {
11
+ ModifierNotFoundError,
12
+ };
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ class NotFoundError extends Error {
4
+ constructor({ modelClass, data = {}, statusCode = 404, ...rest } = {}) {
5
+ super(rest.message || 'NotFoundError');
6
+
7
+ this.type = 'NotFound';
8
+ this.name = this.constructor.name;
9
+ this.data = { ...rest, ...data };
10
+ this.statusCode = statusCode;
11
+
12
+ // Add as non-enumerable in case people are passing instances of
13
+ // this error directly to `JSON.stringify`.
14
+ Object.defineProperty(this, 'modelClass', {
15
+ value: modelClass,
16
+ enumerable: false,
17
+ });
18
+ }
19
+ }
20
+
21
+ module.exports = {
22
+ NotFoundError,
23
+ };
@@ -0,0 +1,14 @@
1
+ 'use strict';
2
+
3
+ class RelationDoesNotExistError extends Error {
4
+ constructor(relationName) {
5
+ super(`unknown relation "${relationName}" in a relation expression`);
6
+
7
+ this.name = this.constructor.name;
8
+ this.relationName = relationName;
9
+ }
10
+ }
11
+
12
+ module.exports = {
13
+ RelationDoesNotExistError,
14
+ };
@@ -0,0 +1,54 @@
1
+ 'use strict';
2
+
3
+ const { asArray, isString } = require('../utils/objectUtils');
4
+
5
+ const ValidationErrorType = {
6
+ ModelValidation: 'ModelValidation',
7
+ RelationExpression: 'RelationExpression',
8
+ UnallowedRelation: 'UnallowedRelation',
9
+ InvalidGraph: 'InvalidGraph',
10
+ };
11
+
12
+ class ValidationError extends Error {
13
+ static get Type() {
14
+ return ValidationErrorType;
15
+ }
16
+
17
+ constructor({ type, message, modelClass, data = {}, statusCode = 400 }) {
18
+ super(message || errorsToMessage(data));
19
+
20
+ this.name = this.constructor.name;
21
+ this.type = type;
22
+ this.data = data;
23
+ this.statusCode = statusCode;
24
+
25
+ // Add as non-enumerable in case people are passing instances of
26
+ // this error directly to `JSON.stringify`.
27
+ Object.defineProperty(this, 'modelClass', {
28
+ value: modelClass,
29
+ enumerable: false,
30
+ });
31
+ }
32
+ }
33
+
34
+ function errorsToMessage(data) {
35
+ return Object.keys(data)
36
+ .reduce((messages, key) => {
37
+ messages.push(`${key}: ${asArray(data[key]).map(message).join(', ')}`);
38
+ return messages;
39
+ }, [])
40
+ .join(', ');
41
+ }
42
+
43
+ function message(it) {
44
+ if (isString(it)) {
45
+ return it;
46
+ } else {
47
+ return it.message;
48
+ }
49
+ }
50
+
51
+ module.exports = {
52
+ ValidationError,
53
+ ValidationErrorType,
54
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ class Validator {
4
+ constructor(...args) {
5
+ this.constructor.init(this, ...args);
6
+ }
7
+
8
+ static init() {}
9
+
10
+ beforeValidate({ model, json, options }) {
11
+ model.$beforeValidate(null, json, options);
12
+ }
13
+
14
+ validate() {
15
+ /* istanbul ignore next */
16
+ throw new Error('not implemented');
17
+ }
18
+
19
+ afterValidate({ model, json, options }) {
20
+ model.$afterValidate(json, options);
21
+ }
22
+ }
23
+
24
+ module.exports = {
25
+ Validator,
26
+ };
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ // A small helper method for cached lazy-importing of the Model class.
4
+ let Model;
5
+ const getModel = () => Model || (Model = require('./Model').Model);
6
+
7
+ module.exports = {
8
+ getModel,
9
+ };
@@ -0,0 +1,80 @@
1
+ 'use strict';
2
+
3
+ const { ModelGraphBuilder } = require('./ModelGraphBuilder');
4
+ const NOT_CALCULATED = {};
5
+
6
+ class ModelGraph {
7
+ constructor(nodes, edges) {
8
+ this.nodes = nodes;
9
+ this.edges = edges;
10
+
11
+ // These are calculated lazily.
12
+ this._nodesByObjects = NOT_CALCULATED;
13
+ this._nodesByIdPathKeys = NOT_CALCULATED;
14
+ }
15
+
16
+ static create(rootModelClass, roots) {
17
+ const builder = ModelGraphBuilder.buildGraph(rootModelClass, roots);
18
+ return new ModelGraph(builder.nodes, builder.edges);
19
+ }
20
+
21
+ static createEmpty() {
22
+ return new ModelGraph([], []);
23
+ }
24
+
25
+ get rootObjects() {
26
+ return this.nodes.filter((node) => !node.parentEdge).map((node) => node.obj);
27
+ }
28
+
29
+ nodeForObject(obj) {
30
+ if (!obj) {
31
+ return null;
32
+ }
33
+
34
+ if (this._nodesByObjects === NOT_CALCULATED) {
35
+ this._nodesByObjects = createNodesByObjectsMap(this.nodes);
36
+ }
37
+
38
+ return this._nodesByObjects.get(obj) || null;
39
+ }
40
+
41
+ nodeForNode(node) {
42
+ if (!node) {
43
+ return null;
44
+ }
45
+
46
+ if (this._nodesByIdPathKeys === NOT_CALCULATED) {
47
+ this._nodesByIdPathKeys = createNodesByIdPathKeysMap(this.nodes);
48
+ }
49
+
50
+ return this._nodesByIdPathKeys.get(node.idPathKey) || null;
51
+ }
52
+ }
53
+
54
+ function createNodesByObjectsMap(nodes) {
55
+ const nodesByObjects = new Map();
56
+
57
+ for (const node of nodes) {
58
+ nodesByObjects.set(node.obj, node);
59
+ }
60
+
61
+ return nodesByObjects;
62
+ }
63
+
64
+ function createNodesByIdPathKeysMap(nodes) {
65
+ const nodesByIdPathKeys = new Map();
66
+
67
+ for (const node of nodes) {
68
+ const idPathKey = node.idPathKey;
69
+
70
+ if (idPathKey !== null) {
71
+ nodesByIdPathKeys.set(idPathKey, node);
72
+ }
73
+ }
74
+
75
+ return nodesByIdPathKeys;
76
+ }
77
+
78
+ module.exports = {
79
+ ModelGraph,
80
+ };
@@ -0,0 +1,241 @@
1
+ 'use strict';
2
+
3
+ const { isObject, isString, asArray, asSingle } = require('../../utils/objectUtils');
4
+ const { ValidationErrorType } = require('../../model/ValidationError');
5
+ const { ModelGraphNode } = require('./ModelGraphNode');
6
+ const { ModelGraphEdge } = require('./ModelGraphEdge');
7
+
8
+ class ModelGraphBuilder {
9
+ constructor() {
10
+ this.nodes = [];
11
+ this.edges = [];
12
+ }
13
+
14
+ static buildGraph(rootModelClass, roots) {
15
+ const builder = new this();
16
+ builder._buildGraph(rootModelClass, roots);
17
+
18
+ return builder;
19
+ }
20
+
21
+ _buildGraph(rootModelClass, roots) {
22
+ if (roots) {
23
+ if (Array.isArray(roots)) {
24
+ this._buildNodes(rootModelClass, roots);
25
+ } else if (isObject(roots)) {
26
+ this._buildNode(rootModelClass, roots);
27
+ } else {
28
+ throw createNotModelError(rootModelClass, roots);
29
+ }
30
+ }
31
+
32
+ this._buildReferences();
33
+ }
34
+
35
+ _buildNodes(modelClass, objs, parentNode = null, relation = null) {
36
+ objs = asArray(objs);
37
+
38
+ objs.forEach((obj, index) => {
39
+ this._buildNode(modelClass, obj, parentNode, relation, index);
40
+ });
41
+ }
42
+
43
+ _buildNode(modelClass, obj, parentNode = null, relation = null, index = null) {
44
+ obj = asSingle(obj);
45
+
46
+ if (!isObject(obj) || !obj.$isObjectionModel) {
47
+ throw createNotModelError(modelClass, obj);
48
+ }
49
+
50
+ const node = new ModelGraphNode(modelClass, obj);
51
+ this.nodes.push(node);
52
+
53
+ if (parentNode) {
54
+ const edge = new ModelGraphEdge(
55
+ ModelGraphEdge.Type.Relation,
56
+ parentNode,
57
+ node,
58
+ relation,
59
+ index,
60
+ );
61
+
62
+ node.parentEdge = edge;
63
+ this._addEdge(parentNode, node, edge);
64
+ }
65
+
66
+ this._buildRelationNodes(node);
67
+ }
68
+
69
+ _buildRelationNodes(node) {
70
+ for (const relationName of node.modelClass.getRelationNames()) {
71
+ const relatedObjects = node.obj[relationName];
72
+
73
+ if (!relatedObjects) {
74
+ continue;
75
+ }
76
+
77
+ const relation = node.modelClass.getRelation(relationName);
78
+
79
+ if (relation.isOneToOne()) {
80
+ this._buildNode(relation.relatedModelClass, relatedObjects, node, relation);
81
+ } else {
82
+ this._buildNodes(relation.relatedModelClass, relatedObjects, node, relation);
83
+ }
84
+ }
85
+ }
86
+
87
+ _buildReferences() {
88
+ const nodesByUid = this._nodesByUid();
89
+
90
+ this._buildObjectReferences(nodesByUid);
91
+ this._buildPropertyReferences(nodesByUid);
92
+ }
93
+
94
+ _nodesByUid() {
95
+ const nodesByUid = new Map();
96
+
97
+ for (const node of this.nodes) {
98
+ const uid = node.uid;
99
+
100
+ if (uid === undefined) {
101
+ continue;
102
+ }
103
+
104
+ nodesByUid.set(uid, node);
105
+ }
106
+
107
+ return nodesByUid;
108
+ }
109
+
110
+ _buildObjectReferences(nodesByUid) {
111
+ for (const node of this.nodes) {
112
+ const ref = node.reference;
113
+
114
+ if (ref === undefined) {
115
+ continue;
116
+ }
117
+
118
+ const refNode = nodesByUid.get(ref);
119
+
120
+ if (!refNode) {
121
+ throw createReferenceNotFoundError(ref);
122
+ }
123
+
124
+ const edge = new ModelGraphEdge(ModelGraphEdge.Type.Reference, node, refNode);
125
+ edge.refType = ModelGraphEdge.ReferenceType.Object;
126
+
127
+ this._addEdge(node, refNode, edge);
128
+ }
129
+ }
130
+
131
+ _buildPropertyReferences(nodesByUid) {
132
+ for (const node of this.nodes) {
133
+ forEachPropertyReference(node.obj, ({ path, refMatch, ref, refPath }) => {
134
+ const refNode = nodesByUid.get(ref);
135
+
136
+ if (!refNode) {
137
+ throw createReferenceNotFoundError(ref);
138
+ }
139
+
140
+ const edge = new ModelGraphEdge(ModelGraphEdge.Type.Reference, node, refNode);
141
+
142
+ edge.refType = ModelGraphEdge.ReferenceType.Property;
143
+ edge.refMatch = refMatch;
144
+ edge.refOwnerDataPath = path.slice();
145
+ edge.refRelatedDataPath = refPath;
146
+
147
+ this._addEdge(node, refNode, edge);
148
+ });
149
+ }
150
+ }
151
+
152
+ _addEdge(ownerNode, relatedNode, edge) {
153
+ this.edges.push(edge);
154
+
155
+ ownerNode.edges.push(edge);
156
+ relatedNode.edges.push(edge);
157
+
158
+ if (edge.type === ModelGraphEdge.Type.Reference) {
159
+ ownerNode.refEdges.push(edge);
160
+ relatedNode.refEdges.push(edge);
161
+ }
162
+ }
163
+ }
164
+
165
+ function forEachPropertyReference(obj, callback) {
166
+ const modelClass = obj.constructor;
167
+ const relationNames = modelClass.getRelationNames();
168
+
169
+ for (const prop of Object.keys(obj)) {
170
+ if (relationNames.includes(prop)) {
171
+ continue;
172
+ }
173
+
174
+ visitStrings(obj[prop], [prop], (str, path) => {
175
+ forEachMatch(modelClass.propRefRegex, str, (match) => {
176
+ const [refMatch, ref, refPath] = match;
177
+ callback({ path, refMatch, ref, refPath: refPath.trim().split('.') });
178
+ });
179
+ });
180
+ }
181
+ }
182
+
183
+ function visitStrings(value, path, visit) {
184
+ if (Array.isArray(value)) {
185
+ visitStringsInArray(value, path, visit);
186
+ } else if (isObject(value) && !Buffer.isBuffer(value)) {
187
+ visitStringsInObject(value, path, visit);
188
+ } else if (isString(value)) {
189
+ visit(value, path);
190
+ }
191
+ }
192
+
193
+ function visitStringsInArray(value, path, visit) {
194
+ for (let i = 0; i < value.length; ++i) {
195
+ path.push(i);
196
+ visitStrings(value[i], path, visit);
197
+ path.pop();
198
+ }
199
+ }
200
+
201
+ function visitStringsInObject(value, path, visit) {
202
+ for (const prop of Object.keys(value)) {
203
+ path.push(prop);
204
+ visitStrings(value[prop], path, visit);
205
+ path.pop();
206
+ }
207
+ }
208
+
209
+ function forEachMatch(regex, str, cb) {
210
+ let matchResult = regex.exec(str);
211
+
212
+ while (matchResult) {
213
+ cb(matchResult);
214
+ matchResult = regex.exec(str);
215
+ }
216
+ }
217
+
218
+ function createReferenceNotFoundError(ref) {
219
+ return new Error(
220
+ [
221
+ `could not resolve reference ${ref} in a graph.`,
222
+ `If you are sure the #id exist in the same graph,`,
223
+ `this may be due to a limitation that a subgraph under a related item`,
224
+ `cannot reference an item in a subgraph under another related item.`,
225
+ `If you run into this limitation, please open an issue in objection github.`,
226
+ ].join(' '),
227
+ );
228
+ }
229
+
230
+ function createNotModelError(modelClass, value) {
231
+ throw modelClass.createValidationError({
232
+ type: ValidationErrorType.InvalidGraph,
233
+ message: `expected value "${value}" to be an instance of ${modelClass.name}`,
234
+ });
235
+ }
236
+
237
+ module.exports = {
238
+ ModelGraphBuilder,
239
+ createNotModelError,
240
+ forEachPropertyReference,
241
+ };
@@ -0,0 +1,52 @@
1
+ 'use strict';
2
+
3
+ const Type = {
4
+ Relation: 'Relation',
5
+ Reference: 'Reference',
6
+ };
7
+
8
+ const ReferenceType = {
9
+ Object: 'Object',
10
+ Property: 'Property',
11
+ };
12
+
13
+ class ModelGraphEdge {
14
+ constructor(type, ownerNode, relatedNode, relation = null, relationIndex = null) {
15
+ this.type = type;
16
+
17
+ this.ownerNode = ownerNode;
18
+ this.relatedNode = relatedNode;
19
+ this.relation = relation;
20
+ this.relationIndex = relationIndex;
21
+
22
+ this.refType = null;
23
+ this.refMatch = null;
24
+
25
+ this.refOwnerDataPath = null;
26
+ this.refRelatedDataPath = null;
27
+ }
28
+
29
+ static get Type() {
30
+ return Type;
31
+ }
32
+
33
+ static get ReferenceType() {
34
+ return ReferenceType;
35
+ }
36
+
37
+ getOtherNode(node) {
38
+ return this.isOwnerNode(node) ? this.relatedNode : this.ownerNode;
39
+ }
40
+
41
+ isOwnerNode(node) {
42
+ return node === this.ownerNode;
43
+ }
44
+
45
+ isRelatedNode(node) {
46
+ return node === this.relatedNode;
47
+ }
48
+ }
49
+
50
+ module.exports = {
51
+ ModelGraphEdge,
52
+ };