tspace-mysql 1.4.7 → 1.4.9
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 +128 -49
- package/dist/lib/{tspace/Interface.d.ts → Interface.d.ts} +18 -2
- package/dist/lib/connection/index.d.ts +1 -1
- package/dist/lib/constants/index.js +3 -3
- package/dist/lib/tspace/{Abstract → Abstracts}/AbstractBuilder.d.ts +3 -3
- package/dist/lib/tspace/{Abstract → Abstracts}/AbstractBuilder.js +2 -2
- package/dist/lib/tspace/{Abstract → Abstracts}/AbstractDB.d.ts +8 -2
- package/dist/lib/tspace/{Abstract → Abstracts}/AbstractModel.d.ts +22 -2
- package/dist/lib/tspace/Blueprint.d.ts +19 -5
- package/dist/lib/tspace/Blueprint.js +41 -19
- package/dist/lib/tspace/Builder.d.ts +26 -11
- package/dist/lib/tspace/Builder.js +378 -330
- package/dist/lib/tspace/DB.d.ts +42 -2
- package/dist/lib/tspace/DB.js +61 -5
- package/dist/lib/tspace/Decorator.d.ts +20 -0
- package/dist/lib/tspace/Decorator.js +166 -0
- package/dist/lib/tspace/{ProxyHandler.js → Handlers/Proxy.js} +1 -1
- package/dist/lib/tspace/{RelationHandler.d.ts → Handlers/Relation.d.ts} +4 -4
- package/dist/lib/tspace/{RelationHandler.js → Handlers/Relation.js} +103 -28
- package/dist/lib/tspace/{StateHandler.js → Handlers/State.js} +3 -2
- package/dist/lib/tspace/Model.d.ts +275 -11
- package/dist/lib/tspace/Model.js +989 -99
- package/dist/lib/tspace/Schema.js +5 -8
- package/dist/lib/tspace/index.d.ts +4 -0
- package/dist/lib/tspace/index.js +20 -2
- package/dist/lib/utils/index.d.ts +1 -0
- package/dist/lib/utils/index.js +9 -0
- package/dist/tests/01-Pool.test.d.ts +1 -0
- package/dist/tests/01-Pool.test.js +45 -0
- package/dist/tests/02-DB.test.d.ts +1 -0
- package/dist/tests/02-DB.test.js +109 -0
- package/dist/tests/03-Model.test.d.ts +1 -0
- package/dist/tests/03-Model.test.js +73 -0
- package/package.json +14 -3
- /package/dist/lib/{tspace/Interface.js → Interface.js} +0 -0
- /package/dist/lib/tspace/{Abstract → Abstracts}/AbstractDB.js +0 -0
- /package/dist/lib/tspace/{Abstract → Abstracts}/AbstractModel.js +0 -0
- /package/dist/lib/tspace/{ProxyHandler.d.ts → Handlers/Proxy.d.ts} +0 -0
- /package/dist/lib/tspace/{StateHandler.d.ts → Handlers/State.d.ts} +0 -0
package/dist/lib/tspace/DB.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { AbstractDB } from './
|
|
2
|
-
import { Connection, ConnectionOptions, ConnectionTransaction } from '
|
|
1
|
+
import { AbstractDB } from './Abstracts/AbstractDB';
|
|
2
|
+
import { Connection, ConnectionOptions, ConnectionTransaction } from '../Interface';
|
|
3
3
|
/**
|
|
4
4
|
* 'DB' class is a component of the database system
|
|
5
5
|
* @param {string?} table table name
|
|
@@ -95,6 +95,46 @@ declare class DB extends AbstractDB {
|
|
|
95
95
|
* @return {string} string
|
|
96
96
|
*/
|
|
97
97
|
static generateUUID(): string;
|
|
98
|
+
/**
|
|
99
|
+
* The 'snakeCase' methid is used to covert value to snakeCase pattern.
|
|
100
|
+
* @return {string} string
|
|
101
|
+
*/
|
|
102
|
+
snakeCase(value: string): string;
|
|
103
|
+
/**
|
|
104
|
+
* The 'snakeCase' methid is used to covert value to snake_case pattern.
|
|
105
|
+
* @return {string} string
|
|
106
|
+
*/
|
|
107
|
+
static snakeCase(value: string): string;
|
|
108
|
+
/**
|
|
109
|
+
* The 'camelCase' methid is used to covert value to camelCase pattern.
|
|
110
|
+
* @return {string} string
|
|
111
|
+
*/
|
|
112
|
+
camelCase(value: string): string;
|
|
113
|
+
/**
|
|
114
|
+
* The 'camelCase' methid is used to covert value to camelCase pattern.
|
|
115
|
+
* @return {string} string
|
|
116
|
+
*/
|
|
117
|
+
static camelCase(value: string): string;
|
|
118
|
+
/**
|
|
119
|
+
* The 'escape' methid is used to escaping SQL injections.
|
|
120
|
+
* @return {string} string
|
|
121
|
+
*/
|
|
122
|
+
escape(value: string): string;
|
|
123
|
+
/**
|
|
124
|
+
* The 'escape' methid is used to escaping SQL injections.
|
|
125
|
+
* @return {string} string
|
|
126
|
+
*/
|
|
127
|
+
static escape(value: string): string;
|
|
128
|
+
/**
|
|
129
|
+
* The 'escapeXSS' methid is used to escaping XSS characters.
|
|
130
|
+
* @return {string} string
|
|
131
|
+
*/
|
|
132
|
+
escapeXSS(value: string): string;
|
|
133
|
+
/**
|
|
134
|
+
* The 'escapeXSS' methid is used to escaping XSS characters.
|
|
135
|
+
* @return {string} string
|
|
136
|
+
*/
|
|
137
|
+
static escapeXSS(value: string): string;
|
|
98
138
|
/**
|
|
99
139
|
* The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
|
|
100
140
|
* @param {string} sql
|
package/dist/lib/tspace/DB.js
CHANGED
|
@@ -24,10 +24,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.DB = void 0;
|
|
27
|
-
const AbstractDB_1 = require("./
|
|
28
|
-
const
|
|
27
|
+
const AbstractDB_1 = require("./Abstracts/AbstractDB");
|
|
28
|
+
const Proxy_1 = require("./Handlers/Proxy");
|
|
29
29
|
const connection_1 = require("../connection");
|
|
30
|
-
const
|
|
30
|
+
const State_1 = __importDefault(require("./Handlers/State"));
|
|
31
31
|
/**
|
|
32
32
|
* 'DB' class is a component of the database system
|
|
33
33
|
* @param {string?} table table name
|
|
@@ -40,7 +40,7 @@ class DB extends AbstractDB_1.AbstractDB {
|
|
|
40
40
|
this._initialDB();
|
|
41
41
|
if (table)
|
|
42
42
|
this.table(table);
|
|
43
|
-
return new Proxy(this,
|
|
43
|
+
return new Proxy(this, Proxy_1.proxyHandler);
|
|
44
44
|
}
|
|
45
45
|
/**
|
|
46
46
|
* The 'table' method is used to define the table name.
|
|
@@ -178,6 +178,62 @@ class DB extends AbstractDB_1.AbstractDB {
|
|
|
178
178
|
static generateUUID() {
|
|
179
179
|
return new this().generateUUID();
|
|
180
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* The 'snakeCase' methid is used to covert value to snakeCase pattern.
|
|
183
|
+
* @return {string} string
|
|
184
|
+
*/
|
|
185
|
+
snakeCase(value) {
|
|
186
|
+
return this.$utils.snakeCase(value);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* The 'snakeCase' methid is used to covert value to snake_case pattern.
|
|
190
|
+
* @return {string} string
|
|
191
|
+
*/
|
|
192
|
+
static snakeCase(value) {
|
|
193
|
+
return new this().$utils.snakeCase(value);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The 'camelCase' methid is used to covert value to camelCase pattern.
|
|
197
|
+
* @return {string} string
|
|
198
|
+
*/
|
|
199
|
+
camelCase(value) {
|
|
200
|
+
return this.$utils.camelCase(value);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* The 'camelCase' methid is used to covert value to camelCase pattern.
|
|
204
|
+
* @return {string} string
|
|
205
|
+
*/
|
|
206
|
+
static camelCase(value) {
|
|
207
|
+
return new this().$utils.camelCase(value);
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* The 'escape' methid is used to escaping SQL injections.
|
|
211
|
+
* @return {string} string
|
|
212
|
+
*/
|
|
213
|
+
escape(value) {
|
|
214
|
+
return this.$utils.escape(value);
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* The 'escape' methid is used to escaping SQL injections.
|
|
218
|
+
* @return {string} string
|
|
219
|
+
*/
|
|
220
|
+
static escape(value) {
|
|
221
|
+
return new this().$utils.escape(value);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* The 'escapeXSS' methid is used to escaping XSS characters.
|
|
225
|
+
* @return {string} string
|
|
226
|
+
*/
|
|
227
|
+
escapeXSS(value) {
|
|
228
|
+
return this.$utils.escapeXSS(value);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* The 'escapeXSS' methid is used to escaping XSS characters.
|
|
232
|
+
* @return {string} string
|
|
233
|
+
*/
|
|
234
|
+
static escapeXSS(value) {
|
|
235
|
+
return new this().$utils.escapeXSS(value);
|
|
236
|
+
}
|
|
181
237
|
/**
|
|
182
238
|
* The 'raw' methid is used to allow for raw sql queries to some method in 'DB' or 'Model'.
|
|
183
239
|
* @param {string} sql
|
|
@@ -276,7 +332,7 @@ class DB extends AbstractDB_1.AbstractDB {
|
|
|
276
332
|
});
|
|
277
333
|
}
|
|
278
334
|
_initialDB() {
|
|
279
|
-
this.$state = new
|
|
335
|
+
this.$state = new State_1.default(this.$constants('DB'));
|
|
280
336
|
return this;
|
|
281
337
|
}
|
|
282
338
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { RelationQuery, ValidateSchemaDecorator } from "../Interface";
|
|
2
|
+
import { Blueprint } from "./Blueprint";
|
|
3
|
+
export declare const Table: (name: string) => (constructor: Function) => void;
|
|
4
|
+
export declare const TableSingular: () => (constructor: Function) => void;
|
|
5
|
+
export declare const TablePlural: () => (constructor: Function) => void;
|
|
6
|
+
export declare const Column: (blueprint: () => Blueprint) => (target: any, key: string) => void;
|
|
7
|
+
export declare const Validate: (validate: ValidateSchemaDecorator) => (target: any, key: string) => void;
|
|
8
|
+
export declare const UUID: (column?: string) => (constructor: Function) => void;
|
|
9
|
+
export declare const Timestamp: (timestampColumns?: {
|
|
10
|
+
createdAt: string;
|
|
11
|
+
updatedAt: string;
|
|
12
|
+
}) => (constructor: Function) => void;
|
|
13
|
+
export declare const SoftDelete: (column?: string) => (constructor: Function) => void;
|
|
14
|
+
export declare const Pattern: (pattern: 'camelCase' | 'snake_case') => (constructor: Function) => void;
|
|
15
|
+
export declare const CamelCase: () => (constructor: Function) => void;
|
|
16
|
+
export declare const SnakeCase: () => (constructor: Function) => void;
|
|
17
|
+
export declare const HasOne: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
|
|
18
|
+
export declare const HasMany: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
|
|
19
|
+
export declare const BelongsTo: ({ name, as, model, localKey, foreignKey, freezeTable }: RelationQuery) => (target: any, key: string) => void;
|
|
20
|
+
export declare const BelongsToMany: ({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }: RelationQuery) => (target: any, key: string) => void;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.BelongsToMany = exports.BelongsTo = exports.HasMany = exports.HasOne = exports.SnakeCase = exports.CamelCase = exports.Pattern = exports.SoftDelete = exports.Timestamp = exports.UUID = exports.Validate = exports.Column = exports.TablePlural = exports.TableSingular = exports.Table = void 0;
|
|
7
|
+
const pluralize_1 = __importDefault(require("pluralize"));
|
|
8
|
+
const Blueprint_1 = require("./Blueprint");
|
|
9
|
+
const Table = (name) => {
|
|
10
|
+
return (constructor) => {
|
|
11
|
+
if (constructor.prototype == null)
|
|
12
|
+
return;
|
|
13
|
+
constructor.prototype.$table = name;
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
exports.Table = Table;
|
|
17
|
+
const TableSingular = () => {
|
|
18
|
+
return (constructor) => {
|
|
19
|
+
if (constructor.prototype == null)
|
|
20
|
+
return;
|
|
21
|
+
const name = constructor.name.replace(/([A-Z])/g, (str) => '_' + str.toLowerCase()).slice(1);
|
|
22
|
+
constructor.prototype.$table = pluralize_1.default.singular(name);
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
exports.TableSingular = TableSingular;
|
|
26
|
+
const TablePlural = () => {
|
|
27
|
+
return (constructor) => {
|
|
28
|
+
if (constructor.prototype == null)
|
|
29
|
+
return;
|
|
30
|
+
const name = constructor.name.replace(/([A-Z])/g, (str) => '_' + str.toLowerCase()).slice(1);
|
|
31
|
+
constructor.prototype.$table = pluralize_1.default.plural(name);
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
exports.TablePlural = TablePlural;
|
|
35
|
+
const Column = (blueprint) => {
|
|
36
|
+
return (target, key) => {
|
|
37
|
+
if (!(blueprint() instanceof Blueprint_1.Blueprint))
|
|
38
|
+
return;
|
|
39
|
+
if (target.$schema == null)
|
|
40
|
+
target.$schema = {};
|
|
41
|
+
target.$schema = Object.assign(Object.assign({}, target.$schema), { [key]: blueprint() });
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
exports.Column = Column;
|
|
45
|
+
const Validate = (validate) => {
|
|
46
|
+
return (target, key) => {
|
|
47
|
+
if (target.$validateSchema == null)
|
|
48
|
+
target.$validateSchema = {};
|
|
49
|
+
target.$validateSchema = Object.assign(Object.assign({}, target.$validateSchema), { [key]: validate });
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
exports.Validate = Validate;
|
|
53
|
+
const UUID = (column) => {
|
|
54
|
+
return (constructor) => {
|
|
55
|
+
if (constructor.prototype == null)
|
|
56
|
+
return;
|
|
57
|
+
constructor.prototype.$uuid = true;
|
|
58
|
+
constructor.prototype.$uuidColumn = column;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
exports.UUID = UUID;
|
|
62
|
+
const Timestamp = (timestampColumns) => {
|
|
63
|
+
return (constructor) => {
|
|
64
|
+
if (constructor.prototype == null)
|
|
65
|
+
return;
|
|
66
|
+
constructor.prototype.$timestamp = true;
|
|
67
|
+
constructor.prototype.$timestampColumns = timestampColumns;
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
exports.Timestamp = Timestamp;
|
|
71
|
+
const SoftDelete = (column) => {
|
|
72
|
+
return (constructor) => {
|
|
73
|
+
if (constructor.prototype == null)
|
|
74
|
+
return;
|
|
75
|
+
constructor.prototype.$softDelete = true;
|
|
76
|
+
constructor.prototype.$softDeleteColumn = column;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
exports.SoftDelete = SoftDelete;
|
|
80
|
+
const Pattern = (pattern) => {
|
|
81
|
+
return (constructor) => {
|
|
82
|
+
if (constructor.prototype == null)
|
|
83
|
+
return;
|
|
84
|
+
constructor.prototype.$pattern = pattern;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
exports.Pattern = Pattern;
|
|
88
|
+
const CamelCase = () => {
|
|
89
|
+
return (constructor) => {
|
|
90
|
+
if (constructor.prototype == null)
|
|
91
|
+
return;
|
|
92
|
+
constructor.prototype.$pattern = 'camelCase';
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
exports.CamelCase = CamelCase;
|
|
96
|
+
const SnakeCase = () => {
|
|
97
|
+
return (constructor) => {
|
|
98
|
+
if (constructor.prototype == null)
|
|
99
|
+
return;
|
|
100
|
+
constructor.prototype.$pattern = 'snake_case';
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
exports.SnakeCase = SnakeCase;
|
|
104
|
+
const HasOne = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
|
|
105
|
+
return (target, key) => {
|
|
106
|
+
if (target.$hasOne == null)
|
|
107
|
+
target.$hasOne = [];
|
|
108
|
+
target.$hasOne.push({
|
|
109
|
+
name: name == null ? key : name,
|
|
110
|
+
as,
|
|
111
|
+
model,
|
|
112
|
+
localKey,
|
|
113
|
+
foreignKey,
|
|
114
|
+
freezeTable
|
|
115
|
+
});
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
exports.HasOne = HasOne;
|
|
119
|
+
const HasMany = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
|
|
120
|
+
return (target, key) => {
|
|
121
|
+
if (target.$hasMany == null)
|
|
122
|
+
target.$hasMany = [];
|
|
123
|
+
target.$hasMany.push({
|
|
124
|
+
name: name == null ? key : name,
|
|
125
|
+
as,
|
|
126
|
+
model,
|
|
127
|
+
localKey,
|
|
128
|
+
foreignKey,
|
|
129
|
+
freezeTable
|
|
130
|
+
});
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
exports.HasMany = HasMany;
|
|
134
|
+
const BelongsTo = ({ name, as, model, localKey, foreignKey, freezeTable }) => {
|
|
135
|
+
return (target, key) => {
|
|
136
|
+
if (target.$belongsTo == null)
|
|
137
|
+
target.$belongsTo = [];
|
|
138
|
+
target.$belongsTo.push({
|
|
139
|
+
name: name == null ? key : name,
|
|
140
|
+
as,
|
|
141
|
+
model,
|
|
142
|
+
localKey,
|
|
143
|
+
foreignKey,
|
|
144
|
+
freezeTable
|
|
145
|
+
});
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
exports.BelongsTo = BelongsTo;
|
|
149
|
+
const BelongsToMany = ({ name, as, model, localKey, foreignKey, freezeTable, pivot, oldVersion, modelPivot }) => {
|
|
150
|
+
return (target, key) => {
|
|
151
|
+
if (target.$belongsToMany == null)
|
|
152
|
+
target.$belongsToMany = [];
|
|
153
|
+
target.$belongsToMany.push({
|
|
154
|
+
name: name == null ? key : name,
|
|
155
|
+
as,
|
|
156
|
+
model,
|
|
157
|
+
localKey,
|
|
158
|
+
foreignKey,
|
|
159
|
+
freezeTable,
|
|
160
|
+
pivot,
|
|
161
|
+
oldVersion,
|
|
162
|
+
modelPivot
|
|
163
|
+
});
|
|
164
|
+
};
|
|
165
|
+
};
|
|
166
|
+
exports.BelongsToMany = BelongsToMany;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Relation, RelationQuery } from "
|
|
2
|
-
import { Model } from "
|
|
1
|
+
import { Relation, RelationQuery } from "../../Interface";
|
|
2
|
+
import { Model } from "../Model";
|
|
3
3
|
declare class RelationHandler {
|
|
4
4
|
private MODEL;
|
|
5
5
|
private $constants;
|
|
@@ -7,7 +7,7 @@ declare class RelationHandler {
|
|
|
7
7
|
constructor(model: Model);
|
|
8
8
|
load(parents: Record<string, any>[], relation: Relation): Promise<any[]>;
|
|
9
9
|
loadExists(): string;
|
|
10
|
-
apply(nameRelations: string[], type: 'all' | 'exists' | 'trashed' | 'default'): Relation[];
|
|
10
|
+
apply(nameRelations: string[], type: 'all' | 'exists' | 'trashed' | 'count' | 'default'): Relation[];
|
|
11
11
|
callback(nameRelation: string, cb: Function): void;
|
|
12
12
|
hasOne({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
|
|
13
13
|
hasMany({ name, as, model, localKey, foreignKey, freezeTable }: Relation): void;
|
|
@@ -23,7 +23,7 @@ declare class RelationHandler {
|
|
|
23
23
|
private _relationMapData;
|
|
24
24
|
private _belongsToMany;
|
|
25
25
|
private _valueInRelation;
|
|
26
|
-
|
|
26
|
+
protected _valuePattern(value: string): string;
|
|
27
27
|
private _assertError;
|
|
28
28
|
protected _getState(key: string): any;
|
|
29
29
|
protected _setState(key: string, value: any): void;
|
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.RelationHandler = void 0;
|
|
16
16
|
const pluralize_1 = __importDefault(require("pluralize"));
|
|
17
|
-
const Model_1 = require("
|
|
17
|
+
const Model_1 = require("../Model");
|
|
18
18
|
class RelationHandler {
|
|
19
19
|
constructor(model) {
|
|
20
20
|
this.MODEL = model;
|
|
@@ -36,7 +36,7 @@ class RelationHandler {
|
|
|
36
36
|
const data = parent[localKey];
|
|
37
37
|
if (parent.hasOwnProperty(localKey))
|
|
38
38
|
return data;
|
|
39
|
-
this.MODEL['_assertError'](data == null, `
|
|
39
|
+
this.MODEL['_assertError'](data == null, `This relationship lacks a primary or foreign key in the '${relation === null || relation === void 0 ? void 0 : relation.name}' relation. Please review the query to identify whether the key '${localKey}' or '${foreignKey}' is missing.`);
|
|
40
40
|
})
|
|
41
41
|
.filter(d => d != null);
|
|
42
42
|
const parentIds = Array.from(new Set(localKeyId)) || [];
|
|
@@ -44,6 +44,19 @@ class RelationHandler {
|
|
|
44
44
|
return [];
|
|
45
45
|
const query = relation.query;
|
|
46
46
|
this._assertError(query == null, `Unknown callback query in [Relation : ${relation.name}]`);
|
|
47
|
+
if (relation.count) {
|
|
48
|
+
const results = yield query
|
|
49
|
+
.whereIn(foreignKey, parentIds)
|
|
50
|
+
.select(foreignKey)
|
|
51
|
+
.selectRaw(`${this.$constants('COUNT')}(${foreignKey}) ${this.$constants('AS')} \`aggregate\``)
|
|
52
|
+
.debug(this._getState('DEBUG'))
|
|
53
|
+
.when(relation.trashed, (query) => query.onlyTrashed())
|
|
54
|
+
.when(relation.all, (query) => query.disableSoftDelete())
|
|
55
|
+
.bind(this.MODEL['$pool'].get())
|
|
56
|
+
.groupBy(foreignKey)
|
|
57
|
+
.get();
|
|
58
|
+
return this._relationMapData(parents, results, relation);
|
|
59
|
+
}
|
|
47
60
|
const results = yield query
|
|
48
61
|
.whereIn(foreignKey, parentIds)
|
|
49
62
|
.debug(this._getState('DEBUG'))
|
|
@@ -70,6 +83,8 @@ class RelationHandler {
|
|
|
70
83
|
const cloneRelations = clone['_getState']('RELATIONS');
|
|
71
84
|
if (cloneRelations.length) {
|
|
72
85
|
for (const r of cloneRelations) {
|
|
86
|
+
if (!r.exists)
|
|
87
|
+
continue;
|
|
73
88
|
if (r.query == null)
|
|
74
89
|
continue;
|
|
75
90
|
const sql = (_c = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._handleRelationsExists(r)) !== null && _c !== void 0 ? _c : '';
|
|
@@ -82,21 +97,21 @@ class RelationHandler {
|
|
|
82
97
|
: new Model_1.Model().table(String(pivot));
|
|
83
98
|
const sql = clone
|
|
84
99
|
.bind(this.MODEL['$pool'].get())
|
|
85
|
-
.
|
|
86
|
-
.whereReference(`\`${query.getTableName()}\`.\`${foreignKey}\``, `\`${
|
|
100
|
+
.selectRaw("1")
|
|
101
|
+
.whereReference(`\`${query.getTableName()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${localKey}\``)
|
|
87
102
|
.toString();
|
|
88
103
|
thisPivot.whereExists(sql);
|
|
89
104
|
const sqlPivot = thisPivot
|
|
90
105
|
.bind(this.MODEL['$pool'].get())
|
|
91
|
-
.
|
|
92
|
-
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${
|
|
106
|
+
.selectRaw("1")
|
|
107
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
|
|
93
108
|
.toString();
|
|
94
109
|
this.MODEL['whereExists'](sqlPivot);
|
|
95
110
|
continue;
|
|
96
111
|
}
|
|
97
112
|
const sql = clone
|
|
98
113
|
.bind(this.MODEL['$pool'].get())
|
|
99
|
-
.
|
|
114
|
+
.selectRaw("1")
|
|
100
115
|
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${query.getTableName()}\`.\`${foreignKey}\``)
|
|
101
116
|
.toString();
|
|
102
117
|
this.MODEL['whereExists'](sql);
|
|
@@ -108,7 +123,7 @@ class RelationHandler {
|
|
|
108
123
|
const relations = nameRelations.map((name) => {
|
|
109
124
|
var _a, _b, _c;
|
|
110
125
|
const relation = (_a = this._getState('RELATION')) === null || _a === void 0 ? void 0 : _a.find((data) => data.name === name);
|
|
111
|
-
this._assertError(relation == null, `
|
|
126
|
+
this._assertError(relation == null, `The relation '${name}' is not registered in the model '${(_b = this.MODEL.constructor) === null || _b === void 0 ? void 0 : _b.name}'.`);
|
|
112
127
|
const relationHasExists = (_c = Object.values(this.$constants('RELATIONSHIP'))) === null || _c === void 0 ? void 0 : _c.includes(relation.relation);
|
|
113
128
|
this._assertError(!relationHasExists, `Unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
114
129
|
if (relation.query == null)
|
|
@@ -133,7 +148,7 @@ class RelationHandler {
|
|
|
133
148
|
callback(nameRelation, cb) {
|
|
134
149
|
var _a, _b;
|
|
135
150
|
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}"`);
|
|
151
|
+
this._assertError(relation == null, `This Relation "${nameRelation}" not be register in Model "${(_a = this.MODEL.constructor) === null || _a === void 0 ? void 0 : _a.name}"`);
|
|
137
152
|
const relationHasExists = (_b = Object.values(this.$constants('RELATIONSHIP'))) === null || _b === void 0 ? void 0 : _b.includes(relation.relation);
|
|
138
153
|
this._assertError(!relationHasExists, `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
139
154
|
relation.query = cb(new relation.model());
|
|
@@ -284,7 +299,7 @@ class RelationHandler {
|
|
|
284
299
|
return;
|
|
285
300
|
}
|
|
286
301
|
_handleRelationsExists(relation) {
|
|
287
|
-
var _a, _b, _c;
|
|
302
|
+
var _a, _b, _c, _d;
|
|
288
303
|
this._assertError(!((_a = Object.keys(relation)) === null || _a === void 0 ? void 0 : _a.length), `unknown [relation]`);
|
|
289
304
|
const { localKey, foreignKey } = this._valueInRelation(relation);
|
|
290
305
|
const query = relation.query;
|
|
@@ -293,16 +308,46 @@ class RelationHandler {
|
|
|
293
308
|
const cloneRelations = clone['_getState']('RELATIONS');
|
|
294
309
|
if (cloneRelations.length) {
|
|
295
310
|
for (const r of cloneRelations) {
|
|
311
|
+
if (!r.exists)
|
|
312
|
+
continue;
|
|
296
313
|
if (r.query == null)
|
|
297
314
|
continue;
|
|
298
|
-
|
|
315
|
+
if (r.relation === this.$constants('RELATIONSHIP').belongsToMany) {
|
|
316
|
+
const data = (_b = clone['$relation']) === null || _b === void 0 ? void 0 : _b._valueInRelation(r);
|
|
317
|
+
if (data == null)
|
|
318
|
+
continue;
|
|
319
|
+
const { modelPivot, pivot, foreignKey } = data;
|
|
320
|
+
const thisPivot = modelPivot == null && pivot == null
|
|
321
|
+
? new Model_1.Model().table(`${this._valuePattern([
|
|
322
|
+
pluralize_1.default.singular(clone.getTableName()),
|
|
323
|
+
pluralize_1.default.singular(this.MODEL['getTableName']())
|
|
324
|
+
].join("_"))}`)
|
|
325
|
+
: modelPivot ? new modelPivot : new Model_1.Model().table(`${pivot}`);
|
|
326
|
+
const sql = clone
|
|
327
|
+
.bind(this.MODEL['$pool'].get())
|
|
328
|
+
.selectRaw("1")
|
|
329
|
+
.whereReference(`\`${clone.getTableName()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([
|
|
330
|
+
pluralize_1.default.singular(clone.getTableName()),
|
|
331
|
+
localKey
|
|
332
|
+
].join('_'))}\``)
|
|
333
|
+
.toString();
|
|
334
|
+
thisPivot.whereExists(sql);
|
|
335
|
+
const sqlPivot = thisPivot
|
|
336
|
+
.bind(this.MODEL['$pool'].get())
|
|
337
|
+
.selectRaw("1")
|
|
338
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${foreignKey}\``, `\`${thisPivot.getTableName()}\`.\`${this._valuePattern([pluralize_1.default.singular(this.MODEL['getTableName']()), foreignKey].join("_"))}\``)
|
|
339
|
+
.toString();
|
|
340
|
+
clone.whereExists(sqlPivot);
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
const sql = (_d = (_c = clone['$relation']) === null || _c === void 0 ? void 0 : _c._handleRelationsExists(r)) !== null && _d !== void 0 ? _d : '';
|
|
299
344
|
clone.whereExists(sql);
|
|
300
345
|
}
|
|
301
346
|
}
|
|
302
347
|
const sql = clone
|
|
303
348
|
.bind(this.MODEL['$pool'].get())
|
|
304
|
-
.
|
|
305
|
-
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${
|
|
349
|
+
.selectRaw("1")
|
|
350
|
+
.whereReference(`\`${this.MODEL['getTableName']()}\`.\`${localKey}\``, `\`${clone.getTableName()}\`.\`${foreignKey}\``)
|
|
306
351
|
.toString();
|
|
307
352
|
return sql;
|
|
308
353
|
}
|
|
@@ -311,16 +356,16 @@ class RelationHandler {
|
|
|
311
356
|
this._setState('RELATION', [...this._getState('RELATION'), relation]);
|
|
312
357
|
this.MODEL['with'](nameRelation);
|
|
313
358
|
const r = this._getState('RELATIONS').find((data) => data.name === nameRelation);
|
|
314
|
-
this._assertError(relation == null, `
|
|
315
|
-
this._assertError(!Object.values(this.$constants('RELATIONSHIP')).includes(r.relation), `unknown relationship in [${this.$constants('RELATIONSHIP')}] !`);
|
|
359
|
+
this._assertError(relation == null, `The relation '${nameRelation}' is not registered in the model '${(_a = this.MODEL.constructor) === null || _a === void 0 ? void 0 : _a.name}'.`);
|
|
316
360
|
return r;
|
|
317
361
|
}
|
|
318
362
|
_functionRelationName() {
|
|
319
363
|
const functionName = [...this.$logger.get()][this.$logger.get().length - 2];
|
|
320
364
|
return functionName.replace(/([A-Z])/g, (str) => `_${str.toLowerCase()}`);
|
|
321
365
|
}
|
|
322
|
-
_relationMapData(dataParents, dataChilds,
|
|
323
|
-
|
|
366
|
+
_relationMapData(dataParents, dataChilds, r) {
|
|
367
|
+
var _a;
|
|
368
|
+
const { name, as, relation, localKey, foreignKey } = this._valueInRelation(r);
|
|
324
369
|
const keyRelation = as !== null && as !== void 0 ? as : name;
|
|
325
370
|
for (const dataParent of dataParents) {
|
|
326
371
|
const relationIsHasOneOrBelongsTo = [
|
|
@@ -329,11 +374,15 @@ class RelationHandler {
|
|
|
329
374
|
].some(r => r === relation);
|
|
330
375
|
dataParent[keyRelation] = [];
|
|
331
376
|
if (relationIsHasOneOrBelongsTo)
|
|
332
|
-
dataParent[keyRelation] = null;
|
|
377
|
+
dataParent[keyRelation] = r.count ? 0 : null;
|
|
333
378
|
if (!dataChilds.length)
|
|
334
379
|
continue;
|
|
335
380
|
for (const dataChild of dataChilds) {
|
|
336
381
|
if (dataChild[foreignKey] === dataParent[localKey]) {
|
|
382
|
+
if (r.count) {
|
|
383
|
+
dataParent[keyRelation] = (_a = dataChild === null || dataChild === void 0 ? void 0 : dataChild.aggregate) !== null && _a !== void 0 ? _a : 0;
|
|
384
|
+
continue;
|
|
385
|
+
}
|
|
337
386
|
const relationIsHasOneOrBelongsTo = [
|
|
338
387
|
this.$constants('RELATIONSHIP').hasOne,
|
|
339
388
|
this.$constants('RELATIONSHIP').belongsTo
|
|
@@ -351,14 +400,14 @@ class RelationHandler {
|
|
|
351
400
|
return dataParents;
|
|
352
401
|
}
|
|
353
402
|
_belongsToMany(parents, relation) {
|
|
354
|
-
var _a;
|
|
403
|
+
var _a, _b;
|
|
355
404
|
return __awaiter(this, void 0, void 0, function* () {
|
|
356
405
|
const { name, foreignKey, localKey, pivot, oldVersion, modelPivot } = this._valueInRelation(relation);
|
|
357
406
|
const localKeyId = parents.map((parent) => {
|
|
358
407
|
const data = parent[foreignKey];
|
|
359
408
|
if (parent.hasOwnProperty(foreignKey))
|
|
360
409
|
return data;
|
|
361
|
-
this._assertError(data == null, `
|
|
410
|
+
this._assertError(data == null, `This relationship lacks a primary or foreign key in the '${relation === null || relation === void 0 ? void 0 : relation.name}' relation. Please review the query to identify whether the key '${localKey}' or '${foreignKey}' is missing.`);
|
|
362
411
|
}).filter((d) => d != null);
|
|
363
412
|
const mainResultIds = Array.from(new Set(localKeyId));
|
|
364
413
|
if (!mainResultIds.length && this._getState('RELATIONS_EXISTS'))
|
|
@@ -371,23 +420,49 @@ class RelationHandler {
|
|
|
371
420
|
const pivotTable = String(((_a = relation.pivot) !== null && _a !== void 0 ? _a : pivot));
|
|
372
421
|
const sqlPivotExists = new Model_1.Model()
|
|
373
422
|
.copyModel(modelRelation)
|
|
374
|
-
.
|
|
423
|
+
.selectRaw("1")
|
|
375
424
|
.whereReference(`\`${modelRelation.getTableName()}\`.\`${foreignKey}\``, `\`${pivotTable}\`.\`${localKey}\``)
|
|
376
425
|
.toString();
|
|
377
426
|
const queryPivot = modelPivot
|
|
378
427
|
? new modelPivot()
|
|
379
428
|
: new Model_1.Model().table(pivotTable);
|
|
380
|
-
|
|
429
|
+
if (relation.count) {
|
|
430
|
+
const pivotResults = yield queryPivot
|
|
431
|
+
.whereIn(localKeyPivotTable, mainResultIds)
|
|
432
|
+
.select(localKeyPivotTable)
|
|
433
|
+
.selectRaw(`${this.$constants('COUNT')}(${localKeyPivotTable}) ${this.$constants('AS')} \`aggregate\``)
|
|
434
|
+
.when(relation.exists, (query) => query.whereExists(sqlPivotExists))
|
|
435
|
+
.when(relation.trashed, (query) => query.onlyTrashed())
|
|
436
|
+
.when(relation.all, (query) => query.disableSoftDelete())
|
|
437
|
+
.groupBy(localKeyPivotTable)
|
|
438
|
+
.bind(this.MODEL['$pool'].get())
|
|
439
|
+
.debug(this._getState('DEBUG'))
|
|
440
|
+
.get();
|
|
441
|
+
for (const parent of parents) {
|
|
442
|
+
if (parent[name] == null)
|
|
443
|
+
parent[name] = 0;
|
|
444
|
+
for (const pivotResult of pivotResults) {
|
|
445
|
+
if (pivotResult[localKeyPivotTable] !== parent[foreignKey])
|
|
446
|
+
continue;
|
|
447
|
+
parent[name] = (_b = pivotResult.aggregate) !== null && _b !== void 0 ? _b : 0;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
if (this._getState('HIDDEN').length)
|
|
451
|
+
this.MODEL['_hiddenColumnModel'](parents);
|
|
452
|
+
return parents;
|
|
453
|
+
}
|
|
454
|
+
const pivotResults = yield queryPivot
|
|
381
455
|
.whereIn(localKeyPivotTable, mainResultIds)
|
|
382
456
|
.when(relation.exists, (query) => query.whereExists(sqlPivotExists))
|
|
383
457
|
.when(relation.trashed, (query) => query.onlyTrashed())
|
|
384
458
|
.when(relation.all, (query) => query.disableSoftDelete())
|
|
385
|
-
.
|
|
386
|
-
|
|
459
|
+
.bind(this.MODEL['$pool'].get())
|
|
460
|
+
.debug(this._getState('DEBUG'))
|
|
461
|
+
.get();
|
|
387
462
|
const relationIds = Array.from(new Set(pivotResults
|
|
388
463
|
.map((pivotResult) => pivotResult[relationForeignKey])
|
|
389
464
|
.filter((d) => d != null)));
|
|
390
|
-
const relationResults = yield this.MODEL
|
|
465
|
+
const relationResults = yield this.MODEL.rawQuery(modelRelation
|
|
391
466
|
.whereIn(mainlocalKey, relationIds)
|
|
392
467
|
.when(relation.trashed, (query) => query.disableSoftDelete())
|
|
393
468
|
.toString());
|
|
@@ -435,8 +510,8 @@ class RelationHandler {
|
|
|
435
510
|
}
|
|
436
511
|
_valueInRelation(relationModel) {
|
|
437
512
|
var _a, _b, _c;
|
|
438
|
-
this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, '
|
|
439
|
-
this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model_1.Model), '
|
|
513
|
+
this._assertError((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Promise, 'The Promise method does not support nested relations.');
|
|
514
|
+
this._assertError(!((relationModel === null || relationModel === void 0 ? void 0 : relationModel.query) instanceof Model_1.Model), 'The callback function only supports instances of the Model class.');
|
|
440
515
|
const relation = relationModel.relation;
|
|
441
516
|
const model = (_a = relationModel.model) === null || _a === void 0 ? void 0 : _a.name;
|
|
442
517
|
const modelPivot = relationModel.modelPivot;
|
|
@@ -447,7 +522,7 @@ class RelationHandler {
|
|
|
447
522
|
let pivot = null;
|
|
448
523
|
const name = relationModel.name;
|
|
449
524
|
const as = relationModel.as;
|
|
450
|
-
this._assertError(!model || model == null, '
|
|
525
|
+
this._assertError(!model || model == null, 'Model not found.');
|
|
451
526
|
let localKey = this._valuePattern(relationModel.localKey
|
|
452
527
|
? relationModel.localKey
|
|
453
528
|
: this._getState('PRIMARY_KEY'));
|