rado 0.3.4 → 0.3.6
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 +277 -277
- package/dist/driver/better-sqlite3.d.ts +1 -0
- package/dist/driver/better-sqlite3.js +3 -0
- package/dist/driver/bun-sqlite.d.ts +1 -0
- package/dist/driver/bun-sqlite.js +3 -0
- package/dist/driver/sql.js.d.ts +1 -0
- package/dist/driver/sql.js.js +3 -0
- package/dist/driver/sqlite3.d.ts +1 -0
- package/dist/driver/sqlite3.js +11 -0
- package/dist/lib/Driver.d.ts +3 -0
- package/dist/lib/Driver.js +3 -0
- package/dist/lib/Formatter.js +2 -2
- package/package.json +74 -74
- package/dist/define/CTE.d.ts +0 -2
- package/dist/define/CTE.js +0 -51
- package/dist/define/Cursor.d.ts +0 -108
- package/dist/define/Cursor.js +0 -338
- package/dist/define/Update.d.ts +0 -4
- package/dist/define/Update.js +0 -0
- package/dist/define/query/Batch.d.ts +0 -7
- package/dist/define/query/Batch.js +0 -17
- package/dist/define/query/CreateTable.d.ts +0 -6
- package/dist/define/query/CreateTable.js +0 -11
- package/dist/define/query/Delete.d.ts +0 -11
- package/dist/define/query/Delete.js +0 -18
- package/dist/define/query/Insert.d.ts +0 -22
- package/dist/define/query/Insert.js +0 -47
- package/dist/define/query/Select.d.ts +0 -39
- package/dist/define/query/Select.js +0 -170
- package/dist/define/query/TableSelect.d.ts +0 -28
- package/dist/define/query/TableSelect.js +0 -79
- package/dist/define/query/Union.d.ts +0 -17
- package/dist/define/query/Union.js +0 -116
- package/dist/define/query/Update.d.ts +0 -12
- package/dist/define/query/Update.js +0 -18
- package/dist/deno/driver/better-sqlite3.js +0 -57
- package/dist/deno/driver/bun-sqlite.js +0 -69
- package/dist/deno/driver/sql.js.js +0 -72
- package/dist/deno/driver/sqlite3.js +0 -123
- package/dist/deno/index.js +0 -14
- package/dist/deno/lib/Driver.js +0 -330
- package/dist/deno/lib/Formatter.js +0 -715
- package/dist/deno/lib/Sanitizer.js +0 -0
- package/dist/deno/lib/SqlError.js +0 -11
- package/dist/deno/lib/Statement.js +0 -108
- package/dist/deno/sqlite/SqliteFormatter.js +0 -70
- package/dist/deno/sqlite/SqliteFunctions.js +0 -150
- package/dist/deno/sqlite/SqliteSchema.js +0 -47
- package/dist/deno/sqlite.js +0 -3
- package/dist/deno/util/Callable.js +0 -15
- package/dist/sqlite/index.d.ts +0 -2
- package/dist/sqlite/index.js +0 -3
- package/dist/src/driver/better-sqlite3.js +0 -49
- package/dist/src/driver/sql.js.js +0 -66
- package/dist/src/driver/sqlite3.js +0 -87
- package/dist/src/index.js +0 -24
- package/dist/src/lib/Column.js +0 -63
- package/dist/src/lib/Cursor.js +0 -231
- package/dist/src/lib/Driver.js +0 -316
- package/dist/src/lib/Expr.js +0 -284
- package/dist/src/lib/Fields.js +0 -0
- package/dist/src/lib/Formatter.js +0 -625
- package/dist/src/lib/Functions.js +0 -11
- package/dist/src/lib/Id.js +0 -0
- package/dist/src/lib/Index.js +0 -20
- package/dist/src/lib/Ops.js +0 -45
- package/dist/src/lib/OrderBy.js +0 -9
- package/dist/src/lib/Param.js +0 -27
- package/dist/src/lib/Query.js +0 -74
- package/dist/src/lib/Sanitizer.js +0 -0
- package/dist/src/lib/Schema.js +0 -67
- package/dist/src/lib/Selection.js +0 -7
- package/dist/src/lib/Statement.js +0 -103
- package/dist/src/lib/Table.js +0 -130
- package/dist/src/lib/Target.js +0 -37
- package/dist/src/lib/Update.js +0 -0
- package/dist/src/sqlite/SqliteFormatter.js +0 -67
- package/dist/src/sqlite/SqliteFunctions.js +0 -146
- package/dist/src/sqlite/SqliteSchema.js +0 -47
- package/dist/src/sqlite.js +0 -3
- package/dist/test/DbSuite.js +0 -28
- package/dist/test/TSTestTypes.js +0 -6
- package/dist/test/TestBasic.js +0 -172
- package/dist/test/TestExtend.js +0 -68
- package/dist/test/TestFts5.js +0 -34
- package/dist/test/TestFunctions.js +0 -28
- package/dist/test/TestJoins.js +0 -34
- package/dist/test/TestJson.js +0 -33
- package/dist/test/TestPrepare.js +0 -27
- package/dist/test/TestRawSql.js +0 -31
- package/dist/test/TestSchema.js +0 -69
- package/dist/test/TestSubQueries.js +0 -79
- package/dist/test/TestTransaction.js +0 -54
- package/dist/test/TestUpdate.js +0 -95
- package/dist/test/index.js +0 -14
package/README.md
CHANGED
|
@@ -1,277 +1,277 @@
|
|
|
1
|
-
[](https://npmjs.org/package/rado)
|
|
2
|
-
|
|
3
|
-
# rado
|
|
4
|
-
|
|
5
|
-
Fully typed, lightweight TypeScript query builder.
|
|
6
|
-
Currently focused on SQLite.
|
|
7
|
-
|
|
8
|
-
- Definition via TypeScript types
|
|
9
|
-
- Composable queries
|
|
10
|
-
- Aggregate rows in selects
|
|
11
|
-
- First class JSON columns
|
|
12
|
-
- No code generation step
|
|
13
|
-
- No dependencies
|
|
14
|
-
|
|
15
|
-
<pre>npm install <a href="https://www.npmjs.com/package/rado">rado</a></pre>
|
|
16
|
-
|
|
17
|
-
## Queries
|
|
18
|
-
|
|
19
|
-
#### Where
|
|
20
|
-
|
|
21
|
-
Conditions can be created by accessing the fields of the table
|
|
22
|
-
instances and using the operators of `Expr`:
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
User.id // This is an Expr<number> which has an `is` method to compare
|
|
26
|
-
User.id.is(1) // Compare with a value, results in an Expr<boolean>
|
|
27
|
-
User.id.is(Post.userId) // Compare to fields on other tables
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
Rows can be selected by passing the condition in the where method:
|
|
31
|
-
|
|
32
|
-
```ts
|
|
33
|
-
// Call a table instance to start a query selecting from that table
|
|
34
|
-
User().where(User.id.is(1))
|
|
35
|
-
// Conditions can be as complex as you want
|
|
36
|
-
User().where(User.id.isGreater(1).and(User.id.isLess(5)))
|
|
37
|
-
// `And` conditions can also be comma separated in `where` to improve readability
|
|
38
|
-
User().where(User.id.isGreater(1), User.id.isLess(5))
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
There's a shortcut for comparing columns of a table directly in its call.
|
|
42
|
-
The first comparison above can be simplified to:
|
|
43
|
-
|
|
44
|
-
```ts
|
|
45
|
-
User({id: 1}) // Is the same as User().where(User.id.is(1))
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
This comes in handy when joining tables too:
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
User({id: 1}).innerJoin(Post({userId: User.id}))
|
|
52
|
-
// Is equal to:
|
|
53
|
-
User().innerJoin(Post, Post.userId.is(User.id)).where(User.id.is(1))
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
#### Select
|
|
57
|
-
|
|
58
|
-
Retrieve a single field
|
|
59
|
-
|
|
60
|
-
```ts
|
|
61
|
-
User().select(User.name)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Or an object of data
|
|
65
|
-
|
|
66
|
-
```ts
|
|
67
|
-
User().select({
|
|
68
|
-
...User, // Get all user fields: id, username
|
|
69
|
-
posts: Post({userId: User.id}) // Aggregate posts of this user
|
|
70
|
-
})
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
You can call the `posts` helper method defined in the example schema below
|
|
74
|
-
to achieve the same:
|
|
75
|
-
|
|
76
|
-
```ts
|
|
77
|
-
User().select({
|
|
78
|
-
...User,
|
|
79
|
-
posts: User.posts()
|
|
80
|
-
})
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
Retrieve all posts with their author and tags and count the tag usage in other
|
|
84
|
-
posts:
|
|
85
|
-
|
|
86
|
-
```ts
|
|
87
|
-
import {count} from 'rado/sqlite'
|
|
88
|
-
// Alias tables using `as`
|
|
89
|
-
const pt = PostTags().as('pt')
|
|
90
|
-
Post().select({
|
|
91
|
-
...Post,
|
|
92
|
-
author: Post.author().select(User.username),
|
|
93
|
-
tags: Post.tags().select({
|
|
94
|
-
count: pt({tagId: Tag.id}).select(count()).first(),
|
|
95
|
-
name: Tag.name
|
|
96
|
-
})
|
|
97
|
-
})
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
Join other tables and select fields from either table:
|
|
101
|
-
|
|
102
|
-
```ts
|
|
103
|
-
User({id: 1}).innerJoin(Post({userId: User.id})).select({
|
|
104
|
-
username: User.username
|
|
105
|
-
post: Post
|
|
106
|
-
})
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
Create expressions to select complex values:
|
|
110
|
-
|
|
111
|
-
```ts
|
|
112
|
-
import {iif} from 'rado/sqlite'
|
|
113
|
-
Person().select({
|
|
114
|
-
name: Person.firstName.concat(' ').concat(Person.lastName),
|
|
115
|
-
isMario: Person.firstName.is('Mario'),
|
|
116
|
-
isActor: Person.id.isIn(Actor().select(Actor.personId)),
|
|
117
|
-
email: iif(Person.email.isNotNull(), Person.email, 'its.me@mario'),
|
|
118
|
-
twitterHandle: Person.socialMedia
|
|
119
|
-
.filter(media => media.type.is('twitter'))
|
|
120
|
-
.map(media => media.handle)
|
|
121
|
-
.maybeFirst()
|
|
122
|
-
})
|
|
123
|
-
```
|
|
124
|
-
|
|
125
|
-
Order, group, limit queries:
|
|
126
|
-
|
|
127
|
-
```ts
|
|
128
|
-
User()
|
|
129
|
-
.orderBy(User.username.asc())
|
|
130
|
-
.groupBy(User.id, User.username)
|
|
131
|
-
.skip(20)
|
|
132
|
-
.take(10)
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
#### Insert
|
|
136
|
-
|
|
137
|
-
Insert a single row and return the result:
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
User().insertOne({username: 'Mario'})
|
|
141
|
-
```
|
|
142
|
-
|
|
143
|
-
Insert multiple rows:
|
|
144
|
-
|
|
145
|
-
```ts
|
|
146
|
-
User().insertAll([{username: 'Mario'}, {username: 'Luigi'}])
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
#### Update
|
|
150
|
-
|
|
151
|
-
Set values
|
|
152
|
-
|
|
153
|
-
```ts
|
|
154
|
-
User({id: 1}).set({username: 'Bowser'})
|
|
155
|
-
```
|
|
156
|
-
|
|
157
|
-
Use expressions to update complex values:
|
|
158
|
-
|
|
159
|
-
```ts
|
|
160
|
-
User()
|
|
161
|
-
.set({username: User.username.concat(' [removed]')})
|
|
162
|
-
.where(User.deleted)
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
#### Delete
|
|
166
|
-
|
|
167
|
-
Delete rows
|
|
168
|
-
|
|
169
|
-
```ts
|
|
170
|
-
User({id: 1}).delete()
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Schema definition
|
|
174
|
-
|
|
175
|
-
```ts
|
|
176
|
-
import {table, column} from 'rado'
|
|
177
|
-
|
|
178
|
-
const User = table({
|
|
179
|
-
// Pass a definition under a key with the actual name of the table in database
|
|
180
|
-
user: class {
|
|
181
|
-
id = column.integer.primaryKey()
|
|
182
|
-
username = column.string
|
|
183
|
-
|
|
184
|
-
// Define helper methods directly on the model
|
|
185
|
-
posts() {
|
|
186
|
-
return Post({userId: this.id})
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
})
|
|
190
|
-
|
|
191
|
-
const Post = table({
|
|
192
|
-
post: class {
|
|
193
|
-
id = column.integer.primaryKey()
|
|
194
|
-
userId = column.integer.references(() => User.id)
|
|
195
|
-
content = column.string
|
|
196
|
-
|
|
197
|
-
author() {
|
|
198
|
-
return User({id: this.userId}).first()
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
tags() {
|
|
202
|
-
return Tag({id: PostTags.tagId}).innerJoin(PostTags({postId: this.id}))
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
})
|
|
206
|
-
|
|
207
|
-
const Tag = table({
|
|
208
|
-
tag: class {
|
|
209
|
-
id = column.integer.primaryKey()
|
|
210
|
-
name = column.string
|
|
211
|
-
}
|
|
212
|
-
})
|
|
213
|
-
|
|
214
|
-
const PostTags = table({
|
|
215
|
-
post_tag: class {
|
|
216
|
-
postId = column.integer.references(() => Post.id)
|
|
217
|
-
tagId = column.integer.references(() => Tag.id)
|
|
218
|
-
}
|
|
219
|
-
})
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Connections
|
|
223
|
-
|
|
224
|
-
Currently supported SQLite drivers:
|
|
225
|
-
`better-sqlite3`, `sql.js`, `sqlite3`, `bun:sqlite`
|
|
226
|
-
|
|
227
|
-
Pass an instance of the database to the `connect` function to get started:
|
|
228
|
-
|
|
229
|
-
```ts
|
|
230
|
-
import Database from 'better-sqlite3'
|
|
231
|
-
import {connect} from 'rado/driver/better-sqlite3'
|
|
232
|
-
|
|
233
|
-
const db = connect(new Database('foobar.db'))
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
Currently all drivers are synchronous except for the `sqlite3` driver which is
|
|
237
|
-
async.
|
|
238
|
-
|
|
239
|
-
#### Run queries
|
|
240
|
-
|
|
241
|
-
Call the connection with a query to retrieve its results:
|
|
242
|
-
|
|
243
|
-
```ts
|
|
244
|
-
const posts = db(Post())
|
|
245
|
-
// For async drivers this will be a Promise:
|
|
246
|
-
const posts = await db(Post())
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
#### Iterate results
|
|
250
|
-
|
|
251
|
-
Iterate over query results:
|
|
252
|
-
|
|
253
|
-
```ts
|
|
254
|
-
const allPosts = Post()
|
|
255
|
-
for (const row of db.iterate(allPosts)) {
|
|
256
|
-
console.log(row)
|
|
257
|
-
}
|
|
258
|
-
// For async drivers:
|
|
259
|
-
for await (const row of db.iterate(allPosts)) {
|
|
260
|
-
console.log(row)
|
|
261
|
-
}
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
#### Transactions
|
|
265
|
-
|
|
266
|
-
Run transactions within the `transaction` method which will isolate a connection
|
|
267
|
-
and can optionally return a result:
|
|
268
|
-
|
|
269
|
-
```ts
|
|
270
|
-
const firstUserId = db.transaction(tx => {
|
|
271
|
-
const createTable = User().create()
|
|
272
|
-
tx(createTable)
|
|
273
|
-
const insertUser = User().insertOne({username: 'Mario'})
|
|
274
|
-
tx(insertUser)
|
|
275
|
-
return insertUser.id
|
|
276
|
-
})
|
|
277
|
-
```
|
|
1
|
+
[](https://npmjs.org/package/rado)
|
|
2
|
+
|
|
3
|
+
# rado
|
|
4
|
+
|
|
5
|
+
Fully typed, lightweight TypeScript query builder.
|
|
6
|
+
Currently focused on SQLite.
|
|
7
|
+
|
|
8
|
+
- Definition via TypeScript types
|
|
9
|
+
- Composable queries
|
|
10
|
+
- Aggregate rows in selects
|
|
11
|
+
- First class JSON columns
|
|
12
|
+
- No code generation step
|
|
13
|
+
- No dependencies
|
|
14
|
+
|
|
15
|
+
<pre>npm install <a href="https://www.npmjs.com/package/rado">rado</a></pre>
|
|
16
|
+
|
|
17
|
+
## Queries
|
|
18
|
+
|
|
19
|
+
#### Where
|
|
20
|
+
|
|
21
|
+
Conditions can be created by accessing the fields of the table
|
|
22
|
+
instances and using the operators of `Expr`:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
User.id // This is an Expr<number> which has an `is` method to compare
|
|
26
|
+
User.id.is(1) // Compare with a value, results in an Expr<boolean>
|
|
27
|
+
User.id.is(Post.userId) // Compare to fields on other tables
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Rows can be selected by passing the condition in the where method:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// Call a table instance to start a query selecting from that table
|
|
34
|
+
User().where(User.id.is(1))
|
|
35
|
+
// Conditions can be as complex as you want
|
|
36
|
+
User().where(User.id.isGreater(1).and(User.id.isLess(5)))
|
|
37
|
+
// `And` conditions can also be comma separated in `where` to improve readability
|
|
38
|
+
User().where(User.id.isGreater(1), User.id.isLess(5))
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
There's a shortcut for comparing columns of a table directly in its call.
|
|
42
|
+
The first comparison above can be simplified to:
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
User({id: 1}) // Is the same as User().where(User.id.is(1))
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
This comes in handy when joining tables too:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
User({id: 1}).innerJoin(Post({userId: User.id}))
|
|
52
|
+
// Is equal to:
|
|
53
|
+
User().innerJoin(Post, Post.userId.is(User.id)).where(User.id.is(1))
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
#### Select
|
|
57
|
+
|
|
58
|
+
Retrieve a single field
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
User().select(User.name)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or an object of data
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
User().select({
|
|
68
|
+
...User, // Get all user fields: id, username
|
|
69
|
+
posts: Post({userId: User.id}) // Aggregate posts of this user
|
|
70
|
+
})
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
You can call the `posts` helper method defined in the example schema below
|
|
74
|
+
to achieve the same:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
User().select({
|
|
78
|
+
...User,
|
|
79
|
+
posts: User.posts()
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Retrieve all posts with their author and tags and count the tag usage in other
|
|
84
|
+
posts:
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import {count} from 'rado/sqlite'
|
|
88
|
+
// Alias tables using `as`
|
|
89
|
+
const pt = PostTags().as('pt')
|
|
90
|
+
Post().select({
|
|
91
|
+
...Post,
|
|
92
|
+
author: Post.author().select(User.username),
|
|
93
|
+
tags: Post.tags().select({
|
|
94
|
+
count: pt({tagId: Tag.id}).select(count()).first(),
|
|
95
|
+
name: Tag.name
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Join other tables and select fields from either table:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
User({id: 1}).innerJoin(Post({userId: User.id})).select({
|
|
104
|
+
username: User.username
|
|
105
|
+
post: Post
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Create expressions to select complex values:
|
|
110
|
+
|
|
111
|
+
```ts
|
|
112
|
+
import {iif} from 'rado/sqlite'
|
|
113
|
+
Person().select({
|
|
114
|
+
name: Person.firstName.concat(' ').concat(Person.lastName),
|
|
115
|
+
isMario: Person.firstName.is('Mario'),
|
|
116
|
+
isActor: Person.id.isIn(Actor().select(Actor.personId)),
|
|
117
|
+
email: iif(Person.email.isNotNull(), Person.email, 'its.me@mario'),
|
|
118
|
+
twitterHandle: Person.socialMedia
|
|
119
|
+
.filter(media => media.type.is('twitter'))
|
|
120
|
+
.map(media => media.handle)
|
|
121
|
+
.maybeFirst()
|
|
122
|
+
})
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Order, group, limit queries:
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
User()
|
|
129
|
+
.orderBy(User.username.asc())
|
|
130
|
+
.groupBy(User.id, User.username)
|
|
131
|
+
.skip(20)
|
|
132
|
+
.take(10)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Insert
|
|
136
|
+
|
|
137
|
+
Insert a single row and return the result:
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
User().insertOne({username: 'Mario'})
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Insert multiple rows:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
User().insertAll([{username: 'Mario'}, {username: 'Luigi'}])
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
#### Update
|
|
150
|
+
|
|
151
|
+
Set values
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
User({id: 1}).set({username: 'Bowser'})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Use expressions to update complex values:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
User()
|
|
161
|
+
.set({username: User.username.concat(' [removed]')})
|
|
162
|
+
.where(User.deleted)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
#### Delete
|
|
166
|
+
|
|
167
|
+
Delete rows
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
User({id: 1}).delete()
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
## Schema definition
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
import {table, column} from 'rado'
|
|
177
|
+
|
|
178
|
+
const User = table({
|
|
179
|
+
// Pass a definition under a key with the actual name of the table in database
|
|
180
|
+
user: class {
|
|
181
|
+
id = column.integer.primaryKey()
|
|
182
|
+
username = column.string
|
|
183
|
+
|
|
184
|
+
// Define helper methods directly on the model
|
|
185
|
+
posts() {
|
|
186
|
+
return Post({userId: this.id})
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
const Post = table({
|
|
192
|
+
post: class {
|
|
193
|
+
id = column.integer.primaryKey()
|
|
194
|
+
userId = column.integer.references(() => User.id)
|
|
195
|
+
content = column.string
|
|
196
|
+
|
|
197
|
+
author() {
|
|
198
|
+
return User({id: this.userId}).first()
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
tags() {
|
|
202
|
+
return Tag({id: PostTags.tagId}).innerJoin(PostTags({postId: this.id}))
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
const Tag = table({
|
|
208
|
+
tag: class {
|
|
209
|
+
id = column.integer.primaryKey()
|
|
210
|
+
name = column.string
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
const PostTags = table({
|
|
215
|
+
post_tag: class {
|
|
216
|
+
postId = column.integer.references(() => Post.id)
|
|
217
|
+
tagId = column.integer.references(() => Tag.id)
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Connections
|
|
223
|
+
|
|
224
|
+
Currently supported SQLite drivers:
|
|
225
|
+
`better-sqlite3`, `sql.js`, `sqlite3`, `bun:sqlite`
|
|
226
|
+
|
|
227
|
+
Pass an instance of the database to the `connect` function to get started:
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import Database from 'better-sqlite3'
|
|
231
|
+
import {connect} from 'rado/driver/better-sqlite3'
|
|
232
|
+
|
|
233
|
+
const db = connect(new Database('foobar.db'))
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Currently all drivers are synchronous except for the `sqlite3` driver which is
|
|
237
|
+
async.
|
|
238
|
+
|
|
239
|
+
#### Run queries
|
|
240
|
+
|
|
241
|
+
Call the connection with a query to retrieve its results:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
const posts = db(Post())
|
|
245
|
+
// For async drivers this will be a Promise:
|
|
246
|
+
const posts = await db(Post())
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
#### Iterate results
|
|
250
|
+
|
|
251
|
+
Iterate over query results:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
const allPosts = Post()
|
|
255
|
+
for (const row of db.iterate(allPosts)) {
|
|
256
|
+
console.log(row)
|
|
257
|
+
}
|
|
258
|
+
// For async drivers:
|
|
259
|
+
for await (const row of db.iterate(allPosts)) {
|
|
260
|
+
console.log(row)
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
#### Transactions
|
|
265
|
+
|
|
266
|
+
Run transactions within the `transaction` method which will isolate a connection
|
|
267
|
+
and can optionally return a result:
|
|
268
|
+
|
|
269
|
+
```ts
|
|
270
|
+
const firstUserId = db.transaction(tx => {
|
|
271
|
+
const createTable = User().create()
|
|
272
|
+
tx(createTable)
|
|
273
|
+
const insertUser = User().insertOne({username: 'Mario'})
|
|
274
|
+
tx(insertUser)
|
|
275
|
+
return insertUser.id
|
|
276
|
+
})
|
|
277
|
+
```
|
|
@@ -8,6 +8,7 @@ export declare class BetterSqlite3Driver extends Driver.Sync {
|
|
|
8
8
|
tableData: (tableName: string) => Array<SqliteSchema.Column>;
|
|
9
9
|
indexData: (tableName: string) => Array<SqliteSchema.Index>;
|
|
10
10
|
constructor(db: Database, options?: DriverOptions);
|
|
11
|
+
close(): void;
|
|
11
12
|
prepareStatement(stmt: Statement): Driver.Sync.PreparedStatement;
|
|
12
13
|
schemaInstructions(tableName: string): SchemaInstructions | undefined;
|
|
13
14
|
export(): Uint8Array;
|
|
@@ -12,6 +12,7 @@ export declare class BunSqliteDriver extends Driver.Sync {
|
|
|
12
12
|
rowsAffected: number;
|
|
13
13
|
};
|
|
14
14
|
constructor(db: Database, options?: DriverOptions);
|
|
15
|
+
close(): void;
|
|
15
16
|
prepareStatement(stmt: Statement): Driver.Sync.PreparedStatement;
|
|
16
17
|
schemaInstructions(tableName: string): SchemaInstructions | undefined;
|
|
17
18
|
}
|
package/dist/driver/sql.js.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class SqlJsDriver extends Driver.Sync {
|
|
|
8
8
|
tableData?: (tableName: string) => Array<SqliteSchema.Column>;
|
|
9
9
|
indexData?: (tableName: string) => Array<SqliteSchema.Index>;
|
|
10
10
|
constructor(db: Database, options?: DriverOptions);
|
|
11
|
+
close(): void;
|
|
11
12
|
prepareStatement(stmt: Statement, discardAfter: boolean): Driver.Sync.PreparedStatement;
|
|
12
13
|
schemaInstructions(tableName: string): SchemaInstructions | undefined;
|
|
13
14
|
export(): Uint8Array;
|
package/dist/driver/sql.js.js
CHANGED
package/dist/driver/sqlite3.d.ts
CHANGED
|
@@ -14,5 +14,6 @@ export declare class Sqlite3Driver extends Driver.Async {
|
|
|
14
14
|
prepareStatement(stmt: Statement): Driver.Async.PreparedStatement;
|
|
15
15
|
schemaInstructions(tableName: string): Promise<SchemaInstructions | undefined>;
|
|
16
16
|
isolate(): [connection: Driver.Async, release: () => Promise<void>];
|
|
17
|
+
close(): Promise<void>;
|
|
17
18
|
}
|
|
18
19
|
export declare function connect(db: Database, options?: DriverOptions): Sqlite3Driver;
|
package/dist/driver/sqlite3.js
CHANGED
|
@@ -109,6 +109,17 @@ class Sqlite3Driver extends Driver.Async {
|
|
|
109
109
|
this.lock = Promise.resolve(this.lock).then(() => trigger);
|
|
110
110
|
return [connection, release];
|
|
111
111
|
}
|
|
112
|
+
async close() {
|
|
113
|
+
await this.lock;
|
|
114
|
+
return new Promise((resolve, reject) => {
|
|
115
|
+
this.db.close((err) => {
|
|
116
|
+
if (err)
|
|
117
|
+
reject(err);
|
|
118
|
+
else
|
|
119
|
+
resolve();
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
112
123
|
}
|
|
113
124
|
function connect(db, options) {
|
|
114
125
|
return new Sqlite3Driver(db, options);
|
package/dist/lib/Driver.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ interface SyncDriver {
|
|
|
29
29
|
declare abstract class SyncDriver extends DriverBase {
|
|
30
30
|
transactionId: number;
|
|
31
31
|
constructor(formatter: Formatter, options?: DriverOptions);
|
|
32
|
+
abstract close(): void;
|
|
32
33
|
abstract prepareStatement(stmt: Statement, discardAfter: boolean): SyncPreparedStatement;
|
|
33
34
|
abstract schemaInstructions(tableName: string): SchemaInstructions | undefined;
|
|
34
35
|
createStatement(stmt: Statement, discardAfter: boolean): SyncPreparedStatement;
|
|
@@ -57,6 +58,7 @@ interface AsyncDriver {
|
|
|
57
58
|
declare abstract class AsyncDriver extends DriverBase {
|
|
58
59
|
transactionId: number;
|
|
59
60
|
constructor(formatter: Formatter, options?: DriverOptions);
|
|
61
|
+
abstract close(): Promise<void>;
|
|
60
62
|
abstract isolate(): [connection: AsyncDriver, release: () => Promise<void>];
|
|
61
63
|
abstract prepareStatement(stmt: Statement, discardAfter: boolean): AsyncPreparedStatement;
|
|
62
64
|
abstract schemaInstructions(tableName: string): Promise<SchemaInstructions | undefined>;
|
|
@@ -72,6 +74,7 @@ declare class SyncWrapper extends AsyncDriver {
|
|
|
72
74
|
private sync;
|
|
73
75
|
lock: Promise<void> | undefined;
|
|
74
76
|
constructor(sync: SyncDriver);
|
|
77
|
+
close(): Promise<void>;
|
|
75
78
|
executeQuery(query: QueryData, stmt?: AsyncPreparedStatement, params?: Array<any>): Promise<unknown>;
|
|
76
79
|
prepareStatement(stmt: Statement, discardAfter: boolean): AsyncPreparedStatement;
|
|
77
80
|
schemaInstructions(tableName: string): Promise<SchemaInstructions | undefined>;
|
package/dist/lib/Driver.js
CHANGED