tspace-mysql 1.5.0 → 1.5.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/README.md +1856 -701
- package/build/cli/dump/db.js +3 -2
- package/build/cli/generate/make.js +17 -15
- package/build/cli/generate/modelDecorator.d.ts +1 -1
- package/build/cli/generate/modelDecorator.js +2 -3
- package/build/cli/index.js +45 -27
- package/build/cli/migrate/make.d.ts +1 -1
- package/build/cli/migrate/make.js +2 -2
- package/build/cli/migrations/make-db.d.ts +4 -0
- package/build/cli/migrations/make-db.js +58 -0
- package/build/cli/migrations/make.d.ts +2 -0
- package/build/cli/migrations/make.js +201 -0
- package/build/lib/Interface.d.ts +24 -5
- package/build/lib/connection/index.d.ts +5 -1
- package/build/lib/connection/index.js +65 -8
- package/build/lib/connection/options.js +2 -2
- package/build/lib/constants/index.js +13 -3
- package/build/lib/{tspace → core}/Abstracts/AbstractBuilder.d.ts +1 -1
- package/build/lib/{tspace → core}/Abstracts/AbstractModel.d.ts +15 -13
- package/build/lib/{tspace → core}/Blueprint.d.ts +14 -3
- package/build/lib/{tspace → core}/Blueprint.js +30 -4
- package/build/lib/{tspace → core}/Builder.d.ts +140 -44
- package/build/lib/{tspace → core}/Builder.js +772 -459
- package/build/lib/{tspace → core}/DB.d.ts +20 -4
- package/build/lib/{tspace → core}/DB.js +73 -39
- package/build/lib/{tspace → core}/Decorator.js +2 -2
- package/build/lib/{tspace → core/Handlers}/Logger.d.ts +3 -3
- package/build/lib/{tspace → core/Handlers}/Logger.js +4 -4
- package/build/lib/{tspace → core}/Handlers/Proxy.js +2 -2
- package/build/lib/{tspace → core}/Handlers/Relation.d.ts +2 -4
- package/build/lib/{tspace → core}/Handlers/Relation.js +69 -48
- package/build/lib/{tspace → core}/Handlers/State.d.ts +1 -1
- package/build/lib/{tspace → core}/Handlers/State.js +3 -3
- package/build/lib/{tspace → core}/Model.d.ts +358 -133
- package/build/lib/{tspace → core}/Model.js +1316 -558
- package/build/lib/core/Schema.d.ts +137 -0
- package/build/lib/{tspace → core}/Schema.js +147 -52
- package/build/lib/core/Type.d.ts +6 -0
- package/build/lib/core/Type.js +2 -0
- package/build/lib/{tspace → core}/index.d.ts +2 -1
- package/build/lib/{tspace → core}/index.js +3 -2
- package/build/lib/index.d.ts +2 -2
- package/build/lib/index.js +2 -2
- package/build/lib/utils/index.d.ts +1 -0
- package/build/lib/utils/index.js +17 -7
- package/package.json +6 -4
- package/build/lib/tspace/Schema.d.ts +0 -70
- /package/build/lib/{tspace → core}/Abstracts/AbstractBuilder.js +0 -0
- /package/build/lib/{tspace → core}/Abstracts/AbstractDB.d.ts +0 -0
- /package/build/lib/{tspace → core}/Abstracts/AbstractDB.js +0 -0
- /package/build/lib/{tspace → core}/Abstracts/AbstractModel.js +0 -0
- /package/build/lib/{tspace → core}/Decorator.d.ts +0 -0
- /package/build/lib/{tspace → core}/Handlers/Proxy.d.ts +0 -0
package/README.md
CHANGED
|
@@ -11,16 +11,61 @@ Install with [npm](https://www.npmjs.com/):
|
|
|
11
11
|
|
|
12
12
|
```sh
|
|
13
13
|
npm install tspace-mysql --save
|
|
14
|
+
npm install tspace-mysql -g
|
|
14
15
|
```
|
|
16
|
+
|
|
15
17
|
## Basic Usage
|
|
18
|
+
|
|
16
19
|
- [Configuration](#configuration)
|
|
17
|
-
- [
|
|
20
|
+
- [Query Builder](#query-builder)
|
|
21
|
+
- [Returning Results](#returning-results)
|
|
22
|
+
- [Select Statements](#select-statements)
|
|
23
|
+
- [Raw Expressions](#raw-expressions)
|
|
24
|
+
- [Ordering, Grouping, Limit and Offset](#ordering-grouping-limit-and-offset)
|
|
25
|
+
- [Ordering](#ordering)
|
|
26
|
+
- [Grouping](#grouping)
|
|
27
|
+
- [Limit and Offset](#limit-and-offset)
|
|
28
|
+
- [Joins](#joins)
|
|
29
|
+
- [Inner Join Clause](#inner-join-clause)
|
|
30
|
+
- [Left Join, Right Join Clause](#left-join-right-join-clause)
|
|
31
|
+
- [Cross Join Clause](#cross-join-clause)
|
|
32
|
+
- [Basic Where Clauses](#basic-where-clauses)
|
|
33
|
+
- [Where Clauses](#where-clauses)
|
|
34
|
+
- [Or Where Clauses](#or-where-clauses)
|
|
35
|
+
- [JSON Where Clauses](#json-where-clauses)
|
|
36
|
+
- [Additional Where Clauses](#additional-where-clauses)
|
|
37
|
+
- [Logical Grouping](#logical-grouping)
|
|
38
|
+
- [Advanced Where Clauses](#advanced-where-clauses)
|
|
39
|
+
- [Where Exists Clauses](#where-exists-clauses)
|
|
40
|
+
- [Subquery Where Clauses](#subquery-where-clauses)
|
|
41
|
+
- [Conditional Where Clauses](#conditional-where-clauses)
|
|
42
|
+
- [Paginating](#paginating)
|
|
43
|
+
- [Insert Statements](#insert-statements)
|
|
44
|
+
- [Update Statements](#update-statements)
|
|
45
|
+
- [Delete Statements](#delete-statements)
|
|
46
|
+
- [Hook Statements](#hook-statements)
|
|
47
|
+
- [Faker Statements](#faker-statements)
|
|
48
|
+
- [More Methods](#more-methods)
|
|
18
49
|
- [Database Transactions](#database-transactions)
|
|
19
50
|
- [Connection](#connection)
|
|
20
51
|
- [Backup](#backup)
|
|
21
52
|
- [Injection](#injection)
|
|
22
53
|
- [Generating Model Classes](#generating-model-classes)
|
|
23
54
|
- [Model Conventions](#model-conventions)
|
|
55
|
+
- [Basic Model Setup](#basic-model-setup)
|
|
56
|
+
- [Table Name](#table-name)
|
|
57
|
+
- [Pattern](#pattern)
|
|
58
|
+
- [UUID](#uuid)
|
|
59
|
+
- [Timestamp](#timestamp)
|
|
60
|
+
- [Debug](#debug)
|
|
61
|
+
- [Observer](#observer)
|
|
62
|
+
- [Logger](#logger)
|
|
63
|
+
- [Hooks](#hooks)
|
|
64
|
+
- [SoftDelete](#soft-delete)
|
|
65
|
+
- [Schema](#schema)
|
|
66
|
+
- [Schema Model](#schema-model)
|
|
67
|
+
- [Validation](#validation)
|
|
68
|
+
- [Sync](#sync)
|
|
24
69
|
- [Relationships](#relationships)
|
|
25
70
|
- [One To One](#one-to-one)
|
|
26
71
|
- [One To Many](#one-to-many)
|
|
@@ -29,11 +74,17 @@ npm install tspace-mysql --save
|
|
|
29
74
|
- [Deeply Nested Relations](#deeply-nested-relations)
|
|
30
75
|
- [Relation Exists](#relation-exists)
|
|
31
76
|
- [Built in Relation Functions](#built-in-relation-functions)
|
|
32
|
-
|
|
33
|
-
- [
|
|
34
|
-
- [
|
|
35
|
-
- [
|
|
36
|
-
- [
|
|
77
|
+
- [Decorator](#decorator)
|
|
78
|
+
- [Type Safety](#type-safety)
|
|
79
|
+
- [Safety Select](#safety-select)
|
|
80
|
+
- [Safety OrderBy](#safety-order-by)
|
|
81
|
+
- [Safety GroupBy](#safety-group-by)
|
|
82
|
+
- [Safety Where](#safety-where)
|
|
83
|
+
- [Safety Insert](#safety-insert)
|
|
84
|
+
- [Safety Update](#safety-update)
|
|
85
|
+
- [Safety Delete](#safety-delete)
|
|
86
|
+
- [Safety Relationships](#safety-relationships)
|
|
87
|
+
- [Blueprint](#blueprint)
|
|
37
88
|
- [Cli](#cli)
|
|
38
89
|
- [Make Model](#make-model)
|
|
39
90
|
- [Make Migration](#make-migration)
|
|
@@ -41,26 +92,30 @@ npm install tspace-mysql --save
|
|
|
41
92
|
- [Query](#query)
|
|
42
93
|
- [Dump](#dump)
|
|
43
94
|
- [Generate Models](#generate-models)
|
|
44
|
-
- [
|
|
95
|
+
- [Migration Models](#migrate-models)
|
|
45
96
|
|
|
46
97
|
## Configuration
|
|
98
|
+
|
|
47
99
|
To establish a connection, the recommended method for creating your environment variables is by using a '.env' file. using the following:
|
|
100
|
+
|
|
48
101
|
```js
|
|
49
|
-
DB_HOST
|
|
50
|
-
DB_PORT
|
|
51
|
-
DB_USERNAME = root
|
|
52
|
-
DB_PASSWORD = password
|
|
53
|
-
DB_DATABASE = database
|
|
102
|
+
DB_HOST = localhost;
|
|
103
|
+
DB_PORT = 3306;
|
|
104
|
+
DB_USERNAME = root;
|
|
105
|
+
DB_PASSWORD = password;
|
|
106
|
+
DB_DATABASE = database;
|
|
54
107
|
|
|
55
|
-
/**
|
|
108
|
+
/**
|
|
56
109
|
* @default
|
|
57
110
|
* DB_CONNECTION_LIMIT = 10
|
|
58
111
|
* DB_QUEUE_LIMIT = 0
|
|
59
112
|
* DB_TIMEOUT = 60000
|
|
60
113
|
* DB_DATE_STRINGS = true
|
|
61
|
-
*/
|
|
114
|
+
*/
|
|
62
115
|
```
|
|
116
|
+
|
|
63
117
|
You can also create a file named 'db.tspace' to configure the connection. using the following:
|
|
118
|
+
|
|
64
119
|
```js
|
|
65
120
|
source db {
|
|
66
121
|
host = localhost
|
|
@@ -68,7 +123,7 @@ source db {
|
|
|
68
123
|
database = npm
|
|
69
124
|
user = root
|
|
70
125
|
password = database
|
|
71
|
-
connectionLimit = 10
|
|
126
|
+
connectionLimit = 10
|
|
72
127
|
dateStrings = true
|
|
73
128
|
connectTimeout = 60000
|
|
74
129
|
waitForConnections = true
|
|
@@ -77,8 +132,11 @@ source db {
|
|
|
77
132
|
}
|
|
78
133
|
|
|
79
134
|
```
|
|
80
|
-
|
|
81
|
-
|
|
135
|
+
|
|
136
|
+
## Query Builder
|
|
137
|
+
|
|
138
|
+
How a database query builder works with a simple example using the following:
|
|
139
|
+
|
|
82
140
|
```js
|
|
83
141
|
+-------------+--------------+----------------------------+
|
|
84
142
|
| table users |
|
|
@@ -99,508 +157,1228 @@ Once you have configured your database connection, you can execute queries using
|
|
|
99
157
|
| 2 | 2 | posts tspace2 |
|
|
100
158
|
+-------------+--------------+----------------------------+
|
|
101
159
|
|
|
102
|
-
import { DB } from 'tspace-mysql'
|
|
103
|
-
(async () => {
|
|
104
|
-
await new DB('users').findMany()
|
|
105
|
-
// SELECT * FROM users => Array
|
|
106
|
-
await new DB('users').findOne()
|
|
107
|
-
// SELECT * FROM users LIMIT 1 => Object
|
|
108
|
-
})()
|
|
109
|
-
|
|
110
160
|
```
|
|
111
|
-
|
|
161
|
+
|
|
162
|
+
### Returning Results
|
|
163
|
+
|
|
112
164
|
```js
|
|
113
|
-
const
|
|
114
|
-
|
|
165
|
+
const user = await new DB("users").find(1); // Object or null
|
|
166
|
+
|
|
167
|
+
const user = await new DB("users").findOne(); // Object or null
|
|
168
|
+
|
|
169
|
+
const user = await new DB("users").first(); // Object or null
|
|
170
|
+
|
|
171
|
+
const user = await new DB("users").firstOrError(message); // Object or error
|
|
172
|
+
|
|
173
|
+
const users = await new DB("users").findMany(); // Array-object of users
|
|
115
174
|
|
|
175
|
+
const users = await new DB("users").get(); // Array-object of users
|
|
176
|
+
|
|
177
|
+
const users = await new DB("users").toArray(); // Array of users
|
|
178
|
+
|
|
179
|
+
const users = await new DB("users").toJSON(); // JSON of users
|
|
180
|
+
|
|
181
|
+
const user = await new DB("users").exists(); // Boolean true if user exists otherwise false
|
|
182
|
+
|
|
183
|
+
const user = await new DB("users").count(); // Number of users counted
|
|
184
|
+
|
|
185
|
+
const user = await new DB("users").avg(); // Number of users avg
|
|
186
|
+
|
|
187
|
+
const user = await new DB("users").sum(); // Number of users sum
|
|
188
|
+
|
|
189
|
+
const user = await new DB("users").max(); // Number of users max
|
|
190
|
+
|
|
191
|
+
const user = await new DB("user").min(); // Number of users min
|
|
192
|
+
|
|
193
|
+
const users = await new DB("users").toString(); // sql query string
|
|
194
|
+
|
|
195
|
+
const users = await new DB("users").toSQL(); // sql query string
|
|
196
|
+
|
|
197
|
+
const users = await new DB("users").toRawSQL(); // sql query string
|
|
198
|
+
|
|
199
|
+
const users = await new DB("users").pagination(); // Object of pagination
|
|
200
|
+
|
|
201
|
+
const users = await new DB("users").makeSelectStatement() // query string for select statement
|
|
202
|
+
|
|
203
|
+
const users = await new DB("users").makeInsertStatement() // query string for insert statement
|
|
204
|
+
|
|
205
|
+
const users = await new DB("users").makeUpdateStatement() // query string for update statement
|
|
206
|
+
|
|
207
|
+
const users = await new DB("users").makeDeleteStatement() // query string for delete statement
|
|
208
|
+
|
|
209
|
+
const users = await new DB("users").makeCreateTableStatement() // query string for create table statement
|
|
116
210
|
```
|
|
117
|
-
|
|
211
|
+
|
|
212
|
+
## Select Statements
|
|
213
|
+
|
|
118
214
|
```js
|
|
119
|
-
const select = await new DB(
|
|
215
|
+
const select = await new DB("users").select("id", "username").findOne();
|
|
120
216
|
// SELECT `users`.`id`, `users`.`username` FROM `users` LIMIT 1;
|
|
121
217
|
|
|
122
|
-
const selectRaw = await new DB(
|
|
218
|
+
const selectRaw = await new DB("users").selectRaw("COUNT(id)").findMany();
|
|
123
219
|
// SELECT COUNT(id) FROM `users`;
|
|
220
|
+
// also you can use the DB.raw() function
|
|
221
|
+
// const selectRaw = await new DB("users").selec(DB.raw("COUNT(id)")).findMany();
|
|
222
|
+
|
|
223
|
+
const selectObject = await new DB("posts")
|
|
224
|
+
.join("posts.user_id", "users.id")
|
|
225
|
+
.select("posts.*")
|
|
226
|
+
.selectObject(
|
|
227
|
+
{ id: "users.id", name: "users.name", email: "users.email" },
|
|
228
|
+
"user"
|
|
229
|
+
)
|
|
230
|
+
.findOne();
|
|
231
|
+
|
|
232
|
+
// SELECT posts.*, JSON_OBJECT('id' , `users`.`id` , 'name' , `users`.`name` , 'email' , `users`.`email`) AS `user`
|
|
233
|
+
// FROM `posts` INNER JOIN `users` ON `posts`.`user_id` = `users`.`id` LIMIT 1;
|
|
124
234
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
.select('posts.*')
|
|
128
|
-
.selectObject({ id : 'users.id', name : 'users.name' , email : 'users.email'} , 'user')
|
|
129
|
-
.findOne()
|
|
235
|
+
await new DB("users").except("id").findOne();
|
|
236
|
+
// SELECT `users`.`email`, `users`.`username` FROM `users` LIMIT 1;
|
|
130
237
|
|
|
131
|
-
|
|
132
|
-
//
|
|
238
|
+
await new DB("users").distinct().select("id").findOne();
|
|
239
|
+
// SELECT DISTINCT `users`.`id` FROM `users` LIMIT 1;
|
|
240
|
+
```
|
|
133
241
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
await new DB(
|
|
138
|
-
|
|
242
|
+
## Raw Expressions
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
const users = await new DB("users")
|
|
246
|
+
.select(DB.raw("COUNT(`username`) as c"), "username")
|
|
247
|
+
.groupBy("username")
|
|
248
|
+
.having("c > 1")
|
|
249
|
+
.findMany();
|
|
250
|
+
// SELECT COUNT(`username`) as c, `users`.`username` FROM `users` GROUP BY `username` HAVING c > 1;
|
|
251
|
+
|
|
252
|
+
const users = await new DB("users")
|
|
253
|
+
.where(
|
|
254
|
+
"id",
|
|
255
|
+
DB.raw(new DB("users").select("id").where("id", "1").limit(1).toString())
|
|
256
|
+
)
|
|
257
|
+
.findMany();
|
|
258
|
+
// SELECT * FROM `users` WHERE `users`.`id` = (SELECT `users`.`id` FROM `users` WHERE `users`.`id` = '1' LIMIT 1);
|
|
139
259
|
```
|
|
140
260
|
|
|
141
|
-
|
|
261
|
+
## Ordering, Grouping, Limit and Offset
|
|
262
|
+
|
|
263
|
+
### Ordering
|
|
264
|
+
|
|
142
265
|
```js
|
|
143
|
-
await new DB(
|
|
266
|
+
await new DB("users").orderBy("id", "asc").findOne();
|
|
144
267
|
// SELECT * FROM `users` ORDER BY `id` ASC LIMIT 1;
|
|
145
268
|
|
|
146
|
-
await new DB(
|
|
269
|
+
await new DB("users").orderBy("id", "desc").findOne();
|
|
147
270
|
// SELECT * FROM `users` ORDER BY `id` DESC LIMIT 1;
|
|
148
271
|
|
|
149
|
-
await new DB(
|
|
272
|
+
await new DB("users").oldest("id").findOne();
|
|
150
273
|
// SELECT * FROM `users` ORDER BY `id` ASC LIMIT 1;
|
|
151
274
|
|
|
152
|
-
await new DB(
|
|
275
|
+
await new DB("users").latest("id").findOne();
|
|
153
276
|
// SELECT * FROM `users` ORDER BY `id` DESC LIMIT 1;
|
|
154
277
|
|
|
155
|
-
await new DB(
|
|
278
|
+
await new DB("users").random().findMany();
|
|
279
|
+
// SELECT * FROM `users` ORDER BY RAND();
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Grouping
|
|
283
|
+
|
|
284
|
+
```js
|
|
285
|
+
await new DB("users").groupBy("id").findOne();
|
|
156
286
|
// SELECT * FROM `users` GROUP BY `id` LIMIT 1;
|
|
157
287
|
|
|
158
|
-
await new DB(
|
|
288
|
+
await new DB("users").groupBy("id", "username").findOne();
|
|
159
289
|
// SELECT * FROM `users` GROUP BY `id`, `username` LIMIT 1;
|
|
160
290
|
|
|
161
|
-
await new DB(
|
|
162
|
-
|
|
291
|
+
await new DB("users")
|
|
292
|
+
.select(DB.raw("COUNT(username) as c"), "username")
|
|
293
|
+
.groupBy("username")
|
|
294
|
+
.having("c > 1")
|
|
295
|
+
.findMany();
|
|
296
|
+
// SELECT COUNT(username) as c, `users`.`username` FROM `users` GROUP BY `username` HAVING c > 1;
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### Limit and Offset
|
|
300
|
+
|
|
301
|
+
```js
|
|
302
|
+
await new DB("users").limit(5).findMany();
|
|
303
|
+
// SELECT * FROM `users` LIMIT 5;
|
|
163
304
|
|
|
305
|
+
await new DB("users").offset(1).findOne();
|
|
306
|
+
// SELECT * FROM `users` LIMIT 1 OFFSET 1;
|
|
164
307
|
```
|
|
165
308
|
|
|
166
|
-
|
|
309
|
+
## Joins
|
|
310
|
+
|
|
311
|
+
### Inner Join Clause
|
|
312
|
+
|
|
167
313
|
```js
|
|
168
|
-
await new DB(
|
|
314
|
+
await new DB("posts").join("posts.user_id", "users.id").findMany();
|
|
169
315
|
// SELECT * FROM `posts` INNER JOIN `users` ON `posts`.`user_id` = `users`.`id`;
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Left Join, Right Join Clause
|
|
170
319
|
|
|
171
|
-
|
|
320
|
+
```js
|
|
321
|
+
await new DB("posts").leftJoin("posts.user_id", "users.id").findMany();
|
|
172
322
|
// SELECT * FROM `posts` LEFT JOIN `users` ON `posts`.`user_id` = `users`.`id`;
|
|
173
323
|
|
|
174
|
-
await new DB(
|
|
324
|
+
await new DB("posts").rightJoin("posts.user_id", "users.id").findMany();
|
|
175
325
|
// SELECT * FROM `posts` RIGHT JOIN `users` ON `posts`.`user_id` = `users`.`id`;
|
|
176
326
|
```
|
|
177
327
|
|
|
178
|
-
|
|
179
|
-
```js
|
|
180
|
-
const whereEqual = await new DB('users').where('id',1).findOne()
|
|
181
|
-
// SELECT * FROM `users` WHERE `users`.`id` = '1' LIMIT 1;
|
|
182
|
-
|
|
183
|
-
const whereNotEqual = await new DB('users').where('id','!=',1).findMany()
|
|
184
|
-
// SELECT * FROM `users` WHERE `users`.`id` != '1';
|
|
328
|
+
### Cross Join Clause
|
|
185
329
|
|
|
186
|
-
|
|
187
|
-
|
|
330
|
+
```js
|
|
331
|
+
await new DB("posts").crossJoin("posts.user_id", "users.id").findMany();
|
|
332
|
+
// SELECT * FROM `posts` CROSS JOIN `users` ON `posts`.`user_id` = `users`.`id`;
|
|
333
|
+
```
|
|
188
334
|
|
|
189
|
-
|
|
190
|
-
// SELECT * FROM `users` WHERE `users`.`id` BETWEEN '1' AND '2';
|
|
335
|
+
## Basic Where Clauses
|
|
191
336
|
|
|
192
|
-
|
|
193
|
-
// SELECT * FROM `users` WHERE `users`.`id` IN (SELECT id FROM users);
|
|
194
|
-
// also you can use -> await new DB('users').whereSubQuery('id',new DB('users').select('id').toString()).findMany()
|
|
337
|
+
### Where Clauses
|
|
195
338
|
|
|
196
|
-
|
|
197
|
-
|
|
339
|
+
```js
|
|
340
|
+
const users = await new DB("users").where("id", 1).findMany();
|
|
341
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1'
|
|
198
342
|
|
|
199
|
-
const
|
|
200
|
-
|
|
343
|
+
const users = await new DB("users")
|
|
344
|
+
.where("id", 1)
|
|
345
|
+
.where("username", "try to find")
|
|
346
|
+
.findMany();
|
|
347
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1' and `users`.`username` = 'try to find'
|
|
201
348
|
|
|
202
|
-
const
|
|
203
|
-
// SELECT * FROM `users` WHERE
|
|
349
|
+
const users = await new DB("users").where("id", ">", 1).findMany();
|
|
350
|
+
// SELECT * FROM `users` WHERE `users`.`id` > '1';
|
|
204
351
|
|
|
205
|
-
const
|
|
206
|
-
// SELECT * FROM `users` WHERE
|
|
352
|
+
const users = await new DB("users").where("id", "<>", 1).findMany();
|
|
353
|
+
// SELECT * FROM `users` WHERE `users`.`id` <> '1';
|
|
354
|
+
```
|
|
207
355
|
|
|
208
|
-
|
|
209
|
-
// SELECT * FROM `users` WHERE `users`.`json`->>'$.id' = '1234' LIMIT 1;
|
|
356
|
+
### Or Where Clauses
|
|
210
357
|
|
|
211
|
-
|
|
212
|
-
|
|
358
|
+
```js
|
|
359
|
+
const users = await new DB("users").where("id", 1).orWhere("id", 2).findMany();
|
|
360
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1' OR `users`.`id` = '2'
|
|
213
361
|
|
|
214
|
-
const
|
|
215
|
-
|
|
362
|
+
const users = await new DB("users")
|
|
363
|
+
.where("id", 1)
|
|
364
|
+
.whereQuery((query) => {
|
|
365
|
+
return query
|
|
366
|
+
.where("id", "<>", 2)
|
|
367
|
+
.orWhere("username", "try to find")
|
|
368
|
+
.orWhere("email", "find@example.com");
|
|
369
|
+
})
|
|
370
|
+
.findMany();
|
|
371
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1'
|
|
372
|
+
// AND
|
|
373
|
+
// ( `users`.`id` <> '2' OR `users`.`username` = 'try to find' OR `users`.`email` = 'find@example.com');
|
|
374
|
+
|
|
375
|
+
const users = await new DB("users")
|
|
376
|
+
.where("id", 1)
|
|
377
|
+
.orWhereQuery((query) => {
|
|
378
|
+
return query
|
|
379
|
+
.where("id", "<>", 2)
|
|
380
|
+
.where("username", "try to find")
|
|
381
|
+
.where("email", "find@example.com");
|
|
382
|
+
})
|
|
383
|
+
.findMany();
|
|
384
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1'
|
|
385
|
+
// OR
|
|
386
|
+
// ( `users`.`id` <> '2' AND `users`.`username` = 'try to find' AND `users`.`email` = 'find@example.com');
|
|
216
387
|
```
|
|
217
388
|
|
|
218
|
-
|
|
389
|
+
### JSON Where Clauses
|
|
390
|
+
|
|
219
391
|
```js
|
|
220
|
-
const
|
|
221
|
-
|
|
392
|
+
const whereJSON = await new DB("users")
|
|
393
|
+
.whereJSON("json", { key: "id", value: "1234" })
|
|
394
|
+
.findMany();
|
|
395
|
+
// SELECT * FROM `users` WHERE `users`.`json`->>'$.id' = '1234';
|
|
222
396
|
```
|
|
223
397
|
|
|
224
|
-
|
|
398
|
+
### Additional Where Clauses
|
|
399
|
+
|
|
225
400
|
```js
|
|
401
|
+
const users = await new DB("users").whereIn("id", [1, 2]).findMany();
|
|
402
|
+
// SELECT * FROM `users` WHERE `users`.`id` IN ('1','2');
|
|
226
403
|
|
|
227
|
-
await new DB(
|
|
404
|
+
const users = await new DB("users").whereNotIn("id", [1, 2]).findMany();
|
|
405
|
+
// SELECT * FROM `users` WHERE `users`.`id` NOT IN ('1','2');
|
|
228
406
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
407
|
+
const users = await new DB("users").whereBetween("id", [1, 2]).findMany();
|
|
408
|
+
// SELECT * FROM `users` WHERE `users`.`id` BETWEEN '1' AND '2';
|
|
409
|
+
|
|
410
|
+
const users = await new DB("users").whereNotBetween("id", [1, 2]).findMany();
|
|
411
|
+
// SELECT * FROM `users` WHERE `users`.`id` NOT BETWEEN '1' AND '2';
|
|
412
|
+
|
|
413
|
+
const users = await new DB("users").whereNull("username").findMany();
|
|
414
|
+
// SELECT * FROM `users` WHERE `users`.`username` IS NULL;
|
|
415
|
+
|
|
416
|
+
const users = await new DB("users").whereNotNull("username").findMany();
|
|
417
|
+
// SELECT * FROM `users` WHERE `users`.`username` IS NOT NULL;
|
|
236
418
|
```
|
|
237
419
|
|
|
238
|
-
|
|
420
|
+
### Logical Grouping
|
|
421
|
+
|
|
239
422
|
```js
|
|
240
|
-
const
|
|
241
|
-
.
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
.save()
|
|
246
|
-
// INSERT INTO `users` (`name`,`email`) VALUES ('tspace3','tspace3@gmail.com');
|
|
423
|
+
const users = await new DB("users")
|
|
424
|
+
.whereQuery((query) => query.where("id", 1).where("username", "values"))
|
|
425
|
+
.whereIn("id", [1, 2])
|
|
426
|
+
.findOne();
|
|
427
|
+
// SELECT * FROM `users` WHERE ( `users`.`id` = '1' AND `users`.`username` = 'values') AND `users`.`id` IN ('1','2'') LIMIT 1;
|
|
247
428
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
429
|
+
const users = await new DB("users")
|
|
430
|
+
.where("id", 1)
|
|
431
|
+
.whereQuery((query) => {
|
|
432
|
+
return query
|
|
433
|
+
.where("id", "<>", 2)
|
|
434
|
+
.where("username", "try to find")
|
|
435
|
+
.where("email", "find@example.com");
|
|
436
|
+
})
|
|
437
|
+
.findMany();
|
|
438
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1'
|
|
439
|
+
// AND
|
|
440
|
+
// ( `users`.`id` <> '2' AND `users`.`username` = 'try to find' AND `users`.`email` = 'find@example.com');
|
|
441
|
+
|
|
442
|
+
const users = await new DB("users")
|
|
443
|
+
.whereAny(["name", "username", "email"], "like", `%v%`)
|
|
444
|
+
.findMany();
|
|
445
|
+
// SELECT * FROM `users` WHERE ( `users`.`name` LIKE '%v%' OR `users`.`username` LIKE '%v%' OR `users`.`email` LIKE '%v%');
|
|
446
|
+
|
|
447
|
+
const users = await new DB("users")
|
|
448
|
+
.whereAll(["name", "username", "email"], "like", `%v%`)
|
|
449
|
+
.findMany();
|
|
450
|
+
// SELECT * FROM `users` WHERE ( `users`.`name` LIKE '%v%' AND `users`.`username` LIKE '%v%' AND `users`.`email` LIKE '%v%');
|
|
451
|
+
```
|
|
265
452
|
|
|
266
|
-
|
|
453
|
+
## Advanced Where Clauses
|
|
267
454
|
|
|
268
|
-
|
|
269
|
-
.where('name','tspace4')
|
|
270
|
-
.where('email','tspace4@gmail.com')
|
|
271
|
-
.createNotExists({
|
|
272
|
-
name :'tspace4',
|
|
273
|
-
email : 'tspace4@gmail.com'
|
|
274
|
-
})
|
|
275
|
-
.save()
|
|
276
|
-
// if exists return null, if not exists created new data
|
|
277
|
-
// SELECT EXISTS(SELECT 1 FROM `users` WHERE `users`.`name` = 'tspace4' AND `users`.`email` = 'tspace4@gmail.com' LIMIT 1) AS 'exists';
|
|
278
|
-
// INSERT INTO `users` (`name`,`email`) VALUES ('tspace4','tspace4@gmail.com');
|
|
455
|
+
### Where Exists Clauses
|
|
279
456
|
|
|
457
|
+
```js
|
|
458
|
+
const users = await new DB("users")
|
|
459
|
+
.whereExists(new DB("users").select("id").where("id", 1).toString())
|
|
460
|
+
.findMany();
|
|
461
|
+
// SELECT * FROM `users` WHERE EXISTS (SELECT `id` FROM `users` WHERE id = 1);
|
|
462
|
+
|
|
463
|
+
const users = await new DB("users")
|
|
464
|
+
.wherNoteExists(new DB("users").select("id").where("id", 1).toString())
|
|
465
|
+
.findMany();
|
|
466
|
+
// SELECT * FROM `users` WHERE NOT EXISTS (SELECT `id` FROM `users` WHERE id = 1);
|
|
467
|
+
```
|
|
280
468
|
|
|
281
|
-
|
|
282
|
-
.where('name','tspace4')
|
|
283
|
-
.where('email','tspace4@gmail.com')
|
|
284
|
-
.createOrSelect({
|
|
285
|
-
name :'tspace4',
|
|
286
|
-
email : 'tspace4@gmail.com'
|
|
287
|
-
})
|
|
288
|
-
.save()
|
|
289
|
-
// if has exists return data, if not exists created new data
|
|
290
|
-
// SELECT EXISTS(SELECT 1 FROM `users` WHERE `users`.`name` = 'tspace4' AND `users`.`email` = 'tspace4@gmail.com' LIMIT 1) AS 'exists';
|
|
291
|
-
// SELECT * FROM `users` WHERE `users`.`name` = 'tspace4' AND `users`.`email` = 'tspace4@gmail.com';
|
|
292
|
-
// INSERT INTO `users` (`name`,`email`) VALUES ('tspace4','tspace4@gmail.com');
|
|
469
|
+
### Subquery Where Clauses
|
|
293
470
|
|
|
294
|
-
```
|
|
295
|
-
Running A Update Query
|
|
296
471
|
```js
|
|
297
|
-
const
|
|
298
|
-
.
|
|
299
|
-
.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
.
|
|
304
|
-
|
|
472
|
+
const users = await new DB("users")
|
|
473
|
+
.whereSubQuery("id", "SELECT id FROM users")
|
|
474
|
+
.findMany();
|
|
475
|
+
// SELECT * FROM `users` WHERE `users`.`id` IN (SELECT id FROM users);
|
|
476
|
+
|
|
477
|
+
const users = await new DB("users")
|
|
478
|
+
.whereSubQuery("id", new DB("users").select("id").toString())
|
|
479
|
+
.findMany();
|
|
480
|
+
// SELECT * FROM `users` WHERE `users`.`id` IN (SELECT id FROM users);
|
|
305
481
|
|
|
306
|
-
const
|
|
307
|
-
.
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
.
|
|
313
|
-
|
|
482
|
+
const users = await new DB("users")
|
|
483
|
+
.whereSubQuery(
|
|
484
|
+
"id",
|
|
485
|
+
new DB("users")
|
|
486
|
+
.select("id")
|
|
487
|
+
.whereSubQuery("id", new DB("posts").select("user_id").toString())
|
|
488
|
+
.toString()
|
|
489
|
+
)
|
|
490
|
+
.findMany();
|
|
491
|
+
/*
|
|
314
492
|
|
|
493
|
+
SELECT * FROM `users`
|
|
494
|
+
WHERE `users`.`id`
|
|
495
|
+
IN (
|
|
496
|
+
SELECT `users`.`id` FROM `users`
|
|
497
|
+
WHERE `users`.`id`
|
|
498
|
+
IN (
|
|
499
|
+
SELECT `posts`.`user_id` FROM `posts`
|
|
500
|
+
)
|
|
501
|
+
);
|
|
502
|
+
*/
|
|
315
503
|
```
|
|
316
|
-
|
|
504
|
+
|
|
505
|
+
### Conditional Where Clauses
|
|
506
|
+
|
|
317
507
|
```js
|
|
318
|
-
const
|
|
319
|
-
.where(
|
|
320
|
-
.
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
508
|
+
const users = await new DB("users")
|
|
509
|
+
.where("id", 1)
|
|
510
|
+
.when(true, (query) => query.where("username", "when is actived"))
|
|
511
|
+
.findMany();
|
|
512
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1' AND `users`.`username` = 'when is actived';
|
|
513
|
+
|
|
514
|
+
const users = await new DB("users")
|
|
515
|
+
.where("id", 1)
|
|
516
|
+
.when(false, (query) => query.where("username", "when is actived"))
|
|
517
|
+
.findMany();
|
|
518
|
+
// SELECT * FROM `users` WHERE `users`.`id` = '1';
|
|
519
|
+
```
|
|
325
520
|
|
|
326
|
-
|
|
327
|
-
```
|
|
521
|
+
## Paginating
|
|
328
522
|
|
|
329
|
-
Running A Delete Query
|
|
330
523
|
```js
|
|
331
|
-
const
|
|
332
|
-
//
|
|
333
|
-
|
|
334
|
-
## Database Transactions
|
|
524
|
+
const users = await new DB("users").paginate();
|
|
525
|
+
// SELECT * FROM `users` LIMIT 15 OFFSET 0;
|
|
526
|
+
// SELECT COUNT(*) AS total FROM `users`;
|
|
335
527
|
|
|
336
|
-
|
|
528
|
+
const pageTwoUsers = await new DB("users").paginate({ page: 2, limit: 5 });
|
|
529
|
+
|
|
530
|
+
/*
|
|
531
|
+
SELECT * FROM `users` LIMIT 5 OFFSET 5;
|
|
532
|
+
SELECT COUNT(*) AS total FROM `users`;
|
|
533
|
+
|
|
534
|
+
the results are returned
|
|
535
|
+
{
|
|
536
|
+
meta: {
|
|
537
|
+
total: n,
|
|
538
|
+
limit: 5,
|
|
539
|
+
total_page: 5,
|
|
540
|
+
current_page: 2,
|
|
541
|
+
last_page: n,
|
|
542
|
+
next_page: 3,
|
|
543
|
+
prev_page: 1
|
|
544
|
+
},
|
|
545
|
+
data: [...your data here]
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
*/
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
## Insert Statement
|
|
337
552
|
|
|
338
553
|
```js
|
|
339
|
-
const
|
|
554
|
+
const user = await new DB("users")
|
|
555
|
+
.create({
|
|
556
|
+
name: "tspace3",
|
|
557
|
+
email: "tspace3@gmail.com",
|
|
558
|
+
})
|
|
559
|
+
.save();
|
|
560
|
+
/**
|
|
561
|
+
INSERT INTO `users`
|
|
562
|
+
(`users`.`name`,`users`.`email`)
|
|
563
|
+
VALUES
|
|
564
|
+
('tspace3','tspace3@gmail.com');
|
|
340
565
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
* @startTransaction start transaction in scopes function
|
|
345
|
-
*/
|
|
346
|
-
await connection.startTransaction()
|
|
566
|
+
-- then return the result inserted --
|
|
567
|
+
SELECT * FROM `users` WHERE `users`.`id` = ${INSERT ID};
|
|
568
|
+
*/
|
|
347
569
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
570
|
+
const users = await new DB("users")
|
|
571
|
+
.createMultiple([
|
|
572
|
+
{
|
|
573
|
+
name: "tspace4",
|
|
574
|
+
email: "tspace4@gmail.com",
|
|
575
|
+
},
|
|
576
|
+
{
|
|
577
|
+
name: "tspace5",
|
|
578
|
+
email: "tspace5@gmail.com",
|
|
579
|
+
},
|
|
580
|
+
{
|
|
581
|
+
name: "tspace6",
|
|
582
|
+
email: "tspace6@gmail.com",
|
|
583
|
+
},
|
|
584
|
+
])
|
|
585
|
+
.save();
|
|
360
586
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
title : `tspace-post2`
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
user_id : user.id,
|
|
373
|
-
title : `tspace-post3`
|
|
374
|
-
}
|
|
375
|
-
])
|
|
376
|
-
.bind(connection) // don't forget this
|
|
377
|
-
.save()
|
|
587
|
+
/**
|
|
588
|
+
INSERT INTO `users`
|
|
589
|
+
(`users`.`name`,`users`.`email`)
|
|
590
|
+
VALUES
|
|
591
|
+
('tspace4','tspace4@gmail.com'),
|
|
592
|
+
('tspace5','tspace5@gmail.com'),
|
|
593
|
+
('tspace6','tspace6@gmail.com');
|
|
594
|
+
*/
|
|
378
595
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
596
|
+
const users = await new DB("users")
|
|
597
|
+
.where("name", "tspace4")
|
|
598
|
+
.where("email", "tspace4@gmail.com")
|
|
599
|
+
.createNotExists({
|
|
600
|
+
name: "tspace4",
|
|
601
|
+
email: "tspace4@gmail.com",
|
|
602
|
+
})
|
|
603
|
+
.save();
|
|
604
|
+
/*
|
|
605
|
+
-- if exists return null, if not exists created new data --
|
|
606
|
+
SELECT EXISTS(
|
|
607
|
+
SELECT 1 FROM `users`
|
|
608
|
+
WHERE `users`.`name` = 'tspace4'
|
|
609
|
+
AND `users`.`email` = 'tspace4@gmail.com'
|
|
610
|
+
LIMIT 1
|
|
611
|
+
) AS 'exists';
|
|
612
|
+
|
|
613
|
+
INSERT INTO `users` (`users`.`name`,`users`.`email`) VALUES ('tspace4','tspace4@gmail.com');
|
|
614
|
+
*/
|
|
384
615
|
|
|
385
|
-
|
|
616
|
+
const users = await new DB("users")
|
|
617
|
+
.where("name", "tspace4")
|
|
618
|
+
.where("email", "tspace4@gmail.com")
|
|
619
|
+
.createOrSelect({
|
|
620
|
+
name: "tspace4",
|
|
621
|
+
email: "tspace4@gmail.com",
|
|
622
|
+
})
|
|
623
|
+
.save();
|
|
624
|
+
/**
|
|
625
|
+
-- if has exists return data, if not exists created new data --
|
|
626
|
+
SELECT EXISTS(
|
|
627
|
+
SELECT 1 FROM `users`
|
|
628
|
+
WHERE `users`.`name` = 'tspace4'
|
|
629
|
+
AND `users`.`email` = 'tspace4@gmail.com'
|
|
630
|
+
LIMIT 1
|
|
631
|
+
) AS 'exists';
|
|
386
632
|
|
|
387
|
-
|
|
388
|
-
*
|
|
389
|
-
* @rollback rollback transaction
|
|
390
|
-
*/
|
|
391
|
-
await connection.rollback()
|
|
392
|
-
}
|
|
633
|
+
INSERT INTO `users` (`users`.`name`,`users`.`email`) VALUES ('tspace4','tspace4@gmail.com');
|
|
393
634
|
|
|
635
|
+
SELECT * FROM `users` WHERE `users`.`id` = '4';
|
|
636
|
+
*/
|
|
394
637
|
```
|
|
395
|
-
## Connection
|
|
396
|
-
When establishing a connection, you can specify options as follows:
|
|
397
|
-
```js
|
|
398
|
-
const connection = await new DB().getConnection({
|
|
399
|
-
host: 'localhost',
|
|
400
|
-
port : 3306,
|
|
401
|
-
database: 'database'
|
|
402
|
-
username: 'username',
|
|
403
|
-
password: 'password',
|
|
404
|
-
})
|
|
405
638
|
|
|
406
|
-
|
|
407
|
-
.bind(connection) // don't forget this
|
|
408
|
-
.findMany()
|
|
409
|
-
```
|
|
639
|
+
## Update Statements
|
|
410
640
|
|
|
411
|
-
## Backup
|
|
412
|
-
To backup a database, you can perform the following steps:
|
|
413
641
|
```js
|
|
642
|
+
const user = await new DB("users")
|
|
643
|
+
.where("id", 1)
|
|
644
|
+
.update({
|
|
645
|
+
name: "tspace1**",
|
|
646
|
+
email: "tspace1@gmail.com",
|
|
647
|
+
})
|
|
648
|
+
.save();
|
|
414
649
|
/**
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
650
|
+
|
|
651
|
+
UPDATE `users` SET
|
|
652
|
+
`users`.`name` = 'tspace1',
|
|
653
|
+
`users`.`email` = 'tspace1@gmail.com'
|
|
654
|
+
WHERE `users`.`id` = '1' LIMIT 1;
|
|
655
|
+
|
|
418
656
|
*/
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
})
|
|
657
|
+
|
|
658
|
+
const user = await new DB("users")
|
|
659
|
+
.where("id", 1)
|
|
660
|
+
.updateMany({
|
|
661
|
+
name: "tspace1",
|
|
662
|
+
email: "tspace1@gmail.com",
|
|
663
|
+
})
|
|
664
|
+
.save();
|
|
428
665
|
/**
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
666
|
+
UPDATE `users` SET
|
|
667
|
+
`users`.`name` = 'tspace1',
|
|
668
|
+
`users`.`email` = 'tspace1@gmail.com'
|
|
669
|
+
WHERE `users`.`id` = '1';
|
|
433
670
|
*/
|
|
434
|
-
const backupToFile = await new DB().backupToFile({
|
|
435
|
-
database: 'try-to-backup',
|
|
436
|
-
filePath: 'backup.sql',
|
|
437
|
-
connection ?: {
|
|
438
|
-
host: 'localhost',
|
|
439
|
-
port : 3306,
|
|
440
|
-
database: 'database'
|
|
441
|
-
username: 'username',
|
|
442
|
-
password: 'password',
|
|
443
|
-
}
|
|
444
|
-
})
|
|
445
|
-
// backupToFile => backup.sql
|
|
446
671
|
|
|
672
|
+
const user = await new DB("users")
|
|
673
|
+
.where("id", 1)
|
|
674
|
+
.update(
|
|
675
|
+
{
|
|
676
|
+
name: "tspace1",
|
|
677
|
+
email: "tspace1@gmail.com",
|
|
678
|
+
},
|
|
679
|
+
["name"]
|
|
680
|
+
)
|
|
681
|
+
.save();
|
|
447
682
|
/**
|
|
448
|
-
|
|
449
|
-
|
|
683
|
+
UPDATE `users` SET
|
|
684
|
+
`name` =
|
|
685
|
+
CASE WHEN (`name` = '' OR `name` IS NULL)
|
|
686
|
+
THEN 'tspace1' ELSE `name`
|
|
687
|
+
END,
|
|
688
|
+
`email` =
|
|
689
|
+
'tspace1@gmail.com'
|
|
690
|
+
WHERE `users`.`id` = '1' LIMIT 1;
|
|
450
691
|
*/
|
|
451
|
-
await new DB().cloneDB('try-to-clone')
|
|
452
692
|
|
|
693
|
+
const user = await new DB("users")
|
|
694
|
+
.updateMultiple([
|
|
695
|
+
{
|
|
696
|
+
when: {
|
|
697
|
+
id: 1,
|
|
698
|
+
name: "name1",
|
|
699
|
+
},
|
|
700
|
+
columns: {
|
|
701
|
+
name: "update row1",
|
|
702
|
+
email: "row1@example.com",
|
|
703
|
+
},
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
when: {
|
|
707
|
+
id: 2,
|
|
708
|
+
},
|
|
709
|
+
columns: {
|
|
710
|
+
name: "update row2",
|
|
711
|
+
email: "row2@example.com",
|
|
712
|
+
},
|
|
713
|
+
},
|
|
714
|
+
])
|
|
715
|
+
.whereIn("id", [1, 2])
|
|
716
|
+
.save();
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
UPDATE `users` SET
|
|
720
|
+
`users`.`name` = (
|
|
721
|
+
CASE WHEN `users`.`id` = '1'
|
|
722
|
+
AND `users`.`name` = 'name1'
|
|
723
|
+
THEN 'update row1'
|
|
724
|
+
WHEN `users`.`id` = '2'
|
|
725
|
+
THEN 'update row2'
|
|
726
|
+
ELSE `users`.`name`
|
|
727
|
+
END
|
|
728
|
+
),
|
|
729
|
+
`users`.`email` = (
|
|
730
|
+
CASE WHEN `users`.`id` = '1'
|
|
731
|
+
AND `users`.`name` = 'name1'
|
|
732
|
+
THEN 'row1@example.com'
|
|
733
|
+
WHEN `users`.`id` = '2'
|
|
734
|
+
THEN 'row2@example.com'
|
|
735
|
+
ELSE `users`.`email`
|
|
736
|
+
END
|
|
737
|
+
)
|
|
738
|
+
WHERE `users`.`id` IN ('1','2') LIMIT 2;
|
|
739
|
+
|
|
740
|
+
*/
|
|
741
|
+
|
|
742
|
+
const user = await new DB("users")
|
|
743
|
+
.where("id", 1)
|
|
744
|
+
.updateOrCreate({
|
|
745
|
+
name: "tspace1**",
|
|
746
|
+
email: "tspace1@gmail.com",
|
|
747
|
+
})
|
|
748
|
+
.save();
|
|
749
|
+
// if has exists return update, if not exists created new data
|
|
750
|
+
// UPDATE `users` SET `name` = 'tspace1**',`email` = 'tspace1@gmail.com' WHERE `users`.`id` = '1' LIMIT 1;
|
|
751
|
+
// INSERT INTO `users` (`name`,`email`) VALUES ('tspace1**','tspace1@gmail.com');
|
|
453
752
|
```
|
|
454
753
|
|
|
455
|
-
##
|
|
456
|
-
|
|
457
|
-
Let's example a escape SQL injection and XSs injection:
|
|
754
|
+
## Delete Statements
|
|
755
|
+
|
|
458
756
|
```js
|
|
459
|
-
const
|
|
460
|
-
|
|
461
|
-
// admin OR 1=1
|
|
757
|
+
const deleted = await new DB("users").where("id", 1).delete();
|
|
758
|
+
// DELETE FROM `users` WHERE `users`.`id` = '1' LIMIT 1;
|
|
462
759
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
760
|
+
const deleted = await new DB("users").where("id", 1).deleteMany();
|
|
761
|
+
// DELETE FROM `users` WHERE `users`.`id` = '1' ;
|
|
762
|
+
```
|
|
763
|
+
|
|
764
|
+
## Hook Statements
|
|
467
765
|
|
|
766
|
+
```js
|
|
767
|
+
const hookImage = async (results) => {
|
|
768
|
+
for(const result of results) {
|
|
769
|
+
result.image = await ...getImage()
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
const user = await new DB("users").where("id", 1).hook(hookResult).findMany();
|
|
468
773
|
```
|
|
469
774
|
|
|
470
|
-
##
|
|
471
|
-
To get started, install the 'tspace-mysql' package globally using the following npm command:
|
|
775
|
+
## Faker Statements
|
|
472
776
|
|
|
473
777
|
```js
|
|
778
|
+
await new DB("users").faker(2);
|
|
474
779
|
/**
|
|
475
|
-
|
|
476
|
-
|
|
780
|
+
INSERT INTO `users`
|
|
781
|
+
(`users`.`username`,`users`.`email`)
|
|
782
|
+
VALUES
|
|
783
|
+
('ivsvtagyta86n571z9d81maz','fxcwkubccdi5ewos521uqexy'),
|
|
784
|
+
('rnr4esoki7fgekmdtarqewt','gv0mzb1m3rlbinsdyb6')
|
|
477
785
|
*/
|
|
478
|
-
|
|
786
|
+
|
|
787
|
+
// custom faker
|
|
788
|
+
await new DB("users").faker(5, (row, index) => {
|
|
789
|
+
return {
|
|
790
|
+
username: `username-${index + 1}`,
|
|
791
|
+
email: `email-${index + 1}`,
|
|
792
|
+
};
|
|
793
|
+
});
|
|
479
794
|
|
|
480
795
|
/**
|
|
481
|
-
|
|
796
|
+
|
|
797
|
+
INSERT INTO `users`
|
|
798
|
+
(`users`.`username`,`users`.`email`)
|
|
799
|
+
VALUES
|
|
800
|
+
('username-1','email-1'),
|
|
801
|
+
('username-2','email-2'),
|
|
802
|
+
('username-3','email-3'),
|
|
803
|
+
('username-4','email-4'),
|
|
804
|
+
('username-5','email-5');
|
|
805
|
+
|
|
806
|
+
*/
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
## More Methods
|
|
810
|
+
|
|
811
|
+
```js
|
|
812
|
+
where(column , operator , value)
|
|
813
|
+
whereSensitive(column , operator , value)
|
|
814
|
+
whereId(id)
|
|
815
|
+
whereUser(userId)
|
|
816
|
+
whereEmail(value)
|
|
817
|
+
whereIn(column , [])
|
|
818
|
+
whereNotIn(column , [])
|
|
819
|
+
whereNull(column)
|
|
820
|
+
whereNotNull(column)
|
|
821
|
+
whereBetween (column , [value1 , value2])
|
|
822
|
+
whereQuery(callback)
|
|
823
|
+
whereJson(column, { targetKey, value , operator })
|
|
824
|
+
whereRaw(sql)
|
|
825
|
+
whereExists(sql)
|
|
826
|
+
whereSubQuery(colmn , rawSQL)
|
|
827
|
+
whereNotSubQuery(colmn , rawSQL)
|
|
828
|
+
orWhere(column , operator , value)
|
|
829
|
+
orWhereRaw(sql)
|
|
830
|
+
orWhereIn(column , [])
|
|
831
|
+
orWhereSubQuery(colmn , rawSQL)
|
|
832
|
+
when(contition , callback)
|
|
833
|
+
select(column1 ,column2 ,...N)
|
|
834
|
+
distinct()
|
|
835
|
+
selectRaw(column1 ,column2 ,...N)
|
|
836
|
+
except(column1 ,column2 ,...N)
|
|
837
|
+
exceptTimestamp()
|
|
838
|
+
only(column1 ,column2 ,...N)
|
|
839
|
+
hidden(column1 ,column2 ,...N)
|
|
840
|
+
join(primary key , table.foreign key)
|
|
841
|
+
rightJoin (primary key , table.foreign key)
|
|
842
|
+
leftJoin (primary key , table.foreign key)
|
|
843
|
+
limit (limit)
|
|
844
|
+
having (condition)
|
|
845
|
+
havingRaw (condition)
|
|
846
|
+
orderBy (column ,'ASC' || 'DSCE')
|
|
847
|
+
orderByRaw(column ,'ASC' || 'DSCE')
|
|
848
|
+
latest (column)
|
|
849
|
+
latestRaw (column)
|
|
850
|
+
oldest (column)
|
|
851
|
+
oldestRaw (column)
|
|
852
|
+
groupBy (column)
|
|
853
|
+
groupByRaw (column)
|
|
854
|
+
create(objects)
|
|
855
|
+
createMultiple(array objects)
|
|
856
|
+
update (objects)
|
|
857
|
+
updateMany (objects)
|
|
858
|
+
updateMultiple(array objects)
|
|
859
|
+
createNotExists(objects)
|
|
860
|
+
updateOrCreate (objects)
|
|
861
|
+
onlyTrashed()
|
|
862
|
+
connection(options)
|
|
863
|
+
backup({ database , connection })
|
|
864
|
+
backupToFile({ filePath, database , connection })
|
|
865
|
+
hook((result) => ...) // callback result to function
|
|
866
|
+
sleep(seconds)
|
|
867
|
+
|
|
868
|
+
/**
|
|
869
|
+
* registry relation in your models
|
|
870
|
+
* @relationship
|
|
871
|
+
*/
|
|
872
|
+
hasOne({ name, model, localKey, foreignKey, freezeTable , as })
|
|
873
|
+
hasMany({ name, model, localKey, foreignKey, freezeTable , as })
|
|
874
|
+
belongsTo({ name, model, localKey, foreignKey, freezeTable , as })
|
|
875
|
+
belongsToMany({ name, model, localKey, foreignKey, freezeTable, as, pivot })
|
|
876
|
+
/**
|
|
877
|
+
* @relation using registry in your models
|
|
878
|
+
*/
|
|
879
|
+
relations(name1 , name2,...nameN) // with(name1, name2,...nameN)
|
|
880
|
+
/**
|
|
881
|
+
* @relation using registry in your models ignore soft delete
|
|
882
|
+
*/
|
|
883
|
+
relationsAll(name1 , name2,...nameN) // withAll(name1, name2,...nameN)
|
|
884
|
+
/**
|
|
885
|
+
* @relation using registry in your models. if exists child data remove this data
|
|
886
|
+
*/
|
|
887
|
+
relationsExists(name1 , name2,...nameN) // withExists(name1, name2,...nameN)
|
|
888
|
+
/**
|
|
889
|
+
* @relation using registry in your models return only in trash (soft delete)
|
|
890
|
+
*/
|
|
891
|
+
relationsTrashed(name1 , name2,...nameN) // withTrashed(name1, name2,...nameN)
|
|
892
|
+
/**
|
|
893
|
+
* @relation call a name of relation in registry, callback query of data
|
|
894
|
+
*/
|
|
895
|
+
relationQuery(name, (callback) ) // withQuery(name1, (callback))
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
/**
|
|
899
|
+
* queries statements
|
|
900
|
+
* @execute data of statements
|
|
901
|
+
*/
|
|
902
|
+
findMany() // get()
|
|
903
|
+
findOne() // first()
|
|
904
|
+
find(id)
|
|
905
|
+
delelte()
|
|
906
|
+
delelteMany()
|
|
907
|
+
exists()
|
|
908
|
+
toString()
|
|
909
|
+
toJSON()
|
|
910
|
+
toArray(column)
|
|
911
|
+
count(column)
|
|
912
|
+
sum(column)
|
|
913
|
+
avg(column)
|
|
914
|
+
max(column)
|
|
915
|
+
min(column)
|
|
916
|
+
pagination({ limit , page })
|
|
917
|
+
save() /* for actions statements insert or update */
|
|
918
|
+
makeSelectStatement()
|
|
919
|
+
makeInsertStatement()
|
|
920
|
+
makeUpdateStatement()
|
|
921
|
+
makeDeleteStatement()
|
|
922
|
+
makeCreateTableStatement()
|
|
923
|
+
|
|
924
|
+
```
|
|
925
|
+
|
|
926
|
+
## Database Transactions
|
|
927
|
+
|
|
928
|
+
Within a database transaction, you can utilize the following:
|
|
929
|
+
|
|
930
|
+
```js
|
|
931
|
+
const connection = await new DB().beginTransaction();
|
|
932
|
+
|
|
933
|
+
try {
|
|
934
|
+
/**
|
|
935
|
+
*
|
|
936
|
+
* @startTransaction start transaction in scopes function
|
|
937
|
+
*/
|
|
938
|
+
await connection.startTransaction();
|
|
939
|
+
|
|
940
|
+
const user = await new User()
|
|
941
|
+
.create({
|
|
942
|
+
name: `tspace`,
|
|
943
|
+
email: "tspace@example.com",
|
|
944
|
+
})
|
|
945
|
+
/**
|
|
946
|
+
*
|
|
947
|
+
* bind method for make sure this connection has same transaction in connection
|
|
948
|
+
* @params {Function} connection
|
|
949
|
+
*/
|
|
950
|
+
.bind(connection)
|
|
951
|
+
.save();
|
|
952
|
+
|
|
953
|
+
const posts = await new Post()
|
|
954
|
+
.createMultiple([
|
|
955
|
+
{
|
|
956
|
+
user_id: user.id,
|
|
957
|
+
title: `tspace-post1`,
|
|
958
|
+
},
|
|
959
|
+
{
|
|
960
|
+
user_id: user.id,
|
|
961
|
+
title: `tspace-post2`,
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
user_id: user.id,
|
|
965
|
+
title: `tspace-post3`,
|
|
966
|
+
},
|
|
967
|
+
])
|
|
968
|
+
.bind(connection) // don't forget this
|
|
969
|
+
.save();
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
*
|
|
973
|
+
* @commit commit transaction to database
|
|
974
|
+
*/
|
|
975
|
+
await connection.commit();
|
|
976
|
+
} catch (err) {
|
|
977
|
+
/**
|
|
978
|
+
*
|
|
979
|
+
* @rollback rollback transaction
|
|
980
|
+
*/
|
|
981
|
+
await connection.rollback();
|
|
982
|
+
}
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
## Connection
|
|
986
|
+
|
|
987
|
+
When establishing a connection, you can specify options as follows:
|
|
988
|
+
|
|
989
|
+
```js
|
|
990
|
+
const connection = await new DB().getConnection({
|
|
991
|
+
host: 'localhost',
|
|
992
|
+
port : 3306,
|
|
993
|
+
database: 'database'
|
|
994
|
+
username: 'username',
|
|
995
|
+
password: 'password',
|
|
996
|
+
})
|
|
997
|
+
|
|
998
|
+
const users = await new DB('users')
|
|
999
|
+
.bind(connection) // don't forget this
|
|
1000
|
+
.findMany()
|
|
1001
|
+
```
|
|
1002
|
+
|
|
1003
|
+
## Backup
|
|
1004
|
+
|
|
1005
|
+
To backup a database, you can perform the following steps:
|
|
1006
|
+
|
|
1007
|
+
```js
|
|
1008
|
+
/**
|
|
1009
|
+
*
|
|
1010
|
+
* @param {string} database Database selected
|
|
1011
|
+
* @param {object | null} to defalut new current connection
|
|
1012
|
+
*/
|
|
1013
|
+
const backup = await new DB().backup({
|
|
1014
|
+
database: 'try-to-backup', // clone current database to this database
|
|
1015
|
+
to ?: {
|
|
1016
|
+
host: 'localhost',
|
|
1017
|
+
port : 3306,
|
|
1018
|
+
username: 'username',
|
|
1019
|
+
password: 'password',
|
|
1020
|
+
}
|
|
1021
|
+
})
|
|
1022
|
+
/**
|
|
1023
|
+
*
|
|
1024
|
+
* @param {string} database Database selected
|
|
1025
|
+
* @param {string} filePath file path
|
|
1026
|
+
* @param {object | null} conection defalut current connection
|
|
1027
|
+
*/
|
|
1028
|
+
const backupToFile = await new DB().backupToFile({
|
|
1029
|
+
database: 'try-to-backup',
|
|
1030
|
+
filePath: 'backup.sql',
|
|
1031
|
+
connection ?: {
|
|
1032
|
+
host: 'localhost',
|
|
1033
|
+
port : 3306,
|
|
1034
|
+
database: 'database'
|
|
1035
|
+
username: 'username',
|
|
1036
|
+
password: 'password',
|
|
1037
|
+
}
|
|
1038
|
+
})
|
|
1039
|
+
// backupToFile => backup.sql
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
*
|
|
1043
|
+
* @param {string} database new db name
|
|
1044
|
+
*/
|
|
1045
|
+
await new DB().cloneDB('try-to-clone')
|
|
1046
|
+
|
|
1047
|
+
```
|
|
1048
|
+
|
|
1049
|
+
## Injection
|
|
1050
|
+
|
|
1051
|
+
The 'tspace-mysql' library is configured to automatically escape SQL injection by default.
|
|
1052
|
+
Let's example a escape SQL injection and XSs injection:
|
|
1053
|
+
|
|
1054
|
+
```js
|
|
1055
|
+
const input = "admin' OR '1'='1";
|
|
1056
|
+
DB.escape(input);
|
|
1057
|
+
// "admin\' OR \'1\'=\'1"
|
|
1058
|
+
|
|
1059
|
+
//XSS
|
|
1060
|
+
const input = "text hello!<script>alert('XSS attack');</script>";
|
|
1061
|
+
DB.escapeXSS(input);
|
|
1062
|
+
// "text hello!"
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
## Generating Model Classes
|
|
1066
|
+
|
|
1067
|
+
To get started, install the 'tspace-mysql' package globally using the following npm command:
|
|
1068
|
+
|
|
1069
|
+
```js
|
|
1070
|
+
/**
|
|
1071
|
+
*
|
|
1072
|
+
* @install global command
|
|
1073
|
+
*/
|
|
1074
|
+
npm install tspace-mysql -g
|
|
1075
|
+
|
|
1076
|
+
/**
|
|
1077
|
+
*
|
|
482
1078
|
* @make Model
|
|
483
|
-
*/
|
|
1079
|
+
*/
|
|
484
1080
|
tspace-mysql make:model <model name> --dir=< directory >
|
|
485
1081
|
|
|
486
|
-
# tspace-mysql make:model User --dir=App/Models
|
|
1082
|
+
# tspace-mysql make:model User --dir=App/Models
|
|
487
1083
|
# App/Models/User.ts
|
|
488
1084
|
```
|
|
1085
|
+
|
|
489
1086
|
## Model Conventions
|
|
490
|
-
|
|
1087
|
+
|
|
1088
|
+
Models generated by the make:model command will be placed in the specific directory.
|
|
491
1089
|
Let's example a basic model class:
|
|
492
1090
|
|
|
493
1091
|
```js
|
|
494
|
-
import { Model } from
|
|
1092
|
+
import { Model } from "tspace-mysql";
|
|
495
1093
|
// If you want to specify a global setting for the 'Model'
|
|
496
1094
|
Model.global({
|
|
497
1095
|
uuid: true,
|
|
498
1096
|
softDelete: true,
|
|
499
|
-
timestamp: true
|
|
500
|
-
|
|
1097
|
+
timestamp: true,
|
|
1098
|
+
logger: true,
|
|
1099
|
+
});
|
|
1100
|
+
|
|
1101
|
+
class User extends Model {
|
|
1102
|
+
constructor() {
|
|
1103
|
+
super();
|
|
1104
|
+
/**
|
|
1105
|
+
*
|
|
1106
|
+
* Assign setting global in your model
|
|
1107
|
+
* @useMethod
|
|
1108
|
+
* this.usePattern('camelCase') // => default 'snake_case'
|
|
1109
|
+
* this.useCamelCase()
|
|
1110
|
+
* this.useSnakeCase()
|
|
1111
|
+
* this.useLogger()
|
|
1112
|
+
* this.useDebug()
|
|
1113
|
+
* this.usePrimaryKey('id')
|
|
1114
|
+
* this.useTimestamp({
|
|
1115
|
+
* createdAt : 'created_at',
|
|
1116
|
+
* updatedAt : 'updated_at'
|
|
1117
|
+
* }) // runing a timestamp when insert or update
|
|
1118
|
+
* this.useSoftDelete('deletedAt') // => default target to colmun deleted_at
|
|
1119
|
+
* this.useTable('users')
|
|
1120
|
+
* this.useTableSingular() // => 'user'
|
|
1121
|
+
* this.useTablePlural() // => 'users'
|
|
1122
|
+
* this.useUUID('uuid') // => runing a uuid (universally unique identifier) when insert new data
|
|
1123
|
+
* this.useRegistry() // => build-in functions registry
|
|
1124
|
+
* this.useLoadRelationsInRegistry() // => auto generated result from relationship to results
|
|
1125
|
+
* this.useBuiltInRelationFunctions() // => build-in functions relationships to results
|
|
1126
|
+
* this.useHooks([(r) => console.log(r)])
|
|
1127
|
+
* this.useObserver(Observe)
|
|
1128
|
+
* this.useSchema ({
|
|
1129
|
+
* id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1130
|
+
* uuid : new Blueprint().varchar(50).null(),
|
|
1131
|
+
* name : new Blueprint().varchar(191).notNull(),
|
|
1132
|
+
* email : new Blueprint().varchar(191).notNull(),
|
|
1133
|
+
* created_at : new Blueprint().timestamp().null(),
|
|
1134
|
+
* updated_at : new Blueprint().timestamp().null(),
|
|
1135
|
+
* deleted_at : new Blueprint().timestamp().null()
|
|
1136
|
+
* }) // auto-generated table when table is not exists and auto-create column when column not exists
|
|
1137
|
+
*
|
|
1138
|
+
* // validate input when create or update reference to the schema in 'this.useSchema'
|
|
1139
|
+
* this.useValidateSchema({
|
|
1140
|
+
* id : Number,
|
|
1141
|
+
* uuid : Number,
|
|
1142
|
+
* name : {
|
|
1143
|
+
* type : String,
|
|
1144
|
+
* length : 191
|
|
1145
|
+
* require : true
|
|
1146
|
+
* },
|
|
1147
|
+
* email : {
|
|
1148
|
+
* type : String,
|
|
1149
|
+
* require : true,
|
|
1150
|
+
* length : 191,
|
|
1151
|
+
* match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
1152
|
+
* unique : true,
|
|
1153
|
+
* fn : (email : string) => !/^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
|
|
1154
|
+
* },
|
|
1155
|
+
* created_at : Date,
|
|
1156
|
+
* updated_at : Date,
|
|
1157
|
+
* deleted_at : Date
|
|
1158
|
+
* })
|
|
1159
|
+
*/
|
|
1160
|
+
|
|
1161
|
+
/*
|
|
1162
|
+
* the "snake case", plural name of the class will be used as the table name
|
|
1163
|
+
*
|
|
1164
|
+
* @param {string} name The table associated with the model.
|
|
1165
|
+
*/
|
|
1166
|
+
this.useTable("users");
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
export { User };
|
|
1170
|
+
export default User;
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Basic Model Setup
|
|
1174
|
+
|
|
1175
|
+
#### Table Name
|
|
1176
|
+
|
|
1177
|
+
```js
|
|
1178
|
+
import { Model } from 'tspace-mysql'
|
|
1179
|
+
class User extends Model {
|
|
1180
|
+
constructor() {
|
|
1181
|
+
super()
|
|
1182
|
+
// By default, the model knows that the table name for this User is 'users'
|
|
1183
|
+
|
|
1184
|
+
this.useTable('fixtable') // fixtable
|
|
1185
|
+
this.useTablePlural() // users
|
|
1186
|
+
this.useTableSingular() // user
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
#### Pattern
|
|
1193
|
+
|
|
1194
|
+
```js
|
|
1195
|
+
|
|
1196
|
+
import { Model } from 'tspace-mysql'
|
|
1197
|
+
class UserPhone extends Model {
|
|
1198
|
+
constructor() {
|
|
1199
|
+
super()
|
|
1200
|
+
// By default, the model is pattern snake_case
|
|
1201
|
+
// The table name is user_phones
|
|
1202
|
+
this.useSnakeCase()
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
this.useCamelCase()
|
|
1206
|
+
// The table name is userPhones
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// set the pattern CamelCase for the model
|
|
1211
|
+
const userPhone = await new UserPhone().where('user_id',1).findOne()
|
|
1212
|
+
// covert 'user_id' to 'userId'
|
|
1213
|
+
// SELECT * FROM `userPhones` WHERE `userPhones`.`userId` = '1' LIMIT 1;
|
|
1214
|
+
|
|
1215
|
+
```
|
|
1216
|
+
|
|
1217
|
+
#### UUID
|
|
1218
|
+
|
|
1219
|
+
```js
|
|
1220
|
+
|
|
1221
|
+
import { Model } from 'tspace-mysql'
|
|
1222
|
+
class User extends Model {
|
|
1223
|
+
constructor() {
|
|
1224
|
+
super()
|
|
1225
|
+
this.useUUID() // insert uuid when creating
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
```
|
|
1230
|
+
|
|
1231
|
+
#### Timestamp
|
|
1232
|
+
|
|
1233
|
+
```js
|
|
1234
|
+
|
|
1235
|
+
import { Model } from 'tspace-mysql'
|
|
1236
|
+
class User extends Model {
|
|
1237
|
+
constructor() {
|
|
1238
|
+
super()
|
|
1239
|
+
// insert created_at and updated_at when creating
|
|
1240
|
+
// update updated_at when updating
|
|
1241
|
+
// 'created_at' and 'updated_at' still relate to pettern the model
|
|
1242
|
+
// this.useCamelCase() will covert 'created_at' to 'createdAt' and 'updated_at' to 'updatedAt'
|
|
1243
|
+
this.useTimestamp()
|
|
1244
|
+
|
|
1245
|
+
// custom the columns
|
|
1246
|
+
this.useTimestamp({
|
|
1247
|
+
createdAt : 'createdAtCustom',
|
|
1248
|
+
updatedAt : 'updatedAtCustom'
|
|
1249
|
+
})
|
|
1250
|
+
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
```
|
|
1255
|
+
|
|
1256
|
+
#### Debug
|
|
1257
|
+
|
|
1258
|
+
```js
|
|
1259
|
+
|
|
1260
|
+
import { Model } from 'tspace-mysql'
|
|
1261
|
+
class User extends Model {
|
|
1262
|
+
constructor() {
|
|
1263
|
+
super()
|
|
1264
|
+
this.useDebug() // show the query sql in console when executing
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
```
|
|
1269
|
+
#### Observer
|
|
1270
|
+
|
|
1271
|
+
```js
|
|
501
1272
|
|
|
502
|
-
/**
|
|
503
1273
|
class Observe {
|
|
504
1274
|
|
|
505
|
-
public selected(results
|
|
1275
|
+
public selected(results) {
|
|
506
1276
|
console.log({ results , selected : true })
|
|
507
1277
|
}
|
|
508
1278
|
|
|
509
|
-
public created(results
|
|
1279
|
+
public created(results) {
|
|
510
1280
|
console.log({ results , created : true })
|
|
511
1281
|
}
|
|
512
1282
|
|
|
513
|
-
public updated(results
|
|
1283
|
+
public updated(results) {
|
|
514
1284
|
console.log({ results , updated : true })
|
|
515
1285
|
}
|
|
516
1286
|
|
|
517
|
-
public deleted(results
|
|
1287
|
+
public deleted(results) {
|
|
518
1288
|
console.log({ results , deleted : true })
|
|
519
1289
|
}
|
|
520
1290
|
}
|
|
521
|
-
|
|
1291
|
+
|
|
1292
|
+
import { Model } from 'tspace-mysql'
|
|
1293
|
+
class User extends Model {
|
|
1294
|
+
constructor() {
|
|
1295
|
+
super()
|
|
1296
|
+
this.useObserver(Observe) // returning to the observers by statements
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
```
|
|
1301
|
+
|
|
1302
|
+
#### Logger
|
|
1303
|
+
|
|
1304
|
+
```js
|
|
1305
|
+
|
|
1306
|
+
import { Model } from 'tspace-mysql'
|
|
1307
|
+
class User extends Model {
|
|
1308
|
+
constructor() {
|
|
1309
|
+
super()
|
|
1310
|
+
// keep logging everything except select to the table '$loggers'
|
|
1311
|
+
// the table will automatically be created
|
|
1312
|
+
this.useLogger()
|
|
1313
|
+
|
|
1314
|
+
// keep logging everything
|
|
1315
|
+
this.useLogger({
|
|
1316
|
+
selected : true,
|
|
1317
|
+
inserted : true,
|
|
1318
|
+
updated : true,
|
|
1319
|
+
deleted : true,
|
|
1320
|
+
})
|
|
1321
|
+
}
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
```
|
|
1325
|
+
|
|
1326
|
+
#### Hooks
|
|
1327
|
+
|
|
1328
|
+
```js
|
|
1329
|
+
|
|
1330
|
+
import { Model } from 'tspace-mysql'
|
|
522
1331
|
class User extends Model {
|
|
523
|
-
constructor(){
|
|
1332
|
+
constructor() {
|
|
524
1333
|
super()
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
* createdAt : 'created_at',
|
|
534
|
-
* updatedAt : 'updated_at'
|
|
535
|
-
* }) // runing a timestamp when insert or update
|
|
536
|
-
* this.useSoftDelete('deletedAt') // => default target to colmun deleted_at
|
|
537
|
-
* this.useTable('users')
|
|
538
|
-
* this.useTableSingular() // => 'user'
|
|
539
|
-
* this.useTablePlural() // => 'users'
|
|
540
|
-
* this.useUUID('uuid') // => runing a uuid (universally unique identifier) when insert new data
|
|
541
|
-
* this.useRegistry() // => build-in functions registry
|
|
542
|
-
* this.useLoadRelationsInRegistry() // => auto generated result from relationship to results
|
|
543
|
-
* this.useBuiltInRelationFunctions() // => build-in functions relationships to results
|
|
544
|
-
* this.useHooks([(r) => console.log(r)])
|
|
545
|
-
* this.useObserver(Observe)
|
|
546
|
-
* this.useSchema ({
|
|
547
|
-
* id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
548
|
-
* uuid : new Blueprint().varchar(50).null(),
|
|
549
|
-
* name : new Blueprint().varchar(191).notNull(),
|
|
550
|
-
* email : new Blueprint().varchar(191).notNull(),
|
|
551
|
-
* created_at : new Blueprint().timestamp().null(),
|
|
552
|
-
* updated_at : new Blueprint().timestamp().null(),
|
|
553
|
-
* deleted_at : new Blueprint().timestamp().null()
|
|
554
|
-
* }) // auto-generated table when table is not exists and auto-create column when column not exists
|
|
555
|
-
*
|
|
556
|
-
* // validate input when create or update reference to the schema in 'this.useSchema'
|
|
557
|
-
* this.useValidateSchema({
|
|
558
|
-
* id : Number,
|
|
559
|
-
* uuid : Number,
|
|
560
|
-
* name : {
|
|
561
|
-
* type : String,
|
|
562
|
-
* length : 191
|
|
563
|
-
* require : true
|
|
564
|
-
* },
|
|
565
|
-
* email : {
|
|
566
|
-
* type : String,
|
|
567
|
-
* require : true,
|
|
568
|
-
* length : 191,
|
|
569
|
-
* match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
570
|
-
* unique : true,
|
|
571
|
-
* fn : (email : string) => !/^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
|
|
572
|
-
* },
|
|
573
|
-
* created_at : Date,
|
|
574
|
-
* updated_at : Date,
|
|
575
|
-
* deleted_at : Date
|
|
576
|
-
* })
|
|
577
|
-
*/
|
|
1334
|
+
// when executed will returning the results to any hooks function
|
|
1335
|
+
this.useHooks([
|
|
1336
|
+
(results1) => console.log(results1),
|
|
1337
|
+
(results2) => console.log(results2),
|
|
1338
|
+
(results3) => console.log(results3)
|
|
1339
|
+
])
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
578
1342
|
|
|
1343
|
+
```
|
|
579
1344
|
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
1345
|
+
### SoftDelete
|
|
1346
|
+
|
|
1347
|
+
```js
|
|
1348
|
+
|
|
1349
|
+
import { Model } from 'tspace-mysql'
|
|
1350
|
+
class User extends Model {
|
|
1351
|
+
constructor() {
|
|
1352
|
+
super()
|
|
1353
|
+
this.useSoftDelete() // All query will be where 'deleted_at' is null
|
|
1354
|
+
|
|
1355
|
+
// you can also use patterns camelCase to covert the 'deleted_at' to 'deletedAt'
|
|
1356
|
+
// you can also customize the column 'deleted_at'
|
|
1357
|
+
this.useSoftDelete('deletedAtCustom')
|
|
1358
|
+
}
|
|
587
1359
|
}
|
|
588
|
-
|
|
589
|
-
|
|
1360
|
+
|
|
1361
|
+
const user = await new User().where('user_id',1).findOne()
|
|
1362
|
+
// SELECT * FROM `users` WHERE `users`.`userId` = '1' and `users`.`deletedAtCustom` IS NULL LIMIT 1;
|
|
1363
|
+
|
|
590
1364
|
```
|
|
591
|
-
|
|
592
|
-
Relationships
|
|
1365
|
+
|
|
1366
|
+
### Relationships
|
|
1367
|
+
|
|
1368
|
+
Relationships are defined as methods on your Model classes.
|
|
593
1369
|
Let's example a basic relationship:
|
|
594
1370
|
|
|
595
|
-
|
|
1371
|
+
#### One To One
|
|
1372
|
+
|
|
596
1373
|
A one-to-one relationship is used to define relationships where a single model is the parent to one child models
|
|
1374
|
+
|
|
597
1375
|
```js
|
|
598
1376
|
import { Model } from 'tspace-mysql'
|
|
599
1377
|
import Phone from '../Phone'
|
|
600
1378
|
class User extends Model {
|
|
601
1379
|
constructor(){
|
|
602
1380
|
super()
|
|
603
|
-
this.useTimestamp()
|
|
1381
|
+
this.useTimestamp()
|
|
604
1382
|
/**
|
|
605
1383
|
*
|
|
606
1384
|
* @hasOne Get the phone associated with the user.
|
|
@@ -609,12 +1387,12 @@ class User extends Model {
|
|
|
609
1387
|
this.hasOne({ name : 'phone' , model : Phone })
|
|
610
1388
|
}
|
|
611
1389
|
/**
|
|
612
|
-
* Mark a method for relationship
|
|
1390
|
+
* Mark a method for relationship
|
|
613
1391
|
* @hasOne Get the phone associated with the user. using function callback
|
|
614
|
-
* @function
|
|
1392
|
+
* @function
|
|
615
1393
|
*/
|
|
616
|
-
phone (callback
|
|
617
|
-
|
|
1394
|
+
phone (callback) {
|
|
1395
|
+
return this.hasOneBuilder({ name : 'phone' , model : Phone } , callback)
|
|
618
1396
|
}
|
|
619
1397
|
}
|
|
620
1398
|
export default User
|
|
@@ -622,14 +1400,16 @@ export default User
|
|
|
622
1400
|
+--------------------------------------------------------------------------+
|
|
623
1401
|
|
|
624
1402
|
import User from '../User'
|
|
625
|
-
const user = await new User().relations('
|
|
626
|
-
// user?.phone => {...}
|
|
1403
|
+
const user = await new User().relations('phone').findOne() // can use the method .with('roles') also
|
|
1404
|
+
// user?.phone => {...}
|
|
627
1405
|
const userUsingFunction = await new User().phone().findOne()
|
|
628
|
-
// userUsingFunction?.phone => {...}
|
|
1406
|
+
// userUsingFunction?.phone => {...}
|
|
629
1407
|
```
|
|
630
1408
|
|
|
631
|
-
|
|
1409
|
+
### One To Many
|
|
1410
|
+
|
|
632
1411
|
A one-to-many relationship is used to define relationships where a single model is the parent to one or more child models.
|
|
1412
|
+
|
|
633
1413
|
```js
|
|
634
1414
|
import { Model } from 'tspace-mysql'
|
|
635
1415
|
import Comment from '../Comment'
|
|
@@ -645,11 +1425,11 @@ class Post extends Model {
|
|
|
645
1425
|
this.hasMany({ name : 'comments' , model : Comment })
|
|
646
1426
|
}
|
|
647
1427
|
/**
|
|
648
|
-
*
|
|
1428
|
+
*
|
|
649
1429
|
* @hasManyQuery Get the comments for the post. using function callback
|
|
650
|
-
* @function
|
|
1430
|
+
* @function
|
|
651
1431
|
*/
|
|
652
|
-
comments (callback
|
|
1432
|
+
comments (callback) {
|
|
653
1433
|
return this.hasManyBuilder({ name : 'comments' , model : Comment } , callback)
|
|
654
1434
|
}
|
|
655
1435
|
}
|
|
@@ -664,8 +1444,10 @@ const postsUsingFunction = await new Post().comments().findOne()
|
|
|
664
1444
|
// postsUsingFunction?.comments => [{...}]
|
|
665
1445
|
```
|
|
666
1446
|
|
|
667
|
-
|
|
1447
|
+
#### Belongs To
|
|
1448
|
+
|
|
668
1449
|
A belongsto relationship is used to define relationships where a single model is the child to parent models.
|
|
1450
|
+
|
|
669
1451
|
```js
|
|
670
1452
|
import { Model } from 'tspace-mysql'
|
|
671
1453
|
import User from '../User'
|
|
@@ -681,11 +1463,11 @@ class Phone extends Model {
|
|
|
681
1463
|
this.belognsTo({ name : 'user' , model : User })
|
|
682
1464
|
}
|
|
683
1465
|
/**
|
|
684
|
-
*
|
|
1466
|
+
*
|
|
685
1467
|
* @belongsToBuilder Get the user that owns the phone.. using function callback
|
|
686
|
-
* @function
|
|
1468
|
+
* @function
|
|
687
1469
|
*/
|
|
688
|
-
user (callback
|
|
1470
|
+
user (callback) {
|
|
689
1471
|
return this.belongsToBuilder({ name : 'user' , model : User }, callback)
|
|
690
1472
|
}
|
|
691
1473
|
}
|
|
@@ -700,8 +1482,10 @@ const phoneUsingFunction = await new Phone().user().findOne()
|
|
|
700
1482
|
// phoneUsingFunction?.user => {...}
|
|
701
1483
|
```
|
|
702
1484
|
|
|
703
|
-
|
|
1485
|
+
#### Many To Many
|
|
1486
|
+
|
|
704
1487
|
Many-to-many relations are slightly more complicated than hasOne and hasMany relationships.
|
|
1488
|
+
|
|
705
1489
|
```js
|
|
706
1490
|
import { Model } from 'tspace-mysql'
|
|
707
1491
|
import Role from '../Role'
|
|
@@ -718,9 +1502,9 @@ class User extends Model {
|
|
|
718
1502
|
}
|
|
719
1503
|
/**
|
|
720
1504
|
* @belongsToBuilder Get the user that owns the phone.. using function callback
|
|
721
|
-
* @function
|
|
1505
|
+
* @function
|
|
722
1506
|
*/
|
|
723
|
-
roles (callback
|
|
1507
|
+
roles (callback) {
|
|
724
1508
|
return this.belognsToManyBuilder({ model : Role } , callback)
|
|
725
1509
|
}
|
|
726
1510
|
}
|
|
@@ -735,9 +1519,11 @@ const userUsingFunction = await new User().roles().findOne()
|
|
|
735
1519
|
// user?.roles => [{...}]
|
|
736
1520
|
```
|
|
737
1521
|
|
|
738
|
-
|
|
739
|
-
|
|
1522
|
+
#### Deeply Nested Relations
|
|
1523
|
+
|
|
1524
|
+
Relationships can involve deep connections.
|
|
740
1525
|
Let's example of a deep relationship:
|
|
1526
|
+
|
|
741
1527
|
```js
|
|
742
1528
|
import { Model } from 'tspace-mysql'
|
|
743
1529
|
|
|
@@ -767,7 +1553,7 @@ class Comment extends Model {
|
|
|
767
1553
|
// Deeply nested relations
|
|
768
1554
|
await new User()
|
|
769
1555
|
.relations('posts')
|
|
770
|
-
.relationQuery('posts', (query : Post) => {
|
|
1556
|
+
.relationQuery('posts', (query : Post) => {
|
|
771
1557
|
return query.relations('comments','user')
|
|
772
1558
|
.relationQuery('comments', (query : Comment) => {
|
|
773
1559
|
return query.relations('user','post')
|
|
@@ -781,7 +1567,7 @@ await new User()
|
|
|
781
1567
|
})
|
|
782
1568
|
.findMany()
|
|
783
1569
|
|
|
784
|
-
// Select some columns in nested relations
|
|
1570
|
+
// Select some columns in nested relations
|
|
785
1571
|
await new User()
|
|
786
1572
|
.relations('posts')
|
|
787
1573
|
.relationQuery('posts', (query : Post) => query.select('id','user_id','title'))
|
|
@@ -811,9 +1597,12 @@ await new User()
|
|
|
811
1597
|
.findMany()
|
|
812
1598
|
|
|
813
1599
|
```
|
|
814
|
-
|
|
815
|
-
|
|
1600
|
+
|
|
1601
|
+
#### Relation Exists
|
|
1602
|
+
|
|
1603
|
+
Relationships can return results only if they are not empty in relations, considering soft deletes.
|
|
816
1604
|
Let's illustrate this with an example of an existence check in relations:
|
|
1605
|
+
|
|
817
1606
|
```js
|
|
818
1607
|
+-------------+--------------+----------------------------+--------------------+
|
|
819
1608
|
| table users | |
|
|
@@ -864,7 +1653,7 @@ await new User().relations('posts').findMany()
|
|
|
864
1653
|
* id : 1,
|
|
865
1654
|
* username: "tspace1",
|
|
866
1655
|
* email : "tspace1@gmail.com",
|
|
867
|
-
* posts : []
|
|
1656
|
+
* posts : []
|
|
868
1657
|
* },
|
|
869
1658
|
* {
|
|
870
1659
|
* id : 2,
|
|
@@ -876,19 +1665,19 @@ await new User().relations('posts').findMany()
|
|
|
876
1665
|
* user_id : 2,
|
|
877
1666
|
* title : "posts 2"
|
|
878
1667
|
* }
|
|
879
|
-
* ]
|
|
1668
|
+
* ]
|
|
880
1669
|
* },
|
|
881
1670
|
* {
|
|
882
1671
|
* id : 3,
|
|
883
1672
|
* username: "tspace3",
|
|
884
1673
|
* email : "tspace3@gmail.com",
|
|
885
|
-
* posts : []
|
|
1674
|
+
* posts : []
|
|
886
1675
|
* }
|
|
887
1676
|
* ]
|
|
888
1677
|
*/
|
|
889
1678
|
|
|
890
1679
|
await new User().relationsExists('posts').findMany()
|
|
891
|
-
/*
|
|
1680
|
+
/*
|
|
892
1681
|
* @returns [
|
|
893
1682
|
* {
|
|
894
1683
|
* id : 2,
|
|
@@ -900,7 +1689,7 @@ await new User().relationsExists('posts').findMany()
|
|
|
900
1689
|
* user_id : 2,
|
|
901
1690
|
* title : "posts 2"
|
|
902
1691
|
* }
|
|
903
|
-
* ]
|
|
1692
|
+
* ]
|
|
904
1693
|
* }
|
|
905
1694
|
* ]
|
|
906
1695
|
* because posts id 1 and id 3 has been removed from database (using soft delete)
|
|
@@ -908,8 +1697,11 @@ await new User().relationsExists('posts').findMany()
|
|
|
908
1697
|
|
|
909
1698
|
|
|
910
1699
|
```
|
|
911
|
-
|
|
1700
|
+
|
|
1701
|
+
### Built in Relation Functions
|
|
1702
|
+
|
|
912
1703
|
Certainly, let's illustrate the use of a built-in function in the results of relationships:
|
|
1704
|
+
|
|
913
1705
|
```js
|
|
914
1706
|
import { Model } from 'tspace-mysql'
|
|
915
1707
|
|
|
@@ -949,38 +1741,38 @@ for (const post of posts) {
|
|
|
949
1741
|
|
|
950
1742
|
```
|
|
951
1743
|
|
|
952
|
-
|
|
1744
|
+
### Decorator
|
|
1745
|
+
|
|
953
1746
|
Decorators can be used in a Model.
|
|
954
1747
|
Let's illustrate this with an example of a decorators:
|
|
1748
|
+
|
|
955
1749
|
```js
|
|
956
1750
|
|
|
957
|
-
import {
|
|
958
|
-
Blueprint, Model ,
|
|
959
|
-
Table ,TableSingular, TablePlural,
|
|
1751
|
+
import {
|
|
1752
|
+
Blueprint, Model ,
|
|
1753
|
+
Table ,TableSingular, TablePlural,
|
|
960
1754
|
UUID, SoftDelete, Timestamp,
|
|
961
1755
|
Pattern, CamelCase , snakeCase ,
|
|
962
|
-
Column, Validate, Observer
|
|
963
|
-
HasMany, HasOne, BelongsTo, BelongsToMany
|
|
964
|
-
|
|
1756
|
+
Column, Validate, Observer
|
|
965
1757
|
} from 'tspace-mysql'
|
|
966
1758
|
import { Post } from './Post'
|
|
967
1759
|
import { PostUser } from './PostUser'
|
|
968
1760
|
|
|
969
1761
|
class UserObserve {
|
|
970
1762
|
|
|
971
|
-
public selected(results
|
|
1763
|
+
public selected(results) {
|
|
972
1764
|
console.log({ results , selected : true })
|
|
973
1765
|
}
|
|
974
|
-
|
|
975
|
-
public created(results
|
|
1766
|
+
|
|
1767
|
+
public created(results) {
|
|
976
1768
|
console.log({ results , created : true })
|
|
977
1769
|
}
|
|
978
|
-
|
|
979
|
-
public updated(results
|
|
1770
|
+
|
|
1771
|
+
public updated(results) {
|
|
980
1772
|
console.log({ results , updated : true })
|
|
981
1773
|
}
|
|
982
|
-
|
|
983
|
-
public deleted(results
|
|
1774
|
+
|
|
1775
|
+
public deleted(results) {
|
|
984
1776
|
console.log({ results , deleted : true })
|
|
985
1777
|
}
|
|
986
1778
|
}
|
|
@@ -1027,244 +1819,643 @@ class User extends Model {
|
|
|
1027
1819
|
|
|
1028
1820
|
@Column(() => new Blueprint().timestamp().null())
|
|
1029
1821
|
public deletedAt!: Date
|
|
1030
|
-
|
|
1031
|
-
@HasMany({ model : Post })
|
|
1032
|
-
public posts!: Post[]
|
|
1033
1822
|
|
|
1034
|
-
|
|
1035
|
-
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
export { User }
|
|
1826
|
+
export default User
|
|
1827
|
+
|
|
1828
|
+
```
|
|
1829
|
+
|
|
1830
|
+
### Schema
|
|
1831
|
+
|
|
1832
|
+
The schema refers to the structure of the database as it pertains to the objects and classes in the model.
|
|
1833
|
+
using the following:
|
|
1834
|
+
|
|
1835
|
+
#### Schema Model
|
|
1836
|
+
|
|
1837
|
+
```js
|
|
1838
|
+
import { Model, Blueprint } from "tspace-mysql";
|
|
1839
|
+
class User extends Model {
|
|
1840
|
+
constructor() {
|
|
1841
|
+
super();
|
|
1842
|
+
this.useCamelCase()
|
|
1843
|
+
this.useSchema({
|
|
1844
|
+
id: new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1845
|
+
uuid: new Blueprint().varchar(50).null(),
|
|
1846
|
+
name: new Blueprint().varchar(191).notNull(),
|
|
1847
|
+
email: new Blueprint().varchar(191).notNull(),
|
|
1848
|
+
createdAt: new Blueprint().timestamp().null().bindColumn('created_at'), // you can fix the column name with 'bindColumn'
|
|
1849
|
+
updatedAt: new Blueprint().timestamp().null().bindColumn('updated_at'),
|
|
1850
|
+
deletedAt: new Blueprint().timestamp().null().bindColumn('deleted_at')
|
|
1851
|
+
})
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
|
|
1855
|
+
|
|
1856
|
+
```
|
|
1857
|
+
|
|
1858
|
+
#### Validation
|
|
1859
|
+
|
|
1860
|
+
Validate the schema of Model
|
|
1861
|
+
let's example a validator model:
|
|
1862
|
+
|
|
1863
|
+
```js
|
|
1864
|
+
import { Model, Blueprint } from "tspace-mysql";
|
|
1865
|
+
class User extends Model {
|
|
1866
|
+
constructor() {
|
|
1867
|
+
super();
|
|
1868
|
+
this.useCamelCase();
|
|
1869
|
+
this.useSchema({
|
|
1870
|
+
id: new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1871
|
+
uuid: new Blueprint().varchar(50).null(),
|
|
1872
|
+
name: new Blueprint().varchar(191).notNull(),
|
|
1873
|
+
email: new Blueprint().varchar(191).notNull(),
|
|
1874
|
+
createdAt: new Blueprint().timestamp().null(),
|
|
1875
|
+
updatedAt: new Blueprint().timestamp().null(),
|
|
1876
|
+
deletedAt: new Blueprint().timestamp().null(),
|
|
1877
|
+
});
|
|
1878
|
+
|
|
1879
|
+
// validate input when create or update reference to the schema in 'this.useSchema'
|
|
1880
|
+
this.useValidateSchema({
|
|
1881
|
+
id: Number,
|
|
1882
|
+
uuid: Number,
|
|
1883
|
+
name: {
|
|
1884
|
+
type: String,
|
|
1885
|
+
length: 191,
|
|
1886
|
+
require: true,
|
|
1887
|
+
json: true,
|
|
1888
|
+
},
|
|
1889
|
+
email: {
|
|
1890
|
+
type: String,
|
|
1891
|
+
require: true,
|
|
1892
|
+
length: 191,
|
|
1893
|
+
match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
1894
|
+
unique: true,
|
|
1895
|
+
fn: (email: string) => {
|
|
1896
|
+
return /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
|
|
1897
|
+
}
|
|
1898
|
+
},
|
|
1899
|
+
createdAt: Date,
|
|
1900
|
+
updatedAt: Date,
|
|
1901
|
+
deletedAt: Date,
|
|
1902
|
+
});
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
```
|
|
1906
|
+
|
|
1907
|
+
#### Sync
|
|
1908
|
+
|
|
1909
|
+
Sync the schema with the "Models" setting in your directory.
|
|
1910
|
+
This process will verify and update table columns and foreign keys as needed.
|
|
1911
|
+
Ensure that the relationships are correctly established through the 'useSchema' method in your models.
|
|
1912
|
+
Let's examine a basic sync class:
|
|
1913
|
+
|
|
1914
|
+
```js
|
|
1915
|
+
/**
|
|
1916
|
+
*
|
|
1917
|
+
* @Ex directory
|
|
1918
|
+
*
|
|
1919
|
+
* - node_modules
|
|
1920
|
+
* - src
|
|
1921
|
+
* - index.ts
|
|
1922
|
+
* - Models
|
|
1923
|
+
* - User.ts
|
|
1924
|
+
* - Post.ts
|
|
1925
|
+
*/
|
|
1926
|
+
|
|
1927
|
+
// file User
|
|
1928
|
+
class User extends Model {
|
|
1929
|
+
constructor() {
|
|
1930
|
+
super();
|
|
1931
|
+
this.hasMany({ name: "posts", model: Post });
|
|
1932
|
+
|
|
1933
|
+
// if you need to initialize data when creating the table, you can use the following.
|
|
1934
|
+
this.beforeCreatingTable(async () => {
|
|
1935
|
+
return await new User()
|
|
1936
|
+
.create({
|
|
1937
|
+
...columns,
|
|
1938
|
+
})
|
|
1939
|
+
.void()
|
|
1940
|
+
.save();
|
|
1941
|
+
});
|
|
1942
|
+
|
|
1943
|
+
this.useSchema({
|
|
1944
|
+
id: new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1945
|
+
uuid: new Blueprint().varchar(50).null(),
|
|
1946
|
+
email: new Blueprint().int().notNull().unique(),
|
|
1947
|
+
name: new Blueprint().varchar(255).null(),
|
|
1948
|
+
created_at: new Blueprint().timestamp().null(),
|
|
1949
|
+
updated_at: new Blueprint().timestamp().null(),
|
|
1950
|
+
deleted_at: new Blueprint().timestamp().null(),
|
|
1951
|
+
});
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
// file Post
|
|
1956
|
+
import User from "./User";
|
|
1957
|
+
class Post extends Model {
|
|
1958
|
+
constructor() {
|
|
1959
|
+
super();
|
|
1960
|
+
this.hasMany({ name: "comments", model: Comment });
|
|
1961
|
+
this.belongsTo({ name: "user", model: User });
|
|
1962
|
+
this.useSchema({
|
|
1963
|
+
id: new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1964
|
+
uuid: new Blueprint().varchar(50).null(),
|
|
1965
|
+
user_id: new Blueprint().int().notNull().foreign({
|
|
1966
|
+
references: "id",
|
|
1967
|
+
on: User,
|
|
1968
|
+
onDelete: "CASCADE",
|
|
1969
|
+
onUpdate: "CASCADE",
|
|
1970
|
+
}),
|
|
1971
|
+
title: new Blueprint().varchar(255).null(),
|
|
1972
|
+
created_at: new Blueprint().timestamp().null(),
|
|
1973
|
+
updated_at: new Blueprint().timestamp().null(),
|
|
1974
|
+
deleted_at: new Blueprint().timestamp().null(),
|
|
1975
|
+
});
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1979
|
+
await Schema.sync(`/src/Models`, {
|
|
1980
|
+
force: true,
|
|
1981
|
+
log: true,
|
|
1982
|
+
foreign: true,
|
|
1983
|
+
changed: true,
|
|
1984
|
+
});
|
|
1985
|
+
|
|
1986
|
+
// also you can sync by Model
|
|
1987
|
+
await new User().sync({ force: true, foreign: true, changed: true });
|
|
1988
|
+
```
|
|
1989
|
+
|
|
1990
|
+
### Type Safety
|
|
1991
|
+
Type safety in TypeScript refers to the ability of the language to detect and prevent type errors during compile-time.
|
|
1992
|
+
Type safety still works when you add additional types to your model, using the following:
|
|
1993
|
+
|
|
1994
|
+
```js
|
|
1995
|
+
// in file User.ts
|
|
1996
|
+
import { Model , Blueprint , SchemaType } from 'tspace-mysql'
|
|
1997
|
+
import Phone from '../Phone'
|
|
1998
|
+
|
|
1999
|
+
const schemaUser = {
|
|
2000
|
+
id :new Blueprint().int().notNull().primary().autoIncrement(),
|
|
2001
|
+
uuid :new Blueprint().varchar(50).null(),
|
|
2002
|
+
email :new Blueprint().varchar(50).null(),
|
|
2003
|
+
name :new Blueprint().varchar(255).null(),
|
|
2004
|
+
username : new Blueprint().varchar(255).null(),
|
|
2005
|
+
password : new Blueprint().varchar(255).null(),
|
|
2006
|
+
createdAt :new Blueprint().timestamp().null(),
|
|
2007
|
+
updatedAt :new Blueprint().timestamp().null()
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
type SchemaUserType = SchemaType<typeof schemaUser>
|
|
2011
|
+
|
|
2012
|
+
// you can re-assign type for schema
|
|
2013
|
+
/**
|
|
2014
|
+
type SchemaUserType = SchemaType<typeof schemaUser , {
|
|
2015
|
+
id : number,
|
|
2016
|
+
uuid : string,
|
|
2017
|
+
...
|
|
2018
|
+
}>
|
|
2019
|
+
|
|
2020
|
+
*/
|
|
2021
|
+
|
|
2022
|
+
class User extends Model<SchemaUserType> { // add this type for the Model
|
|
2023
|
+
constructor() {
|
|
2024
|
+
super()
|
|
2025
|
+
this.useSchema(schemaUser)
|
|
2026
|
+
this.hasOne({ model : Phone, name : 'phone' })
|
|
2027
|
+
this.hasMany({ model : Phone, name : 'phones' })
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
export { User , SchemaUserType }
|
|
2032
|
+
export default User
|
|
2033
|
+
|
|
2034
|
+
+--------------------------------------------------------------------------+
|
|
2035
|
+
|
|
2036
|
+
// in file Phone.ts
|
|
2037
|
+
import { Model , Blueprint , SchemaType } from 'tspace-mysql'
|
|
2038
|
+
import { User } from './User.ts'
|
|
2039
|
+
const schemaPhone = {
|
|
2040
|
+
id :new Blueprint().int().notNull().primary().autoIncrement(),
|
|
2041
|
+
uuid :new Blueprint().varchar(50).null(),
|
|
2042
|
+
userId : new Blueprint().int().notNull(),
|
|
2043
|
+
number :new Blueprint().varchar(50).notNull(),
|
|
2044
|
+
createdAt :new Blueprint().timestamp().null(),
|
|
2045
|
+
updatedAt :new Blueprint().timestamp().null()
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
type SchemaPhoneType = SchemaType<typeof schemaPhone>
|
|
2049
|
+
|
|
2050
|
+
class Phone extends Model<SchemaPhoneType> {
|
|
2051
|
+
constructor() {
|
|
2052
|
+
super()
|
|
2053
|
+
this.useSchema(schemaPhone)
|
|
2054
|
+
this.useBelongsTo({ model : User, name : 'user'})
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
export { Phone , SchemaPhoneType }
|
|
2059
|
+
export default Phone
|
|
2060
|
+
|
|
2061
|
+
+--------------------------------------------------------------------------+
|
|
2062
|
+
```
|
|
2063
|
+
|
|
2064
|
+
### Safety Select
|
|
2065
|
+
|
|
2066
|
+
```js
|
|
2067
|
+
import { User , schemaUserType } from './User.ts'
|
|
2068
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2069
|
+
|
|
2070
|
+
const users = await new User().select('id','username').findMany() ✅
|
|
2071
|
+
const users = await new User().select('idx','username').findMany() ❌
|
|
2072
|
+
|
|
2073
|
+
const users = await new User().except('id','username').findMany() ✅
|
|
2074
|
+
const users = await new User().except('idx','username').findMany() ❌
|
|
2075
|
+
|
|
2076
|
+
```
|
|
2077
|
+
|
|
2078
|
+
### Safety OrderBy
|
|
2079
|
+
|
|
2080
|
+
```js
|
|
2081
|
+
|
|
2082
|
+
import { User , schemaUserType } from './User.ts'
|
|
2083
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2084
|
+
|
|
2085
|
+
const users = await new User().orderBy('id','DESC').findMany() ✅
|
|
2086
|
+
const users = await new User().orderBy('idx','DESC').findMany() ❌
|
|
2087
|
+
|
|
2088
|
+
const users = await new User().latest('id').findMany() ✅
|
|
2089
|
+
const users = await new User().latest('idx').findMany() ❌
|
|
2090
|
+
|
|
2091
|
+
const users = await new User().oldest('id').findMany() ✅
|
|
2092
|
+
const users = await new User().oldest('idx').findMany() ❌
|
|
2093
|
+
|
|
2094
|
+
```
|
|
2095
|
+
|
|
2096
|
+
### Safety GroupBy
|
|
2097
|
+
|
|
2098
|
+
```js
|
|
2099
|
+
import { User , schemaUserType } from './User.ts'
|
|
2100
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2101
|
+
|
|
2102
|
+
const users = await new User().groupBy('id').findMany() ✅
|
|
2103
|
+
const users = await new User().groupBy('idx').findMany() ❌
|
|
2104
|
+
|
|
2105
|
+
```
|
|
2106
|
+
|
|
2107
|
+
### Safety Where
|
|
2108
|
+
|
|
2109
|
+
```js
|
|
2110
|
+
import { User , schemaUserType } from './User.ts'
|
|
2111
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2112
|
+
|
|
2113
|
+
const users = await new User().where('id',1).findMany() ✅
|
|
2114
|
+
const users = await new User().where('idxx',1).findMany() ❌
|
|
2115
|
+
|
|
2116
|
+
const users = await new User().where('id',1).orWhere('id',5).findMany() ✅
|
|
2117
|
+
const users = await new User().where('id',1).orWhere('idxx',5).findMany() ❌
|
|
2118
|
+
|
|
2119
|
+
const users = await new User().whereIn('id',[1]).findMany() ✅
|
|
2120
|
+
const users = await new User().whereIn('idx',[1]).findMany() ❌
|
|
2121
|
+
|
|
2122
|
+
const users = await new User().whereNull('id').findMany() ✅
|
|
2123
|
+
const users = await new User().whereNull('idx').findMany() ❌
|
|
2124
|
+
|
|
2125
|
+
const users = await new User().whereNotNull('id').findMany()
|
|
2126
|
+
const users = await new User().whereNotNull('idx').findMany()
|
|
2127
|
+
|
|
2128
|
+
const users = await new User().whereBetween('id',[1,2]).findMany() ✅
|
|
2129
|
+
const users = await new User().whereBetween('idx',[1,2]).findMany() ❌
|
|
2130
|
+
|
|
2131
|
+
const users = await new User()
|
|
2132
|
+
.whereSubQuery(
|
|
2133
|
+
'id',
|
|
2134
|
+
new User().select('id').toString()
|
|
2135
|
+
).findMany() ✅
|
|
2136
|
+
|
|
2137
|
+
const users = await new User()
|
|
2138
|
+
.whereSubQuery(
|
|
2139
|
+
'idx',
|
|
2140
|
+
new User().select('id').toString()
|
|
2141
|
+
).findMany() ❌
|
|
2142
|
+
|
|
2143
|
+
```
|
|
2144
|
+
|
|
2145
|
+
### Safety Insert
|
|
2146
|
+
|
|
2147
|
+
```js
|
|
2148
|
+
import { User , schemaUserType } from './User.ts'
|
|
2149
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2150
|
+
|
|
2151
|
+
const users = await new User().create({ id : 10 }).save() ✅
|
|
2152
|
+
|
|
2153
|
+
const users = await new User().create({ idx : 10 }).save() ❌
|
|
2154
|
+
|
|
2155
|
+
```
|
|
2156
|
+
|
|
2157
|
+
### Safety Update
|
|
2158
|
+
|
|
2159
|
+
```js
|
|
2160
|
+
import { User , schemaUserType } from './User.ts'
|
|
2161
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2162
|
+
|
|
2163
|
+
const users = await new User().update({ id : 10 }).where('id',1).save() ✅
|
|
2164
|
+
const users = await new User().update({ id : 10 }).where('idx',1).save() ❌
|
|
2165
|
+
const users = await new User().update({ idx : 10 }).where('idx',1).save() ❌
|
|
2166
|
+
|
|
2167
|
+
```
|
|
2168
|
+
|
|
2169
|
+
### Safety Delete
|
|
2170
|
+
|
|
2171
|
+
```js
|
|
2172
|
+
import { User , schemaUserType } from './User.ts'
|
|
2173
|
+
import { Phone, schemaPhoneType } from './Phone.ts'
|
|
2174
|
+
|
|
2175
|
+
const users = await new User().where('id',1).delete() ✅
|
|
2176
|
+
const users = await new User().where('idx',1).delete() ❌
|
|
2177
|
+
|
|
2178
|
+
```
|
|
2179
|
+
|
|
2180
|
+
### Safety Relationships
|
|
2181
|
+
|
|
2182
|
+
```js
|
|
2183
|
+
import { User } from './User.ts'
|
|
2184
|
+
import { Phone } from './Phone.ts'
|
|
2185
|
+
// Case #1 : Relationship with 2 relations 'phone' and 'phones'
|
|
2186
|
+
const users = await new User()
|
|
2187
|
+
.relations('phone','phones')
|
|
2188
|
+
.findMany()
|
|
2189
|
+
|
|
2190
|
+
for(const user of users) {
|
|
2191
|
+
user.phone ❌
|
|
2192
|
+
user.phones ❌
|
|
2193
|
+
}
|
|
2194
|
+
|
|
2195
|
+
// You can also specify the type for the results
|
|
2196
|
+
// bad 👎👎👎
|
|
2197
|
+
const users = await new User()
|
|
2198
|
+
.relations('phone','phones')
|
|
2199
|
+
.findMany<{ phone : Record<string,any> , phones : any[]}>()
|
|
2200
|
+
|
|
2201
|
+
for(const user of users) {
|
|
2202
|
+
user.phone ✅
|
|
2203
|
+
user.phones ✅
|
|
2204
|
+
user.phone.id ✅
|
|
2205
|
+
user.phone.idx ✅💩💩💩
|
|
2206
|
+
user.phones.map(phone => phone.id) ✅
|
|
2207
|
+
user.phones.map(phone => phone.idx) ✅💩💩💩
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
// good 👍👍👍
|
|
2211
|
+
const users = await new User()
|
|
2212
|
+
.relations('phone','phones')
|
|
2213
|
+
.findMany<{ phone : schemaPhoneType , phones : schemaPhoneType[] }>()
|
|
2214
|
+
|
|
2215
|
+
for(const user of users) {
|
|
2216
|
+
user.phone ✅
|
|
2217
|
+
user.phones ✅
|
|
2218
|
+
user.phone.id ✅
|
|
2219
|
+
user.phone.idx ❌
|
|
2220
|
+
user.phones.map(phone => phone.id) ✅
|
|
2221
|
+
user.phones.map(phone => phone.idx) ❌
|
|
2222
|
+
}
|
|
2223
|
+
|
|
2224
|
+
+--------------------------------------------------------------------------+
|
|
2225
|
+
|
|
2226
|
+
// Case #2 : There is a relationship between two entities, 'phone' and 'phones', both of which are related to the 'user' entity through nested relations
|
|
2227
|
+
const users = await new User()
|
|
2228
|
+
.relations('phone','phones')
|
|
2229
|
+
.relationQuery('phone' , (query : Phone) => query.relations('user'))
|
|
2230
|
+
.relationQuery('phones' , (query : Phone) => query.relations('user'))
|
|
2231
|
+
.findMany<{ phone : schemaPhoneType , phones : schemaPhoneType[] }>()
|
|
2232
|
+
|
|
2233
|
+
for(const user of users) {
|
|
2234
|
+
user.phone.user ❌
|
|
2235
|
+
user.phones.map(phone =>phone.user) ❌
|
|
2236
|
+
}
|
|
2237
|
+
|
|
2238
|
+
// You can also specify the type for the results
|
|
2239
|
+
// bad 👎👎👎
|
|
2240
|
+
const users = await new User()
|
|
2241
|
+
.relations('phone','phones')
|
|
2242
|
+
.relationQuery('phone' , (query : Phone) => query.relations('user'))
|
|
2243
|
+
.relationQuery('phones' , (query : Phone) => query.relations('user'))
|
|
2244
|
+
.findMany<{ phone : Record<string,any> , phones : Record<string,any>[] }>()
|
|
2245
|
+
|
|
2246
|
+
for(const user of users) {
|
|
2247
|
+
user.phone.user ✅💩💩💩
|
|
2248
|
+
user.phones.map(phone =>phone.user) ✅💩💩💩
|
|
2249
|
+
user.phone.user.idx ✅💩💩💩
|
|
2250
|
+
user.phones.map(phone =>phone.user.idx) ✅💩💩💩
|
|
2251
|
+
}
|
|
2252
|
+
|
|
2253
|
+
// good 👍👍👍
|
|
2254
|
+
const users = await new User()
|
|
2255
|
+
.relations('phone','phones')
|
|
2256
|
+
.relationQuery('phone' , (query : Phone) => query.relations('user'))
|
|
2257
|
+
.relationQuery('phones' , (query : Phone) => query.relations('user'))
|
|
2258
|
+
.findMany<{
|
|
2259
|
+
phone : Partial<SchemaPhoneType> & { user : SchemaUserType};
|
|
2260
|
+
phones : (Partial<SchemaPhoneType> & { user : SchemaUserType})[];
|
|
2261
|
+
}>()
|
|
2262
|
+
|
|
2263
|
+
for(const user of users) {
|
|
2264
|
+
user.phone.user ✅
|
|
2265
|
+
user.phone.user.id ✅
|
|
2266
|
+
user.phone.userx ❌
|
|
2267
|
+
user.phone.user.idx ❌
|
|
2268
|
+
user.phones.map(phone =>phone.user.id) ✅
|
|
2269
|
+
user.phones.map(phone =>phone.user.idx) ❌
|
|
2270
|
+
}
|
|
2271
|
+
|
|
2272
|
+
+--------------------------------------------------------------------------+
|
|
2273
|
+
// If you don't want to set types for every returning method such as 'findOne', 'findMany', and so on...
|
|
2274
|
+
|
|
2275
|
+
import { Model , Blueprint , SchemaType , RelationType } from 'tspace-mysql'
|
|
2276
|
+
import { Phone , SchemaPhoneType } from '../Phone'
|
|
2277
|
+
|
|
2278
|
+
const schemaUser = {
|
|
2279
|
+
id :new Blueprint().int().notNull().primary().autoIncrement(),
|
|
2280
|
+
uuid :new Blueprint().varchar(50).null(),
|
|
2281
|
+
email :new Blueprint().varchar(50).null(),
|
|
2282
|
+
name :new Blueprint().varchar(255).null(),
|
|
2283
|
+
username : new Blueprint().varchar(255).null(),
|
|
2284
|
+
password : new Blueprint().varchar(255).null(),
|
|
2285
|
+
createdAt :new Blueprint().timestamp().null(),
|
|
2286
|
+
updatedAt :new Blueprint().timestamp().null()
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
type SchemaUserType = SchemaType<typeof schemaUser>
|
|
1036
2290
|
|
|
1037
|
-
|
|
1038
|
-
|
|
2291
|
+
type RelationUserType = RelationType<{
|
|
2292
|
+
phones : SchemaPhoneType[]
|
|
2293
|
+
phone : SchemaPhoneType
|
|
2294
|
+
}>
|
|
2295
|
+
|
|
2296
|
+
class User extends Model<SchemaUserType, RelationUserType> {
|
|
2297
|
+
constructor() {
|
|
2298
|
+
super()
|
|
2299
|
+
this.useSchema(schemaUser)
|
|
2300
|
+
this.hasOne({ model : Phone, name : 'phonex' }) ❌
|
|
2301
|
+
this.hasMany({ model : Phone, name : 'phonesx' }) ❌
|
|
2302
|
+
this.hasOne({ model : Phone, name : 'phone' }) ✅
|
|
2303
|
+
this.hasMany({ model : Phone, name : 'phones' }) ✅
|
|
2304
|
+
}
|
|
1039
2305
|
}
|
|
1040
2306
|
|
|
1041
|
-
export { User }
|
|
2307
|
+
export { User , SchemaUserType }
|
|
1042
2308
|
export default User
|
|
1043
2309
|
|
|
1044
|
-
|
|
1045
|
-
## Schema Model
|
|
1046
|
-
Define the schema of a Model
|
|
2310
|
+
+--------------------------------------------------------------------------+
|
|
1047
2311
|
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
2312
|
+
// in file Phone.ts
|
|
2313
|
+
import { Model , Blueprint , SchemaType , RelationType} from 'tspace-mysql'
|
|
2314
|
+
import { User } from './User.ts'
|
|
2315
|
+
const schemaPhone = {
|
|
2316
|
+
id :new Blueprint().int().notNull().primary().autoIncrement(),
|
|
2317
|
+
uuid :new Blueprint().varchar(50).null(),
|
|
2318
|
+
userId : new Blueprint().int().notNull(),
|
|
2319
|
+
number :new Blueprint().varchar(50).notNull(),
|
|
2320
|
+
createdAt :new Blueprint().timestamp().null(),
|
|
2321
|
+
updatedAt :new Blueprint().timestamp().null()
|
|
2322
|
+
}
|
|
2323
|
+
|
|
2324
|
+
type SchemaPhoneType = SchemaType<typeof schemaPhone>
|
|
2325
|
+
|
|
2326
|
+
type RelationPhoneType = RelationType<{
|
|
2327
|
+
user : SchemaPhoneType[]
|
|
2328
|
+
}>
|
|
2329
|
+
|
|
2330
|
+
class Phone extends Model<SchemaPhoneType,RelationPhoneType> {
|
|
2331
|
+
constructor() {
|
|
1055
2332
|
super()
|
|
1056
|
-
this.
|
|
1057
|
-
this.
|
|
1058
|
-
|
|
1059
|
-
uuid : new Blueprint().varchar(50).null(),
|
|
1060
|
-
name : new Blueprint().varchar(191).notNull(),
|
|
1061
|
-
email : new Blueprint().varchar(191).notNull(),
|
|
1062
|
-
createdAt : new Blueprint().timestamp().null(),
|
|
1063
|
-
updatedAt : new Blueprint().timestamp().null(),
|
|
1064
|
-
deletedAt : new Blueprint().timestamp().null()
|
|
1065
|
-
})
|
|
1066
|
-
// validate input when create or update reference to the schema in 'this.useSchema'
|
|
1067
|
-
this.useValidateSchema({
|
|
1068
|
-
id : Number,
|
|
1069
|
-
uuid : Number,
|
|
1070
|
-
name : {
|
|
1071
|
-
type : String,
|
|
1072
|
-
length : 191,
|
|
1073
|
-
require : true,
|
|
1074
|
-
json : true
|
|
1075
|
-
},
|
|
1076
|
-
email : {
|
|
1077
|
-
type : String,
|
|
1078
|
-
require : true,
|
|
1079
|
-
length : 191,
|
|
1080
|
-
match: /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
|
|
1081
|
-
unique : true,
|
|
1082
|
-
fn : (email : string) => /^[a-zA-Z0-9._]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email)
|
|
1083
|
-
},
|
|
1084
|
-
createdAt : Date,
|
|
1085
|
-
updatedAt : Date,
|
|
1086
|
-
deletedAt : Date
|
|
1087
|
-
})
|
|
2333
|
+
this.useSchema(schemaPhone)
|
|
2334
|
+
this.useBelongsTo({ model : User, name : 'userx'}) ❌
|
|
2335
|
+
this.useBelongsTo({ model : User, name : 'user'}) ✅
|
|
1088
2336
|
}
|
|
1089
2337
|
}
|
|
1090
2338
|
|
|
2339
|
+
export { Phone , SchemaPhoneType }
|
|
2340
|
+
export default Phone
|
|
2341
|
+
|
|
2342
|
+
+--------------------------------------------------------------------------+
|
|
2343
|
+
|
|
2344
|
+
const users = await new User()
|
|
2345
|
+
.relations('phonex','phonesx') ❌
|
|
2346
|
+
.relationQuery('phonex' ❌ , (query : Phone) => query.relations('user')) ✅
|
|
2347
|
+
.relationQuery('phonesx' ❌ , (query : Phone) => query.relations('user')) ✅
|
|
2348
|
+
.findMany()
|
|
2349
|
+
|
|
2350
|
+
const users = await new User()
|
|
2351
|
+
.relations('phone','phones') ✅
|
|
2352
|
+
.relationQuery('phonex' ❌ , (query : Phone) => query.relations('user')) ✅
|
|
2353
|
+
.relationQuery('phonesx' ❌ , (query : Phone) => query.relations('user')) ✅
|
|
2354
|
+
.findMany()
|
|
2355
|
+
|
|
2356
|
+
const users = await new User()
|
|
2357
|
+
.relations('phone','phones')
|
|
2358
|
+
.relationQuery('phone' , (query : Phone) => query.relations('userx')) ❌
|
|
2359
|
+
.relationQuery('phones' , (query : Phone) => query.relations('userx')) ❌
|
|
2360
|
+
.findMany()
|
|
2361
|
+
|
|
2362
|
+
const users = await new User()
|
|
2363
|
+
.relations('phone','phones') ✅
|
|
2364
|
+
.relationQuery('phone' ✅ , (query : Phone) => query.relations('user')) ✅
|
|
2365
|
+
.relationQuery('phones'✅ , (query : Phone) => query.relations('user')) ✅
|
|
2366
|
+
.findMany()
|
|
2367
|
+
|
|
2368
|
+
for(const user of users) {
|
|
2369
|
+
user.phone.user ✅
|
|
2370
|
+
user.phone.user.id ✅
|
|
2371
|
+
user.phone.userx ❌
|
|
2372
|
+
user.phone.user.idx ❌
|
|
2373
|
+
user.phones.map(phone =>phone.user.id) ✅
|
|
2374
|
+
user.phones.map(phone =>phone.user.idx) ❌
|
|
2375
|
+
}
|
|
2376
|
+
|
|
1091
2377
|
```
|
|
1092
2378
|
|
|
1093
|
-
##
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
Related by method 'useSchema' in your models.
|
|
1097
|
-
Let's examine a basic model sync class:
|
|
2379
|
+
## Blueprint
|
|
2380
|
+
|
|
2381
|
+
Schema table created by command make:migration, you may use the:
|
|
1098
2382
|
|
|
1099
2383
|
```js
|
|
2384
|
+
import { Schema , Blueprint , DB } from 'tspace-mysql'
|
|
2385
|
+
(async () => {
|
|
2386
|
+
await new Schema().table('users', {
|
|
2387
|
+
id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
2388
|
+
uuid : new Blueprint().varchar(120).null()
|
|
2389
|
+
name : new Blueprint().varchar(120).default('name'),
|
|
2390
|
+
email : new Blueprint().varchar(255).unique().notNull(),
|
|
2391
|
+
email_verify : new Blueprint().tinyInt(),
|
|
2392
|
+
password : new Blueprint().varchar(255),
|
|
2393
|
+
json : new Blueprint().json(),
|
|
2394
|
+
created_at : new Blueprint().null().timestamp(),
|
|
2395
|
+
updated_at : new Blueprint().null().timestamp(),
|
|
2396
|
+
deleted_at : new Blueprint().null().timestamp()
|
|
2397
|
+
})
|
|
2398
|
+
/**
|
|
2399
|
+
*
|
|
2400
|
+
* @Faker fake data 5 raw
|
|
2401
|
+
* await new DB().table('users').faker(5)
|
|
2402
|
+
*/
|
|
2403
|
+
})()
|
|
2404
|
+
|
|
1100
2405
|
/**
|
|
1101
|
-
*
|
|
1102
|
-
* @
|
|
1103
|
-
*
|
|
1104
|
-
* - node_modules
|
|
1105
|
-
* - src
|
|
1106
|
-
* - index.ts
|
|
1107
|
-
* - Models
|
|
1108
|
-
* - User.ts
|
|
1109
|
-
* - Post.ts
|
|
2406
|
+
* To add types of the schema to the database
|
|
2407
|
+
* @Types
|
|
2408
|
+
*
|
|
1110
2409
|
*/
|
|
2410
|
+
int (number)
|
|
2411
|
+
tinyInt (number)
|
|
2412
|
+
bigInt (number)
|
|
2413
|
+
double ()
|
|
2414
|
+
float ()
|
|
2415
|
+
json ()
|
|
2416
|
+
varchar (number)
|
|
2417
|
+
char (number)
|
|
2418
|
+
longText()
|
|
2419
|
+
mediumText()
|
|
2420
|
+
tinyText()
|
|
2421
|
+
text()
|
|
2422
|
+
enum(...n)
|
|
2423
|
+
date()
|
|
2424
|
+
dateTime()
|
|
2425
|
+
timestamp ()
|
|
1111
2426
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
})
|
|
1126
|
-
}
|
|
1127
|
-
}
|
|
1128
|
-
|
|
1129
|
-
// file Post
|
|
1130
|
-
import User from './User'
|
|
1131
|
-
class Post extends Model {
|
|
1132
|
-
constructor(){
|
|
1133
|
-
super()
|
|
1134
|
-
this.hasMany({ name : 'comments' , model : Comment })
|
|
1135
|
-
this.belongsTo({ name : 'user' , model : User })
|
|
1136
|
-
this.useSchema ({
|
|
1137
|
-
id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1138
|
-
uuid : new Blueprint().varchar(50).null(),
|
|
1139
|
-
user_id : new Blueprint().int().notNull()
|
|
1140
|
-
.foreign({ references : 'id' , on : User ,onDelete : 'CASCADE' , onUpdate : 'CASCADE' }),
|
|
1141
|
-
title : new Blueprint().varchar(255).null(),
|
|
1142
|
-
created_at : new Blueprint().timestamp().null(),
|
|
1143
|
-
updated_at : new Blueprint().timestamp().null(),
|
|
1144
|
-
deleted_at : new Blueprint().timestamp().null()
|
|
1145
|
-
})
|
|
1146
|
-
}
|
|
1147
|
-
}
|
|
1148
|
-
await Schema.sync(`src/Models` , { force : true })
|
|
1149
|
-
|
|
1150
|
-
// also you can sync by Model
|
|
1151
|
-
await new User().sync({ force : true })
|
|
1152
|
-
|
|
1153
|
-
```
|
|
1154
|
-
## Query Builder
|
|
1155
|
-
Methods builder for queries
|
|
1156
|
-
```js
|
|
1157
|
-
where(column , operator , value)
|
|
1158
|
-
whereSensitive(column , operator , value)
|
|
1159
|
-
whereId(id)
|
|
1160
|
-
whereUser(userId)
|
|
1161
|
-
whereEmail(value)
|
|
1162
|
-
whereIn(column , [])
|
|
1163
|
-
whereNotIn(column , [])
|
|
1164
|
-
whereNull(column)
|
|
1165
|
-
whereNotNull(column)
|
|
1166
|
-
whereBetween (column , [value1 , value2])
|
|
1167
|
-
whereQuery(callback)
|
|
1168
|
-
whereJson(column, { targetKey, value , operator })
|
|
1169
|
-
whereRaw(sql)
|
|
1170
|
-
whereExists(sql)
|
|
1171
|
-
whereSubQuery(colmn , rawSQL)
|
|
1172
|
-
whereNotSubQuery(colmn , rawSQL)
|
|
1173
|
-
orWhere(column , operator , value)
|
|
1174
|
-
orWhereRaw(sql)
|
|
1175
|
-
orWhereIn(column , [])
|
|
1176
|
-
orWhereSubQuery(colmn , rawSQL)
|
|
1177
|
-
when(contition , callback)
|
|
1178
|
-
select(column1 ,column2 ,...N)
|
|
1179
|
-
distinct()
|
|
1180
|
-
selectRaw(column1 ,column2 ,...N)
|
|
1181
|
-
except(column1 ,column2 ,...N)
|
|
1182
|
-
only(column1 ,column2 ,...N)
|
|
1183
|
-
hidden(column1 ,column2 ,...N)
|
|
1184
|
-
join(primary key , table.foreign key)
|
|
1185
|
-
rightJoin (primary key , table.foreign key)
|
|
1186
|
-
leftJoin (primary key , table.foreign key)
|
|
1187
|
-
limit (limit)
|
|
1188
|
-
having (condition)
|
|
1189
|
-
havingRaw (condition)
|
|
1190
|
-
orderBy (column ,'ASC' || 'DSCE')
|
|
1191
|
-
orderByRaw(column ,'ASC' || 'DSCE')
|
|
1192
|
-
latest (column)
|
|
1193
|
-
latestRaw (column)
|
|
1194
|
-
oldest (column)
|
|
1195
|
-
oldestRaw (column)
|
|
1196
|
-
groupBy (column)
|
|
1197
|
-
groupByRaw (column)
|
|
1198
|
-
create(objects)
|
|
1199
|
-
createMultiple(array objects)
|
|
1200
|
-
update (objects)
|
|
1201
|
-
updateMany (objects)
|
|
1202
|
-
createNotExists(objects)
|
|
1203
|
-
updateOrCreate (objects)
|
|
1204
|
-
onlyTrashed()
|
|
1205
|
-
connection(options)
|
|
1206
|
-
backup({ database , connection })
|
|
1207
|
-
backupToFile({ filePath, database , connection })
|
|
1208
|
-
hook((result) => ...) // callback result to function
|
|
2427
|
+
/**
|
|
2428
|
+
* To add attributes of the schema to the database
|
|
2429
|
+
* @Attrbuites
|
|
2430
|
+
*
|
|
2431
|
+
*/
|
|
2432
|
+
unsigned()
|
|
2433
|
+
unique()
|
|
2434
|
+
null()
|
|
2435
|
+
notNull()
|
|
2436
|
+
primary()
|
|
2437
|
+
default(string)
|
|
2438
|
+
defaultTimestamp()
|
|
2439
|
+
autoIncrement()
|
|
1209
2440
|
|
|
1210
|
-
/**
|
|
1211
|
-
*
|
|
1212
|
-
*
|
|
1213
|
-
*/
|
|
1214
|
-
hasOne({ name, model, localKey, foreignKey, freezeTable , as })
|
|
1215
|
-
hasMany({ name, model, localKey, foreignKey, freezeTable , as })
|
|
1216
|
-
belongsTo({ name, model, localKey, foreignKey, freezeTable , as })
|
|
1217
|
-
belongsToMany({ name, model, localKey, foreignKey, freezeTable, as, pivot })
|
|
1218
|
-
/**
|
|
1219
|
-
* @relation using registry in your models
|
|
1220
|
-
*/
|
|
1221
|
-
relations(name1 , name2,...nameN)
|
|
1222
|
-
/**
|
|
1223
|
-
* @relation using registry in your models ignore soft delete
|
|
1224
|
-
*/
|
|
1225
|
-
relationsAll(name1 , name2,...nameN)
|
|
1226
|
-
/**
|
|
1227
|
-
* @relation using registry in your models. if exists child data remove this data
|
|
1228
|
-
*/
|
|
1229
|
-
relationsExists(name1 , name2,...nameN)
|
|
1230
|
-
/**
|
|
1231
|
-
* @relation call a name of relation in registry, callback query of data
|
|
2441
|
+
/**
|
|
2442
|
+
* To add a foreign key to the column
|
|
2443
|
+
* @ForeginKey
|
|
1232
2444
|
*/
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
2445
|
+
foreign({ references : ${COLUMN} , on : ${TABLE-NAME OR MODEL CLASSES} })
|
|
2446
|
+
|
|
2447
|
+
/**
|
|
2448
|
+
*
|
|
2449
|
+
* Binding a column in the key of the schema forwards the key to the corresponding column in the database.
|
|
2450
|
+
* @BindColumn
|
|
1236
2451
|
*/
|
|
1237
|
-
|
|
2452
|
+
bindColumn('<REAL-NAME-COLUMN-IN-DB>')
|
|
1238
2453
|
|
|
1239
2454
|
|
|
1240
|
-
/**
|
|
1241
|
-
* queries statements
|
|
1242
|
-
* @execute data of statements
|
|
1243
|
-
*/
|
|
1244
|
-
findMany()
|
|
1245
|
-
findOne()
|
|
1246
|
-
find(id)
|
|
1247
|
-
delelte()
|
|
1248
|
-
delelteMany()
|
|
1249
|
-
exists()
|
|
1250
|
-
toString()
|
|
1251
|
-
toJSON()
|
|
1252
|
-
toArray(column)
|
|
1253
|
-
count(column)
|
|
1254
|
-
sum(column)
|
|
1255
|
-
avg(column)
|
|
1256
|
-
max(column)
|
|
1257
|
-
min(column)
|
|
1258
|
-
pagination({ limit , page })
|
|
1259
|
-
save() /* for actions statements insert or update */
|
|
1260
|
-
makeSelectStatement()
|
|
1261
|
-
makeInsertStatement()
|
|
1262
|
-
makeUpdateStatement()
|
|
1263
|
-
makeDeleteStatement()
|
|
1264
|
-
makeCreateStatement()
|
|
1265
2455
|
```
|
|
1266
2456
|
|
|
1267
2457
|
## Cli
|
|
2458
|
+
|
|
1268
2459
|
To get started, let's install tspace-mysql
|
|
1269
2460
|
you may use a basic cli :
|
|
1270
2461
|
|
|
@@ -1272,12 +2463,15 @@ you may use a basic cli :
|
|
|
1272
2463
|
npm install tspace-mysql -g
|
|
1273
2464
|
|
|
1274
2465
|
```
|
|
2466
|
+
|
|
1275
2467
|
## Make Model
|
|
2468
|
+
|
|
1276
2469
|
Command will be placed Model in the specific directory
|
|
2470
|
+
|
|
1277
2471
|
```js
|
|
1278
2472
|
|
|
1279
|
-
/**
|
|
1280
|
-
*
|
|
2473
|
+
/**
|
|
2474
|
+
*
|
|
1281
2475
|
* @make Model
|
|
1282
2476
|
* @options
|
|
1283
2477
|
* @arg --m => created scheme table for migrate. short cut migration table like Make Migration
|
|
@@ -1285,12 +2479,12 @@ Command will be placed Model in the specific directory
|
|
|
1285
2479
|
* @arg --type=js // extension js. default ts
|
|
1286
2480
|
*/
|
|
1287
2481
|
tspace-mysql make:model <model name> --m --dir=.... --type=....
|
|
1288
|
-
|
|
1289
|
-
tspace-mysql make:model User --m --dir=app/Models
|
|
2482
|
+
|
|
2483
|
+
tspace-mysql make:model User --m --dir=app/Models
|
|
1290
2484
|
/**
|
|
1291
|
-
*
|
|
2485
|
+
*
|
|
1292
2486
|
* @Ex directory
|
|
1293
|
-
*/
|
|
2487
|
+
*/
|
|
1294
2488
|
- node_modules
|
|
1295
2489
|
- app
|
|
1296
2490
|
- Models
|
|
@@ -1298,10 +2492,12 @@ tspace-mysql make:model User --m --dir=app/Models
|
|
|
1298
2492
|
```
|
|
1299
2493
|
|
|
1300
2494
|
## Make Migration
|
|
2495
|
+
|
|
1301
2496
|
Command will be placed Migration in the specific directory
|
|
2497
|
+
|
|
1302
2498
|
```js
|
|
1303
|
-
/**
|
|
1304
|
-
*
|
|
2499
|
+
/**
|
|
2500
|
+
*
|
|
1305
2501
|
* @make Migration Table
|
|
1306
2502
|
* @options
|
|
1307
2503
|
* @arg --dir=directory => created scheme table in directory. default root directory
|
|
@@ -1311,9 +2507,9 @@ tspace-mysql make:migration <table name> --type=... --dir=....
|
|
|
1311
2507
|
|
|
1312
2508
|
tspace-mysql make:migration users --dir=app/Models/Migrations
|
|
1313
2509
|
/**
|
|
1314
|
-
*
|
|
2510
|
+
*
|
|
1315
2511
|
* @Ex directory
|
|
1316
|
-
*/
|
|
2512
|
+
*/
|
|
1317
2513
|
- node_modules
|
|
1318
2514
|
- app
|
|
1319
2515
|
- Models
|
|
@@ -1321,23 +2517,25 @@ tspace-mysql make:migration users --dir=app/Models/Migrations
|
|
|
1321
2517
|
create_users_table.ts
|
|
1322
2518
|
User.ts
|
|
1323
2519
|
```
|
|
2520
|
+
|
|
1324
2521
|
## Migrate
|
|
2522
|
+
|
|
1325
2523
|
```js
|
|
1326
|
-
/**
|
|
1327
|
-
*
|
|
2524
|
+
/**
|
|
2525
|
+
*
|
|
1328
2526
|
* @run Migrate table
|
|
1329
2527
|
* @options
|
|
1330
2528
|
* @arg --dir=directory => find migrate in directory. default find in root folder
|
|
1331
2529
|
* @arg --type=js // extension js default ts
|
|
1332
2530
|
*/
|
|
1333
2531
|
tspace-mysql migrate <folder> --type=<type file js or ts> --dir=<directory for migrate>
|
|
1334
|
-
|
|
2532
|
+
|
|
1335
2533
|
tspace-mysql migrate --dir=app/Models/Migrations --type=js
|
|
1336
2534
|
|
|
1337
2535
|
/**
|
|
1338
|
-
*
|
|
2536
|
+
*
|
|
1339
2537
|
* @Ex directory
|
|
1340
|
-
*/
|
|
2538
|
+
*/
|
|
1341
2539
|
- node_modules
|
|
1342
2540
|
- app
|
|
1343
2541
|
- Models
|
|
@@ -1350,13 +2548,18 @@ tspace-mysql migrate --dir=app/Models/Migrations --type=js
|
|
|
1350
2548
|
```
|
|
1351
2549
|
|
|
1352
2550
|
# Query
|
|
2551
|
+
|
|
1353
2552
|
Command will be execute a query
|
|
2553
|
+
|
|
1354
2554
|
```js
|
|
1355
2555
|
tspace-mysql query "SELECT * FROM users"
|
|
1356
2556
|
|
|
1357
2557
|
```
|
|
2558
|
+
|
|
1358
2559
|
# Dump
|
|
2560
|
+
|
|
1359
2561
|
Command will be dump database or table into file
|
|
2562
|
+
|
|
1360
2563
|
```js
|
|
1361
2564
|
tspace-mysql dump:db "database" --values // backup with values in the tables
|
|
1362
2565
|
|
|
@@ -1365,73 +2568,25 @@ tspace-mysql dump:table "table" --values // backup with values in the table
|
|
|
1365
2568
|
```
|
|
1366
2569
|
|
|
1367
2570
|
# Generate Models
|
|
2571
|
+
|
|
1368
2572
|
Command will be generate models from table in database
|
|
2573
|
+
|
|
1369
2574
|
```js
|
|
1370
|
-
tspace-mysql generate:models --dir=<folder for creating>
|
|
1371
|
-
|
|
1372
|
-
tspace-mysql gen:models --dir=<folder for creating> --env=development
|
|
1373
|
-
or
|
|
2575
|
+
tspace-mysql generate:models --dir=<folder for creating>
|
|
2576
|
+
|
|
1374
2577
|
tspace-mysql generate:models --dir=app/Models --env=development --decorators
|
|
1375
2578
|
|
|
1376
2579
|
```
|
|
1377
2580
|
|
|
1378
|
-
|
|
1379
|
-
|
|
2581
|
+
# Migration Models
|
|
2582
|
+
|
|
2583
|
+
Command will be generate migrations by schema in your models
|
|
2584
|
+
|
|
1380
2585
|
```js
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
await new Schema().table('users', {
|
|
1384
|
-
id : new Blueprint().int().notNull().primary().autoIncrement(),
|
|
1385
|
-
uuid : new Blueprint().varchar(120).null()
|
|
1386
|
-
name : new Blueprint().varchar(120).default('name'),
|
|
1387
|
-
email : new Blueprint().varchar(255).unique().notNull(),
|
|
1388
|
-
email_verify : new Blueprint().tinyInt(),
|
|
1389
|
-
password : new Blueprint().varchar(255),
|
|
1390
|
-
json : new Blueprint().json(),
|
|
1391
|
-
created_at : new Blueprint().null().timestamp(),
|
|
1392
|
-
updated_at : new Blueprint().null().timestamp()
|
|
1393
|
-
})
|
|
1394
|
-
/**
|
|
1395
|
-
*
|
|
1396
|
-
* @Faker fake data 5 raw
|
|
1397
|
-
* await new DB().table('users').faker(5)
|
|
1398
|
-
*/
|
|
1399
|
-
})()
|
|
2586
|
+
tspace-mysql migrations:models --dir=<path to migration> --models=<path to your models> --generate
|
|
2587
|
+
tspace-mysql migrations:models --dir=<path to migration> --push
|
|
1400
2588
|
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
* @Types
|
|
1404
|
-
*
|
|
1405
|
-
*/
|
|
1406
|
-
int (number)
|
|
1407
|
-
tinyInt (number)
|
|
1408
|
-
bigInt (number)
|
|
1409
|
-
double ()
|
|
1410
|
-
float ()
|
|
1411
|
-
json ()
|
|
1412
|
-
varchar (number)
|
|
1413
|
-
char (number)
|
|
1414
|
-
longText()
|
|
1415
|
-
mediumText()
|
|
1416
|
-
tinyText()
|
|
1417
|
-
text()
|
|
1418
|
-
enum(...n)
|
|
1419
|
-
date()
|
|
1420
|
-
dateTime()
|
|
1421
|
-
timestamp ()
|
|
2589
|
+
tspace-mysql migrations:models --models=src/app/models --dir=migrations --generate
|
|
2590
|
+
tspace-mysql migrations:models --dir=migrations --push
|
|
1422
2591
|
|
|
1423
|
-
|
|
1424
|
-
* add Attrbuites of schema in database
|
|
1425
|
-
* @Attrbuites
|
|
1426
|
-
*
|
|
1427
|
-
*/
|
|
1428
|
-
unsigned()
|
|
1429
|
-
unique()
|
|
1430
|
-
null()
|
|
1431
|
-
notNull()
|
|
1432
|
-
primary()
|
|
1433
|
-
default(string)
|
|
1434
|
-
defaultTimestamp()
|
|
1435
|
-
autoIncrement()
|
|
1436
|
-
foreign({ references : <column> , on : <table or model>}),
|
|
1437
|
-
```
|
|
2592
|
+
```
|