tspace-mysql 1.4.6 → 1.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +161 -69
- package/dist/cli/generate/model.js +1 -1
- package/dist/lib/connection/index.d.ts +1 -1
- package/dist/lib/connection/index.js +1 -1
- package/dist/lib/constants/index.js +12 -10
- package/dist/lib/tspace/Abstract/AbstractBuilder.d.ts +4 -2
- package/dist/lib/tspace/Abstract/AbstractBuilder.js +5 -1
- package/dist/lib/tspace/Abstract/AbstractDB.d.ts +0 -2
- package/dist/lib/tspace/Abstract/AbstractModel.d.ts +6 -4
- package/dist/lib/tspace/Abstract/AbstractModel.js +2 -5
- package/dist/lib/tspace/Blueprint.d.ts +10 -2
- package/dist/lib/tspace/Blueprint.js +11 -1
- package/dist/lib/tspace/Builder.d.ts +556 -189
- package/dist/lib/tspace/Builder.js +1400 -947
- package/dist/lib/tspace/DB.d.ts +100 -88
- package/dist/lib/tspace/DB.js +134 -212
- package/dist/lib/tspace/Interface.d.ts +24 -4
- package/dist/lib/tspace/Model.d.ts +312 -205
- package/dist/lib/tspace/Model.js +921 -1073
- package/dist/lib/tspace/RelationHandler.d.ts +32 -0
- package/dist/lib/tspace/RelationHandler.js +529 -0
- package/dist/lib/tspace/Schema.d.ts +9 -4
- package/dist/lib/tspace/Schema.js +119 -45
- package/dist/lib/tspace/StateHandler.js +4 -0
- package/dist/lib/utils/index.d.ts +4 -1
- package/dist/lib/utils/index.js +29 -3
- package/package.json +1 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Relation, RelationQuery } from "./Interface";
|
|
2
|
+
import { Model } from "./Model";
|
|
3
|
+
declare class RelationHandler {
|
|
4
|
+
private MODEL;
|
|
5
|
+
private $constants;
|
|
6
|
+
private $logger;
|
|
7
|
+
constructor(model: Model);
|
|
8
|
+
load(parents: Record<string, any>[], relation: Relation): Promise<any[]>;
|
|
9
|
+
loadExists(): string;
|
|
10
|
+
apply(nameRelations: string[], type: 'all' | 'exists' | 'trashed' | 'default'): Relation[];
|
|
11
|
+
callback(nameRelation: string, cb: Function): void;
|
|
12
|
+
hasOne({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
|
|
13
|
+
hasMany({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
|
|
14
|
+
belongsTo({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
|
|
15
|
+
belongsToMany({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }: Relation): void;
|
|
16
|
+
hasOneBuilder({ name, as, model, localKey, foreignKey, freezeTable, }: RelationQuery, callback?: Function): this | undefined;
|
|
17
|
+
hasManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, }: RelationQuery, callback?: Function): this | undefined;
|
|
18
|
+
belongsToBuilder({ name, as, model, localKey, foreignKey, freezeTable, }: RelationQuery, callback?: Function): this | undefined;
|
|
19
|
+
belongsToManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, pivot }: RelationQuery, callback?: Function): this | undefined;
|
|
20
|
+
private _handleRelationsExists;
|
|
21
|
+
private _relationBuilder;
|
|
22
|
+
private _functionRelationName;
|
|
23
|
+
private _relationMapData;
|
|
24
|
+
private _belongsToMany;
|
|
25
|
+
private _valueInRelation;
|
|
26
|
+
private _valuePattern;
|
|
27
|
+
private _assertError;
|
|
28
|
+
protected _getState(key: string): any;
|
|
29
|
+
protected _setState(key: string, value: any): void;
|
|
30
|
+
}
|
|
31
|
+
export { RelationHandler };
|
|
32
|
+
export default RelationHandler;
|
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.RelationHandler = void 0;
|
|
16
|
+
const pluralize_1 = __importDefault(require("pluralize"));
|
|
17
|
+
const Model_1 = require("./Model");
|
|
18
|
+
class RelationHandler {
|
|
19
|
+
constructor(model) {
|
|
20
|
+
this.MODEL = model;
|
|
21
|
+
this.$constants = this.MODEL["$constants"];
|
|
22
|
+
this.$logger = this.MODEL["$logger"];
|
|
23
|
+
}
|
|
24
|
+
load(parents, relation) {
|
|
25
|
+
var _a;
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
const relationIsBelongsToMany = relation.relation === this.$constants('RELATIONSHIP').belongsToMany;
|
|
28
|
+
if (relationIsBelongsToMany) {
|
|
29
|
+
return yield this._belongsToMany(parents, relation);
|
|
30
|
+
}
|
|
31
|
+
if (!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length))
|
|
32
|
+
return [];
|
|
33
|
+
const { localKey, foreignKey } = this._valueInRelation(relation);
|
|
34
|
+
const localKeyId = parents
|
|
35
|
+
.map((parent) => {
|
|
36
|
+
const data = parent[localKey];
|
|
37
|
+
if (parent.hasOwnProperty(localKey))
|
|
38
|
+
return data;
|
|
39
|
+
this.MODEL['_assertError'](data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
|
|
40
|
+
})
|
|
41
|
+
.filter(d => d != null);
|
|
42
|
+
const parentIds = Array.from(new Set(localKeyId)) || [];
|
|
43
|
+
if (!parentIds.length && this._getState('RELATIONS_EXISTS'))
|
|
44
|
+
return [];
|
|
45
|
+
const query = relation.query;
|
|
46
|
+
this._assertError(query == null, `Unknown callback query in [Relation : ${relation.name}]`);
|
|
47
|
+
const results = yield query
|
|
48
|
+
.whereIn(foreignKey, parentIds)
|
|
49
|
+
.debug(this._getState('DEBUG'))
|
|
50
|
+
.when(relation.trashed, (query) => query.onlyTrashed())
|
|
51
|
+
.when(relation.all, (query) => query.disableSoftDelete())
|
|
52
|
+
.bind(this.MODEL['$pool'].get())
|
|
53
|
+
.get();
|
|
54
|
+
return this._relationMapData(parents, results, relation);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
loadExists() {
|
|
58
|
+
var _a, _b, _c;
|
|
59
|
+
const relations = this._getState('RELATIONS');
|
|
60
|
+
for (const index in relations) {
|
|
61
|
+
const relation = relations[index];
|
|
62
|
+
if (!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length))
|
|
63
|
+
continue;
|
|
64
|
+
if (relation.exists == null)
|
|
65
|
+
continue;
|
|
66
|
+
const { localKey, foreignKey, pivot, modelPivot } = this._valueInRelation(relation);
|
|
67
|
+
const query = relation.query;
|
|
68
|
+
this._assertError(query == null, `Unknown callback query in [Relation : '${relation.name}']`);
|
|
69
|
+
let clone = new Model_1.Model().clone(query);
|
|
70
|
+
const cloneRelations = clone['_getState']('RELATIONS');
|
|
71
|
+
if (cloneRelations.length) {
|
|
72
|
+
for (const r of cloneRelations) {
|
|
73
|
+
if (r.query == null)
|
|
74
|
+
continue;
|
|
75
|
+
const sql = (_c = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._handleRelationsExists(r)) !== null && _c !== void 0 ? _c : '';
|
|
76
|
+
clone.whereExists(sql);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (relation.relation === this.$constants('RELATIONSHIP').belongsToMany) {
|
|
80
|
+
const thisPivot = modelPivot
|
|
81
|
+
? new modelPivot
|
|
82
|
+
: new Model_1.Model().table(String(pivot));
|
|
83
|
+
const sql = clone
|
|
84
|
+
.bind(this.MODEL['$pool'].get())
|
|
85
|
+
.select(this._getState('PRIMARY_KEY'))
|
|
86
|
+
.whereReference(`\`${query.getTableName()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${localKey}\``)
|
|
87
|
+
.toString();
|
|
88
|
+
thisPivot.whereExists(sql);
|
|
89
|
+
const sqlPivot = thisPivot
|
|
90
|
+
.bind(this.MODEL['$pool'].get())
|
|
91
|
+
.select(thisPivot['$state'].get('PRIMARY_KEY'))
|
|
92
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${pivot}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
|
|
93
|
+
.toString();
|
|
94
|
+
this.MODEL['whereExists'](sqlPivot);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const sql = clone
|
|
98
|
+
.bind(this.MODEL['$pool'].get())
|
|
99
|
+
.select(this._getState('PRIMARY_KEY'))
|
|
100
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${query.getTableName()}\`.\`${foreignKey}\``)
|
|
101
|
+
.toString();
|
|
102
|
+
this.MODEL['whereExists'](sql);
|
|
103
|
+
}
|
|
104
|
+
const sql = this.MODEL['_queryBuilder']().select();
|
|
105
|
+
return sql;
|
|
106
|
+
}
|
|
107
|
+
apply(nameRelations, type) {
|
|
108
|
+
const relations = nameRelations.map((name) => {
|
|
109
|
+
var _a, _b, _c;
|
|
110
|
+
const relation = (_a = this._getState('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
|
|
111
|
+
this._assertError(relation == null, `This Relation "${name}" not be register in Model "${(_b = this.constructor) === null || _b === void 0 ? void 0 : _b.name}"`);
|
|
112
|
+
const relationHasExists = (_c = Object.values(this.$constants('RELATIONSHIP'))) === null || _c === void 0 ? void 0 : _c.includes(relation.relation);
|
|
113
|
+
this._assertError(!relationHasExists, `Unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
114
|
+
if (relation.query == null)
|
|
115
|
+
relation.query = new relation.model();
|
|
116
|
+
return relation;
|
|
117
|
+
});
|
|
118
|
+
for (const relation of relations) {
|
|
119
|
+
if (type === 'default')
|
|
120
|
+
break;
|
|
121
|
+
relation[type] = true;
|
|
122
|
+
}
|
|
123
|
+
return this._getState('RELATIONS').length
|
|
124
|
+
? [...relations.map((w) => {
|
|
125
|
+
const exists = this._getState('RELATIONS').find((r) => r.name === w.name);
|
|
126
|
+
if (exists)
|
|
127
|
+
return null;
|
|
128
|
+
return w;
|
|
129
|
+
}).filter((d) => d != null),
|
|
130
|
+
...this._getState('RELATIONS')]
|
|
131
|
+
: relations;
|
|
132
|
+
}
|
|
133
|
+
callback(nameRelation, cb) {
|
|
134
|
+
var _a, _b;
|
|
135
|
+
const relation = this._getState('RELATIONS').find((data) => data.name === nameRelation);
|
|
136
|
+
this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
|
|
137
|
+
const relationHasExists = (_b = Object.values(this.$constants('RELATIONSHIP'))) === null || _b === void 0 ? void 0 : _b.includes(relation.relation);
|
|
138
|
+
this._assertError(!relationHasExists, `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
139
|
+
relation.query = cb(new relation.model());
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
hasOne({ name, as, model, localKey, foreignKey, freezeTable }) {
|
|
143
|
+
const relation = {
|
|
144
|
+
name,
|
|
145
|
+
model,
|
|
146
|
+
as,
|
|
147
|
+
relation: this.$constants('RELATIONSHIP').hasOne,
|
|
148
|
+
localKey,
|
|
149
|
+
foreignKey,
|
|
150
|
+
freezeTable,
|
|
151
|
+
query: null
|
|
152
|
+
};
|
|
153
|
+
return this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
154
|
+
}
|
|
155
|
+
hasMany({ name, as, model, localKey, foreignKey, freezeTable }) {
|
|
156
|
+
const relation = {
|
|
157
|
+
name,
|
|
158
|
+
model,
|
|
159
|
+
as,
|
|
160
|
+
relation: this.$constants('RELATIONSHIP').hasMany,
|
|
161
|
+
localKey,
|
|
162
|
+
foreignKey,
|
|
163
|
+
freezeTable,
|
|
164
|
+
query: null
|
|
165
|
+
};
|
|
166
|
+
return this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
167
|
+
}
|
|
168
|
+
belongsTo({ name, as, model, localKey, foreignKey, freezeTable }) {
|
|
169
|
+
const relation = {
|
|
170
|
+
name,
|
|
171
|
+
model,
|
|
172
|
+
as,
|
|
173
|
+
relation: this.$constants('RELATIONSHIP').belongsTo,
|
|
174
|
+
localKey,
|
|
175
|
+
foreignKey,
|
|
176
|
+
freezeTable,
|
|
177
|
+
query: null
|
|
178
|
+
};
|
|
179
|
+
return this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
180
|
+
}
|
|
181
|
+
belongsToMany({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }) {
|
|
182
|
+
const relation = {
|
|
183
|
+
name,
|
|
184
|
+
model,
|
|
185
|
+
as,
|
|
186
|
+
relation: this.$constants('RELATIONSHIP').belongsToMany,
|
|
187
|
+
localKey,
|
|
188
|
+
foreignKey,
|
|
189
|
+
freezeTable,
|
|
190
|
+
pivot,
|
|
191
|
+
oldVersion,
|
|
192
|
+
query: null,
|
|
193
|
+
modelPivot
|
|
194
|
+
};
|
|
195
|
+
return this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
196
|
+
}
|
|
197
|
+
hasOneBuilder({ name, as, model, localKey, foreignKey, freezeTable, }, callback) {
|
|
198
|
+
const nameRelation = name == null
|
|
199
|
+
? this._functionRelationName()
|
|
200
|
+
: String(name);
|
|
201
|
+
const relation = {
|
|
202
|
+
name: nameRelation,
|
|
203
|
+
model,
|
|
204
|
+
as,
|
|
205
|
+
relation: this.$constants('RELATIONSHIP').hasOne,
|
|
206
|
+
localKey,
|
|
207
|
+
foreignKey,
|
|
208
|
+
freezeTable,
|
|
209
|
+
query: null
|
|
210
|
+
};
|
|
211
|
+
const r = this._relationBuilder(nameRelation, relation);
|
|
212
|
+
if (callback == null) {
|
|
213
|
+
r.query = new r.model();
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
r.query = callback(new r.model());
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
hasManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, }, callback) {
|
|
220
|
+
const nameRelation = name == null
|
|
221
|
+
? this._functionRelationName()
|
|
222
|
+
: String(name);
|
|
223
|
+
const relation = {
|
|
224
|
+
name: nameRelation,
|
|
225
|
+
model,
|
|
226
|
+
as,
|
|
227
|
+
relation: this.$constants('RELATIONSHIP').hasMany,
|
|
228
|
+
localKey,
|
|
229
|
+
foreignKey,
|
|
230
|
+
freezeTable,
|
|
231
|
+
query: null
|
|
232
|
+
};
|
|
233
|
+
const r = this._relationBuilder(nameRelation, relation);
|
|
234
|
+
if (callback == null) {
|
|
235
|
+
r.query = new r.model();
|
|
236
|
+
return this;
|
|
237
|
+
}
|
|
238
|
+
r.query = callback(new r.model());
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
belongsToBuilder({ name, as, model, localKey, foreignKey, freezeTable, }, callback) {
|
|
242
|
+
const nameRelation = name == null
|
|
243
|
+
? this._functionRelationName()
|
|
244
|
+
: String(name);
|
|
245
|
+
const relation = {
|
|
246
|
+
name: nameRelation,
|
|
247
|
+
model,
|
|
248
|
+
as,
|
|
249
|
+
relation: this.$constants('RELATIONSHIP').belongsTo,
|
|
250
|
+
localKey,
|
|
251
|
+
foreignKey,
|
|
252
|
+
freezeTable,
|
|
253
|
+
query: null
|
|
254
|
+
};
|
|
255
|
+
const r = this._relationBuilder(nameRelation, relation);
|
|
256
|
+
if (callback == null) {
|
|
257
|
+
r.query = new r.model();
|
|
258
|
+
return this;
|
|
259
|
+
}
|
|
260
|
+
r.query = callback(new r.model());
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
belongsToManyBuilder({ name, as, model, localKey, foreignKey, freezeTable, pivot }, callback) {
|
|
264
|
+
const nameRelation = name == null
|
|
265
|
+
? this._functionRelationName()
|
|
266
|
+
: String(name);
|
|
267
|
+
const relation = {
|
|
268
|
+
name: nameRelation,
|
|
269
|
+
model,
|
|
270
|
+
as,
|
|
271
|
+
relation: this.$constants('RELATIONSHIP').belongsToMany,
|
|
272
|
+
localKey,
|
|
273
|
+
foreignKey,
|
|
274
|
+
freezeTable,
|
|
275
|
+
pivot,
|
|
276
|
+
query: null
|
|
277
|
+
};
|
|
278
|
+
const r = this._relationBuilder(nameRelation, relation);
|
|
279
|
+
if (callback == null) {
|
|
280
|
+
r.query = new r.model();
|
|
281
|
+
return this;
|
|
282
|
+
}
|
|
283
|
+
r.query = callback(new r.model());
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
_handleRelationsExists(relation) {
|
|
287
|
+
var _a, _b, _c;
|
|
288
|
+
this._assertError(!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length), `unknown [relation]`);
|
|
289
|
+
const { localKey, foreignKey } = this._valueInRelation(relation);
|
|
290
|
+
const query = relation.query;
|
|
291
|
+
this._assertError(query == null, `Unknown callback query in [Relation : '${relation.name}']`);
|
|
292
|
+
const clone = new Model_1.Model().clone(query);
|
|
293
|
+
const cloneRelations = clone['_getState']('RELATIONS');
|
|
294
|
+
if (cloneRelations.length) {
|
|
295
|
+
for (const r of cloneRelations) {
|
|
296
|
+
if (r.query == null)
|
|
297
|
+
continue;
|
|
298
|
+
const sql = (_c = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._handleRelationsExists(r)) !== null && _c !== void 0 ? _c : '';
|
|
299
|
+
clone.whereExists(sql);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const sql = clone
|
|
303
|
+
.bind(this.MODEL['$pool'].get())
|
|
304
|
+
.select(this._getState('PRIMARY_KEY'))
|
|
305
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${query.getTableName()}\`.\`${foreignKey}\``)
|
|
306
|
+
.toString();
|
|
307
|
+
return sql;
|
|
308
|
+
}
|
|
309
|
+
_relationBuilder(nameRelation, relation) {
|
|
310
|
+
var _a;
|
|
311
|
+
this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
312
|
+
this.MODEL['with'](nameRelation);
|
|
313
|
+
const r = this._getState('RELATIONS').find((data) => data.name === nameRelation);
|
|
314
|
+
this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
|
|
315
|
+
this._assertError(!Object.values(this.$constants('RELATIONSHIP')).includes(r.relation), `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
316
|
+
return r;
|
|
317
|
+
}
|
|
318
|
+
_functionRelationName() {
|
|
319
|
+
const functionName = [...this.$logger.get()][this.$logger.get().length - 2];
|
|
320
|
+
return functionName.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
|
|
321
|
+
}
|
|
322
|
+
_relationMapData(dataParents, dataChilds, relations) {
|
|
323
|
+
const { name, as, relation, localKey, foreignKey } = this._valueInRelation(relations);
|
|
324
|
+
const keyRelation = as !== null && as !== void 0 ? as : name;
|
|
325
|
+
for (const dataParent of dataParents) {
|
|
326
|
+
const relationIsHasOneOrBelongsTo = [
|
|
327
|
+
this.$constants('RELATIONSHIP').hasOne,
|
|
328
|
+
this.$constants('RELATIONSHIP').belongsTo
|
|
329
|
+
].some(r => r === relation);
|
|
330
|
+
dataParent[keyRelation] = [];
|
|
331
|
+
if (relationIsHasOneOrBelongsTo)
|
|
332
|
+
dataParent[keyRelation] = null;
|
|
333
|
+
if (!dataChilds.length)
|
|
334
|
+
continue;
|
|
335
|
+
for (const dataChild of dataChilds) {
|
|
336
|
+
if (dataChild[foreignKey] === dataParent[localKey]) {
|
|
337
|
+
const relationIsHasOneOrBelongsTo = [
|
|
338
|
+
this.$constants('RELATIONSHIP').hasOne,
|
|
339
|
+
this.$constants('RELATIONSHIP').belongsTo
|
|
340
|
+
].some(r => r === relation);
|
|
341
|
+
if (relationIsHasOneOrBelongsTo) {
|
|
342
|
+
dataParent[keyRelation] = dataParent[keyRelation] || dataChild;
|
|
343
|
+
continue;
|
|
344
|
+
}
|
|
345
|
+
if (dataParent[keyRelation] == null)
|
|
346
|
+
dataParent[keyRelation] = [];
|
|
347
|
+
dataParent[keyRelation].push(dataChild);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return dataParents;
|
|
352
|
+
}
|
|
353
|
+
_belongsToMany(parents, relation) {
|
|
354
|
+
var _a;
|
|
355
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
356
|
+
const { name, foreignKey, localKey, pivot, oldVersion, modelPivot } = this._valueInRelation(relation);
|
|
357
|
+
const localKeyId = parents.map((parent) => {
|
|
358
|
+
const data = parent[foreignKey];
|
|
359
|
+
if (parent.hasOwnProperty(foreignKey))
|
|
360
|
+
return data;
|
|
361
|
+
this._assertError(data == null, `Unknown relationship without primary or foreign key in Relation : [${relation === null || relation === void 0 ? void 0 : relation.name}]`);
|
|
362
|
+
}).filter((d) => d != null);
|
|
363
|
+
const mainResultIds = Array.from(new Set(localKeyId));
|
|
364
|
+
if (!mainResultIds.length && this._getState('RELATIONS_EXISTS'))
|
|
365
|
+
return [];
|
|
366
|
+
const modelRelation = new relation.model();
|
|
367
|
+
const relationColumn = this.MODEL['_classToTableName'](modelRelation.constructor.name, { singular: true });
|
|
368
|
+
const mainlocalKey = 'id';
|
|
369
|
+
const relationForeignKey = this._valuePattern(`${relationColumn}Id`);
|
|
370
|
+
const localKeyPivotTable = this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"));
|
|
371
|
+
const pivotTable = String(((_a = relation.pivot) !== null && _a !== void 0 ? _a : pivot));
|
|
372
|
+
const sqlPivotExists = new Model_1.Model()
|
|
373
|
+
.copyModel(modelRelation)
|
|
374
|
+
.select(this._getState('PRIMARY_KEY'))
|
|
375
|
+
.whereReference(`\`${modelRelation.getTableName()}\`.\`${foreignKey}\``, `\`${pivotTable}\`.\`${localKey}\``)
|
|
376
|
+
.toString();
|
|
377
|
+
const queryPivot = modelPivot
|
|
378
|
+
? new modelPivot()
|
|
379
|
+
: new Model_1.Model().table(pivotTable);
|
|
380
|
+
const sqlPivot = queryPivot
|
|
381
|
+
.whereIn(localKeyPivotTable, mainResultIds)
|
|
382
|
+
.when(relation.exists, (query) => query.whereExists(sqlPivotExists))
|
|
383
|
+
.when(relation.trashed, (query) => query.onlyTrashed())
|
|
384
|
+
.when(relation.all, (query) => query.disableSoftDelete())
|
|
385
|
+
.toString();
|
|
386
|
+
const pivotResults = yield this.MODEL['_queryStatement'](sqlPivot);
|
|
387
|
+
const relationIds = Array.from(new Set(pivotResults
|
|
388
|
+
.map((pivotResult) => pivotResult[relationForeignKey])
|
|
389
|
+
.filter((d) => d != null)));
|
|
390
|
+
const relationResults = yield this.MODEL['_queryStatement'](modelRelation
|
|
391
|
+
.whereIn(mainlocalKey, relationIds)
|
|
392
|
+
.when(relation.trashed, (query) => query.disableSoftDelete())
|
|
393
|
+
.toString());
|
|
394
|
+
if (oldVersion) {
|
|
395
|
+
for (const pivotResult of pivotResults) {
|
|
396
|
+
for (const relationResult of relationResults) {
|
|
397
|
+
if (relationResult[mainlocalKey] !== pivotResult[relationForeignKey])
|
|
398
|
+
continue;
|
|
399
|
+
pivotResult[relationColumn] = relationResult;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
for (const parent of parents) {
|
|
403
|
+
if (parent[name] == null)
|
|
404
|
+
parent[name] = [];
|
|
405
|
+
for (const pivotResult of pivotResults) {
|
|
406
|
+
if (pivotResult[localKeyPivotTable] !== parent[foreignKey])
|
|
407
|
+
continue;
|
|
408
|
+
parent[name].push(pivotResult);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
if (this._getState('HIDDEN').length)
|
|
412
|
+
this.MODEL['_hiddenColumnModel'](parents);
|
|
413
|
+
return parents;
|
|
414
|
+
}
|
|
415
|
+
for (const parent of parents) {
|
|
416
|
+
if (parent[name] == null)
|
|
417
|
+
parent[name] = [];
|
|
418
|
+
for (const pivotResult of pivotResults) {
|
|
419
|
+
if (pivotResult[localKeyPivotTable] !== parent[foreignKey])
|
|
420
|
+
continue;
|
|
421
|
+
const data = relationResults.find(relationResult => relationResult[foreignKey] === pivotResult[localKey]);
|
|
422
|
+
if (data == null)
|
|
423
|
+
continue;
|
|
424
|
+
data.pivot = {
|
|
425
|
+
[localKeyPivotTable]: pivotResult[localKeyPivotTable],
|
|
426
|
+
[localKey]: pivotResult[localKey],
|
|
427
|
+
};
|
|
428
|
+
parent[name].push(data);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (this._getState('HIDDEN').length)
|
|
432
|
+
this.MODEL['_hiddenColumnModel'](parents);
|
|
433
|
+
return parents;
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
_valueInRelation(relationModel) {
|
|
437
|
+
var _a, _b, _c;
|
|
438
|
+
this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, 'Nested Relation isn\'t supported Promise method');
|
|
439
|
+
this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model_1.Model), 'Callback function supported instance of Model only');
|
|
440
|
+
const relation = relationModel.relation;
|
|
441
|
+
const model = (_a = relationModel.model) === null || _a === void 0 ? void 0 : _a.name;
|
|
442
|
+
const modelPivot = relationModel.modelPivot;
|
|
443
|
+
const oldVersion = relationModel.oldVersion;
|
|
444
|
+
const table = relationModel.freezeTable
|
|
445
|
+
? relationModel.freezeTable
|
|
446
|
+
: (_b = relationModel.query) === null || _b === void 0 ? void 0 : _b.getTableName();
|
|
447
|
+
let pivot = null;
|
|
448
|
+
const name = relationModel.name;
|
|
449
|
+
const as = relationModel.as;
|
|
450
|
+
this._assertError(!model || model == null, 'Not found model');
|
|
451
|
+
let localKey = this._valuePattern(relationModel.localKey
|
|
452
|
+
? relationModel.localKey
|
|
453
|
+
: this._getState('PRIMARY_KEY'));
|
|
454
|
+
let foreignKey = relationModel.foreignKey
|
|
455
|
+
? relationModel.foreignKey
|
|
456
|
+
: this._valuePattern([
|
|
457
|
+
`${pluralize_1.default.singular(this.MODEL['getTableName']())}`,
|
|
458
|
+
`${this._getState('PRIMARY_KEY')}`
|
|
459
|
+
].join('_'));
|
|
460
|
+
const checkRelationIsBelongsTo = [
|
|
461
|
+
relationModel.localKey == null,
|
|
462
|
+
relationModel.foreignKey == null,
|
|
463
|
+
relation === this.$constants('RELATIONSHIP').belongsTo
|
|
464
|
+
].every(r => r);
|
|
465
|
+
if (checkRelationIsBelongsTo) {
|
|
466
|
+
foreignKey = localKey;
|
|
467
|
+
localKey = this._valuePattern([
|
|
468
|
+
`${pluralize_1.default.singular(table !== null && table !== void 0 ? table : '')}`,
|
|
469
|
+
`${this._getState('PRIMARY_KEY')}`
|
|
470
|
+
].join('_'));
|
|
471
|
+
}
|
|
472
|
+
const checkRelationIsBelongsToMany = [
|
|
473
|
+
relationModel.localKey == null,
|
|
474
|
+
relationModel.foreignKey == null,
|
|
475
|
+
relation === this.$constants('RELATIONSHIP').belongsToMany
|
|
476
|
+
].every(r => r);
|
|
477
|
+
if (checkRelationIsBelongsToMany) {
|
|
478
|
+
localKey = this._valuePattern([
|
|
479
|
+
`${pluralize_1.default.singular(table !== null && table !== void 0 ? table : '')}`,
|
|
480
|
+
`${this._getState('PRIMARY_KEY')}`
|
|
481
|
+
].join('_'));
|
|
482
|
+
foreignKey = 'id';
|
|
483
|
+
const pivotModel = relationModel.query;
|
|
484
|
+
pivot = (_c = relationModel.pivot) !== null && _c !== void 0 ? _c : this._valuePattern([
|
|
485
|
+
pluralize_1.default.singular(this.MODEL['getTableName']()),
|
|
486
|
+
pluralize_1.default.singular(pivotModel.getTableName())
|
|
487
|
+
].sort().join('_'));
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
name,
|
|
491
|
+
as,
|
|
492
|
+
relation,
|
|
493
|
+
table,
|
|
494
|
+
localKey,
|
|
495
|
+
foreignKey,
|
|
496
|
+
model,
|
|
497
|
+
pivot,
|
|
498
|
+
oldVersion,
|
|
499
|
+
modelPivot
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
_valuePattern(value) {
|
|
503
|
+
switch (this._getState('PATTERN')) {
|
|
504
|
+
case this.$constants('PATTERN').snake_case: {
|
|
505
|
+
return value.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
|
|
506
|
+
}
|
|
507
|
+
case this.$constants('PATTERN').camelCase: {
|
|
508
|
+
return value.replace(/(.(\_|-|\s)+.)/g, (str) => `${str[0]}${str[str.length - 1].toUpperCase()}`);
|
|
509
|
+
}
|
|
510
|
+
default: return value;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
_assertError(condition = true, message = 'error') {
|
|
514
|
+
if (typeof condition === 'string') {
|
|
515
|
+
throw new Error(condition);
|
|
516
|
+
}
|
|
517
|
+
if (condition)
|
|
518
|
+
throw new Error(message);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
_getState(key) {
|
|
522
|
+
return this.MODEL['_getState'](key.toLocaleUpperCase());
|
|
523
|
+
}
|
|
524
|
+
_setState(key, value) {
|
|
525
|
+
return this.MODEL['_setState'](key, value);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
exports.RelationHandler = RelationHandler;
|
|
529
|
+
exports.default = RelationHandler;
|
|
@@ -4,9 +4,11 @@ declare class Schema extends Builder {
|
|
|
4
4
|
createTable: (table: string, schemas: Record<string, any>) => string;
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
7
|
-
* Sync
|
|
7
|
+
* The 'Sync' method is used to check for create or update table or columns with your schema in your model.
|
|
8
|
+
*
|
|
9
|
+
* The schema can define with method 'useSchema'
|
|
8
10
|
* @param {string} pathFolders directory to models
|
|
9
|
-
* @property {boolean} options.force - forec
|
|
11
|
+
* @property {boolean} options.force - forec always check all columns if not exists will be created
|
|
10
12
|
* @property {boolean} options.log - show log execution with sql statements
|
|
11
13
|
* @property {boolean} options.delay - wait for execution
|
|
12
14
|
* @example
|
|
@@ -43,7 +45,7 @@ declare class Schema extends Builder {
|
|
|
43
45
|
* this.useSchema ({
|
|
44
46
|
* id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
45
47
|
* uuid : new Blueprint().varchar(50).null(),
|
|
46
|
-
* user_id : new Blueprint().int().notNull(),
|
|
48
|
+
* user_id : new Blueprint().int().notNull().foreign({ references : 'id' , on : User , onDelete : 'CASCADE' , onUpdate : 'CASCADE' }),,
|
|
47
49
|
* title : new Blueprint().varchar(255).null(),
|
|
48
50
|
* created_at : new Blueprint().timestamp().null(),
|
|
49
51
|
* updated_at : new Blueprint().timestamp().null(),
|
|
@@ -54,12 +56,15 @@ declare class Schema extends Builder {
|
|
|
54
56
|
*
|
|
55
57
|
* await Schema.sync(`app/Models` , { force : true })
|
|
56
58
|
*/
|
|
57
|
-
static sync(pathFolders: string, { force, log, delay }?: {
|
|
59
|
+
static sync(pathFolders: string, { force, log, foreign, delay }?: {
|
|
58
60
|
force?: boolean | undefined;
|
|
59
61
|
log?: boolean | undefined;
|
|
62
|
+
foreign?: boolean | undefined;
|
|
60
63
|
delay?: number | undefined;
|
|
61
64
|
}): Promise<void>;
|
|
65
|
+
private static _import;
|
|
62
66
|
private static _syncExecute;
|
|
67
|
+
private static _syncForeignKey;
|
|
63
68
|
}
|
|
64
69
|
export { Schema };
|
|
65
70
|
export default Schema;
|