@type32/tauri-sqlite-orm 0.1.16 → 0.1.18-0
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 +109 -190
- package/dist/index.d.mts +131 -431
- package/dist/index.d.ts +131 -431
- package/dist/index.js +308 -1665
- package/dist/index.mjs +298 -1627
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
##
|
|
1
|
+
## Tauri SQLite ORM
|
|
2
2
|
|
|
3
|
-
A Drizzle-like TypeScript ORM tailored for Tauri v2's `@tauri-apps/plugin-sql` (SQLite).
|
|
3
|
+
A Drizzle-like TypeScript ORM tailored for Tauri v2's `@tauri-apps/plugin-sql` (SQLite). It provides a simple, type-safe query builder and migration tools to help you manage your database with ease.
|
|
4
4
|
|
|
5
|
-
###
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
- **Drizzle-like Schema:** Define your database schema using a familiar, chainable API.
|
|
8
|
+
- **Type-Safe Query Builder:** Build SQL queries with TypeScript, ensuring type safety and autocompletion.
|
|
9
|
+
- **Simplified Migrations:** Keep your database schema in sync with your application's models using automatic schema detection and migration tools.
|
|
10
|
+
- **Lightweight & Performant:** Designed to be a thin layer over the Tauri SQL plugin, ensuring minimal overhead.
|
|
11
|
+
|
|
12
|
+
### Installation
|
|
6
13
|
|
|
7
14
|
```bash
|
|
8
15
|
bun add @type32/tauri-sqlite-orm @tauri-apps/plugin-sql
|
|
@@ -10,243 +17,155 @@ bun add @type32/tauri-sqlite-orm @tauri-apps/plugin-sql
|
|
|
10
17
|
|
|
11
18
|
Make sure the SQL plugin is registered on the Rust side (see Tauri docs).
|
|
12
19
|
|
|
13
|
-
### Quick
|
|
20
|
+
### Quick Start
|
|
14
21
|
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
TauriORM,
|
|
18
|
-
defineTable,
|
|
19
|
-
integer,
|
|
20
|
-
text,
|
|
21
|
-
relations,
|
|
22
|
-
} from "tauri-sqlite-orm";
|
|
22
|
+
Here’s a quick example to get you started:
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
```typescript
|
|
25
|
+
// src/db/schema.ts
|
|
26
|
+
import { sqliteTable, text, integer } from "@type32/tauri-sqlite-orm";
|
|
25
27
|
|
|
26
|
-
export const users =
|
|
27
|
-
id: integer("id").primaryKey(
|
|
28
|
+
export const users = sqliteTable("users", {
|
|
29
|
+
id: integer("id").primaryKey().autoincrement(),
|
|
28
30
|
name: text("name").notNull(),
|
|
29
|
-
email: text("email"),
|
|
31
|
+
email: text("email").unique(),
|
|
30
32
|
});
|
|
31
33
|
|
|
32
|
-
export const posts =
|
|
34
|
+
export const posts = sqliteTable("posts", {
|
|
33
35
|
id: integer("id").primaryKey(),
|
|
34
36
|
content: text("content"),
|
|
35
|
-
|
|
36
|
-
authorId: integer("author_id"),
|
|
37
|
+
authorId: integer("author_id").references(() => users.id),
|
|
37
38
|
});
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
// src/db/index.ts
|
|
41
|
+
import { TauriORM } from "@type32/tauri-sqlite-orm";
|
|
42
|
+
import Database from "@tauri-apps/plugin-sql";
|
|
43
|
+
import * as schema from "./schema";
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
await
|
|
45
|
+
// Load the database
|
|
46
|
+
const dbInstance = await Database.load("sqlite:app.db");
|
|
45
47
|
|
|
46
|
-
// Create
|
|
47
|
-
|
|
48
|
-
.insert(users)
|
|
49
|
-
.values({ name: "Dan", email: "dan@example.com" })
|
|
50
|
-
.execute();
|
|
48
|
+
// Create the ORM instance
|
|
49
|
+
export const db = new TauriORM(dbInstance, schema);
|
|
51
50
|
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
51
|
+
// Migrate the database if the schema has changed
|
|
52
|
+
await db.migrateIfDirty();
|
|
53
|
+
|
|
54
|
+
// Now you can use the ORM to interact with your database
|
|
55
|
+
const newUser = await db
|
|
56
|
+
.insert(schema.users)
|
|
57
|
+
.values({ name: "John Doe", email: "john.doe@example.com" });
|
|
58
|
+
const allUsers = await db.select(schema.users).execute();
|
|
57
59
|
```
|
|
58
60
|
|
|
59
61
|
### Documentation
|
|
60
62
|
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- Indexes & Constraints: `docs/indexes-constraints.md`
|
|
71
|
-
- Migrations: `docs/migrations.md`
|
|
72
|
-
|
|
73
|
-
### Schema builder
|
|
74
|
-
|
|
75
|
-
Chainable, Drizzle-style:
|
|
76
|
-
|
|
77
|
-
```ts
|
|
78
|
-
import {
|
|
79
|
-
defineTable,
|
|
80
|
-
integer,
|
|
81
|
-
text,
|
|
82
|
-
real,
|
|
83
|
-
blob,
|
|
84
|
-
numeric,
|
|
85
|
-
sql,
|
|
86
|
-
} from "tauri-sqlite-orm";
|
|
87
|
-
|
|
88
|
-
type Data = { foo: string; bar: number };
|
|
89
|
-
|
|
90
|
-
export const example = defineTable("example", {
|
|
91
|
-
id: integer("id").primaryKey({ autoIncrement: true }),
|
|
92
|
-
isActive: integer("is_active", { mode: "boolean" }),
|
|
93
|
-
createdAt: integer("created_at", { mode: "timestamp" }).default(
|
|
94
|
-
sql`(strftime('%s','now'))`
|
|
95
|
-
),
|
|
96
|
-
rating: real("rating"),
|
|
97
|
-
status: text("status", { enum: ["active", "inactive"] as const }),
|
|
98
|
-
name: text("name").notNull().default("Anonymous"),
|
|
99
|
-
data: blob("data"),
|
|
100
|
-
jsonField: blob("json_field", { mode: "json" }).$type<Data>(),
|
|
101
|
-
bigCounter: blob("big_counter", { mode: "bigint" }),
|
|
102
|
-
valueNumeric: numeric("value_numeric"),
|
|
103
|
-
valueNumericNum: numeric("value_numeric_num", { mode: "number" }),
|
|
104
|
-
valueNumericBig: numeric("value_numeric_big", { mode: "bigint" }),
|
|
105
|
-
});
|
|
63
|
+
- [Getting Started](docs/getting-started.md)
|
|
64
|
+
- [Schema and Types](docs/schema-and-types.md)
|
|
65
|
+
- [CRUD Operations (SELECT)](docs/queries-select.md)
|
|
66
|
+
- [CRUD Operations (INSERT)](docs/crud-insert.md)
|
|
67
|
+
- [CRUD Operations (UPDATE)](docs/crud-update.md)
|
|
68
|
+
- [CRUD Operations (DELETE)](docs/crud-delete.md)
|
|
69
|
+
- [Migrations](docs/migrations.md)
|
|
70
|
+
- [Transactions](docs/transactions.md)
|
|
71
|
+
- [Relations](docs/relations.md)
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
userId: integer("user_id")
|
|
111
|
-
.references(() => users.id, { onDelete: "cascade" })
|
|
112
|
-
.notNull(),
|
|
113
|
-
});
|
|
114
|
-
```
|
|
73
|
+
### Schema Definition
|
|
74
|
+
|
|
75
|
+
Define your tables and columns using a chainable, Drizzle-style API.
|
|
115
76
|
|
|
116
|
-
|
|
77
|
+
```typescript
|
|
78
|
+
import { sqliteTable, text, integer, boolean } from "@type32/tauri-sqlite-orm";
|
|
117
79
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
80
|
+
export const users = sqliteTable("users", {
|
|
81
|
+
id: integer("id").primaryKey().autoincrement(),
|
|
82
|
+
name: text("name").notNull(),
|
|
83
|
+
email: text("email").unique(),
|
|
84
|
+
isActive: boolean("is_active").default(true),
|
|
85
|
+
createdAt: integer("created_at", { mode: "timestamp" }).$defaultFn(
|
|
86
|
+
() => new Date()
|
|
87
|
+
),
|
|
124
88
|
});
|
|
125
89
|
```
|
|
126
90
|
|
|
127
|
-
|
|
91
|
+
### CRUD Operations
|
|
128
92
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
Tracked simple migrations are part of the ORM instance:
|
|
93
|
+
Perform `CREATE`, `READ`, `UPDATE`, and `DELETE` operations using a type-safe query builder.
|
|
132
94
|
|
|
133
|
-
|
|
134
|
-
// one-off for specific tables
|
|
135
|
-
await db.migrate([users, posts], { name: "init:users,posts" });
|
|
95
|
+
**SELECT**
|
|
136
96
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
```
|
|
97
|
+
```typescript
|
|
98
|
+
import { eq, and } from "@type32/tauri-sqlite-orm";
|
|
140
99
|
|
|
141
|
-
|
|
100
|
+
// Select all users
|
|
101
|
+
const allUsers = await db.select(users).execute();
|
|
142
102
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
```ts
|
|
146
|
-
// Insert
|
|
147
|
-
await db.insert(users).values({ name: "Alice" }).execute();
|
|
148
|
-
await db
|
|
149
|
-
.insert(users)
|
|
150
|
-
.values([{ name: "A" }, { name: "B" }])
|
|
151
|
-
.execute();
|
|
103
|
+
// Select specific columns
|
|
104
|
+
const userNames = await db.select(users, ["name"]).execute();
|
|
152
105
|
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
.
|
|
157
|
-
.set({ email: "new@mail.com" })
|
|
158
|
-
.where(eq(users.id, 1))
|
|
106
|
+
// Use WHERE conditions
|
|
107
|
+
const activeUsers = await db
|
|
108
|
+
.select(users)
|
|
109
|
+
.where(eq(users.isActive, true))
|
|
159
110
|
.execute();
|
|
160
|
-
|
|
161
|
-
// Delete
|
|
162
|
-
await db.delete(users).where(eq(users.id, 2)).execute();
|
|
163
111
|
```
|
|
164
112
|
|
|
165
|
-
|
|
113
|
+
**INSERT**
|
|
166
114
|
|
|
167
|
-
```
|
|
168
|
-
|
|
115
|
+
```typescript
|
|
116
|
+
// Insert a single user
|
|
117
|
+
const newUser = await db
|
|
118
|
+
.insert(users)
|
|
119
|
+
.values({ name: "Jane Doe", email: "jane.doe@example.com" });
|
|
169
120
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
),
|
|
176
|
-
// Called on update when not explicitly set; if no default is provided, also used on insert
|
|
177
|
-
updatedAt: integer("updated_at", { mode: "timestamp" }).$onUpdateFn(
|
|
178
|
-
() => new Date()
|
|
179
|
-
),
|
|
180
|
-
token: text("token").$default(() => crypto.randomUUID()),
|
|
181
|
-
});
|
|
121
|
+
// Insert multiple users
|
|
122
|
+
await db.insert(users).values([
|
|
123
|
+
{ name: "Alice", email: "alice@example.com" },
|
|
124
|
+
{ name: "Bob", email: "bob@example.com" },
|
|
125
|
+
]);
|
|
182
126
|
```
|
|
183
127
|
|
|
184
|
-
|
|
128
|
+
**UPDATE**
|
|
185
129
|
|
|
186
|
-
|
|
130
|
+
```typescript
|
|
131
|
+
import { eq } from "@type32/tauri-sqlite-orm";
|
|
187
132
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
133
|
+
// Update a user's email
|
|
134
|
+
await db
|
|
135
|
+
.update(users)
|
|
136
|
+
.set({ email: "new.email@example.com" })
|
|
137
|
+
.where(eq(users.id, 1));
|
|
138
|
+
```
|
|
191
139
|
|
|
192
|
-
|
|
193
|
-
with: { posts: true },
|
|
194
|
-
join: true,
|
|
195
|
-
where: (users, { eq }) => eq(users.id, 1),
|
|
196
|
-
orderBy: (users, { asc }) => [asc(users.id)],
|
|
197
|
-
limit: 10,
|
|
198
|
-
offset: 0,
|
|
199
|
-
columns: { id: true, name: true },
|
|
200
|
-
});
|
|
140
|
+
**DELETE**
|
|
201
141
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
with: {
|
|
205
|
-
posts: {
|
|
206
|
-
with: { comments: true },
|
|
207
|
-
columns: ["id", "content"],
|
|
208
|
-
},
|
|
209
|
-
},
|
|
210
|
-
});
|
|
142
|
+
```typescript
|
|
143
|
+
import { eq } from "@type32/tauri-sqlite-orm";
|
|
211
144
|
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
where: (users, { eq }) => eq(users.id, 1),
|
|
215
|
-
});
|
|
145
|
+
// Delete a user
|
|
146
|
+
await db.delete(users).where(eq(users.id, 1));
|
|
216
147
|
```
|
|
217
148
|
|
|
218
|
-
|
|
149
|
+
### Migrations
|
|
219
150
|
|
|
220
|
-
|
|
221
|
-
- `orderBy` accepts typed helpers or a callback `(table, { asc, desc }) => [...]`.
|
|
222
|
-
- `columns` accepts string[] or object map of base table columns.
|
|
223
|
-
- `join: true` only for one-level `with` (flat). Nested uses batched selects.
|
|
151
|
+
The ORM includes a simple migration system that automatically detects schema changes and applies them to the database.
|
|
224
152
|
|
|
225
|
-
|
|
153
|
+
```typescript
|
|
154
|
+
// This will check if the schema has changed and run migrations if it has
|
|
155
|
+
await db.migrateIfDirty();
|
|
226
156
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
db.query.posts.findMany({
|
|
230
|
-
where: (posts, { eq }) => eq(posts.authorId, 1),
|
|
231
|
-
orderBy: (posts, { asc }) => [asc(posts.id)],
|
|
232
|
-
});
|
|
157
|
+
// You can also run migrations manually
|
|
158
|
+
await db.migrate();
|
|
233
159
|
```
|
|
234
160
|
|
|
235
|
-
###
|
|
236
|
-
|
|
237
|
-
Initialize in a client plugin and ensure a single ORM instance is created:
|
|
238
|
-
|
|
239
|
-
```ts
|
|
240
|
-
// plugins/orm.client.ts
|
|
241
|
-
import { TauriORM } from "tauri-sqlite-orm";
|
|
242
|
-
import { users, posts, usersRelations } from "@/lib/schema";
|
|
161
|
+
### Transactions
|
|
243
162
|
|
|
244
|
-
|
|
245
|
-
const db = new TauriORM("sqlite:app.db");
|
|
246
|
-
db.configure({ users, posts }, { users: usersRelations });
|
|
247
|
-
await db.migrateConfigured({ name: "init:users,posts" });
|
|
163
|
+
Run multiple database operations within a transaction to ensure atomicity.
|
|
248
164
|
|
|
249
|
-
|
|
165
|
+
```typescript
|
|
166
|
+
await db.transaction(async (tx) => {
|
|
167
|
+
await tx.insert(users).values({ name: "From Transaction" });
|
|
168
|
+
await tx.delete(users).where(eq(users.id, 1));
|
|
250
169
|
});
|
|
251
170
|
```
|
|
252
171
|
|