tspace-mysql 1.9.1 → 1.9.3
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 +269 -24
- package/dist/lib/core/Abstracts/AbstractBuilder.d.ts +16 -16
- package/dist/lib/core/Abstracts/AbstractBuilder.js.map +1 -1
- package/dist/lib/core/Abstracts/AbstractDB.d.ts +1 -1
- package/dist/lib/core/Abstracts/AbstractModel.d.ts +7 -2
- package/dist/lib/core/Abstracts/AbstractModel.js.map +1 -1
- package/dist/lib/core/Blueprint.d.ts +14 -14
- package/dist/lib/core/Blueprint.js +2 -4
- package/dist/lib/core/Blueprint.js.map +1 -1
- package/dist/lib/core/Builder.d.ts +52 -34
- package/dist/lib/core/Builder.js +76 -44
- package/dist/lib/core/Builder.js.map +1 -1
- package/dist/lib/core/Cache/MemoryCache.js +9 -4
- package/dist/lib/core/Cache/MemoryCache.js.map +1 -1
- package/dist/lib/core/Cache/index.js +32 -13
- package/dist/lib/core/Cache/index.js.map +1 -1
- package/dist/lib/core/Contracts/Audit.d.ts +4 -4
- package/dist/lib/core/Contracts/Audit.js.map +1 -1
- package/dist/lib/core/Contracts/Logger.d.ts +3 -3
- package/dist/lib/core/Contracts/Logger.js.map +1 -1
- package/dist/lib/core/DB.d.ts +2 -2
- package/dist/lib/core/DB.js +6 -19
- package/dist/lib/core/DB.js.map +1 -1
- package/dist/lib/core/Driver/index.d.ts +7 -5
- package/dist/lib/core/Driver/index.js +4 -2
- package/dist/lib/core/Driver/index.js.map +1 -1
- package/dist/lib/core/Driver/mariadb/MariadbDriver.js +14 -6
- package/dist/lib/core/Driver/mariadb/MariadbDriver.js.map +1 -1
- package/dist/lib/core/Driver/mariadb/MariadbQueryBuilder.d.ts +3 -3
- package/dist/lib/core/Driver/mariadb/MariadbQueryBuilder.js +24 -7
- package/dist/lib/core/Driver/mariadb/MariadbQueryBuilder.js.map +1 -1
- package/dist/lib/core/Driver/mongodb/MongodbDriver.js +18 -12
- package/dist/lib/core/Driver/mongodb/MongodbDriver.js.map +1 -1
- package/dist/lib/core/Driver/mongodb/MongodbQueryBuilder.d.ts +3 -3
- package/dist/lib/core/Driver/mongodb/MongodbQueryBuilder.js +9 -1
- package/dist/lib/core/Driver/mongodb/MongodbQueryBuilder.js.map +1 -1
- package/dist/lib/core/Driver/mysql/MysqlDriver.js +15 -7
- package/dist/lib/core/Driver/mysql/MysqlDriver.js.map +1 -1
- package/dist/lib/core/Driver/mysql/MysqlQueryBuilder.d.ts +3 -3
- package/dist/lib/core/Driver/mysql/MysqlQueryBuilder.js +24 -7
- package/dist/lib/core/Driver/mysql/MysqlQueryBuilder.js.map +1 -1
- package/dist/lib/core/Driver/postgres/PostgresDriver.js +14 -6
- package/dist/lib/core/Driver/postgres/PostgresDriver.js.map +1 -1
- package/dist/lib/core/Driver/postgres/PostgresQueryBuilder.d.ts +3 -3
- package/dist/lib/core/Driver/postgres/PostgresQueryBuilder.js +22 -7
- package/dist/lib/core/Driver/postgres/PostgresQueryBuilder.js.map +1 -1
- package/dist/lib/core/Driver/sqlite/SqliteDriver.d.ts +1 -0
- package/dist/lib/core/Driver/sqlite/SqliteDriver.js +25 -4
- package/dist/lib/core/Driver/sqlite/SqliteDriver.js.map +1 -1
- package/dist/lib/core/Driver/sqlite/SqliteQueryBuilder.d.ts +2 -0
- package/dist/lib/core/Driver/sqlite/SqliteQueryBuilder.js +27 -21
- package/dist/lib/core/Driver/sqlite/SqliteQueryBuilder.js.map +1 -1
- package/dist/lib/core/Join.d.ts +63 -5
- package/dist/lib/core/Join.js +92 -15
- package/dist/lib/core/Join.js.map +1 -1
- package/dist/lib/core/JoinModel.d.ts +65 -9
- package/dist/lib/core/JoinModel.js +79 -50
- package/dist/lib/core/JoinModel.js.map +1 -1
- package/dist/lib/core/Meta.d.ts +7 -7
- package/dist/lib/core/Meta.js +10 -9
- package/dist/lib/core/Meta.js.map +1 -1
- package/dist/lib/core/Model.d.ts +225 -57
- package/dist/lib/core/Model.js +376 -90
- package/dist/lib/core/Model.js.map +1 -1
- package/dist/lib/core/Queue.d.ts +36 -7
- package/dist/lib/core/Queue.js +69 -29
- package/dist/lib/core/Queue.js.map +1 -1
- package/dist/lib/core/RelationManager.d.ts +4 -4
- package/dist/lib/core/RelationManager.js +141 -16
- package/dist/lib/core/RelationManager.js.map +1 -1
- package/dist/lib/core/Repository.d.ts +1 -1
- package/dist/lib/core/Repository.js +5 -1
- package/dist/lib/core/Repository.js.map +1 -1
- package/dist/lib/core/Schema.d.ts +13 -13
- package/dist/lib/core/Schema.js +12 -0
- package/dist/lib/core/Schema.js.map +1 -1
- package/dist/lib/core/StateManager.d.ts +6 -0
- package/dist/lib/core/StateManager.js +1 -0
- package/dist/lib/core/StateManager.js.map +1 -1
- package/dist/lib/core/UtilityTypes.d.ts +69 -76
- package/dist/lib/core/UtilityTypes.js.map +1 -1
- package/dist/lib/types/index.d.ts +55 -9
- package/dist/lib/utils/index.d.ts +3 -1
- package/dist/lib/utils/index.js +42 -3
- package/dist/lib/utils/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -43,7 +43,29 @@ npm install -g tspace-mysql
|
|
|
43
43
|
|
|
44
44
|
## Documentation
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
### For LLMs & AI Assistants
|
|
47
|
+
|
|
48
|
+
📚 **Complete Skills Documentation** is available in the [`skills/`](./skills) folder. This includes comprehensive, verified guides for:
|
|
49
|
+
|
|
50
|
+
- Model Setup & Blueprint
|
|
51
|
+
- Query Builder & SQL Operations
|
|
52
|
+
- Relationships (hasOne, hasMany, belongsTo, belongsToMany)
|
|
53
|
+
- Repository Pattern
|
|
54
|
+
- Decorators
|
|
55
|
+
- Type Safety (T namespace)
|
|
56
|
+
- Transactions
|
|
57
|
+
- Caching (DB_CACHE, .cache())
|
|
58
|
+
- Queue System
|
|
59
|
+
- CLI Commands
|
|
60
|
+
- Complete Real-World Examples
|
|
61
|
+
|
|
62
|
+
All skills documentation is **100% verified** against the source code.
|
|
63
|
+
|
|
64
|
+
### Human-Readable Documentation
|
|
65
|
+
|
|
66
|
+
See the [`docs/`](./docs) directory for full documentation with examples.
|
|
67
|
+
|
|
68
|
+
Online: https://thanathip41.github.io/tspace-mysql
|
|
47
69
|
|
|
48
70
|
## TypeScript
|
|
49
71
|
|
|
@@ -66,6 +88,8 @@ npm install -D typescript@5.9.3
|
|
|
66
88
|
- [MySQL Database](#mysql-database)
|
|
67
89
|
- [Mariadb Database](#mariadb-database)
|
|
68
90
|
- [Postgres Database](#postgres-database)
|
|
91
|
+
- [SQLite Database](#sqlite-database)
|
|
92
|
+
- [Mongodb Database](#mongodb-database)
|
|
69
93
|
- [Cluster Database](#cluster-database)
|
|
70
94
|
- [SQL Like](#sql-Like)
|
|
71
95
|
- [Query Builder](#query-builder)
|
|
@@ -107,6 +131,7 @@ npm install -D typescript@5.9.3
|
|
|
107
131
|
- [More Methods](#more-methods)
|
|
108
132
|
- [Database Transactions](#database-transactions)
|
|
109
133
|
- [Race Condition](#race-condition)
|
|
134
|
+
- [Lock Table](#lock-table)
|
|
110
135
|
- [Connection](#connection)
|
|
111
136
|
- [Backup](#backup)
|
|
112
137
|
- [Injection](#injection)
|
|
@@ -247,6 +272,50 @@ DB_PASSWORD = password
|
|
|
247
272
|
DB_DATABASE = database
|
|
248
273
|
```
|
|
249
274
|
|
|
275
|
+
### SQLite Database
|
|
276
|
+
|
|
277
|
+
To connect the application to a SQLite database, using the following:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
npm install better-sqlite3 --save
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```js
|
|
284
|
+
DB_DRIVER = sqlite
|
|
285
|
+
DB_DATABASE = app.db
|
|
286
|
+
```
|
|
287
|
+
⚠️ Requirements for better-sqlite3
|
|
288
|
+
Node.js 22 or higher is required
|
|
289
|
+
|
|
290
|
+
### Mongodb Database
|
|
291
|
+
|
|
292
|
+
To connect the application to a Mongodb database, using the following:
|
|
293
|
+
```sh
|
|
294
|
+
npm install mongodb --save
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
```js
|
|
298
|
+
DB_DRIVER = mongodb
|
|
299
|
+
DB_HOST = localhost
|
|
300
|
+
DB_PORT = 27017
|
|
301
|
+
DB_USERNAME = root
|
|
302
|
+
DB_PASSWORD = password
|
|
303
|
+
DB_DATABASE = database
|
|
304
|
+
```
|
|
305
|
+
✅ Supported Features
|
|
306
|
+
|
|
307
|
+
CRUD operations (create, read, update, delete)
|
|
308
|
+
Basic joins & relations (via abstraction layer)
|
|
309
|
+
|
|
310
|
+
⚠️ Limitations
|
|
311
|
+
|
|
312
|
+
MongoDB support is partially implemented and may not fully match SQL-based drivers like MySQL or PostgreSQL
|
|
313
|
+
|
|
314
|
+
* Advanced ORM features may be limited
|
|
315
|
+
* Complex joins rely on abstraction (not native MongoDB behavior)
|
|
316
|
+
* Some features may behave differently compared to relational databases
|
|
317
|
+
* Transactions / advanced optimizations may be limited
|
|
318
|
+
|
|
250
319
|
### Cluster Database
|
|
251
320
|
If you need strict race condition control, it is required to use multiple nodes for write and read. <br>
|
|
252
321
|
Avoid using a node load balancer in this case, as it may bypass proper write/read distribution and compromise consistency.<br>
|
|
@@ -1251,7 +1320,7 @@ whereNotIn(column , [])
|
|
|
1251
1320
|
whereNull(column)
|
|
1252
1321
|
whereNotNull(column)
|
|
1253
1322
|
whereBetween (column , [value1 , value2])
|
|
1254
|
-
whereQuery(
|
|
1323
|
+
whereQuery(query)
|
|
1255
1324
|
whereJson(column, { targetKey, value , OP })
|
|
1256
1325
|
whereRaw(sql)
|
|
1257
1326
|
whereExists(sql)
|
|
@@ -1261,7 +1330,7 @@ orWhere(column , OP , value)
|
|
|
1261
1330
|
orWhereRaw(sql)
|
|
1262
1331
|
orWhereIn(column , [])
|
|
1263
1332
|
orWhereSubQuery(colmn , rawSQL)
|
|
1264
|
-
when(contition ,
|
|
1333
|
+
when(contition , query)
|
|
1265
1334
|
select(column1 ,column2 ,...N)
|
|
1266
1335
|
distinct()
|
|
1267
1336
|
selectRaw(column1 ,column2 ,...N)
|
|
@@ -1294,7 +1363,7 @@ onlyTrashed()
|
|
|
1294
1363
|
connection(options)
|
|
1295
1364
|
backup({ database , connection })
|
|
1296
1365
|
backupToFile({ filePath, database , connection })
|
|
1297
|
-
hook((result) => ...) //
|
|
1366
|
+
hook((result) => ...) // query result to function
|
|
1298
1367
|
sleep(seconds)
|
|
1299
1368
|
|
|
1300
1369
|
/**
|
|
@@ -1322,9 +1391,9 @@ relationsExists(name1 , name2,...nameN) // withExists(name1, name2,...nameN)
|
|
|
1322
1391
|
*/
|
|
1323
1392
|
relationsTrashed(name1 , name2,...nameN) // withTrashed(name1, name2,...nameN)
|
|
1324
1393
|
/**
|
|
1325
|
-
* @relation call a name of relation in registry,
|
|
1394
|
+
* @relation call a name of relation in registry, query query of data
|
|
1326
1395
|
*/
|
|
1327
|
-
relationQuery(name, (
|
|
1396
|
+
relationQuery(name, (query) ) // withQuery(name1, (query))
|
|
1328
1397
|
|
|
1329
1398
|
|
|
1330
1399
|
/**
|
|
@@ -1603,6 +1672,148 @@ async function simulateRaceConnection(): Promise<void> {
|
|
|
1603
1672
|
|
|
1604
1673
|
simulateRaceConnection();
|
|
1605
1674
|
|
|
1675
|
+
```
|
|
1676
|
+
## Lock Table
|
|
1677
|
+
|
|
1678
|
+
Within a lock table, you can utilize the following:
|
|
1679
|
+
|
|
1680
|
+
This approach is not recommended in clustered or load-balance environments,
|
|
1681
|
+
because locks are session-bound and requests may be routed to different database connections.
|
|
1682
|
+
|
|
1683
|
+
READ:
|
|
1684
|
+
- Other sessions can read.
|
|
1685
|
+
- Other sessions must wait before writing.
|
|
1686
|
+
- SELECT: allowed
|
|
1687
|
+
- INSERT: waits
|
|
1688
|
+
- UPDATE: waits
|
|
1689
|
+
- DELETE: waits
|
|
1690
|
+
|
|
1691
|
+
WRITE:
|
|
1692
|
+
- Other sessions must wait before reading or writing.
|
|
1693
|
+
- SELECT: waits
|
|
1694
|
+
- INSERT: waits
|
|
1695
|
+
- UPDATE: waits
|
|
1696
|
+
- DELETE: waits
|
|
1697
|
+
|
|
1698
|
+
The lock is released automatically after the query completes.
|
|
1699
|
+
|
|
1700
|
+
```js
|
|
1701
|
+
import { Model, Blueprint } from 'tspace-mysql'
|
|
1702
|
+
|
|
1703
|
+
class User extends Model {
|
|
1704
|
+
protected boot() {
|
|
1705
|
+
this.useSchema({
|
|
1706
|
+
id : Blueprint.int().notNull().primary().autoIncrement(),
|
|
1707
|
+
email : Blueprint.varchar(20).notNull()
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
async function requestA() {
|
|
1713
|
+
|
|
1714
|
+
try {
|
|
1715
|
+
|
|
1716
|
+
console.log("A: locking table...");
|
|
1717
|
+
|
|
1718
|
+
// READ | WRITE
|
|
1719
|
+
await User.lockTable('WRITE', async (query) => {
|
|
1720
|
+
console.log("A: table LOCKED");
|
|
1721
|
+
|
|
1722
|
+
// Simulate a long-running write transaction.
|
|
1723
|
+
// WRITE operations from other sessions will wait
|
|
1724
|
+
// until the table lock is released.
|
|
1725
|
+
//
|
|
1726
|
+
// READ behavior depends on the selected lock mode:
|
|
1727
|
+
// - READ lock: other readers are allowed
|
|
1728
|
+
// - WRITE lock: readers/writers may be blocked
|
|
1729
|
+
await new Promise((r) => setTimeout(r, 1000 * 10));
|
|
1730
|
+
|
|
1731
|
+
// IMPORTANT:
|
|
1732
|
+
// While the table is locked, all database operations
|
|
1733
|
+
// must use the provided `query` instance.
|
|
1734
|
+
//
|
|
1735
|
+
// This guarantees the operation runs on the same
|
|
1736
|
+
// database session/connection that owns the lock.
|
|
1737
|
+
//
|
|
1738
|
+
// ❌ May fail because it can use a different connection:
|
|
1739
|
+
// await new User().insert({...}).save();
|
|
1740
|
+
//
|
|
1741
|
+
// ✅ Uses the lock owner session:
|
|
1742
|
+
await query.insert({...}).save();
|
|
1743
|
+
|
|
1744
|
+
// In READ mode this write operation will throw,
|
|
1745
|
+
// because writes are not permitted under a READ lock.
|
|
1746
|
+
// In WRITE mode it executes successfully.
|
|
1747
|
+
|
|
1748
|
+
console.log("A: unlocking table...");
|
|
1749
|
+
});
|
|
1750
|
+
|
|
1751
|
+
console.log("A: done");
|
|
1752
|
+
|
|
1753
|
+
} catch (err:any) {
|
|
1754
|
+
|
|
1755
|
+
console.error('❌ SHOULD NOT FAIL:', err.message);
|
|
1756
|
+
}
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
async function requestB(n: number = 1) {
|
|
1760
|
+
console.log(`B(${n}): waiting 1s before query...`);
|
|
1761
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
1762
|
+
|
|
1763
|
+
console.log(`B(${n}): trying SELECT...`);
|
|
1764
|
+
|
|
1765
|
+
const start = Date.now();
|
|
1766
|
+
|
|
1767
|
+
try {
|
|
1768
|
+
|
|
1769
|
+
const users = await new User().select('id').get();
|
|
1770
|
+
console.log(`B(${n}): result`, users.length);
|
|
1771
|
+
|
|
1772
|
+
console.log(`B(${n}): finished in`, Date.now() - start, "ms");
|
|
1773
|
+
} catch (err:any) {
|
|
1774
|
+
console.error(`B(${n}): ERROR`, err.message);
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
async function requestC(n: number = 1) {
|
|
1779
|
+
console.log(`C(${n}): waiting 1s before query...`);
|
|
1780
|
+
await new Promise((r) => setTimeout(r, 1000));
|
|
1781
|
+
|
|
1782
|
+
console.log(`C(${n}): trying Insert...Select`);
|
|
1783
|
+
|
|
1784
|
+
const start = Date.now();
|
|
1785
|
+
|
|
1786
|
+
try {
|
|
1787
|
+
|
|
1788
|
+
await new User().faker(1);
|
|
1789
|
+
|
|
1790
|
+
const users = await new User().select('id').get();
|
|
1791
|
+
console.log(`C(${n}): result`, users.length);
|
|
1792
|
+
|
|
1793
|
+
console.log(`C(${n}): finished in`, Date.now() - start, "ms");
|
|
1794
|
+
} catch (err:any) {
|
|
1795
|
+
console.error(`C(${n}): ERROR`, err.message);
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
(async () => {
|
|
1800
|
+
// Test scenario:
|
|
1801
|
+
//
|
|
1802
|
+
// 1. Request A acquires a table lock.
|
|
1803
|
+
// 2. Requests B perform concurrent reads.
|
|
1804
|
+
// 3. Request C performs a concurrent write.
|
|
1805
|
+
// 4. Observe whether operations are blocked, queued, or rejected
|
|
1806
|
+
// according to the selected lock mode.
|
|
1807
|
+
await Promise.all([
|
|
1808
|
+
requestA(),
|
|
1809
|
+
requestB(1),
|
|
1810
|
+
requestB(2),
|
|
1811
|
+
requestC(3)
|
|
1812
|
+
])
|
|
1813
|
+
.then(r => process.exit(1))
|
|
1814
|
+
|
|
1815
|
+
})()
|
|
1816
|
+
|
|
1606
1817
|
```
|
|
1607
1818
|
|
|
1608
1819
|
## Connection
|
|
@@ -1757,6 +1968,26 @@ class User extends Model {
|
|
|
1757
1968
|
* updated_at : Blueprint.timestamp().null(),
|
|
1758
1969
|
* deleted_at : Blueprint.timestamp().null()
|
|
1759
1970
|
* }) // auto-generated table when table is not exists and auto-create column when column not exists
|
|
1971
|
+
*
|
|
1972
|
+
* this.useLifecycle('beforeInsert', () => console.log('beforeInsert'))
|
|
1973
|
+
* this.useLifecycle('afterInsert', () => console.log('afterInsert'))
|
|
1974
|
+
* this.useLifecycle('beforeUpdate', () => console.log('beforeUpdate'))
|
|
1975
|
+
* this.useLifecycle('afterUpdate', () => console.log('afterUpdate'))
|
|
1976
|
+
* this.useLifecycle('beforeRemove', () => console.log('beforeRemove'))
|
|
1977
|
+
* this.useLifecycle('afterRemove', () => console.log('afterRemove'))
|
|
1978
|
+
*
|
|
1979
|
+
* this.useTransform({
|
|
1980
|
+
* name : {
|
|
1981
|
+
* to : async (name) => `${name}-> transform@before`,
|
|
1982
|
+
* from : async (name) => `${name}-> transform@after`,
|
|
1983
|
+
* }
|
|
1984
|
+
* })
|
|
1985
|
+
*
|
|
1986
|
+
* this.useHooks([
|
|
1987
|
+
* (r:any) => console.log(r,'hook1'),
|
|
1988
|
+
* (r:any) => console.log(r,'hook2'),
|
|
1989
|
+
* (r:any) => console.log(r,'hook3')
|
|
1990
|
+
* ])
|
|
1760
1991
|
*
|
|
1761
1992
|
* // validate input when create or update reference to the schema in 'this.useSchema'
|
|
1762
1993
|
* this.useValidateSchema({
|
|
@@ -2053,7 +2284,8 @@ Let's example a basic relationship:
|
|
|
2053
2284
|
A one-to-one relationship is used to define relationships where a single model is the parent to one child models
|
|
2054
2285
|
|
|
2055
2286
|
```js
|
|
2056
|
-
import { Model } from 'tspace-mysql'
|
|
2287
|
+
import { Model , type T } from 'tspace-mysql';
|
|
2288
|
+
|
|
2057
2289
|
import Phone from '../Phone'
|
|
2058
2290
|
class User extends Model {
|
|
2059
2291
|
constructor(){
|
|
@@ -2068,12 +2300,15 @@ class User extends Model {
|
|
|
2068
2300
|
}
|
|
2069
2301
|
/**
|
|
2070
2302
|
* Mark a method for relationship
|
|
2071
|
-
* @hasOne Get the phone associated with the user. using function
|
|
2303
|
+
* @hasOne Get the phone associated with the user. using function query
|
|
2072
2304
|
* @function
|
|
2073
2305
|
*/
|
|
2074
|
-
phone (
|
|
2075
|
-
return this.hasOneBuilder({
|
|
2306
|
+
public phone (query ?: T.QueryModifier<Phone>) {
|
|
2307
|
+
return this.hasOneBuilder({ model : Phone } , query)
|
|
2076
2308
|
}
|
|
2309
|
+
|
|
2310
|
+
// or
|
|
2311
|
+
public phone = this.createRelation(Phone,{ type : 'hasOne'})
|
|
2077
2312
|
}
|
|
2078
2313
|
export default User
|
|
2079
2314
|
|
|
@@ -2091,8 +2326,8 @@ const userUsingFunction = await new User().phone().findOne()
|
|
|
2091
2326
|
A one-to-many relationship is used to define relationships where a single model is the parent to one or more child models.
|
|
2092
2327
|
|
|
2093
2328
|
```js
|
|
2094
|
-
import { Model } from 'tspace-mysql'
|
|
2095
|
-
import Comment from '../Comment'
|
|
2329
|
+
import { Model, type T } from 'tspace-mysql';
|
|
2330
|
+
import Comment from '../Comment';
|
|
2096
2331
|
class Post extends Model {
|
|
2097
2332
|
constructor(){
|
|
2098
2333
|
super()
|
|
@@ -2106,12 +2341,15 @@ class Post extends Model {
|
|
|
2106
2341
|
}
|
|
2107
2342
|
/**
|
|
2108
2343
|
*
|
|
2109
|
-
* @hasManyQuery Get the comments for the post. using function
|
|
2344
|
+
* @hasManyQuery Get the comments for the post. using function query
|
|
2110
2345
|
* @function
|
|
2111
2346
|
*/
|
|
2112
|
-
comments (
|
|
2113
|
-
return this.hasManyBuilder({
|
|
2347
|
+
public comments (query?: T.QueryModifier<Comment>) {
|
|
2348
|
+
return this.hasManyBuilder({ model : Comment } , query)
|
|
2114
2349
|
}
|
|
2350
|
+
|
|
2351
|
+
// or
|
|
2352
|
+
public comments = this.createRelation(Comment,{ type : 'hasMany'})
|
|
2115
2353
|
}
|
|
2116
2354
|
export default Post
|
|
2117
2355
|
|
|
@@ -2129,7 +2367,7 @@ const postsUsingFunction = await new Post().comments().findOne()
|
|
|
2129
2367
|
A belongsto relationship is used to define relationships where a single model is the child to parent models.
|
|
2130
2368
|
|
|
2131
2369
|
```js
|
|
2132
|
-
import { Model } from 'tspace-mysql'
|
|
2370
|
+
import { Model, type T } from 'tspace-mysql'
|
|
2133
2371
|
import User from '../User'
|
|
2134
2372
|
class Phone extends Model {
|
|
2135
2373
|
constructor(){
|
|
@@ -2144,12 +2382,15 @@ class Phone extends Model {
|
|
|
2144
2382
|
}
|
|
2145
2383
|
/**
|
|
2146
2384
|
*
|
|
2147
|
-
* @belongsToBuilder Get the user that owns the phone.. using function
|
|
2385
|
+
* @belongsToBuilder Get the user that owns the phone.. using function query
|
|
2148
2386
|
* @function
|
|
2149
2387
|
*/
|
|
2150
|
-
user (
|
|
2151
|
-
|
|
2388
|
+
public user (query?: T.QueryModifier<user>) {
|
|
2389
|
+
return this.belongsToBuilder({ model : User }, query)
|
|
2152
2390
|
}
|
|
2391
|
+
|
|
2392
|
+
// or
|
|
2393
|
+
public user = this.createRelation(User,{ type : 'belognsTo'})
|
|
2153
2394
|
}
|
|
2154
2395
|
export default Phone
|
|
2155
2396
|
|
|
@@ -2167,7 +2408,7 @@ const phoneUsingFunction = await new Phone().user().findOne()
|
|
|
2167
2408
|
Many-to-many relations are slightly more complicated than hasOne and hasMany relationships.
|
|
2168
2409
|
|
|
2169
2410
|
```js
|
|
2170
|
-
import { Model } from 'tspace-mysql'
|
|
2411
|
+
import { Model, type T } from 'tspace-mysql'
|
|
2171
2412
|
import Role from '../Role'
|
|
2172
2413
|
class User extends Model {
|
|
2173
2414
|
constructor(){
|
|
@@ -2181,12 +2422,15 @@ class User extends Model {
|
|
|
2181
2422
|
this.belognsToMany({ name : 'roles' , model : Role })
|
|
2182
2423
|
}
|
|
2183
2424
|
/**
|
|
2184
|
-
* @belongsToBuilder Get the user that owns the phone.. using function
|
|
2425
|
+
* @belongsToBuilder Get the user that owns the phone.. using function query
|
|
2185
2426
|
* @function
|
|
2186
2427
|
*/
|
|
2187
|
-
roles (
|
|
2188
|
-
|
|
2428
|
+
public roles (query?: T.QueryModifier<Role>) {
|
|
2429
|
+
return this.belognsToManyBuilder({ model : Role } , query)
|
|
2189
2430
|
}
|
|
2431
|
+
|
|
2432
|
+
// or
|
|
2433
|
+
public roles = this.createRelation(Role, { type : 'belognsToMany'})
|
|
2190
2434
|
}
|
|
2191
2435
|
export default User
|
|
2192
2436
|
|
|
@@ -2700,7 +2944,7 @@ Cache can be used in a Model.
|
|
|
2700
2944
|
Let's illustrate this with an example of a cache:
|
|
2701
2945
|
|
|
2702
2946
|
```js
|
|
2703
|
-
// support memory db
|
|
2947
|
+
// support memory , db , redis
|
|
2704
2948
|
// set cache in file config .env , .env.development ... etc
|
|
2705
2949
|
DB_CACHE = memory // by default
|
|
2706
2950
|
|
|
@@ -2708,6 +2952,7 @@ DB_CACHE = memory // by default
|
|
|
2708
2952
|
DB_CACHE = db
|
|
2709
2953
|
|
|
2710
2954
|
// for redis
|
|
2955
|
+
// npm install redis@5.6.0
|
|
2711
2956
|
DB_CACHE = redis://username:password@server:6379
|
|
2712
2957
|
|
|
2713
2958
|
const users = await new User()
|
|
@@ -2,6 +2,7 @@ import { StateManager } from "../StateManager";
|
|
|
2
2
|
import { TUtils } from "../../utils";
|
|
3
3
|
import { Join } from "../Join";
|
|
4
4
|
import type { TPagination, TConstant, TDriver } from "../../types";
|
|
5
|
+
import { Builder } from "../Builder";
|
|
5
6
|
declare abstract class AbstractBuilder {
|
|
6
7
|
protected $utils: TUtils;
|
|
7
8
|
protected $database: string;
|
|
@@ -49,7 +50,6 @@ declare abstract class AbstractBuilder {
|
|
|
49
50
|
abstract whereIn(column: string, arrayValues: any[]): this;
|
|
50
51
|
abstract orWhereIn(column: string, arrayValues: any[]): this;
|
|
51
52
|
abstract whereNotIn(column: string, arrayValues: any[]): this;
|
|
52
|
-
abstract whereSubQuery(column: string, subQuery: string): this;
|
|
53
53
|
abstract whereNotSubQuery(column: string, subQuery: string): this;
|
|
54
54
|
abstract orWhereSubQuery(column: string, subQuery: string): this;
|
|
55
55
|
abstract whereBetween(column: string, arrayValue: [any, any]): this;
|
|
@@ -77,30 +77,31 @@ declare abstract class AbstractBuilder {
|
|
|
77
77
|
abstract limit(number: number): this;
|
|
78
78
|
abstract insert(data: Record<string, any>, { database }: {
|
|
79
79
|
database?: string;
|
|
80
|
-
}):
|
|
80
|
+
}): Builder<"create">;
|
|
81
81
|
abstract create(data: Record<string, any>, { database }: {
|
|
82
82
|
database?: string;
|
|
83
|
-
}):
|
|
84
|
-
abstract update(data: Record<string, any>, updateNotExists?: string[]):
|
|
85
|
-
abstract updateMany(data: Record<string, any>, updateNotExists?: string[]):
|
|
86
|
-
abstract insertNotExists(data: Record<string, any>):
|
|
87
|
-
abstract createNotExists(data: Record<string, any>):
|
|
88
|
-
abstract insertOrUpdate(data: Record<string, any>):
|
|
89
|
-
abstract createOrUpdate(data: Record<string, any>):
|
|
90
|
-
abstract updateOrInsert(data: Record<string, any>):
|
|
91
|
-
abstract updateOrCreate(data: Record<string, any>):
|
|
83
|
+
}): Builder<"create">;
|
|
84
|
+
abstract update(data: Record<string, any>, updateNotExists?: string[]): Builder<"update">;
|
|
85
|
+
abstract updateMany(data: Record<string, any>, updateNotExists?: string[]): Builder<"updateMany">;
|
|
86
|
+
abstract insertNotExists(data: Record<string, any>): Builder<"create"> | null;
|
|
87
|
+
abstract createNotExists(data: Record<string, any>): Builder<"create"> | null;
|
|
88
|
+
abstract insertOrUpdate(data: Record<string, any>): Builder<"createOrUpdate">;
|
|
89
|
+
abstract createOrUpdate(data: Record<string, any>): Builder<"createOrUpdate">;
|
|
90
|
+
abstract updateOrInsert(data: Record<string, any>): Builder<"createOrUpdate">;
|
|
91
|
+
abstract updateOrCreate(data: Record<string, any>): Builder<"createOrUpdate">;
|
|
92
92
|
abstract createMultiple(data: Record<string, any>[], { database }: {
|
|
93
93
|
database?: string;
|
|
94
|
-
}):
|
|
94
|
+
}): Builder<"createMany">;
|
|
95
95
|
abstract insertMultiple(data: Record<string, any>[], { database }: {
|
|
96
96
|
database?: string;
|
|
97
|
-
}):
|
|
97
|
+
}): Builder<"createMany">;
|
|
98
98
|
abstract createMany(data: Record<string, any>[], { database }: {
|
|
99
99
|
database?: string;
|
|
100
|
-
}):
|
|
100
|
+
}): Builder<"createMany">;
|
|
101
101
|
abstract insertMany(data: Record<string, any>[], { database }: {
|
|
102
102
|
database?: string;
|
|
103
|
-
}):
|
|
103
|
+
}): Builder<"createMany">;
|
|
104
|
+
abstract save(): Promise<any>;
|
|
104
105
|
abstract except(...columns: string[]): this;
|
|
105
106
|
abstract drop(): Promise<any>;
|
|
106
107
|
abstract truncate({ force }: {
|
|
@@ -137,7 +138,6 @@ declare abstract class AbstractBuilder {
|
|
|
137
138
|
abstract delete(): Promise<boolean>;
|
|
138
139
|
abstract deleteMany(): Promise<boolean>;
|
|
139
140
|
abstract exists(): Promise<boolean>;
|
|
140
|
-
abstract save(): Promise<Record<string, any> | any[] | null | undefined>;
|
|
141
141
|
abstract increment(column: string, value: number): Promise<number>;
|
|
142
142
|
abstract decrement(column: string, value: number): Promise<number>;
|
|
143
143
|
abstract faker(round: number, cb?: Function): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractBuilder.js","sourceRoot":"","sources":["../../../../src/lib/core/Abstracts/AbstractBuilder.ts"],"names":[],"mappings":";;;AAGA,yCAA4C;
|
|
1
|
+
{"version":3,"file":"AbstractBuilder.js","sourceRoot":"","sources":["../../../../src/lib/core/Abstracts/AbstractBuilder.ts"],"names":[],"mappings":";;;AAGA,yCAA4C;AAO5C,MAAe,eAAe;IAEhB,MAAM,CAAU;IAEhB,SAAS,GAAY,MAAM,CAAC,eAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAEnD,YAAY,GAAG;QACrB,IAAI,EAAO,eAAM,CAAC,IAAI;QACtB,IAAI,EAAO,MAAM,CAAC,eAAM,CAAC,IAAI,CAAC;QAC9B,QAAQ,EAAG,MAAM,CAAC,eAAM,CAAC,QAAQ,CAAC;QAClC,QAAQ,EAAG,MAAM,CAAC,eAAM,CAAC,QAAQ,CAAC;QAClC,QAAQ,EAAG,eAAM,CAAC,QAAQ;KAC7B,CAAA;IAES,OAAO,GAAI,MAAM,CAAC,eAAM,CAAC,MAAM,IAAI,OAAO,CAAY,CAAC;IAEvD,QAAQ,GAAa,OAAO,CAAC,eAAM,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;IAEtD,UAAU,CAGlB;IAEQ,MAAM,CAAgB;IAEtB,KAAK,GAMX;QACA,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,GAAE,CAAC;QAC1B,GAAG,EAAE,CAAC,IAAU,EAAE,EAAE,GAAE,CAAC;QACvB,GAAG,EAAE,GAAG,EAAE,GAAE,CAAC;QACb,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,WAAW,EAAE,GAAG,EAAE,GAAE,CAAC;KACxB,CAAA;CAyFJ;AAES,0CAAe;AACzB,kBAAe,eAAe,CAAA"}
|
|
@@ -18,7 +18,7 @@ declare abstract class AbstractDB extends Builder {
|
|
|
18
18
|
when: string;
|
|
19
19
|
then: string;
|
|
20
20
|
}[], final?: string): string | [];
|
|
21
|
-
abstract getConnection(options: TConnectionOptions):
|
|
21
|
+
abstract getConnection(options: TConnectionOptions): TPoolConnected;
|
|
22
22
|
}
|
|
23
23
|
export { AbstractDB };
|
|
24
24
|
export default AbstractDB;
|
|
@@ -3,8 +3,9 @@ import { Builder } from '../Builder';
|
|
|
3
3
|
import { RelationManager } from '../RelationManager';
|
|
4
4
|
import { Model } from '../Model';
|
|
5
5
|
import type { T } from '../UtilityTypes';
|
|
6
|
-
import type { TPattern, TValidateSchema, TCache, TRelationOptions, TRelationQueryOptions } from '../../types';
|
|
7
|
-
|
|
6
|
+
import type { TPattern, TValidateSchema, TCache, TRelationOptions, TRelationQueryOptions, TModelOrObject } from '../../types';
|
|
7
|
+
import { JoinModel } from '../JoinModel';
|
|
8
|
+
declare abstract class AbstractModel extends Builder<any> {
|
|
8
9
|
protected $cache: TCache;
|
|
9
10
|
protected $relation: RelationManager;
|
|
10
11
|
protected $schema: Record<string, Blueprint>;
|
|
@@ -76,6 +77,10 @@ declare abstract class AbstractModel extends Builder {
|
|
|
76
77
|
abstract relationsAll<K extends T.RelationKeys<this>>(...nameRelations: K[]): this;
|
|
77
78
|
abstract relationsCount<K extends T.RelationKeys<this>>(...nameRelations: K[]): this;
|
|
78
79
|
abstract relationsTrashed<K extends T.RelationKeys<this>>(...nameRelations: K[]): this;
|
|
80
|
+
abstract joinModel(m1: TModelOrObject | ((join: JoinModel) => JoinModel), m2?: TModelOrObject): this;
|
|
81
|
+
abstract rightJoinModel(m1: TModelOrObject | ((join: JoinModel) => JoinModel), m2?: TModelOrObject): this;
|
|
82
|
+
abstract leftJoinModel(m1: TModelOrObject | ((join: JoinModel) => JoinModel), m2?: TModelOrObject): this;
|
|
83
|
+
abstract crossJoinModel(m1: TModelOrObject | ((join: JoinModel) => JoinModel), m2?: TModelOrObject): this;
|
|
79
84
|
}
|
|
80
85
|
export { AbstractModel };
|
|
81
86
|
export default AbstractModel;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AbstractModel.js","sourceRoot":"","sources":["../../../../src/lib/core/Abstracts/AbstractModel.ts"],"names":[],"mappings":";;;AACA,wCAA8C;
|
|
1
|
+
{"version":3,"file":"AbstractModel.js","sourceRoot":"","sources":["../../../../src/lib/core/Abstracts/AbstractModel.ts"],"names":[],"mappings":";;;AACA,wCAA8C;AAa9C,MAAe,aAAc,SAAQ,iBAAY;IAEnC,MAAM,CAAsB;IAC5B,SAAS,CAA4B;IACrC,OAAO,CAAyC;IAChD,eAAe,CAAsB;IACrC,MAAM,CAAsB;IAC5B,QAAQ,CAAsB;IAC9B,QAAQ,CAAqC;IAC7C,OAAO,CAAsC;IAC7C,UAAU,CAAmC;IAC7C,cAAc,CAA+B;IAC7C,UAAU,CAAmB;IAC7B,WAAW,CAAkB;IAC7B,KAAK,CAAwB;IAC7B,WAAW,CAAiB;IAC5B,iBAAiB,CAAgD;IACjE,iBAAiB,CAAW;IAC5B,SAAS,CAKjB;IACQ,WAAW,CAGZ;CAuJZ;AAEQ,sCAAa;AACtB,kBAAe,aAAa,CAAA"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { type T } from "./UtilityTypes";
|
|
1
2
|
import { Model } from "./Model";
|
|
2
|
-
type
|
|
3
|
-
[_: string]:
|
|
3
|
+
type ExtendType = NumberConstructor | StringConstructor | BooleanConstructor | DateConstructor | readonly ExtendType[] | {
|
|
4
|
+
[_: string]: ExtendType;
|
|
4
5
|
};
|
|
5
6
|
type ResolveType<T> = T extends NumberConstructor ? number : T extends StringConstructor ? string : T extends BooleanConstructor ? boolean : T extends DateConstructor ? Date : T extends readonly (infer U)[] ? ResolveType<U>[] : T extends Record<string, any> ? {
|
|
6
7
|
[K in keyof T]: ResolveType<T[K]>;
|
|
@@ -10,7 +11,6 @@ type ResolveType<T> = T extends NumberConstructor ? number : T extends StringCon
|
|
|
10
11
|
* @example
|
|
11
12
|
* import { Schema , Blueprint } from 'tspace-mysql'
|
|
12
13
|
* import sql from '../../../build/lib/core/SqlLike';
|
|
13
|
-
import { default } from '../../../app/$audit';
|
|
14
14
|
* await new Schema().table('users',{
|
|
15
15
|
* id : Blueprint.int().notNull().primary().autoIncrement(),
|
|
16
16
|
* name : Blueprint.varchar(255).default('my name').index(),
|
|
@@ -148,12 +148,12 @@ declare class Blueprint<T = any> {
|
|
|
148
148
|
* @static
|
|
149
149
|
* @return {Blueprint<T>} Blueprint
|
|
150
150
|
*/
|
|
151
|
-
static boolean(): Blueprint<
|
|
151
|
+
static boolean(): Blueprint<boolean | number>;
|
|
152
152
|
/**
|
|
153
153
|
* Assign type 'BOOLEAN' in table
|
|
154
154
|
* @return {Blueprint<T>} Blueprint
|
|
155
155
|
*/
|
|
156
|
-
boolean(): Blueprint<
|
|
156
|
+
boolean(): Blueprint<boolean | number>;
|
|
157
157
|
/**
|
|
158
158
|
* Assign type 'DOUBLE' in table
|
|
159
159
|
* @static
|
|
@@ -259,12 +259,12 @@ declare class Blueprint<T = any> {
|
|
|
259
259
|
* @static
|
|
260
260
|
* @return {Blueprint<T>} Blueprint
|
|
261
261
|
*/
|
|
262
|
-
static json(): Blueprint<
|
|
262
|
+
static json(): Blueprint<any>;
|
|
263
263
|
/**
|
|
264
264
|
* Assign type 'JSON' in table
|
|
265
265
|
* @return {Blueprint<T>} Blueprint
|
|
266
266
|
*/
|
|
267
|
-
json(): Blueprint<
|
|
267
|
+
json(): Blueprint<any>;
|
|
268
268
|
/**
|
|
269
269
|
* Assign type 'MEDIUMTEXT' in table
|
|
270
270
|
* @static
|
|
@@ -326,13 +326,13 @@ declare class Blueprint<T = any> {
|
|
|
326
326
|
* @param {...string} enums n1, n2, n3, ...n
|
|
327
327
|
* @return {Blueprint<T>} Blueprint
|
|
328
328
|
*/
|
|
329
|
-
static enum<K extends string |
|
|
329
|
+
static enum<K extends string | Record<string, string>>(...enums: K[]): Blueprint<K extends string ? `${K & string}` : `${K[keyof K] & string}`>;
|
|
330
330
|
/**
|
|
331
331
|
* Assign type 'ENUM'
|
|
332
332
|
* @param {...string} enums n1, n2, n3, ...n
|
|
333
333
|
* @return {Blueprint<T>} Blueprint
|
|
334
334
|
*/
|
|
335
|
-
enum<K extends string |
|
|
335
|
+
enum<K extends string | Record<string, string>>(...enums: K[]): Blueprint<K extends string ? `${K & string}` : `${K[keyof K] & string}`>;
|
|
336
336
|
/**
|
|
337
337
|
* Assign type 'DATE' in table
|
|
338
338
|
* @static
|
|
@@ -396,12 +396,12 @@ declare class Blueprint<T = any> {
|
|
|
396
396
|
* Assign attributes 'NOT NULL' in table
|
|
397
397
|
* @return {Blueprint<T>} Blueprint
|
|
398
398
|
*/
|
|
399
|
-
notNull(): Blueprint<T
|
|
399
|
+
notNull(): Blueprint<NonNullable<T>>;
|
|
400
400
|
/**
|
|
401
401
|
* Assign attributes 'NOT NULL' in table
|
|
402
402
|
* @return {Blueprint<T>} Blueprint
|
|
403
403
|
*/
|
|
404
|
-
notnull(): Blueprint<T
|
|
404
|
+
notnull(): Blueprint<NonNullable<T>>;
|
|
405
405
|
/**
|
|
406
406
|
* Assign attributes 'PRIMARY KEY' in table
|
|
407
407
|
* @return {Blueprint<T>} Blueprint
|
|
@@ -412,7 +412,7 @@ declare class Blueprint<T = any> {
|
|
|
412
412
|
* @param {string | number} value default value
|
|
413
413
|
* @return {Blueprint<T>} Blueprint
|
|
414
414
|
*/
|
|
415
|
-
default(value: string
|
|
415
|
+
default<I extends T>(value: I): Blueprint<string extends T ? T.Default<string> : boolean extends T ? T.Default<boolean> : number extends T ? T.Default<number> : `${T & string}` | null>;
|
|
416
416
|
/**
|
|
417
417
|
* Assign attributes 'default currentTimestamp' in table
|
|
418
418
|
* @return {Blueprint<T>} Blueprint
|
|
@@ -466,7 +466,7 @@ declare class Blueprint<T = any> {
|
|
|
466
466
|
* @param {NumberConstructor|StringConstructor|BooleanConstructor|DateConstructor} type
|
|
467
467
|
* @return {Blueprint<T>} Blueprint
|
|
468
468
|
*/
|
|
469
|
-
transform<T extends
|
|
469
|
+
transform<T extends ExtendType>(_: T): Blueprint<ResolveType<T>>;
|
|
470
470
|
get sql(): {
|
|
471
471
|
select?: string;
|
|
472
472
|
where?: string;
|
|
@@ -483,7 +483,7 @@ declare class Blueprint<T = any> {
|
|
|
483
483
|
name?: string;
|
|
484
484
|
} | null;
|
|
485
485
|
get defaultValue(): string | number | null;
|
|
486
|
-
get valueType():
|
|
486
|
+
get valueType(): ExtendType;
|
|
487
487
|
get enums(): string[];
|
|
488
488
|
get isVirtual(): boolean;
|
|
489
489
|
get isEnum(): boolean;
|
|
@@ -6,7 +6,6 @@ exports.Blueprint = void 0;
|
|
|
6
6
|
* @example
|
|
7
7
|
* import { Schema , Blueprint } from 'tspace-mysql'
|
|
8
8
|
* import sql from '../../../build/lib/core/SqlLike';
|
|
9
|
-
import { default } from '../../../app/$audit';
|
|
10
9
|
* await new Schema().table('users',{
|
|
11
10
|
* id : Blueprint.int().notNull().primary().autoIncrement(),
|
|
12
11
|
* name : Blueprint.varchar(255).default('my name').index(),
|
|
@@ -717,9 +716,8 @@ class Blueprint {
|
|
|
717
716
|
* @param {NumberConstructor|StringConstructor|BooleanConstructor|DateConstructor} type
|
|
718
717
|
* @return {Blueprint<T>} Blueprint
|
|
719
718
|
*/
|
|
720
|
-
transform(
|
|
721
|
-
const instance = new Blueprint();
|
|
722
|
-
instance._valueType = type;
|
|
719
|
+
transform(_) {
|
|
720
|
+
const instance = Object.assign(new Blueprint(), this);
|
|
723
721
|
return instance;
|
|
724
722
|
}
|
|
725
723
|
get sql() {
|