Skip to content

Commit 6bc2080

Browse files
chore: wip
1 parent 2fbcd80 commit 6bc2080

File tree

3 files changed

+148
-39
lines changed

3 files changed

+148
-39
lines changed
Lines changed: 146 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
import { db } from '@stacksjs/database'
2+
import type { Collection } from '@stacksjs/collections'
3+
import { collect } from '@stacksjs/collections'
24

35
export interface User {
46
id: number
5-
67
name: string
78
email: string
8-
99
password: string
10-
1110
created_at: Date
1211
}
1312

@@ -17,23 +16,36 @@ export class UserModel {
1716
private _isSelectInvoked = false
1817
public _id: number | undefined = undefined
1918
private cols: string[] = []
19+
private useSoftDeletes = true
2020

2121
queryBuilder = db.selectFrom('users')// Initialize queryBuilder
2222
queryBuilderStore = db.insertInto('users')// Initialize queryBuilder
2323
queryBuilderUpdate = db.updateTable('users')// Initialize queryBuilder
2424
queryBuilderDelete = db.deleteFrom('users')// Initialize queryBuilder
2525

26-
public async find(id: number): Promise<User> {
27-
this._data = await this.queryBuilder.selectAll()
28-
.where('id', '=', id)
29-
.executeTakeFirst()
26+
private getKeyName(): string {
27+
return 'id'
28+
}
3029

31-
if (this._data === undefined)
32-
throw new Error('User not found!')
30+
public async find(id: number | number[]): Promise<User | Collection<User>> {
31+
if (Array.isArray(id))
32+
return await this.findMany(id)
33+
34+
let query = this.queryBuilder.selectAll()
35+
.where(this.getKeyName(), '=', id)
36+
37+
if (this.useSoftDeletes)
38+
query = query.where('deleted_at', 'is', null)
39+
40+
this._data = await query.executeTakeFirst()
3341

3442
return this._createProxy()
3543
}
3644

45+
public async findMany(id: number[] | string[]): Promise<User | Collection<User>> {
46+
return await this.whereIn(this.getKeyName(), id).get()
47+
}
48+
3749
private _createProxy(): User & { [key: string]: Function } {
3850
return new Proxy(this._data || {}, {
3951
get: (target, prop: keyof User | string): any => {
@@ -51,10 +63,10 @@ export class UserModel {
5163
})
5264
}
5365

54-
public update(obj: Partial<User>) {
66+
public update(obj: Partial<User>): any {
5567
if (this._data && this._data?.id) {
5668
return this.queryBuilderUpdate.set(obj)
57-
.where('id', '=', this._data?.id)
69+
.where(this.getKeyName(), '=', this._data?.id)
5870
.executeTakeFirst()
5971
}
6072
}
@@ -64,18 +76,73 @@ export class UserModel {
6476
.execute()
6577
}
6678

67-
public async get() {
79+
public async get(): Promise<Collection<User>> {
80+
if (this.useSoftDeletes)
81+
return collect(await this.getSoftDeletes())
82+
6883
if (this._isSelectInvoked)
69-
return await this.queryBuilder.select(this.cols).execute()
84+
return collect(await this.queryBuilder.select(this.cols).execute())
7085

71-
return await this.queryBuilder.selectAll().execute()
86+
return collect(await this.queryBuilder.selectAll().execute())
7287
}
7388

74-
public where(...args: (string | number | boolean)[]) {
75-
// TODO: resolve this
76-
// @ts-expect-error resolve this
89+
public async trashed() {
90+
if (this._isSelectInvoked)
91+
return await this.queryBuilder.where('deleted_at', 'is not', null).select(this.cols).execute()
92+
93+
return await this.queryBuilder.where('deleted_at', 'is not', null).selectAll().execute()
94+
}
95+
96+
private async getSoftDeletes() {
97+
if (this._isSelectInvoked)
98+
return await this.queryBuilder.where('deleted_at', 'is', null).select(this.cols).execute()
99+
100+
return await this.queryBuilder.where('deleted_at', 'is', null).selectAll().execute()
101+
}
102+
103+
public where(...args: (string | number | boolean)[]): this {
104+
if (args.length === 2) {
105+
const [column, value] = args
106+
this.queryBuilder = this.queryBuilder.where(column, '=', value)
107+
}
108+
else { this.queryBuilder = this.queryBuilder.where(...args) }
109+
110+
return this
111+
}
112+
113+
public orWhere(...args: (string | number | boolean)[]): this {
114+
this.queryBuilder = this.queryBuilder.where(eb => eb.or([
115+
eb(...args),
116+
]))
117+
118+
return this
119+
}
120+
121+
public whereIn(...args: (string[] | string | number[] | boolean[])[]): this {
122+
if (args.length === 2) {
123+
const [column, value] = args
124+
this.queryBuilder = this.queryBuilder.where(column, 'in', value)
125+
}
126+
else { this.queryBuilder = this.queryBuilder.where(...args) }
127+
128+
return this
129+
}
130+
131+
public whereNull(col: string): this {
132+
this.queryBuilder = this.queryBuilder.where(col, 'is', null)
133+
134+
return this
135+
}
77136

78-
this.queryBuilder = this.queryBuilder.where(...args)
137+
public when(condition: boolean, callback: (instance: this) => any): this {
138+
if (condition)
139+
callback(this)
140+
141+
return this
142+
}
143+
144+
public whereNotNull(col: string): this {
145+
this.queryBuilder = this.queryBuilder.where(col, 'is not', null)
79146

80147
return this
81148
}
@@ -86,13 +153,13 @@ export class UserModel {
86153
return this
87154
}
88155

89-
public distinctOn(col: string) {
156+
public distinctOn(col: string): this {
90157
this.queryBuilder = this.queryBuilder.distinctOn(col)
91158

92159
return this
93160
}
94161

95-
public limit(limit: number) {
162+
public limit(limit: number): this {
96163
this.queryBuilder = this.queryBuilder.limit(limit)
97164

98165
return this
@@ -110,82 +177,123 @@ export class UserModel {
110177
return this
111178
}
112179

113-
public innerJoin(...args: (string)[]) {
180+
public innerJoin(...args: string[]): this {
114181
this.queryBuilder = this.queryBuilder.innerJoin(...args)
115182

116183
return this
117184
}
118185

119-
public join(...args: string[]) {
186+
public join(...args: string[]): this {
120187
this.queryBuilder = this.queryBuilder.innerJoin(...args)
121188

122189
return this
123190
}
124191

125-
public rightJoin(...args: string[]) {
192+
public having(...args: string[]): this {
193+
this.queryBuilder = this.queryBuilder.having(...args)
194+
195+
return this
196+
}
197+
198+
public rightJoin(...args: string[]): this {
126199
this.queryBuilder = this.queryBuilder.rightJoin(...args)
127200

128201
return this
129202
}
130203

131-
public leftJoin(...args: string[]) {
204+
public leftJoin(...args: string[]): this {
132205
this.queryBuilder = this.queryBuilder.leftJoin(...args)
133206

134207
return this
135208
}
136209

137-
public offset(offset: number) {
210+
public offset(offset: number): this {
138211
this.queryBuilder = this.queryBuilder.offset(offset)
139212

140213
return this
141214
}
142215

143-
public fullJoin(...args: string[]) {
216+
public fullJoin(...args: string[]): this {
144217
this.queryBuilder = this.queryBuilder.fullJoin(...args)
145218

146219
return this
147220
}
148221

149-
public orderByDesc(col: string) {
222+
public innerJoinLateral(...args: string[]) {
223+
this.queryBuilder.innerJoinLateral(...args)
224+
225+
return this
226+
}
227+
228+
public leftJoinLateral(...args) {
229+
this.queryBuilder.leftJoinLateral(...args)
230+
231+
return this
232+
}
233+
234+
public orderByDesc(col: string): this {
150235
this.queryBuilder = this.queryBuilder.orderBy(col, 'desc')
151236

152237
return this
153238
}
154239

155-
public select(...args: string[]) {
240+
public select(...args: string[]): this {
156241
this.cols = args
157242
this._isSelectInvoked = true
243+
158244
// TODO: resolve this
159245
// @ts-expect-error resolve this
160-
161246
this.queryBuilder = this.queryBuilder.select(...args)
162247

163248
return this
164249
}
165250

166-
public first(): Promise<any> {
251+
public async first(): Promise<User> {
167252
// Execute the query using queryBuilder
168-
return this.queryBuilder.executeTakeFirst()
253+
if (this._isSelectInvoked)
254+
this._data = await this.queryBuilder.select(this.cols).executeTakeFirst()
255+
else
256+
this._data = await this.queryBuilder.selectAll().executeTakeFirst()
257+
258+
return this._createProxy()
169259
}
170260

171-
public store(obj: any[]) {
261+
public store(obj: any[]): User {
172262
// Execute the query using queryBuilder
173263
return this.queryBuilderStore.values(obj)
174264
.executeTakeFirst()
175265
}
176266

177-
public createMany(obj: any[]) {
267+
public createMany(obj: any[]): User[] {
178268
// Execute the query using queryBuilder
179269
return this.queryBuilderStore.values(obj)
180270
.executeTakeFirst()
181271
}
182272

183-
public delete() {
184-
// Execute the query using queryBuilder
185-
return this.queryBuilderDelete
186-
.where('id', '=', 1)
187-
.executeTakeFirst()
273+
public async delete(): Promise<any> {
274+
if (this._data && this._data?.id) {
275+
if (this.useSoftDeletes)
276+
return await this.update({ deleted_at: new Date() })
277+
278+
return this.forceDelete()
279+
}
280+
}
281+
282+
public forceDelete(): any {
283+
if (this._data && this._data?.id) {
284+
return this.queryBuilderDelete.where(this.getKeyName(), '=', this._data?.id)
285+
.executeTakeFirst()
286+
}
188287
}
189288
}
190289

290+
const UserInstance = new UserModel()
291+
292+
const user = await UserInstance.when(true, (query) => {
293+
// Modify the query as needed
294+
return query.where('id', 1)
295+
}).get()
296+
297+
console.log(user)
298+
191299
process.exit(0)

.stacks/core/database/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ if (driver === 'sqlite') {
4646
else {
4747
dialect = new MysqlDialect({
4848
pool: createPool({
49-
database: 'stacks',
49+
database: 'carefree',
5050
host: '127.0.0.1',
5151
user: 'root',
5252
password: '',

app/models/User.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default {
99
// autoIncrement: true, // defaults to true
1010
useUuid: true, // instead of `auto-incrementing id`, defaults to false
1111
searchable: true, // defaults to false, also accepts SearchEngineSettings
12+
useSoftDeletes: true, // defaults to false, also accepts SearchEngineSettings
1213
seedable: { // defaults to a count of 10
1314
count: 10,
1415
},

0 commit comments

Comments
 (0)