forj 0.0.1 → 0.0.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/package.json +13 -4
- package/src/clause-builder.ts +216 -0
- package/src/d1/index.ts +4 -0
- package/src/d1/model.ts +78 -0
- package/src/d1/types.ts +7 -0
- package/src/dynamodb/client.ts +125 -0
- package/src/dynamodb/compact.ts +205 -0
- package/src/dynamodb/decorators.ts +126 -0
- package/src/dynamodb/index.ts +4 -0
- package/src/dynamodb/model.ts +258 -0
- package/src/dynamodb/query-builder.ts +174 -0
- package/src/dynamodb/repository.ts +31 -0
- package/src/dynamodb/schema.ts +107 -0
- package/src/dynamodb/types.ts +32 -0
- package/src/index.ts +1 -0
- package/src/model.ts +258 -0
- package/src/query-builder.ts +371 -0
- package/src/types.ts +260 -0
- package/src/utils.ts +134 -0
- package/dist/chunk-NVO75XBO.js +0 -1
- package/dist/d1.d.ts +0 -113
- package/dist/d1.js +0 -1
- package/dist/index-CwrzXlna.d.ts +0 -163
- package/dist/index.ts.d.ts +0 -2
- package/dist/index.ts.js +0 -1
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type Operator = '=' | '<>' | '<' | '<=' | '>' | '>=' | 'begins_with' | 'between' | 'in' | 'attribute_exists' | 'attribute_not_exists' | 'attribute_type' | 'contains' | 'size'
|
|
2
|
+
|
|
3
|
+
export type Condition = {
|
|
4
|
+
type: 'filter' | 'keyCondition',
|
|
5
|
+
field: string,
|
|
6
|
+
operator: Operator,
|
|
7
|
+
value: any
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type ISchemaStructure = string | Record<string, ISchemaStructure[]>
|
|
11
|
+
export type SchemaStructure = ISchemaStructure[]
|
|
12
|
+
|
|
13
|
+
export type KeySchema = Record<'PK' | 'SK', string>
|
|
14
|
+
export type ModelMetadata = {
|
|
15
|
+
table: string,
|
|
16
|
+
keys?: KeySchema,
|
|
17
|
+
defaultSK?: string,
|
|
18
|
+
zip: boolean,
|
|
19
|
+
fields: SchemaStructure,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ModelOpts = string | {
|
|
23
|
+
table?: string,
|
|
24
|
+
partitionKey?: string,
|
|
25
|
+
sortKey?: string,
|
|
26
|
+
defaultSK?: string,
|
|
27
|
+
zip?: boolean,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type Keys = string | [string] | [string, string]
|
|
31
|
+
export type Model<T extends object> = new (...args: any[]) => T
|
|
32
|
+
export type Filter<T> = (item: T) => boolean
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as QueryBuilder } from './query-builder'
|
package/src/model.ts
ADDED
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import pluralize from 'pluralize'
|
|
2
|
+
import QueryBuilder from './query-builder'
|
|
3
|
+
import type {
|
|
4
|
+
Operator, OrderDirection,
|
|
5
|
+
WhereFn, WhereArgs,
|
|
6
|
+
DBSchema, Pipe,
|
|
7
|
+
} from './types'
|
|
8
|
+
|
|
9
|
+
export default abstract class Model<TB extends keyof DB, DB> {
|
|
10
|
+
// Property only for the compiler (does not exist at runtime)
|
|
11
|
+
readonly $DBShape!: DB
|
|
12
|
+
readonly $TShape!: DB[TB]
|
|
13
|
+
|
|
14
|
+
static $table: string = ''
|
|
15
|
+
static $schema?: DBSchema
|
|
16
|
+
|
|
17
|
+
static pipe<S, T>(): Pipe<S, T> {
|
|
18
|
+
throw new Error(`Database connection not provided.`) // improv this message
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
static builder<S, T>() {
|
|
22
|
+
const table = this.$table || pluralize(this.name.toLowerCase())
|
|
23
|
+
|
|
24
|
+
return new QueryBuilder<S, T>(table, this.$schema, this.pipe<S, T>())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static select< // @ts-ignore
|
|
28
|
+
M extends typeof Model<TB, DB>,
|
|
29
|
+
I extends InstanceType<M>,
|
|
30
|
+
T extends I['$TShape'],
|
|
31
|
+
C extends keyof T
|
|
32
|
+
>(this: M, ...columns: C[] | C[][]) {
|
|
33
|
+
return this.builder<I['$DBShape'], T>().select(...columns)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
static distinct< // @ts-ignore
|
|
37
|
+
M extends typeof Model<TB, DB>,
|
|
38
|
+
I extends InstanceType<M>,
|
|
39
|
+
T extends I['$TShape']
|
|
40
|
+
>(this: M) {
|
|
41
|
+
return this.builder<I['$DBShape'], T>().distinct()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
static where< // @ts-ignore
|
|
45
|
+
M extends typeof Model<TB, DB>,
|
|
46
|
+
I extends InstanceType<M>,
|
|
47
|
+
T extends I['$TShape'],
|
|
48
|
+
C extends keyof T
|
|
49
|
+
>(this: M, fn: WhereFn<T>): QueryBuilder<I['$DBShape'], T, C>
|
|
50
|
+
static where< // @ts-ignore
|
|
51
|
+
M extends typeof Model<TB, DB>,
|
|
52
|
+
I extends InstanceType<M>,
|
|
53
|
+
T extends I['$TShape'],
|
|
54
|
+
C extends keyof T
|
|
55
|
+
>(this: M, column: C, value: T[C]): QueryBuilder<I['$DBShape'], T, C>
|
|
56
|
+
static where< // @ts-ignore
|
|
57
|
+
M extends typeof Model<TB, DB>,
|
|
58
|
+
I extends InstanceType<M>,
|
|
59
|
+
T extends I['$TShape'],
|
|
60
|
+
C extends keyof T
|
|
61
|
+
>(this: M, column: C, operator: Operator, value: T[C]): QueryBuilder<I['$DBShape'], T, C>
|
|
62
|
+
static where< // @ts-ignore
|
|
63
|
+
M extends typeof Model<TB, DB>,
|
|
64
|
+
I extends InstanceType<M>,
|
|
65
|
+
T extends I['$TShape']
|
|
66
|
+
>(this: M, ...args: WhereArgs<T>) {
|
|
67
|
+
return this.builder<I['$DBShape'], T>().where(...args)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
static on< // @ts-ignore
|
|
71
|
+
M extends typeof Model<TB, DB>,
|
|
72
|
+
I extends InstanceType<M>,
|
|
73
|
+
T extends I['$TShape'],
|
|
74
|
+
C extends keyof T
|
|
75
|
+
>(this: M, fn: WhereFn<T>): QueryBuilder<I['$DBShape'], T, C>
|
|
76
|
+
static on< // @ts-ignore
|
|
77
|
+
M extends typeof Model<TB, DB>,
|
|
78
|
+
I extends InstanceType<M>,
|
|
79
|
+
T extends I['$TShape'],
|
|
80
|
+
C extends keyof T
|
|
81
|
+
>(this: M, column: C, value: T[C]): QueryBuilder<I['$DBShape'], T, C>
|
|
82
|
+
static on< // @ts-ignore
|
|
83
|
+
M extends typeof Model<TB, DB>,
|
|
84
|
+
I extends InstanceType<M>,
|
|
85
|
+
T extends I['$TShape'],
|
|
86
|
+
C extends keyof T
|
|
87
|
+
>(this: M, column: C, operator: Operator, value: T[C]): QueryBuilder<I['$DBShape'], T, C>
|
|
88
|
+
static on< // @ts-ignore
|
|
89
|
+
M extends typeof Model<TB, DB>,
|
|
90
|
+
I extends InstanceType<M>,
|
|
91
|
+
T extends I['$TShape']
|
|
92
|
+
>(this: M, ...args: WhereArgs<T>) {
|
|
93
|
+
return this.builder<I['$DBShape'], T>().where(...args)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static whereIn< // @ts-ignore
|
|
97
|
+
M extends typeof Model<TB, DB>,
|
|
98
|
+
I extends InstanceType<M>,
|
|
99
|
+
T extends I['$TShape'],
|
|
100
|
+
C extends keyof T
|
|
101
|
+
>(this: M, column: C, value: T[C][]) {
|
|
102
|
+
return this.builder<I['$DBShape'], T>().whereIn(column, value)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static in< // @ts-ignore
|
|
106
|
+
M extends typeof Model<TB, DB>,
|
|
107
|
+
I extends InstanceType<M>,
|
|
108
|
+
T extends I['$TShape'],
|
|
109
|
+
C extends keyof T
|
|
110
|
+
>(this: M, column: C, value: T[C][]) {
|
|
111
|
+
return this.builder<I['$DBShape'], T>().whereIn(column, value)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static whereNotIn< // @ts-ignore
|
|
115
|
+
M extends typeof Model<TB, DB>,
|
|
116
|
+
I extends InstanceType<M>,
|
|
117
|
+
T extends I['$TShape'],
|
|
118
|
+
C extends keyof T
|
|
119
|
+
>(this: M, column: C, value: T[C][]) {
|
|
120
|
+
return this.builder<I['$DBShape'], T>().whereNotIn(column, value)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static notIn< // @ts-ignore
|
|
124
|
+
M extends typeof Model<TB, DB>,
|
|
125
|
+
I extends InstanceType<M>,
|
|
126
|
+
T extends I['$TShape'],
|
|
127
|
+
C extends keyof T
|
|
128
|
+
>(this: M, column: C, value: T[C][]) {
|
|
129
|
+
return this.builder<I['$DBShape'], T>().whereNotIn(column, value)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
static whereBetween< // @ts-ignore
|
|
133
|
+
M extends typeof Model<TB, DB>,
|
|
134
|
+
I extends InstanceType<M>,
|
|
135
|
+
T extends I['$TShape'],
|
|
136
|
+
C extends keyof T
|
|
137
|
+
>(this: M, column: C, one: T[C], two: T[C]) {
|
|
138
|
+
return this.builder<I['$DBShape'], T>().whereBetween(column, one, two)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static between< // @ts-ignore
|
|
142
|
+
M extends typeof Model<TB, DB>,
|
|
143
|
+
I extends InstanceType<M>,
|
|
144
|
+
T extends I['$TShape'],
|
|
145
|
+
C extends keyof T
|
|
146
|
+
>(this: M, column: C, one: T[C], two: T[C]) {
|
|
147
|
+
return this.builder<I['$DBShape'], T>().whereBetween(column, one, two)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
static whereNotBetween< // @ts-ignore
|
|
151
|
+
M extends typeof Model<TB, DB>,
|
|
152
|
+
I extends InstanceType<M>,
|
|
153
|
+
T extends I['$TShape'],
|
|
154
|
+
C extends keyof T
|
|
155
|
+
>(this: M, column: C, one: T[C], two: T[C]) {
|
|
156
|
+
return this.builder<I['$DBShape'], T>().whereNotBetween(column, one, two)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
static notBetween< // @ts-ignore
|
|
160
|
+
M extends typeof Model<TB, DB>,
|
|
161
|
+
I extends InstanceType<M>,
|
|
162
|
+
T extends I['$TShape'],
|
|
163
|
+
C extends keyof T
|
|
164
|
+
>(this: M, column: C, one: T[C], two: T[C]) {
|
|
165
|
+
return this.builder<I['$DBShape'], T>().whereNotBetween(column, one, two)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
static whereNull< // @ts-ignore
|
|
169
|
+
M extends typeof Model<TB, DB>,
|
|
170
|
+
I extends InstanceType<M>,
|
|
171
|
+
T extends I['$TShape'],
|
|
172
|
+
C extends keyof T
|
|
173
|
+
>(this: M, column: C) {
|
|
174
|
+
return this.builder<I['$DBShape'], T>().whereNull(column)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
static onNull< // @ts-ignore
|
|
178
|
+
M extends typeof Model<TB, DB>,
|
|
179
|
+
I extends InstanceType<M>,
|
|
180
|
+
T extends I['$TShape'],
|
|
181
|
+
C extends keyof T
|
|
182
|
+
>(this: M, column: C) {
|
|
183
|
+
return this.builder<I['$DBShape'], T>().whereNull(column)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
static whereNotNull< // @ts-ignore
|
|
187
|
+
M extends typeof Model<TB, DB>,
|
|
188
|
+
I extends InstanceType<M>,
|
|
189
|
+
T extends I['$TShape'],
|
|
190
|
+
C extends keyof T
|
|
191
|
+
>(this: M, column: C) {
|
|
192
|
+
return this.builder<I['$DBShape'], T>().whereNotNull(column)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
static onNotNull< // @ts-ignore
|
|
196
|
+
M extends typeof Model<TB, DB>,
|
|
197
|
+
I extends InstanceType<M>,
|
|
198
|
+
T extends I['$TShape'],
|
|
199
|
+
C extends keyof T
|
|
200
|
+
>(this: M, column: C) {
|
|
201
|
+
return this.builder<I['$DBShape'], T>().whereNotNull(column)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// TODO: groupBy(...columns: string[])
|
|
205
|
+
|
|
206
|
+
static order< // @ts-ignore
|
|
207
|
+
M extends typeof Model<TB, DB>,
|
|
208
|
+
I extends InstanceType<M>,
|
|
209
|
+
T extends I['$TShape'],
|
|
210
|
+
C extends keyof T
|
|
211
|
+
>(this: M, column: C, direction: OrderDirection = 'ASC') {
|
|
212
|
+
return this.builder<I['$DBShape'], T>().order(column, direction)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
static orderBy< // @ts-ignore
|
|
216
|
+
M extends typeof Model<TB, DB>,
|
|
217
|
+
I extends InstanceType<M>,
|
|
218
|
+
T extends I['$TShape'],
|
|
219
|
+
C extends keyof T
|
|
220
|
+
>(this: M, column: C, direction: OrderDirection = 'ASC') {
|
|
221
|
+
return this.builder<I['$DBShape'], T>().order(column, direction)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static asc< // @ts-ignore
|
|
225
|
+
M extends typeof Model<TB, DB>,
|
|
226
|
+
I extends InstanceType<M>,
|
|
227
|
+
T extends I['$TShape'],
|
|
228
|
+
C extends keyof T
|
|
229
|
+
>(this: M, column: C) {
|
|
230
|
+
return this.builder<I['$DBShape'], T>().asc(column)
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
static desc< // @ts-ignore
|
|
234
|
+
M extends typeof Model<TB, DB>,
|
|
235
|
+
I extends InstanceType<M>,
|
|
236
|
+
T extends I['$TShape'],
|
|
237
|
+
C extends keyof T
|
|
238
|
+
>(this: M, column: C) {
|
|
239
|
+
return this.builder<I['$DBShape'], T>().desc(column)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
static limit< // @ts-ignore
|
|
243
|
+
M extends typeof Model<TB, DB>,
|
|
244
|
+
I extends InstanceType<M>,
|
|
245
|
+
T extends I['$TShape']
|
|
246
|
+
>(this: M, val: number | string) {
|
|
247
|
+
return this.builder<I['$DBShape'], T>().limit(val)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
static offset< // @ts-ignore
|
|
251
|
+
M extends typeof Model<TB, DB>,
|
|
252
|
+
I extends InstanceType<M>,
|
|
253
|
+
T extends I['$TShape']
|
|
254
|
+
>(this: M, val: number | string) {
|
|
255
|
+
return this.builder<I['$DBShape'], T>().offset(val)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import ClauseBuilder from './clause-builder'
|
|
2
|
+
import {
|
|
3
|
+
isOperator,
|
|
4
|
+
parseColumn, parseSelectColumn,
|
|
5
|
+
formatValue,
|
|
6
|
+
isJoinCompare,
|
|
7
|
+
zSame, zType,
|
|
8
|
+
} from './utils'
|
|
9
|
+
import type {
|
|
10
|
+
IJoinBuilder, IClauseBuilder,
|
|
11
|
+
OrderDirection,
|
|
12
|
+
JoinType,
|
|
13
|
+
WhereArgs,
|
|
14
|
+
Values,
|
|
15
|
+
Item,
|
|
16
|
+
JoinArgs,
|
|
17
|
+
DBSchema,
|
|
18
|
+
Pipe,
|
|
19
|
+
} from './types'
|
|
20
|
+
|
|
21
|
+
export default class QueryBuilder<
|
|
22
|
+
S,
|
|
23
|
+
T,
|
|
24
|
+
C extends keyof T = keyof T //,
|
|
25
|
+
// J extends keyof S = keyof S
|
|
26
|
+
// T, // = any,,
|
|
27
|
+
// C extends keyof T = keyof T
|
|
28
|
+
// > {
|
|
29
|
+
> implements IJoinBuilder<S>, IClauseBuilder<T> {
|
|
30
|
+
#table!: string
|
|
31
|
+
#schema?: DBSchema
|
|
32
|
+
#selects: string[] = []
|
|
33
|
+
#clauses!: ClauseBuilder<T>
|
|
34
|
+
#groups: string[] = []
|
|
35
|
+
#orders: string[] = []
|
|
36
|
+
|
|
37
|
+
#distinct = false
|
|
38
|
+
#hasJoin = false
|
|
39
|
+
#limit?: number
|
|
40
|
+
#offset?: number
|
|
41
|
+
|
|
42
|
+
#joins: string[] = []
|
|
43
|
+
|
|
44
|
+
#pipe?: Pipe<S, T, C>
|
|
45
|
+
|
|
46
|
+
constructor(
|
|
47
|
+
table: string,
|
|
48
|
+
schema?: DBSchema,
|
|
49
|
+
pipe?: Pipe<S, T, C>
|
|
50
|
+
) {
|
|
51
|
+
this.#table = table
|
|
52
|
+
this.#schema = schema
|
|
53
|
+
this.#pipe = pipe
|
|
54
|
+
this.#clauses = new ClauseBuilder<T>(table, schema)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async run() {
|
|
58
|
+
if (!this.#pipe?.run)
|
|
59
|
+
throw new Error(`No database connection.`)
|
|
60
|
+
|
|
61
|
+
return await this.#pipe?.run(this)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async first<K extends keyof T>(...columns: K[] | K[][]): Promise<null | Item<T, C>> {
|
|
65
|
+
columns?.length && this.select(...columns)
|
|
66
|
+
const resp = await this.run()
|
|
67
|
+
return resp.results?.length ? resp.results[0] : null
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async all<K extends keyof T>(...columns: K[] | K[][]): Promise<Item<T, C>[]> {
|
|
71
|
+
columns?.length && this.select(...columns)
|
|
72
|
+
const resp = await this.run()
|
|
73
|
+
return resp.results
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
select<K extends keyof T>(...columns: K[] | K[][]): QueryBuilder<S, T, K> {
|
|
77
|
+
this.#selects.push(...columns.flat(Infinity) as string[])
|
|
78
|
+
return this as any
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
distinct() {
|
|
82
|
+
this.#distinct = true
|
|
83
|
+
return this
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#join<J extends keyof S>(
|
|
87
|
+
type: JoinType | undefined,
|
|
88
|
+
table: J,
|
|
89
|
+
...args: JoinArgs<S, J>
|
|
90
|
+
) {
|
|
91
|
+
this.#hasJoin = true
|
|
92
|
+
const query = (type ? type + ' ' : '') + `JOIN ${table as string} ON `
|
|
93
|
+
|
|
94
|
+
if (typeof args[0] == 'function') {
|
|
95
|
+
const join = new ClauseBuilder<S[J]>(table as string, this.#schema)
|
|
96
|
+
args[0](join)
|
|
97
|
+
|
|
98
|
+
this.#joins.push(query + join.clauses.join(' '))
|
|
99
|
+
this.#clauses.args = join.args
|
|
100
|
+
return this
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const length = args.length
|
|
104
|
+
let [column, operator, value, value2] = args
|
|
105
|
+
|
|
106
|
+
if (length == 2) { // @ts-ignore
|
|
107
|
+
value = operator
|
|
108
|
+
operator = '='
|
|
109
|
+
} else if (length == 3 && !isOperator(operator)) { // @ts-ignore
|
|
110
|
+
// console.log(column, operator, value, value2) // @ts-ignore
|
|
111
|
+
value = parseColumn(value as string, operator as string) // TODO: check if value is a valid column
|
|
112
|
+
|
|
113
|
+
if (this.#schema && !isJoinCompare(value, this.#schema))
|
|
114
|
+
throw new Error(`Table column '${value}' doesn't exists.`)
|
|
115
|
+
|
|
116
|
+
operator = '='
|
|
117
|
+
} else if (length == 4) { // @ts-ignore
|
|
118
|
+
// console.log(column, operator, value, value2) // @ts-ignore
|
|
119
|
+
value = parseColumn(value2 as string, value as string)
|
|
120
|
+
operator = '='
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const col = parseColumn(String(column), String(table))
|
|
124
|
+
if (this.#schema && !zSame(col, value, this.#schema))
|
|
125
|
+
throw new Error(`Table column '${col}' of type '${zType(col, this.#schema)}' is not assignable as type of '${typeof value}'.`)
|
|
126
|
+
|
|
127
|
+
if (!isJoinCompare(value, this.#schema)) { // @ts-ignore
|
|
128
|
+
this.#clauses.args = [value] // @ts-ignore // TODO: https://developers.cloudflare.com/d1/worker-api/#type-conversion
|
|
129
|
+
value = '?'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// @ts-ignore
|
|
133
|
+
this.#joins.push(query + col + ` ${operator} ${value}`)
|
|
134
|
+
return this
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
join<J extends keyof S>(table: J, ...args: JoinArgs<S, J>) {
|
|
138
|
+
return this.#join(undefined, table, ...args)
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
innerJoin<J extends keyof S>(table: J, ...args: JoinArgs<S, J>) {
|
|
142
|
+
return this.#join('INNER', table, ...args)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
leftJoin<J extends keyof S>(table: J, ...args: JoinArgs<S, J>) {
|
|
146
|
+
return this.#join('LEFT', table, ...args)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
rightJoin<J extends keyof S>(table: J, ...args: JoinArgs<S, J>) {
|
|
150
|
+
return this.#join('RIGHT', table, ...args)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
crossJoin<J extends keyof S>(table: J, ...args: JoinArgs<S, J>) {
|
|
154
|
+
return this.#join('CROSS', table, ...args)
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
where(...args: WhereArgs<T>) {
|
|
158
|
+
this.#clauses.where(...args)
|
|
159
|
+
return this
|
|
160
|
+
}
|
|
161
|
+
on(...args: WhereArgs<T>) {
|
|
162
|
+
return this.where(...args)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
orWhere(...args: WhereArgs<T>) {
|
|
166
|
+
this.#clauses.orWhere(...args)
|
|
167
|
+
return this
|
|
168
|
+
}
|
|
169
|
+
orOn(...args: WhereArgs<T>) {
|
|
170
|
+
return this.orWhere(...args)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
whereIn(column: C, values: T[C][]) {
|
|
174
|
+
this.#clauses.whereIn(column, values)
|
|
175
|
+
return this
|
|
176
|
+
}
|
|
177
|
+
in(column: C, values: T[C][]) {
|
|
178
|
+
return this.whereIn(column, values)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
whereNotIn(column: C, values: T[C][]) {
|
|
182
|
+
this.#clauses.whereNotIn(column, values)
|
|
183
|
+
return this
|
|
184
|
+
}
|
|
185
|
+
notIn(column: C, values: T[C][]) {
|
|
186
|
+
return this.whereNotIn(column, values)
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
orWhereIn(column: C, values: T[C][]) {
|
|
190
|
+
this.#clauses.orWhereIn(column, values)
|
|
191
|
+
return this
|
|
192
|
+
}
|
|
193
|
+
orIn(column: C, values: T[C][]) {
|
|
194
|
+
return this.orWhereIn(column, values)
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
orWhereNotIn(column: C, values: T[C][]) {
|
|
198
|
+
this.#clauses.orWhereNotIn(column, values)
|
|
199
|
+
return this
|
|
200
|
+
}
|
|
201
|
+
orNotIn(column: C, values: T[C][]) {
|
|
202
|
+
return this.orWhereNotIn(column, values)
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
whereBetween(column: C, one: T[C], two: T[C]) {
|
|
206
|
+
this.#clauses.whereBetween(column, one, two)
|
|
207
|
+
return this
|
|
208
|
+
}
|
|
209
|
+
between(column: C, one: T[C], two: T[C]) {
|
|
210
|
+
return this.whereBetween(column, one, two)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
orWhereBetween(column: C, one: T[C], two: T[C]) {
|
|
214
|
+
this.#clauses.orWhereBetween(column, one, two)
|
|
215
|
+
return this
|
|
216
|
+
}
|
|
217
|
+
orBetween(column: C, one: T[C], two: T[C]) {
|
|
218
|
+
return this.orWhereBetween(column, one, two)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
whereNotBetween(column: C, one: T[C], two: T[C]) {
|
|
222
|
+
this.#clauses.whereNotBetween(column, one, two)
|
|
223
|
+
return this
|
|
224
|
+
}
|
|
225
|
+
notBetween(column: C, one: T[C], two: T[C]) {
|
|
226
|
+
return this.whereNotBetween(column, one, two)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
orWhereNotBetween(column: C, one: T[C], two: T[C]) {
|
|
230
|
+
this.#clauses.orWhereNotBetween(column, one, two)
|
|
231
|
+
return this
|
|
232
|
+
}
|
|
233
|
+
orNotBetween(column: C, one: T[C], two: T[C]) {
|
|
234
|
+
return this.orWhereNotBetween(column, one, two)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
whereNull(column: C) {
|
|
238
|
+
this.#clauses.whereNull(column)
|
|
239
|
+
return this
|
|
240
|
+
}
|
|
241
|
+
onNull(column: C) {
|
|
242
|
+
return this.whereNull(column)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
orWhereNull(column: C) {
|
|
246
|
+
this.#clauses.orWhereNull(column)
|
|
247
|
+
return this
|
|
248
|
+
}
|
|
249
|
+
orOnNull(column: C) {
|
|
250
|
+
return this.orWhereNull(column)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
whereNotNull(column: C) {
|
|
254
|
+
this.#clauses.whereNotNull(column)
|
|
255
|
+
return this
|
|
256
|
+
}
|
|
257
|
+
onNotNull(column: C) {
|
|
258
|
+
return this.whereNotNull(column)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
orWhereNotNull(column: C) {
|
|
262
|
+
this.#clauses.orWhereNotNull(column)
|
|
263
|
+
return this
|
|
264
|
+
}
|
|
265
|
+
orNotNull(column: C) {
|
|
266
|
+
return this.orWhereNotNull(column)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
groupBy(...columns: string[]) {
|
|
270
|
+
this.#groups.push(...columns)
|
|
271
|
+
return this
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
order(column: C, direction: OrderDirection = 'ASC') {
|
|
275
|
+
this.#orders.push(parseColumn(column as string, this.#table, this.#hasJoin) +' '+ direction.toUpperCase())
|
|
276
|
+
return this
|
|
277
|
+
}
|
|
278
|
+
orderBy(column: C, direction: OrderDirection = 'ASC') {
|
|
279
|
+
return this.order(column, direction)
|
|
280
|
+
}
|
|
281
|
+
asc(column: C) {
|
|
282
|
+
return this.order(column, 'ASC')
|
|
283
|
+
}
|
|
284
|
+
desc(column: C) {
|
|
285
|
+
return this.order(column, 'DESC')
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
limit(val: number | string) {
|
|
289
|
+
val = parseInt(String(val)) || 0
|
|
290
|
+
if (val) this.#limit = val
|
|
291
|
+
return this
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
offset(val: number | string) {
|
|
295
|
+
this.#offset = parseInt(String(val)) || 0
|
|
296
|
+
return this
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
#bind(sql: string, values: Values) {
|
|
300
|
+
let i = 0
|
|
301
|
+
let out = ''
|
|
302
|
+
let last = 0
|
|
303
|
+
|
|
304
|
+
for (let pos = sql.indexOf('?'); pos !== -1; pos = sql.indexOf('?', pos + 1)) {
|
|
305
|
+
if (i >= values.length)
|
|
306
|
+
throw new Error(`Missing bind value at position ${i}`)
|
|
307
|
+
|
|
308
|
+
out += sql.slice(last, pos)
|
|
309
|
+
out += formatValue(values[i++])
|
|
310
|
+
last = pos + 1
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (i < values.length)
|
|
314
|
+
throw new Error(`Too many bind values: expected ${i}, got ${values.length}`)
|
|
315
|
+
|
|
316
|
+
return out + sql.slice(last)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
get args() {
|
|
320
|
+
return this.#clauses.args
|
|
321
|
+
}
|
|
322
|
+
get arguments() {
|
|
323
|
+
return this.args
|
|
324
|
+
}
|
|
325
|
+
get bindings() {
|
|
326
|
+
return this.args
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
get query() {
|
|
330
|
+
let sql = ''
|
|
331
|
+
|
|
332
|
+
const selects = new Set<string>()
|
|
333
|
+
this.#selects.forEach(column => {
|
|
334
|
+
column = parseSelectColumn(column, this.#table, this.#hasJoin)
|
|
335
|
+
!selects.has(column) && selects.add(column)
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
sql += `SELECT ${this.#distinct ? 'DISTINCT ' : ''}${
|
|
339
|
+
selects.size ? [...selects].join(', ') : '*'
|
|
340
|
+
}`
|
|
341
|
+
|
|
342
|
+
sql += ' FROM '+ this.#table
|
|
343
|
+
|
|
344
|
+
if (this.#joins.length)
|
|
345
|
+
sql += ' '+ this.#joins.join(' ')
|
|
346
|
+
|
|
347
|
+
if (this.#clauses.length)
|
|
348
|
+
sql += ' WHERE '+ this.#clauses.clauses.join(' ')
|
|
349
|
+
|
|
350
|
+
if (this.#groups.length)
|
|
351
|
+
sql += ' GROUP BY '+ this.#groups.join(', ')
|
|
352
|
+
|
|
353
|
+
if (this.#orders.length)
|
|
354
|
+
sql += ' ORDER BY '+ this.#orders.join(', ')
|
|
355
|
+
|
|
356
|
+
if (this.#limit != undefined)
|
|
357
|
+
sql += ' LIMIT '+ this.#limit
|
|
358
|
+
|
|
359
|
+
if (this.#offset != undefined)
|
|
360
|
+
sql += ' OFFSET '+ this.#offset
|
|
361
|
+
|
|
362
|
+
return sql
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
get sql() {
|
|
366
|
+
return this.#bind(this.query, this.#clauses.args)
|
|
367
|
+
}
|
|
368
|
+
get raw() {
|
|
369
|
+
return this.sql
|
|
370
|
+
}
|
|
371
|
+
}
|