mythix-orm 1.0.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/.eslintrc.js +94 -0
- package/.vscode/launch.json +34 -0
- package/.vscode/settings.json +10 -0
- package/LICENSE +21 -0
- package/README.md +15 -0
- package/lib/connection/connection-base.js +877 -0
- package/lib/connection/index.js +11 -0
- package/lib/connection/literals/average-literal.js +14 -0
- package/lib/connection/literals/count-literal.js +18 -0
- package/lib/connection/literals/distinct-literal.js +14 -0
- package/lib/connection/literals/index.js +23 -0
- package/lib/connection/literals/literal-base.js +62 -0
- package/lib/connection/literals/literal-field-base.js +45 -0
- package/lib/connection/literals/literal.js +11 -0
- package/lib/connection/literals/max-literal.js +14 -0
- package/lib/connection/literals/min-literal.js +14 -0
- package/lib/connection/literals/sum-literal.js +14 -0
- package/lib/connection/query-generator-base.js +864 -0
- package/lib/errors/base-error.js +14 -0
- package/lib/errors/connection/access-denied-error.js +13 -0
- package/lib/errors/connection/connection-acquire-timeout-error.js +13 -0
- package/lib/errors/connection/connection-refused-error.js +13 -0
- package/lib/errors/connection/connection-timed-out-error.js +13 -0
- package/lib/errors/connection/host-not-found-error.js +13 -0
- package/lib/errors/connection/host-not-reachable-error.js +13 -0
- package/lib/errors/connection/index.js +19 -0
- package/lib/errors/connection/invalid-connection-error.js +13 -0
- package/lib/errors/connection-base-error.js +13 -0
- package/lib/errors/database/exclusion-constraint-error.js +13 -0
- package/lib/errors/database/foreign-key-constraint-error.js +13 -0
- package/lib/errors/database/index.js +13 -0
- package/lib/errors/database/timeout-error.js +13 -0
- package/lib/errors/database/unknown-constraint-error.js +13 -0
- package/lib/errors/database-base-error.js +17 -0
- package/lib/errors/index.js +44 -0
- package/lib/field.js +18 -0
- package/lib/index.js +43 -0
- package/lib/model.js +1374 -0
- package/lib/proxy-class/index.js +3 -0
- package/lib/proxy-class/proxy-class.js +269 -0
- package/lib/query-engine/field-scope.js +99 -0
- package/lib/query-engine/index.js +13 -0
- package/lib/query-engine/model-scope.js +198 -0
- package/lib/query-engine/query-engine-base.js +325 -0
- package/lib/query-engine/query-engine.js +212 -0
- package/lib/types/concrete/bigint-type.js +62 -0
- package/lib/types/concrete/blob-type.js +46 -0
- package/lib/types/concrete/boolean-type.js +41 -0
- package/lib/types/concrete/char-type.js +39 -0
- package/lib/types/concrete/date-type.js +87 -0
- package/lib/types/concrete/datetime-type.js +92 -0
- package/lib/types/concrete/float-type.js +47 -0
- package/lib/types/concrete/foreign-key-type.js +208 -0
- package/lib/types/concrete/index.js +53 -0
- package/lib/types/concrete/integer-type.js +51 -0
- package/lib/types/concrete/string-type.js +44 -0
- package/lib/types/concrete/text-type.js +44 -0
- package/lib/types/concrete/uuid-base.js +77 -0
- package/lib/types/concrete/uuid-v1-type.js +99 -0
- package/lib/types/concrete/uuid-v3-type.js +108 -0
- package/lib/types/concrete/uuid-v4-type.js +90 -0
- package/lib/types/concrete/uuid-v5-type.js +108 -0
- package/lib/types/concrete/xid-type.js +58 -0
- package/lib/types/helpers/default-helpers.js +127 -0
- package/lib/types/helpers/index.js +35 -0
- package/lib/types/index.js +94 -0
- package/lib/types/type.js +244 -0
- package/lib/types/virtual/index.js +14 -0
- package/lib/types/virtual/model-type.js +141 -0
- package/lib/types/virtual/models-type.js +264 -0
- package/lib/types/virtual/relational-type-base.js +323 -0
- package/lib/utils/index.js +65 -0
- package/lib/utils/misc-utils.js +73 -0
- package/lib/utils/model-utils.js +704 -0
- package/lib/utils/query-utils.js +186 -0
- package/package.json +63 -0
- package/playground/test01.js +15 -0
- package/spec/connection/connection-base-spec.js +126 -0
- package/spec/connection/literals/average-literal-spec.js +45 -0
- package/spec/connection/literals/count-literal-spec.js +42 -0
- package/spec/connection/literals/distinct-literal-spec.js +42 -0
- package/spec/connection/literals/literal-spec.js +26 -0
- package/spec/connection/literals/max-literal-spec.js +42 -0
- package/spec/connection/literals/min-literal-spec.js +42 -0
- package/spec/connection/literals/sum-literal-spec.js +42 -0
- package/spec/helpers/default-helpers-spec.js +108 -0
- package/spec/model-spec.js +736 -0
- package/spec/proxy-class/proxy-class-spec.js +173 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_chain_query_conditions-001.snapshot +94 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_construct_a_query_context_with_a_model_call-001.snapshot +35 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_construct_a_query_context_with_a_model_sub-001.snapshot +35 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_set_a_default_scope_on_a_model-001.snapshot +57 -0
- package/spec/query-engine/__snapshots__/QueryEngine-operations-query_operations_and_chaining-can_unscope_default_scope_on_a_model-001.snapshot +35 -0
- package/spec/query-engine/query-engine-spec.js +99 -0
- package/spec/support/jasmine.json +13 -0
- package/spec/support/models/blob-test-model.js +19 -0
- package/spec/support/models/extended-user-model.js +38 -0
- package/spec/support/models/index.js +27 -0
- package/spec/support/models/number-model.js +24 -0
- package/spec/support/models/role-model.js +26 -0
- package/spec/support/models/role-thing-model.js +41 -0
- package/spec/support/models/scoped-user-model.js +13 -0
- package/spec/support/models/time-model.js +36 -0
- package/spec/support/models/user-model.js +70 -0
- package/spec/support/models/user-role-model.js +36 -0
- package/spec/support/models/user-thing-model.js +46 -0
- package/spec/support/models/validation-test-model.js +40 -0
- package/spec/support/snapshots.js +293 -0
- package/spec/support/test-helpers.js +13 -0
- package/spec/types/concrete/bigint-type-spec.js +84 -0
- package/spec/types/concrete/boolean-type-spec.js +83 -0
- package/spec/types/concrete/date-type-spec.js +85 -0
- package/spec/types/concrete/datetime-type-spec.js +87 -0
- package/spec/types/concrete/float-type-spec.js +71 -0
- package/spec/types/concrete/foreign-key-type-spec.js +64 -0
- package/spec/types/concrete/integer-type-spec.js +71 -0
- package/spec/types/concrete/string-type-spec.js +91 -0
- package/spec/types/concrete/uuid-v1-type-spec.js +73 -0
- package/spec/types/concrete/uuid-v4-type-spec.js +65 -0
- package/spec/types/type-spec.js +101 -0
- package/spec/types/virtual/model-types-spec.js +401 -0
- package/spec/utils/misc-utils-spec.js +61 -0
- package/spec/utils/model-utils-spec.js +55 -0
- package/spec/utils/query-utils-spec.js +105 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Type = require('./type');
|
|
4
|
+
const ConcreteTypes = require('./concrete');
|
|
5
|
+
const VirtualTypes = require('./virtual');
|
|
6
|
+
const Helpers = require('./helpers');
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
BigIntType,
|
|
10
|
+
BlobType,
|
|
11
|
+
BooleanType,
|
|
12
|
+
CharType,
|
|
13
|
+
DateTimeType,
|
|
14
|
+
DateType,
|
|
15
|
+
FloatType,
|
|
16
|
+
ForeignKeyType,
|
|
17
|
+
IntegerType,
|
|
18
|
+
StringType,
|
|
19
|
+
TextType,
|
|
20
|
+
UUIDV1Type,
|
|
21
|
+
UUIDV3Type,
|
|
22
|
+
UUIDV4Type,
|
|
23
|
+
UUIDV5Type,
|
|
24
|
+
XIDType,
|
|
25
|
+
BIGINT,
|
|
26
|
+
BLOB,
|
|
27
|
+
BOOLEAN,
|
|
28
|
+
CHAR,
|
|
29
|
+
DATE,
|
|
30
|
+
DATETIME,
|
|
31
|
+
FLOAT,
|
|
32
|
+
FOREIGN_KEY,
|
|
33
|
+
INTEGER,
|
|
34
|
+
STRING,
|
|
35
|
+
TEXT,
|
|
36
|
+
UUIDV1,
|
|
37
|
+
UUIDV3,
|
|
38
|
+
UUIDV4,
|
|
39
|
+
UUIDV5,
|
|
40
|
+
XID,
|
|
41
|
+
} = ConcreteTypes;
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
ModelType,
|
|
45
|
+
ModelsType,
|
|
46
|
+
Model,
|
|
47
|
+
Models,
|
|
48
|
+
} = VirtualTypes;
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
DefaultHelpers: Helpers.DefaultHelpers,
|
|
52
|
+
Type,
|
|
53
|
+
Helpers,
|
|
54
|
+
|
|
55
|
+
// Concrete Types
|
|
56
|
+
BigIntType,
|
|
57
|
+
BlobType,
|
|
58
|
+
BooleanType,
|
|
59
|
+
CharType,
|
|
60
|
+
DateTimeType,
|
|
61
|
+
DateType,
|
|
62
|
+
FloatType,
|
|
63
|
+
ForeignKeyType,
|
|
64
|
+
IntegerType,
|
|
65
|
+
StringType,
|
|
66
|
+
TextType,
|
|
67
|
+
UUIDV1Type,
|
|
68
|
+
UUIDV3Type,
|
|
69
|
+
UUIDV4Type,
|
|
70
|
+
UUIDV5Type,
|
|
71
|
+
XIDType,
|
|
72
|
+
BIGINT,
|
|
73
|
+
BLOB,
|
|
74
|
+
BOOLEAN,
|
|
75
|
+
CHAR,
|
|
76
|
+
DATE,
|
|
77
|
+
DATETIME,
|
|
78
|
+
FLOAT,
|
|
79
|
+
FOREIGN_KEY,
|
|
80
|
+
INTEGER,
|
|
81
|
+
STRING,
|
|
82
|
+
TEXT,
|
|
83
|
+
UUIDV1,
|
|
84
|
+
UUIDV3,
|
|
85
|
+
UUIDV4,
|
|
86
|
+
UUIDV5,
|
|
87
|
+
XID,
|
|
88
|
+
|
|
89
|
+
// Virtual Types
|
|
90
|
+
ModelType,
|
|
91
|
+
ModelsType,
|
|
92
|
+
Model,
|
|
93
|
+
Models,
|
|
94
|
+
};
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { checkDefaultValueFlags } = require('./helpers/default-helpers');
|
|
4
|
+
|
|
5
|
+
class Type {
|
|
6
|
+
static _isMythixFieldType = true;
|
|
7
|
+
|
|
8
|
+
static clone = function() {
|
|
9
|
+
return this;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
static isTypeClass(value) {
|
|
13
|
+
if (!value)
|
|
14
|
+
return false;
|
|
15
|
+
|
|
16
|
+
if (value.prototype instanceof Type)
|
|
17
|
+
return true;
|
|
18
|
+
|
|
19
|
+
if (value._isMythixFieldType)
|
|
20
|
+
return true;
|
|
21
|
+
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static isType(value) {
|
|
26
|
+
if (!value)
|
|
27
|
+
return false;
|
|
28
|
+
|
|
29
|
+
if (value instanceof Type)
|
|
30
|
+
return true;
|
|
31
|
+
|
|
32
|
+
if (value.constructor._isMythixFieldType)
|
|
33
|
+
return true;
|
|
34
|
+
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
static instantiateType(_type) {
|
|
39
|
+
let type = _type;
|
|
40
|
+
if (!type)
|
|
41
|
+
throw new TypeError('Type::instantiateType: "type" is required.');
|
|
42
|
+
|
|
43
|
+
// Already instantiated?
|
|
44
|
+
if (Type.isType(type))
|
|
45
|
+
return type.clone();
|
|
46
|
+
|
|
47
|
+
const ThisType = type;
|
|
48
|
+
return new ThisType();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static isVirtual() {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static isRelational() {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static isForeignKey() {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static exposeToModel() {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static wrapConstructor(TypeKlass) {
|
|
68
|
+
let TypeWrapper = function(...args) {
|
|
69
|
+
return new TypeKlass(...args);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const staticPropertiesToCopy = [
|
|
73
|
+
'Default',
|
|
74
|
+
'_isMythixFieldType',
|
|
75
|
+
'clone',
|
|
76
|
+
'isTypeClass',
|
|
77
|
+
'isType',
|
|
78
|
+
'instantiateType',
|
|
79
|
+
'isVirtual',
|
|
80
|
+
'isRelational',
|
|
81
|
+
'isForeignKey',
|
|
82
|
+
'exposeToModel',
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
for (let i = 0, il = staticPropertiesToCopy.length; i < il; i++) {
|
|
86
|
+
let propName = staticPropertiesToCopy[i];
|
|
87
|
+
let value = TypeKlass[propName];
|
|
88
|
+
|
|
89
|
+
if (value !== undefined)
|
|
90
|
+
TypeWrapper[propName] = value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
Object.defineProperties(TypeWrapper, {
|
|
94
|
+
'name': {
|
|
95
|
+
writable: false,
|
|
96
|
+
enumberable: false,
|
|
97
|
+
configurable: false,
|
|
98
|
+
value: `${TypeKlass.name}Wrapper`,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return TypeWrapper;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
constructor(...args) {
|
|
106
|
+
Object.defineProperties(this, {
|
|
107
|
+
'_args': {
|
|
108
|
+
writable: true,
|
|
109
|
+
enumberable: false,
|
|
110
|
+
configurable: true,
|
|
111
|
+
value: args,
|
|
112
|
+
},
|
|
113
|
+
'_Model': {
|
|
114
|
+
writable: true,
|
|
115
|
+
enumberable: false,
|
|
116
|
+
configurable: true,
|
|
117
|
+
value: null,
|
|
118
|
+
},
|
|
119
|
+
'_field': {
|
|
120
|
+
writable: true,
|
|
121
|
+
enumberable: false,
|
|
122
|
+
configurable: true,
|
|
123
|
+
value: null,
|
|
124
|
+
},
|
|
125
|
+
'_modelInstance': {
|
|
126
|
+
writable: true,
|
|
127
|
+
enumberable: false,
|
|
128
|
+
configurable: true,
|
|
129
|
+
value: null,
|
|
130
|
+
},
|
|
131
|
+
'_connection': {
|
|
132
|
+
writable: true,
|
|
133
|
+
enumberable: false,
|
|
134
|
+
configurable: true,
|
|
135
|
+
value: null,
|
|
136
|
+
},
|
|
137
|
+
'_initialized': {
|
|
138
|
+
enumberable: false,
|
|
139
|
+
configurable: true,
|
|
140
|
+
get: () => {
|
|
141
|
+
return !!(this._Model && this._field);
|
|
142
|
+
},
|
|
143
|
+
set: () => {},
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
clone() {
|
|
149
|
+
let Type = this.constructor;
|
|
150
|
+
let newInstance = new Type(...this._args);
|
|
151
|
+
|
|
152
|
+
newInstance._Model = this._Model;
|
|
153
|
+
newInstance._field = this._field;
|
|
154
|
+
newInstance._modelInstance = this._modelInstance;
|
|
155
|
+
|
|
156
|
+
return newInstance;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
isVirtual() {
|
|
160
|
+
return this.constructor.isVirtual.call(this.constructor);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
isRelational() {
|
|
164
|
+
return this.constructor.isRelational.call(this.constructor);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
isForeignKey() {
|
|
168
|
+
return this.constructor.isForeignKey.call(this.constructor);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
exposeToModel() {
|
|
172
|
+
return this.constructor.exposeToModel.call(this.constructor);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
isRemote() {
|
|
176
|
+
let field = this.getField();
|
|
177
|
+
if (!field)
|
|
178
|
+
throw new Error(`${this.constructor.name}::isRemote: Error, the model type must be initialized before you call "isRemote".`);
|
|
179
|
+
|
|
180
|
+
if (field.remote === true)
|
|
181
|
+
return true;
|
|
182
|
+
|
|
183
|
+
return checkDefaultValueFlags(field.defaultValue, [ 'remote' ]);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// eslint-disable-next-line no-unused-vars
|
|
187
|
+
isValidValue(value) {
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
getField() {
|
|
192
|
+
return this._field;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
setField(field) {
|
|
196
|
+
this._field = field;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
getModel() {
|
|
200
|
+
let Model = this._Model;
|
|
201
|
+
if (!Model) {
|
|
202
|
+
let field = this.getField();
|
|
203
|
+
if (!field)
|
|
204
|
+
return;
|
|
205
|
+
|
|
206
|
+
Model = field.Model;
|
|
207
|
+
if (!Model)
|
|
208
|
+
return;
|
|
209
|
+
|
|
210
|
+
this._Model = Model;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return Model;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
setModel(Model) {
|
|
217
|
+
this._Model = Model;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
castToType({ value }) {
|
|
221
|
+
return value;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// eslint-disable-next-line no-unused-vars
|
|
225
|
+
initialize(connection, self) {
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
serialize(value) {
|
|
229
|
+
return value;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
deserialize(value) {
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
toConnectionType(connection, options) {
|
|
237
|
+
if (!connection)
|
|
238
|
+
return this.toString();
|
|
239
|
+
|
|
240
|
+
return connection.typeToString(this, options);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = Type;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// One to one relationships
|
|
4
|
+
const { ModelType, Model } = require('./model-type');
|
|
5
|
+
|
|
6
|
+
// One to many, or many to many relationships
|
|
7
|
+
const { ModelsType, Models } = require('./models-type');
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
ModelType,
|
|
11
|
+
ModelsType,
|
|
12
|
+
Model,
|
|
13
|
+
Models,
|
|
14
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const Nife = require('nife');
|
|
4
|
+
const RelationalTypeBase = require('./relational-type-base');
|
|
5
|
+
const ModelUtils = require('../../utils/model-utils');
|
|
6
|
+
|
|
7
|
+
// These get injected into the class as
|
|
8
|
+
// create{fieldName}, get{fieldName}, etc...
|
|
9
|
+
const TYPE_OPERATIONS = {
|
|
10
|
+
'queryFor': async function({ field, type }, userQuery, options, ...args) {
|
|
11
|
+
return await type.prepareQuery({ connection: null, self: this, field, userQuery, options }, args);
|
|
12
|
+
},
|
|
13
|
+
'create': async function({ field, type, get }, model, options) {
|
|
14
|
+
if (!model)
|
|
15
|
+
return false;
|
|
16
|
+
|
|
17
|
+
let result = await this.getConnection(options && options.connection).transaction(async (connection) => {
|
|
18
|
+
let TargetModel = type.getTargetModel(connection);
|
|
19
|
+
|
|
20
|
+
// Why are we fetching on get? Because this
|
|
21
|
+
// could be a complex relationship, and there
|
|
22
|
+
// might already be something that exists.
|
|
23
|
+
// TODO: Likely a good area for performance
|
|
24
|
+
// improvements... we can likely detect if
|
|
25
|
+
// the relationship is too complex to guess
|
|
26
|
+
// or not.
|
|
27
|
+
let fetchedModel = await get.call(this, TargetModel.where(connection).LIMIT(1), options);
|
|
28
|
+
if (fetchedModel && fetchedModel instanceof TargetModel) {
|
|
29
|
+
fetchedModel.setAttributes(model, true);
|
|
30
|
+
if (fetchedModel.isDirty())
|
|
31
|
+
await fetchedModel.save(options);
|
|
32
|
+
|
|
33
|
+
return fetchedModel;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let storedModels = await ModelUtils.createAndSaveAllRelatedModels(connection, this, field, [ model ], options);
|
|
37
|
+
let resultModel = storedModels[0];
|
|
38
|
+
|
|
39
|
+
// Update this model to reflect the update
|
|
40
|
+
ModelUtils.setRelationalValues(connection, this.getModel(), this, resultModel.getModel(), resultModel);
|
|
41
|
+
|
|
42
|
+
return resultModel;
|
|
43
|
+
}, options);
|
|
44
|
+
|
|
45
|
+
// Save needs to go outside of the transaction
|
|
46
|
+
// otherwise some DBs will violate foreign key
|
|
47
|
+
// constraints
|
|
48
|
+
if (this.isDirty())
|
|
49
|
+
await this.save(options);
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
},
|
|
53
|
+
'get': async function({ field, type }, userQuery, options, ...args) {
|
|
54
|
+
let query = await type.prepareQuery({ connection: null, self: this, field, userQuery, options }, args);
|
|
55
|
+
return await query.first(null, options);
|
|
56
|
+
},
|
|
57
|
+
'update': async function({ fullMethodName, field, type, create }, attributes, _options, ...args) {
|
|
58
|
+
let options = _options || {};
|
|
59
|
+
|
|
60
|
+
let result = await this.getConnection(options.connection).transaction(async (connection) => {
|
|
61
|
+
let query = await type.prepareQuery({ connection, self: this, field, options }, args);
|
|
62
|
+
let model = await query.first(null, options);
|
|
63
|
+
|
|
64
|
+
if (!model) {
|
|
65
|
+
if (options.force === true)
|
|
66
|
+
return await create.call(this, attributes, options);
|
|
67
|
+
|
|
68
|
+
throw new Error(`${field.Model.getModelName}::${fullMethodName}: Model not found to update. You can pass "{ force: true }" to the options to force a creation instead.`);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
model.setAttributes(attributes, true);
|
|
72
|
+
if (!model.isDirty())
|
|
73
|
+
return model;
|
|
74
|
+
|
|
75
|
+
let [ storedModel ] = await connection.update(model.getModel(), [ model ], options);
|
|
76
|
+
|
|
77
|
+
// Update this model to reflect the update
|
|
78
|
+
ModelUtils.setRelationalValues(connection, this.getModel(), this, storedModel.getModel(), storedModel);
|
|
79
|
+
|
|
80
|
+
return storedModel;
|
|
81
|
+
}, options);
|
|
82
|
+
|
|
83
|
+
// Save needs to go outside of the transaction
|
|
84
|
+
// otherwise some DBs will violate foreign key
|
|
85
|
+
// constraints
|
|
86
|
+
if (this.isDirty())
|
|
87
|
+
await this.save(options);
|
|
88
|
+
|
|
89
|
+
return result;
|
|
90
|
+
},
|
|
91
|
+
'destroy': async function({ field, type }, options, ...args) {
|
|
92
|
+
let result = await this.getConnection(options && options.connection).transaction(async (connection) => {
|
|
93
|
+
let query = await type.prepareQuery({ connection, self: this, field, options }, args);
|
|
94
|
+
let model = await query.first(options);
|
|
95
|
+
|
|
96
|
+
if (!model)
|
|
97
|
+
return false;
|
|
98
|
+
|
|
99
|
+
await connection.destroy(model.getModel(), [ model ], options);
|
|
100
|
+
|
|
101
|
+
// Update this model to reflect the deletion
|
|
102
|
+
ModelUtils.setRelationalValues(connection, this.getModel(), this, model.getModel());
|
|
103
|
+
|
|
104
|
+
return true;
|
|
105
|
+
}, options);
|
|
106
|
+
|
|
107
|
+
// Save needs to go outside of the transaction
|
|
108
|
+
// otherwise some DBs will violate foreign key
|
|
109
|
+
// constraints
|
|
110
|
+
if (this.isDirty())
|
|
111
|
+
await this.save(options);
|
|
112
|
+
|
|
113
|
+
return result;
|
|
114
|
+
},
|
|
115
|
+
'exists': async function({ field, type }, options, ...args) {
|
|
116
|
+
let query = await type.prepareQuery({ connection: null, self: this, field, options }, args);
|
|
117
|
+
return await query.exists(options);
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
class ModelType extends RelationalTypeBase {
|
|
122
|
+
isManyRelation() {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
fieldNameToOperationName(field, operation, rootMethod) {
|
|
127
|
+
if (rootMethod)
|
|
128
|
+
return `_${operation}${Nife.capitalize(field.fieldName)}`;
|
|
129
|
+
else
|
|
130
|
+
return `${operation}${Nife.capitalize(field.fieldName)}`;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
initialize(connection, self) {
|
|
134
|
+
return super.initialize(connection, self, TYPE_OPERATIONS);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
module.exports = {
|
|
139
|
+
Model: RelationalTypeBase.wrapConstructor(ModelType),
|
|
140
|
+
ModelType,
|
|
141
|
+
};
|