@nocobase/database 0.9.4-alpha.2 → 0.10.0-alpha.2
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/lib/database.js +2 -1
- package/lib/eager-loading/eager-loading-tree.d.ts +4 -0
- package/lib/eager-loading/eager-loading-tree.js +79 -16
- package/lib/fields/belongs-to-field.d.ts +1 -1
- package/lib/fields/belongs-to-field.js +3 -2
- package/lib/fields/belongs-to-many-field.js +1 -1
- package/lib/fields/has-many-field.js +1 -1
- package/lib/fields/has-one-field.js +1 -1
- package/lib/listeners/append-child-collection-name-after-repository-find.js +5 -1
- package/lib/options-parser.d.ts +1 -1
- package/lib/options-parser.js +15 -11
- package/lib/relation-repository/multiple-relation-repository.js +2 -1
- package/lib/relation-repository/single-relation-repository.js +2 -1
- package/lib/repository.d.ts +12 -0
- package/lib/repository.js +166 -66
- package/lib/update-associations.js +1 -1
- package/lib/view/field-type-map.d.ts +2 -0
- package/lib/view/field-type-map.js +2 -0
- package/lib/view/view-inference.js +52 -26
- package/lib/view-collection.js +0 -1
- package/package.json +4 -4
- package/src/__tests__/eager-loading/eager-loading-tree.test.ts +149 -0
- package/src/__tests__/field-options/sort-by.test.ts +3 -1
- package/src/__tests__/inhertits/collection-inherits.test.ts +165 -0
- package/src/__tests__/repository/create.test.ts +129 -6
- package/src/__tests__/repository/find.test.ts +11 -0
- package/src/__tests__/repository.test.ts +24 -0
- package/src/__tests__/update-associations.test.ts +109 -1
- package/src/__tests__/view/view-inference.test.ts +1 -0
- package/src/database.ts +4 -1
- package/src/eager-loading/eager-loading-tree.ts +92 -17
- package/src/fields/belongs-to-field.ts +6 -4
- package/src/fields/belongs-to-many-field.ts +2 -1
- package/src/fields/has-many-field.ts +1 -1
- package/src/fields/has-one-field.ts +1 -1
- package/src/listeners/append-child-collection-name-after-repository-find.ts +9 -5
- package/src/options-parser.ts +25 -19
- package/src/relation-repository/multiple-relation-repository.ts +1 -0
- package/src/relation-repository/single-relation-repository.ts +1 -0
- package/src/repository.ts +84 -0
- package/src/update-associations.ts +3 -0
- package/src/view/field-type-map.ts +2 -0
- package/src/view/view-inference.ts +75 -43
- package/src/view-collection.ts +0 -1
package/lib/database.js
CHANGED
|
@@ -593,7 +593,8 @@ class Database extends _events().EventEmitter {
|
|
|
593
593
|
if (!Field) {
|
|
594
594
|
throw Error(`unsupported field type ${type}`);
|
|
595
595
|
}
|
|
596
|
-
|
|
596
|
+
const collection = context.collection;
|
|
597
|
+
if (options.field && collection.options.underscored && !collection.isView()) {
|
|
597
598
|
options.field = (0, _utils2.snakeCase)(options.field);
|
|
598
599
|
}
|
|
599
600
|
return new Field(options, context);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Association, Includeable, Model, ModelStatic, Transaction } from 'sequelize';
|
|
2
|
+
import Database from '../database';
|
|
2
3
|
interface EagerLoadingNode {
|
|
3
4
|
model: ModelStatic<any>;
|
|
4
5
|
association: Association;
|
|
@@ -8,15 +9,18 @@ interface EagerLoadingNode {
|
|
|
8
9
|
parent?: EagerLoadingNode;
|
|
9
10
|
instances?: Array<Model>;
|
|
10
11
|
order?: any;
|
|
12
|
+
inspectInheritAttribute?: boolean;
|
|
11
13
|
}
|
|
12
14
|
export declare class EagerLoadingTree {
|
|
13
15
|
root: EagerLoadingNode;
|
|
16
|
+
db: Database;
|
|
14
17
|
constructor(root: EagerLoadingNode);
|
|
15
18
|
static buildFromSequelizeOptions(options: {
|
|
16
19
|
model: ModelStatic<any>;
|
|
17
20
|
rootAttributes: Array<string>;
|
|
18
21
|
rootOrder?: any;
|
|
19
22
|
includeOption: Includeable | Includeable[];
|
|
23
|
+
db: Database;
|
|
20
24
|
}): EagerLoadingTree;
|
|
21
25
|
load(pks: Array<string | number>, transaction?: Transaction): Promise<{}>;
|
|
22
26
|
}
|
|
@@ -4,6 +4,13 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.EagerLoadingTree = void 0;
|
|
7
|
+
function _sequelize() {
|
|
8
|
+
const data = require("sequelize");
|
|
9
|
+
_sequelize = function _sequelize() {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
7
14
|
function _lodash() {
|
|
8
15
|
const data = _interopRequireDefault(require("lodash"));
|
|
9
16
|
_lodash = function _lodash() {
|
|
@@ -11,6 +18,8 @@ function _lodash() {
|
|
|
11
18
|
};
|
|
12
19
|
return data;
|
|
13
20
|
}
|
|
21
|
+
var _optionsParser = require("../options-parser");
|
|
22
|
+
var _appendChildCollectionNameAfterRepositoryFind = require("../listeners/append-child-collection-name-after-repository-find");
|
|
14
23
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
24
|
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
16
25
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
@@ -22,28 +31,49 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar
|
|
|
22
31
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
23
32
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
24
33
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
34
|
+
const pushAttribute = (node, attribute) => {
|
|
35
|
+
if (_lodash().default.isArray(node.attributes) && !node.attributes.includes(attribute)) {
|
|
36
|
+
node.attributes.push(attribute);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const EagerLoadingNodeProto = {
|
|
40
|
+
afterBuild(db) {
|
|
41
|
+
const collection = db.modelCollection.get(this.model);
|
|
42
|
+
if (collection && collection.isParent()) {
|
|
43
|
+
if (!this.attributes) {
|
|
44
|
+
this.attributes = {
|
|
45
|
+
include: []
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
_optionsParser.OptionsParser.appendInheritInspectAttribute(_lodash().default.isArray(this.attributes) ? this.attributes : this.attributes.include, collection);
|
|
49
|
+
this.inspectInheritAttribute = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
25
53
|
class EagerLoadingTree {
|
|
26
54
|
constructor(root) {
|
|
27
55
|
this.root = void 0;
|
|
56
|
+
this.db = void 0;
|
|
28
57
|
this.root = root;
|
|
29
58
|
}
|
|
30
59
|
static buildFromSequelizeOptions(options) {
|
|
31
60
|
const model = options.model,
|
|
32
61
|
rootAttributes = options.rootAttributes,
|
|
33
|
-
includeOption = options.includeOption
|
|
34
|
-
|
|
62
|
+
includeOption = options.includeOption,
|
|
63
|
+
db = options.db;
|
|
64
|
+
const buildNode = node => {
|
|
65
|
+
Object.setPrototypeOf(node, EagerLoadingNodeProto);
|
|
66
|
+
node.afterBuild(db);
|
|
67
|
+
return node;
|
|
68
|
+
};
|
|
69
|
+
const root = buildNode({
|
|
35
70
|
model,
|
|
36
71
|
association: null,
|
|
37
72
|
rawAttributes: _lodash().default.cloneDeep(rootAttributes),
|
|
38
73
|
attributes: _lodash().default.cloneDeep(rootAttributes),
|
|
39
74
|
order: options.rootOrder,
|
|
40
75
|
children: []
|
|
41
|
-
};
|
|
42
|
-
const pushAttribute = (node, attribute) => {
|
|
43
|
-
if (_lodash().default.isArray(node.attributes) && !node.attributes.includes(attribute)) {
|
|
44
|
-
node.attributes.push(attribute);
|
|
45
|
-
}
|
|
46
|
-
};
|
|
76
|
+
});
|
|
47
77
|
const traverseIncludeOption = (includeOption, eagerLoadingTreeParent) => {
|
|
48
78
|
const includeOptions = _lodash().default.castArray(includeOption);
|
|
49
79
|
if (includeOption.length > 0) {
|
|
@@ -61,14 +91,14 @@ class EagerLoadingTree {
|
|
|
61
91
|
}
|
|
62
92
|
const association = eagerLoadingTreeParent.model.associations[include.association];
|
|
63
93
|
const associationType = association.associationType;
|
|
64
|
-
const child = {
|
|
94
|
+
const child = buildNode({
|
|
65
95
|
model: association.target,
|
|
66
96
|
association,
|
|
67
97
|
rawAttributes: _lodash().default.cloneDeep(include.attributes),
|
|
68
98
|
attributes: _lodash().default.cloneDeep(include.attributes),
|
|
69
99
|
parent: eagerLoadingTreeParent,
|
|
70
100
|
children: []
|
|
71
|
-
};
|
|
101
|
+
});
|
|
72
102
|
if (associationType == 'HasOne' || associationType == 'HasMany') {
|
|
73
103
|
const sourceKey = association.sourceKey,
|
|
74
104
|
foreignKey = association.foreignKey;
|
|
@@ -97,12 +127,22 @@ class EagerLoadingTree {
|
|
|
97
127
|
}
|
|
98
128
|
};
|
|
99
129
|
traverseIncludeOption(includeOption, root);
|
|
100
|
-
|
|
130
|
+
const tree = new EagerLoadingTree(root);
|
|
131
|
+
tree.db = db;
|
|
132
|
+
return tree;
|
|
101
133
|
}
|
|
102
134
|
load(pks, transaction) {
|
|
103
135
|
var _this = this;
|
|
104
136
|
return _asyncToGenerator(function* () {
|
|
105
137
|
const result = {};
|
|
138
|
+
const orderOption = association => {
|
|
139
|
+
const targetModel = association.target;
|
|
140
|
+
const order = [];
|
|
141
|
+
if (targetModel.primaryKeyAttribute && targetModel.rawAttributes[targetModel.primaryKeyAttribute].autoIncrement) {
|
|
142
|
+
order.push([targetModel.primaryKeyAttribute, 'ASC']);
|
|
143
|
+
}
|
|
144
|
+
return order;
|
|
145
|
+
};
|
|
106
146
|
const loadRecursive = /*#__PURE__*/function () {
|
|
107
147
|
var _ref = _asyncToGenerator(function* (node, ids) {
|
|
108
148
|
const modelPrimaryKey = node.model.primaryKeyAttribute;
|
|
@@ -132,6 +172,7 @@ class EagerLoadingTree {
|
|
|
132
172
|
[foreignKey]: foreignKeyValues
|
|
133
173
|
},
|
|
134
174
|
attributes: node.attributes,
|
|
175
|
+
order: orderOption(association),
|
|
135
176
|
transaction
|
|
136
177
|
};
|
|
137
178
|
instances = yield node.model.findAll(findOptions);
|
|
@@ -149,15 +190,21 @@ class EagerLoadingTree {
|
|
|
149
190
|
}
|
|
150
191
|
if (associationType == 'BelongsToMany') {
|
|
151
192
|
const foreignKeyValues = node.parent.instances.map(instance => instance.get(association.sourceKey));
|
|
193
|
+
const pivotAssoc = new (_sequelize().HasOne)(association.target, association.through.model, {
|
|
194
|
+
as: '_pivot_',
|
|
195
|
+
foreignKey: association.otherKey,
|
|
196
|
+
sourceKey: association.targetKey
|
|
197
|
+
});
|
|
152
198
|
instances = yield node.model.findAll({
|
|
153
199
|
transaction,
|
|
154
200
|
attributes: node.attributes,
|
|
155
201
|
include: [{
|
|
156
|
-
association:
|
|
202
|
+
association: pivotAssoc,
|
|
157
203
|
where: {
|
|
158
204
|
[association.foreignKey]: foreignKeyValues
|
|
159
205
|
}
|
|
160
|
-
}]
|
|
206
|
+
}],
|
|
207
|
+
order: orderOption(association)
|
|
161
208
|
});
|
|
162
209
|
}
|
|
163
210
|
}
|
|
@@ -252,13 +299,17 @@ class EagerLoadingTree {
|
|
|
252
299
|
if (associationType == 'BelongsToMany') {
|
|
253
300
|
const sourceKey = association.sourceKey;
|
|
254
301
|
const foreignKey = association.foreignKey;
|
|
255
|
-
const
|
|
302
|
+
const as = association.oneFromTarget.as;
|
|
256
303
|
var _iterator6 = _createForOfIteratorHelper(node.instances),
|
|
257
304
|
_step6;
|
|
258
305
|
try {
|
|
259
306
|
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
260
307
|
const instance = _step6.value;
|
|
261
|
-
|
|
308
|
+
// set instance accessor
|
|
309
|
+
instance[as] = instance.dataValues[as] = instance['_pivot_'];
|
|
310
|
+
delete instance.dataValues['_pivot_'];
|
|
311
|
+
delete instance['_pivot_'];
|
|
312
|
+
const parentInstance = node.parent.instances.find(parentInstance => parentInstance.get(sourceKey) == instance.dataValues[as].get(foreignKey));
|
|
262
313
|
if (parentInstance) {
|
|
263
314
|
const children = parentInstance.getDataValue(association.as);
|
|
264
315
|
if (!children) {
|
|
@@ -293,13 +344,25 @@ class EagerLoadingTree {
|
|
|
293
344
|
};
|
|
294
345
|
}();
|
|
295
346
|
yield loadRecursive(_this.root, pks);
|
|
347
|
+
const appendChildCollectionName = (0, _appendChildCollectionNameAfterRepositoryFind.appendChildCollectionNameAfterRepositoryFind)(_this.db);
|
|
296
348
|
const setInstanceAttributes = node => {
|
|
297
|
-
|
|
349
|
+
if (node.inspectInheritAttribute) {
|
|
350
|
+
appendChildCollectionName({
|
|
351
|
+
findOptions: {},
|
|
352
|
+
data: node.instances,
|
|
353
|
+
dataCollection: _this.db.modelCollection.get(node.model)
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
// if no attributes are specified, return empty fields
|
|
357
|
+
const nodeRawAttributes = node.rawAttributes || [];
|
|
298
358
|
if (!_lodash().default.isArray(nodeRawAttributes)) {
|
|
299
359
|
return;
|
|
300
360
|
}
|
|
301
361
|
const nodeChildrenAs = node.children.map(child => child.association.as);
|
|
302
362
|
const includeAttributes = [...nodeRawAttributes, ...nodeChildrenAs];
|
|
363
|
+
if (node.inspectInheritAttribute) {
|
|
364
|
+
includeAttributes.push('__schemaName', '__tableName', '__collection');
|
|
365
|
+
}
|
|
303
366
|
var _iterator8 = _createForOfIteratorHelper(node.instances),
|
|
304
367
|
_step8;
|
|
305
368
|
try {
|
|
@@ -2,8 +2,8 @@ import { BelongsToOptions as SequelizeBelongsToOptions } from 'sequelize';
|
|
|
2
2
|
import { Reference } from '../features/ReferencesMap';
|
|
3
3
|
import { BaseRelationFieldOptions, RelationField } from './relation-field';
|
|
4
4
|
export declare class BelongsToField extends RelationField {
|
|
5
|
-
get dataType(): string;
|
|
6
5
|
static type: string;
|
|
6
|
+
get dataType(): string;
|
|
7
7
|
get target(): any;
|
|
8
8
|
static toReference(db: any, association: any, onDelete: any): {
|
|
9
9
|
sourceCollectionName: any;
|
|
@@ -85,7 +85,8 @@ class BelongsToField extends _relationField.RelationField {
|
|
|
85
85
|
this.options.sourceKey = association.sourceKey;
|
|
86
86
|
}
|
|
87
87
|
this.collection.addIndex([this.options.foreignKey]);
|
|
88
|
-
this.
|
|
88
|
+
const reference = this.reference(association);
|
|
89
|
+
this.database.referenceMap.addReference(reference);
|
|
89
90
|
return true;
|
|
90
91
|
}
|
|
91
92
|
unbind() {
|
|
@@ -105,7 +106,7 @@ class BelongsToField extends _relationField.RelationField {
|
|
|
105
106
|
collection.model.removeAttribute(foreignKey);
|
|
106
107
|
}
|
|
107
108
|
const association = collection.model.associations[this.name];
|
|
108
|
-
if (association) {
|
|
109
|
+
if (association && !this.options.inherit) {
|
|
109
110
|
const reference = this.reference(association);
|
|
110
111
|
this.database.referenceMap.removeReference(reference);
|
|
111
112
|
}
|
|
@@ -119,7 +119,7 @@ class BelongsToManyField extends _relationField.RelationField {
|
|
|
119
119
|
database.removePendingField(this);
|
|
120
120
|
// 删掉 model 的关联字段
|
|
121
121
|
const association = collection.model.associations[this.name];
|
|
122
|
-
if (association) {
|
|
122
|
+
if (association && !this.options.inherit) {
|
|
123
123
|
this.references(association).forEach(reference => this.database.referenceMap.removeReference(reference));
|
|
124
124
|
}
|
|
125
125
|
this.clearAccessors();
|
|
@@ -114,7 +114,7 @@ class HasManyField extends _relationField.RelationField {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
116
|
const association = collection.model.associations[this.name];
|
|
117
|
-
if (association) {
|
|
117
|
+
if (association && !this.options.inherit) {
|
|
118
118
|
this.database.referenceMap.removeReference(this.reference(association));
|
|
119
119
|
}
|
|
120
120
|
this.clearAccessors();
|
|
@@ -118,7 +118,7 @@ class HasOneField extends _relationField.RelationField {
|
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
const association = collection.model.associations[this.name];
|
|
121
|
-
if (association) {
|
|
121
|
+
if (association && !this.options.inherit) {
|
|
122
122
|
this.database.referenceMap.removeReference(this.reference(association));
|
|
123
123
|
}
|
|
124
124
|
this.clearAccessors();
|
|
@@ -19,7 +19,11 @@ const appendChildCollectionNameAfterRepositoryFind = db => {
|
|
|
19
19
|
try {
|
|
20
20
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
21
21
|
const row = _step.value;
|
|
22
|
-
|
|
22
|
+
if (row.__collection) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const fullTableName = findOptions.raw ? `${row['__schemaName']}.${row['__tableName']}` : `${row.get('__schemaName')}.${row.get('__tableName')}`;
|
|
26
|
+
const rowCollection = db.tableNameCollectionMap.get(fullTableName);
|
|
23
27
|
if (!rowCollection) {
|
|
24
28
|
db.logger.warn(`Can not find collection by table name ${JSON.stringify(row)}, current collections: ${Array.from(db.tableNameCollectionMap.keys()).join(', ')}`);
|
|
25
29
|
return;
|
package/lib/options-parser.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare class OptionsParser {
|
|
|
15
15
|
filterParser: FilterParser;
|
|
16
16
|
context: OptionsParserContext;
|
|
17
17
|
constructor(options: FindOptions, context: OptionsParserContext);
|
|
18
|
+
static appendInheritInspectAttribute(include: any, collection: any): any;
|
|
18
19
|
isAssociation(key: string): boolean;
|
|
19
20
|
isAssociationPath(path: string): boolean;
|
|
20
21
|
toSequelizeParams(): any;
|
|
@@ -24,7 +25,6 @@ export declare class OptionsParser {
|
|
|
24
25
|
* @protected
|
|
25
26
|
*/
|
|
26
27
|
protected parseSort(filterParams: any): any;
|
|
27
|
-
protected inheritFromSubQuery(include: any): any;
|
|
28
28
|
protected parseFields(filterParams: any): any;
|
|
29
29
|
protected parseExcept(except: Except, filterParams: any): any;
|
|
30
30
|
protected parseAppends(appends: Appends, filterParams: any): any;
|
package/lib/options-parser.js
CHANGED
|
@@ -43,6 +43,19 @@ class OptionsParser {
|
|
|
43
43
|
});
|
|
44
44
|
this.context = context;
|
|
45
45
|
}
|
|
46
|
+
static appendInheritInspectAttribute(include, collection) {
|
|
47
|
+
// if include already has __tableName, __schemaName, skip
|
|
48
|
+
if (include.find(item => (item === null || item === void 0 ? void 0 : item[1]) === '__tableName')) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
include.push([_sequelize().Sequelize.literal(`(select relname from pg_class where pg_class.oid = "${collection.name}".tableoid)`), '__tableName']);
|
|
52
|
+
include.push([_sequelize().Sequelize.literal(`
|
|
53
|
+
(SELECT n.nspname
|
|
54
|
+
FROM pg_class c
|
|
55
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
56
|
+
WHERE c.oid = "${collection.name}".tableoid)
|
|
57
|
+
`), '__schemaName']);
|
|
58
|
+
}
|
|
46
59
|
isAssociation(key) {
|
|
47
60
|
return this.model.associations[key] !== undefined;
|
|
48
61
|
}
|
|
@@ -113,15 +126,6 @@ class OptionsParser {
|
|
|
113
126
|
}
|
|
114
127
|
return filterParams;
|
|
115
128
|
}
|
|
116
|
-
inheritFromSubQuery(include) {
|
|
117
|
-
include.push([_sequelize().Sequelize.literal(`(select relname from pg_class where pg_class.oid = "${this.collection.name}".tableoid)`), '__tableName']);
|
|
118
|
-
include.push([_sequelize().Sequelize.literal(`
|
|
119
|
-
(SELECT n.nspname
|
|
120
|
-
FROM pg_class c
|
|
121
|
-
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
122
|
-
WHERE c.oid = "${this.collection.name}".tableoid)
|
|
123
|
-
`), '__schemaName']);
|
|
124
|
-
}
|
|
125
129
|
parseFields(filterParams) {
|
|
126
130
|
var _this$options3, _this$options4, _this$options5, _this$options6;
|
|
127
131
|
const appends = ((_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.appends) || [];
|
|
@@ -136,12 +140,12 @@ class OptionsParser {
|
|
|
136
140
|
exclude: []
|
|
137
141
|
}; // out put all fields by default
|
|
138
142
|
if (this.collection.isParent()) {
|
|
139
|
-
|
|
143
|
+
OptionsParser.appendInheritInspectAttribute(attributes.include, this.collection);
|
|
140
144
|
}
|
|
141
145
|
if ((_this$options5 = this.options) === null || _this$options5 === void 0 ? void 0 : _this$options5.fields) {
|
|
142
146
|
attributes = [];
|
|
143
147
|
if (this.collection.isParent()) {
|
|
144
|
-
|
|
148
|
+
OptionsParser.appendInheritInspectAttribute(attributes, this.collection);
|
|
145
149
|
}
|
|
146
150
|
// 将fields拆分为 attributes 和 appends
|
|
147
151
|
var _iterator2 = _createForOfIteratorHelper(this.options.fields),
|
|
@@ -65,7 +65,8 @@ class MultipleRelationRepository extends _relationRepository.RelationRepository
|
|
|
65
65
|
model: _this.targetModel,
|
|
66
66
|
rootAttributes: findOptions.attributes,
|
|
67
67
|
includeOption: findOptions.include,
|
|
68
|
-
rootOrder: findOptions.order
|
|
68
|
+
rootOrder: findOptions.order,
|
|
69
|
+
db: _this.db
|
|
69
70
|
});
|
|
70
71
|
yield eagerLoadingTree.load(ids.map(i => i.pk), transaction);
|
|
71
72
|
return eagerLoadingTree.root.instances;
|
|
@@ -71,7 +71,8 @@ class SingleRelationRepository extends _relationRepository.RelationRepository {
|
|
|
71
71
|
const eagerLoadingTree = _eagerLoadingTree.EagerLoadingTree.buildFromSequelizeOptions({
|
|
72
72
|
model: _this3.targetModel,
|
|
73
73
|
rootAttributes: findOptions.attributes,
|
|
74
|
-
includeOption: findOptions.include
|
|
74
|
+
includeOption: findOptions.include,
|
|
75
|
+
db: _this3.db
|
|
75
76
|
});
|
|
76
77
|
yield eagerLoadingTree.load([templateModel.get(_this3.targetModel.primaryKeyAttribute)], transaction);
|
|
77
78
|
return eagerLoadingTree.root.instances[0];
|
package/lib/repository.d.ts
CHANGED
|
@@ -119,11 +119,18 @@ export interface AggregateOptions {
|
|
|
119
119
|
filter?: Filter;
|
|
120
120
|
distinct?: boolean;
|
|
121
121
|
}
|
|
122
|
+
interface FirstOrCreateOptions extends Transactionable {
|
|
123
|
+
filterKeys: string[];
|
|
124
|
+
values?: Values;
|
|
125
|
+
}
|
|
122
126
|
export declare class Repository<TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes> implements IRepository {
|
|
123
127
|
database: Database;
|
|
124
128
|
collection: Collection;
|
|
125
129
|
model: ModelStatic<Model>;
|
|
126
130
|
constructor(collection: Collection);
|
|
131
|
+
static valuesToFilter(values: Values, filterKeys: Array<string>): {
|
|
132
|
+
$and: any[];
|
|
133
|
+
};
|
|
127
134
|
/**
|
|
128
135
|
* return count by filter
|
|
129
136
|
*/
|
|
@@ -152,6 +159,11 @@ export declare class Repository<TModelAttributes extends {} = any, TCreationAttr
|
|
|
152
159
|
* @param options
|
|
153
160
|
*/
|
|
154
161
|
findOne(options?: FindOneOptions): Promise<any>;
|
|
162
|
+
/**
|
|
163
|
+
* Get the first record matching the attributes or create it.
|
|
164
|
+
*/
|
|
165
|
+
firstOrCreate(options: FirstOrCreateOptions): Promise<any>;
|
|
166
|
+
updateOrCreate(options: FirstOrCreateOptions): Promise<any>;
|
|
155
167
|
/**
|
|
156
168
|
* Save instance to database
|
|
157
169
|
*
|