@atscript/db-sqlite 0.1.37 → 0.1.39
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 +29 -183
- package/dist/index.cjs +281 -295
- package/dist/index.d.ts +39 -6
- package/dist/index.mjs +287 -308
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://atscript.moost.org/logo.svg" alt="Atscript" width="120" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">@atscript/db-sqlite</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Define your models once</strong> — get TypeScript types, runtime validation, and DB metadata from a single <code>.as</code> model.
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
│ │
|
|
13
|
-
BetterSqlite3Driver (your own driver)
|
|
14
|
-
(ships with package) node:sqlite
|
|
15
|
-
sql.js, etc.
|
|
16
|
-
```
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://atscript.moost.org">Documentation</a> · <a href="https://atscript.moost.org/db/adapters/sqlite">SQLite Adapter</a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
---
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
SQLite adapter for `@atscript/db` with a swappable driver architecture. Ships with a `BetterSqlite3Driver` for `better-sqlite3` and supports custom drivers for `node:sqlite` (Node 22.5+), `sql.js`, or any other SQLite engine.
|
|
19
18
|
|
|
20
19
|
## Installation
|
|
21
20
|
|
|
@@ -23,186 +22,33 @@ The adapter defines a minimal `TSqliteDriver` interface — just raw SQL primiti
|
|
|
23
22
|
pnpm add @atscript/db-sqlite better-sqlite3
|
|
24
23
|
```
|
|
25
24
|
|
|
26
|
-
`better-sqlite3` is an **optional peer dependency** — only required if you use the built-in `BetterSqlite3Driver`. Bring your own driver if you prefer a different engine.
|
|
27
|
-
|
|
28
25
|
## Quick Start
|
|
29
26
|
|
|
30
27
|
```typescript
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import { User } from './user.as'
|
|
34
|
-
|
|
35
|
-
// 1. Create a driver (in-memory or file-based)
|
|
36
|
-
const driver = new BetterSqlite3Driver(':memory:')
|
|
37
|
-
// or: new BetterSqlite3Driver('./data.db')
|
|
28
|
+
import { DbSpace } from '@atscript/db'
|
|
29
|
+
import { createAdapter } from '@atscript/db-sqlite'
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const users = new AtscriptDbTable(User, adapter)
|
|
31
|
+
const db = createAdapter('./myapp.db')
|
|
32
|
+
const users = db.getTable(UsersType)
|
|
42
33
|
|
|
43
|
-
// 3. Set up schema
|
|
44
|
-
await users.ensureTable() // CREATE TABLE IF NOT EXISTS
|
|
45
|
-
await users.syncIndexes() // CREATE INDEX / DROP INDEX
|
|
46
|
-
|
|
47
|
-
// 4. CRUD
|
|
48
34
|
await users.insertOne({ name: 'John', email: 'john@example.com' })
|
|
49
|
-
const john = await users.findOne({ name: 'John' })
|
|
50
|
-
await users.findMany({ status: 'active' }, { limit: 10, sort: { name: 1 } })
|
|
51
|
-
await users.count({ status: 'active' })
|
|
52
|
-
await users.updateMany({ status: 'inactive' }, { status: 'archived' })
|
|
53
|
-
await users.deleteOne(123)
|
|
54
|
-
await users.deleteMany({ status: 'archived' })
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
## Swapping the Driver
|
|
58
|
-
|
|
59
|
-
The `TSqliteDriver` interface is minimal — implement these 5 methods:
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
interface TSqliteDriver {
|
|
63
|
-
run(sql: string, params?: unknown[]): TSqliteRunResult
|
|
64
|
-
all<T>(sql: string, params?: unknown[]): T[]
|
|
65
|
-
get<T>(sql: string, params?: unknown[]): T | null
|
|
66
|
-
exec(sql: string): void
|
|
67
|
-
close(): void
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
interface TSqliteRunResult {
|
|
71
|
-
changes: number
|
|
72
|
-
lastInsertRowid: number | bigint
|
|
73
|
-
}
|
|
74
35
|
```
|
|
75
36
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
```typescript
|
|
79
|
-
import { SqliteAdapter, type TSqliteDriver } from '@atscript/db-sqlite'
|
|
80
|
-
|
|
81
|
-
class MyDriver implements TSqliteDriver {
|
|
82
|
-
run(sql: string, params?: unknown[]) {
|
|
83
|
-
// your implementation
|
|
84
|
-
return { changes: 0, lastInsertRowid: 0 }
|
|
85
|
-
}
|
|
86
|
-
all(sql: string, params?: unknown[]) { /* ... */ }
|
|
87
|
-
get(sql: string, params?: unknown[]) { /* ... */ }
|
|
88
|
-
exec(sql: string) { /* ... */ }
|
|
89
|
-
close() { /* ... */ }
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const adapter = new SqliteAdapter(new MyDriver())
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Example: node:sqlite (Node 22.5+)
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
import { DatabaseSync } from 'node:sqlite'
|
|
99
|
-
import { SqliteAdapter, type TSqliteDriver } from '@atscript/db-sqlite'
|
|
100
|
-
|
|
101
|
-
class NodeSqliteDriver implements TSqliteDriver {
|
|
102
|
-
private db: DatabaseSync
|
|
103
|
-
|
|
104
|
-
constructor(path: string) {
|
|
105
|
-
this.db = new DatabaseSync(path)
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
run(sql: string, params?: unknown[]) {
|
|
109
|
-
const stmt = this.db.prepare(sql)
|
|
110
|
-
stmt.run(...(params ?? []))
|
|
111
|
-
return {
|
|
112
|
-
changes: this.db.changes,
|
|
113
|
-
lastInsertRowid: this.db.lastInsertRowId,
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
all<T>(sql: string, params?: unknown[]): T[] {
|
|
118
|
-
return this.db.prepare(sql).all(...(params ?? [])) as T[]
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
get<T>(sql: string, params?: unknown[]): T | null {
|
|
122
|
-
return (this.db.prepare(sql).get(...(params ?? [])) as T) ?? null
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
exec(sql: string) { this.db.exec(sql) }
|
|
126
|
-
close() { this.db.close() }
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const adapter = new SqliteAdapter(new NodeSqliteDriver(':memory:'))
|
|
130
|
-
```
|
|
37
|
+
## Features
|
|
131
38
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
| `{ field: { $gt: 5 } }` | `field > ?` |
|
|
140
|
-
| `{ field: { $gte: 5 } }` | `field >= ?` |
|
|
141
|
-
| `{ field: { $lt: 5 } }` | `field < ?` |
|
|
142
|
-
| `{ field: { $lte: 5 } }` | `field <= ?` |
|
|
143
|
-
| `{ field: { $ne: value } }` | `field != ?` |
|
|
144
|
-
| `{ field: { $in: [1, 2] } }` | `field IN (?, ?)` |
|
|
145
|
-
| `{ field: { $nin: [1, 2] } }` | `field NOT IN (?, ?)` |
|
|
146
|
-
| `{ field: { $exists: true } }` | `field IS NOT NULL` |
|
|
147
|
-
| `{ field: { $regex: '^abc' } }` | `field LIKE 'abc%'` |
|
|
148
|
-
| `{ $and: [...] }` | `(... AND ...)` |
|
|
149
|
-
| `{ $or: [...] }` | `(... OR ...)` |
|
|
150
|
-
| `{ $not: {...} }` | `NOT (...)` |
|
|
151
|
-
|
|
152
|
-
All values are parameterized — no SQL injection risk.
|
|
153
|
-
|
|
154
|
-
## Schema Operations
|
|
155
|
-
|
|
156
|
-
### `ensureTable()`
|
|
157
|
-
|
|
158
|
-
Generates `CREATE TABLE IF NOT EXISTS` from the Atscript type:
|
|
159
|
-
- Column types inferred from `designType` (`string` → TEXT, `number` → REAL, `boolean` → INTEGER)
|
|
160
|
-
- Primary keys from `@meta.id`
|
|
161
|
-
- `NOT NULL` for required fields
|
|
162
|
-
- `@db.column` mappings applied (logical → physical column names)
|
|
163
|
-
- `@db.ignore` fields excluded
|
|
164
|
-
|
|
165
|
-
### `syncIndexes()`
|
|
166
|
-
|
|
167
|
-
Compares existing indexes with `@db.index.*` annotations:
|
|
168
|
-
- Creates missing indexes (`CREATE INDEX` / `CREATE UNIQUE INDEX`)
|
|
169
|
-
- Drops stale indexes no longer in the definition
|
|
170
|
-
- Supports `@db.index.plain`, `@db.index.unique`
|
|
171
|
-
- `@db.index.fulltext` is skipped (requires FTS5 virtual tables — not auto-managed)
|
|
172
|
-
|
|
173
|
-
## Write Pipeline
|
|
174
|
-
|
|
175
|
-
When you call `insertOne(payload)`, `AtscriptDbTable` automatically:
|
|
176
|
-
|
|
177
|
-
1. Applies `@db.default` defaults for missing fields
|
|
178
|
-
2. Validates against the Atscript type
|
|
179
|
-
3. Strips `@db.ignore` fields
|
|
180
|
-
4. Maps `@db.column` logical names to physical column names
|
|
181
|
-
5. Delegates to `SqliteAdapter.insertOne()` which generates and runs the SQL
|
|
182
|
-
|
|
183
|
-
## Exports
|
|
184
|
-
|
|
185
|
-
```typescript
|
|
186
|
-
// Classes
|
|
187
|
-
export { SqliteAdapter } from './sqlite-adapter'
|
|
188
|
-
export { BetterSqlite3Driver } from './better-sqlite3-driver'
|
|
189
|
-
|
|
190
|
-
// Utilities
|
|
191
|
-
export { buildWhere } from './filter-builder'
|
|
192
|
-
|
|
193
|
-
// Types
|
|
194
|
-
export type { TSqliteDriver, TSqliteRunResult } from './types'
|
|
195
|
-
export type { TSqlFragment } from './filter-builder'
|
|
196
|
-
```
|
|
39
|
+
- Swappable driver via `TSqliteDriver` interface (5 methods)
|
|
40
|
+
- Built-in `BetterSqlite3Driver` for immediate use
|
|
41
|
+
- MongoDB-style filter translation to parameterized SQL (no injection risk)
|
|
42
|
+
- Automatic schema management from `@db.*` annotations
|
|
43
|
+
- FTS5 full-text search support
|
|
44
|
+
- Embedded object flattening and `@db.json` storage
|
|
45
|
+
- Schema sync via `@atscript/db/sync`
|
|
197
46
|
|
|
198
|
-
##
|
|
47
|
+
## Documentation
|
|
199
48
|
|
|
200
|
-
|
|
201
|
-
-
|
|
202
|
-
- `better-sqlite3` and `node:sqlite` are both synchronous
|
|
203
|
-
- The `SqliteAdapter` wraps sync calls in promises for the async `BaseDbAdapter` contract
|
|
204
|
-
- For truly async drivers, implement the interface with a synchronous wrapper or create a custom adapter subclass
|
|
49
|
+
- [SQLite Adapter Guide](https://atscript.moost.org/db/adapters/sqlite)
|
|
50
|
+
- [Full Documentation](https://atscript.moost.org)
|
|
205
51
|
|
|
206
52
|
## License
|
|
207
53
|
|
|
208
|
-
|
|
54
|
+
MIT
|