meadow-connection-sqlite 1.0.12 → 1.0.14

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/docs/api.md CHANGED
@@ -1,254 +1,15 @@
1
1
  # API Reference
2
2
 
3
- ## Class: MeadowConnectionSQLite
4
-
5
- Extends `fable-serviceproviderbase`. Manages a connection to a SQLite database file through the better-sqlite3 library.
6
-
7
- ### Constructor
8
-
9
- ```javascript
10
- new MeadowConnectionSQLite(pFable, pManifest, pServiceHash)
11
- ```
12
-
13
- | Parameter | Type | Description |
14
- |-----------|------|-------------|
15
- | `pFable` | object | A Fable instance |
16
- | `pManifest` | object | Service manifest / options (optional) |
17
- | `pServiceHash` | string | Service identifier |
18
-
19
- On construction:
20
-
21
- - Sets `serviceType` to `'MeadowConnectionSQLite'`
22
- - Sets `connected` to `false`
23
- - Reads `SQLiteFilePath` from `fable.settings.SQLite` if available
24
-
25
- The provider is not yet connected after construction — call `connectAsync()` to open the database.
26
-
27
- ---
28
-
29
- ## Properties
30
-
31
- ### connected
32
-
33
- Whether the database connection is open.
34
-
35
- **Type:** `boolean`
36
-
37
- ### db
38
-
39
- The raw `better-sqlite3` `Database` instance. Use this for all query operations. Returns `false` before `connectAsync()` is called.
40
-
41
- **Type:** `Database | false`
42
-
43
- ```javascript
44
- let tmpDB = _Fable.MeadowSQLiteProvider.db;
45
-
46
- // Synchronous query methods from better-sqlite3:
47
- tmpDB.prepare(sql).run(params); // INSERT, UPDATE, DELETE
48
- tmpDB.prepare(sql).get(params); // SELECT single row
49
- tmpDB.prepare(sql).all(params); // SELECT all rows
50
- tmpDB.exec(sql); // Execute raw SQL (multi-statement)
51
- tmpDB.transaction(fn); // Wrap a function in a transaction
52
- tmpDB.pragma(string); // Run a PRAGMA command
53
- tmpDB.close(); // Close the database
54
- ```
55
-
56
- ### SQLite
57
-
58
- Reference to the `better-sqlite3` module constructor. Useful for accessing type constants or creating additional database instances.
59
-
60
- **Type:** `function`
61
-
62
- ```javascript
63
- let tmpSQLiteConstructor = _Fable.MeadowSQLiteProvider.SQLite;
64
- ```
65
-
66
- ### serviceType
67
-
68
- Always `'MeadowConnectionSQLite'`.
69
-
70
- **Type:** `string`
71
-
72
- ---
73
-
74
- ## Methods
75
-
76
- ### connectAsync(fCallback)
77
-
78
- Open a connection to the SQLite database file specified in configuration.
79
-
80
- | Parameter | Type | Description |
81
- |-----------|------|-------------|
82
- | `fCallback` | function | Callback: `(error, database)` |
83
-
84
- **Behavior:**
85
-
86
- - If `SQLiteFilePath` is not configured, calls back with an error
87
- - If already connected, calls back immediately with the existing database (idempotent)
88
- - Creates the database file if it does not exist
89
- - Enables WAL (Write-Ahead Logging) journal mode for performance
90
- - Sets `this.connected = true` on success
91
-
92
- ```javascript
93
- _Fable.MeadowSQLiteProvider.connectAsync(
94
- (pError, pDatabase) =>
95
- {
96
- if (pError)
97
- {
98
- _Fable.log.error(`Connection failed: ${pError}`);
99
- return;
100
- }
101
-
102
- // pDatabase is the same as _Fable.MeadowSQLiteProvider.db
103
- pDatabase.exec('CREATE TABLE IF NOT EXISTS Test (id INTEGER PRIMARY KEY)');
104
- });
105
- ```
106
-
107
- ### connect()
108
-
109
- Synchronous wrapper that calls `connectAsync()` without a callback. Logs a warning about potential race conditions. Prefer `connectAsync()`.
110
-
111
- ---
112
-
113
- ## Configuration
114
-
115
- ### Fable Settings
116
-
117
- ```json
118
- {
119
- "SQLite":
120
- {
121
- "SQLiteFilePath": "./data/myapp.db"
122
- }
123
- }
124
- ```
125
-
126
- | Setting | Type | Required | Description |
127
- |---------|------|----------|-------------|
128
- | `SQLiteFilePath` | string | Yes | File path or `:memory:` for in-memory databases |
129
-
130
- Additional properties are passed through to the `better-sqlite3` constructor:
131
-
132
- | Option | Type | Default | Description |
133
- |--------|------|---------|-------------|
134
- | `readonly` | boolean | `false` | Open the database in read-only mode |
135
- | `fileMustExist` | boolean | `false` | Error if the file does not exist |
136
- | `timeout` | number | `5000` | Milliseconds to wait when the database is locked |
137
-
138
- ---
139
-
140
- ## Service Registration
141
-
142
- The provider integrates with Fable's service manager:
143
-
144
- ```javascript
145
- const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
146
-
147
- // Register the service type
148
- _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
149
-
150
- // Instantiate (optionally with per-instance options)
151
- _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider',
152
- {
153
- SQLiteFilePath: './data/alternate.db',
154
- readonly: true
155
- });
156
-
157
- // Access the provider
158
- _Fable.MeadowSQLiteProvider.connectAsync((pError) => { /* ... */ });
159
- ```
160
-
161
- Constructor options override Fable settings, allowing multiple providers with different configurations.
162
-
163
- ---
164
-
165
- ## better-sqlite3 Query API
166
-
167
- After connecting, all queries go through the `db` getter. Here is a quick reference for the better-sqlite3 methods you will use most:
168
-
169
- ### Execute Raw SQL
170
-
171
- ```javascript
172
- tmpDB.exec(`
173
- CREATE TABLE IF NOT EXISTS Book (
174
- IDBook INTEGER PRIMARY KEY AUTOINCREMENT,
175
- Title TEXT DEFAULT ''
176
- );
177
- CREATE INDEX IF NOT EXISTS idx_book_title ON Book(Title);
178
- `);
179
- ```
180
-
181
- `exec()` runs one or more SQL statements. It does not return data.
182
-
183
- ### Prepared Statements
184
-
185
- ```javascript
186
- let tmpStmt = tmpDB.prepare('SELECT * FROM Book WHERE Author = ?');
187
-
188
- // Single row
189
- let tmpRow = tmpStmt.get('Frank Herbert');
190
-
191
- // All rows
192
- let tmpRows = tmpStmt.all('Frank Herbert');
193
-
194
- // Modification
195
- let tmpInsert = tmpDB.prepare('INSERT INTO Book (Title, Author) VALUES (?, ?)');
196
- let tmpInfo = tmpInsert.run('Dune', 'Frank Herbert');
197
- // tmpInfo.changes = 1, tmpInfo.lastInsertRowid = 1
198
- ```
199
-
200
- ### Named Parameters
201
-
202
- ```javascript
203
- let tmpStmt = tmpDB.prepare('SELECT * FROM Book WHERE Author = @author AND YearPublished > @year');
204
- let tmpRows = tmpStmt.all({ author: 'Isaac Asimov', year: 1950 });
205
- ```
206
-
207
- ### Transactions
208
-
209
- ```javascript
210
- let tmpBulkInsert = tmpDB.transaction(
211
- (pBooks) =>
212
- {
213
- let tmpStmt = tmpDB.prepare('INSERT INTO Book (Title, Author) VALUES (?, ?)');
214
- for (let tmpBook of pBooks)
215
- {
216
- tmpStmt.run(tmpBook.Title, tmpBook.Author);
217
- }
218
- });
219
-
220
- // The entire array is inserted atomically
221
- tmpBulkInsert([
222
- { Title: 'Foundation', Author: 'Isaac Asimov' },
223
- { Title: 'Snow Crash', Author: 'Neal Stephenson' }
224
- ]);
225
- ```
226
-
227
- If any statement inside the transaction throws, the entire transaction is rolled back automatically.
228
-
229
- ### Close
230
-
231
- ```javascript
232
- tmpDB.close();
233
- ```
234
-
235
- ---
236
-
237
- ## Logging
238
-
239
- The provider logs connection events through the Fable logging system:
240
-
241
- | Event | Level | Message |
242
- |-------|-------|---------|
243
- | Connecting | `info` | `Meadow-Connection-SQLite connecting to file [path].` |
244
- | Connected | `info` | `Meadow-Connection-SQLite successfully connected to SQLite file [path].` |
245
- | Already connected | `error` | `...is already connected - skipping the second connect call.` |
246
- | Missing path | `error` | `...database file path is invalid; SQLiteFilePath must be in either...` |
247
- | Connection error | `error` | `...error connecting to SQLite file [path]: [error]` |
248
- | No callback | `error` | `...connect() called without a callback...` |
249
-
250
- ---
251
-
252
- ## Known Limitations
253
-
254
- - **No async queries** — better-sqlite3 is synchronous by design. For CPU-bound workloads, consider running queries in a worker thread.
3
+ The full API reference has moved to the [API Reference](api/reference.md) page.
4
+
5
+ ## Individual Function Documentation
6
+
7
+ - [connectAsync](api/connectAsync.md) -- Open the database and enable WAL (recommended)
8
+ - [connect](api/connect.md) -- Synchronous convenience wrapper
9
+ - [db](api/db.md) -- Access the better-sqlite3 Database instance
10
+ - [SQLite](api/SQLite.md) -- Access the better-sqlite3 module constructor
11
+ - [preparedStatement](api/preparedStatement.md) -- Database handle getter with connection guard
12
+ - [generateCreateTableStatement](api/generateCreateTableStatement.md) -- Generate CREATE TABLE DDL
13
+ - [createTable](api/createTable.md) -- Generate and execute CREATE TABLE
14
+ - [createTables](api/createTables.md) -- Create multiple tables from a schema
15
+ - [generateDropTableStatement](api/generateDropTableStatement.md) -- Generate DROP TABLE DDL
@@ -0,0 +1,250 @@
1
+ # Architecture & Design
2
+
3
+ Meadow Connection SQLite connects Fable applications to SQLite databases through the service provider pattern. This page illustrates the system architecture, connection lifecycle, query model, and how the provider fits into the Meadow ecosystem.
4
+
5
+ ---
6
+
7
+ ## System Architecture
8
+
9
+ ```mermaid
10
+ graph TB
11
+ App["Fable Application"]
12
+ Settings["fable.settings.SQLite"]
13
+ Provider["MeadowConnectionSQLite<br/>(Fable Service Provider)"]
14
+ BetterSQLite["better-sqlite3<br/>(Native C++ Bindings)"]
15
+ File["SQLite Database File<br/>or :memory:"]
16
+
17
+ App -->|"reads config"| Settings
18
+ App -->|"connectAsync()"| Provider
19
+ Provider -->|"new Database(path)"| BetterSQLite
20
+ BetterSQLite -->|"reads/writes"| File
21
+ Provider -->|".db getter"| BetterSQLite
22
+ Settings -->|"SQLiteFilePath"| Provider
23
+ ```
24
+
25
+ ---
26
+
27
+ ## Connection Lifecycle
28
+
29
+ ```mermaid
30
+ sequenceDiagram
31
+ participant App as Application
32
+ participant SM as ServiceManager
33
+ participant Provider as MeadowConnectionSQLite
34
+ participant BS3 as better-sqlite3
35
+ participant File as Database File
36
+
37
+ App->>SM: addServiceType('MeadowSQLiteProvider', lib)
38
+ App->>SM: instantiateServiceProvider('MeadowSQLiteProvider')
39
+ SM->>Provider: new MeadowConnectionSQLite(fable, manifest, hash)
40
+ Note over Provider: connected = false
41
+
42
+ App->>Provider: connectAsync(callback)
43
+
44
+ alt SQLiteFilePath missing
45
+ Provider-->>App: callback(error)
46
+ else Already connected
47
+ Provider-->>App: callback(null, existingDB)
48
+ else Normal connect
49
+ Provider->>BS3: new Database(filePath, options)
50
+ BS3->>File: Open or create file
51
+ File-->>BS3: File handle
52
+ BS3-->>Provider: Database instance
53
+ Provider->>BS3: pragma('journal_mode = WAL')
54
+ Note over Provider: connected = true
55
+ Provider-->>App: callback(null, database)
56
+ end
57
+ ```
58
+
59
+ ---
60
+
61
+ ## Synchronous Query Model
62
+
63
+ Unlike MySQL and MSSQL providers which use asynchronous APIs, the SQLite provider uses better-sqlite3's synchronous API. Every query blocks the event loop for the duration of the operation, but better-sqlite3's native C++ bindings make individual operations extremely fast.
64
+
65
+ ```mermaid
66
+ flowchart LR
67
+ subgraph "better-sqlite3 Synchronous API"
68
+ EXEC["db.exec(sql)<br/>DDL / multi-statement"]
69
+ PREP["db.prepare(sql)"]
70
+ RUN["stmt.run(params)<br/>→ { changes, lastInsertRowid }"]
71
+ GET["stmt.get(params)<br/>→ object | undefined"]
72
+ ALL["stmt.all(params)<br/>→ array of objects"]
73
+ TXN["db.transaction(fn)<br/>→ atomic wrapper"]
74
+ end
75
+
76
+ PREP --> RUN
77
+ PREP --> GET
78
+ PREP --> ALL
79
+
80
+ style EXEC fill:#e8f4e8
81
+ style RUN fill:#e8f0f8
82
+ style GET fill:#e8f0f8
83
+ style ALL fill:#e8f0f8
84
+ style TXN fill:#f8f0e8
85
+ ```
86
+
87
+ ### Query Method Selection
88
+
89
+ | Goal | Method | Returns |
90
+ |------|--------|---------|
91
+ | Create tables, run DDL | `db.exec(sql)` | nothing |
92
+ | INSERT / UPDATE / DELETE | `db.prepare(sql).run(...)` | `{ changes, lastInsertRowid }` |
93
+ | SELECT one row | `db.prepare(sql).get(...)` | object or `undefined` |
94
+ | SELECT multiple rows | `db.prepare(sql).all(...)` | array of objects |
95
+ | Atomic batch operations | `db.transaction(fn)(args)` | return value of `fn` |
96
+
97
+ ---
98
+
99
+ ## Connection Settings Flow
100
+
101
+ ```mermaid
102
+ flowchart TD
103
+ FS["fable.settings.SQLite.SQLiteFilePath"]
104
+ CO["Constructor Options.SQLiteFilePath"]
105
+ Provider["MeadowConnectionSQLite"]
106
+ Decision{{"Which source?"}}
107
+ Use["Use resolved SQLiteFilePath"]
108
+
109
+ FS --> Decision
110
+ CO --> Decision
111
+ Decision -->|"Options override Settings"| Use
112
+ Use --> Provider
113
+ ```
114
+
115
+ Settings priority:
116
+
117
+ 1. **Constructor options** — passed as the second argument to `instantiateServiceProvider()`
118
+ 2. **Fable settings** — `fable.settings.SQLite.SQLiteFilePath`
119
+
120
+ Constructor options take priority, allowing multiple provider instances with different database files.
121
+
122
+ ---
123
+
124
+ ## DDL Generation Flow
125
+
126
+ ```mermaid
127
+ flowchart LR
128
+ Schema["Meadow Table Schema<br/>{ TableName, Columns[] }"]
129
+ Gen["generateCreateTableStatement()"]
130
+ DDL["CREATE TABLE IF NOT EXISTS..."]
131
+ Exec["db.exec(ddl)"]
132
+ Table["SQLite Table"]
133
+
134
+ Schema --> Gen
135
+ Gen --> DDL
136
+ DDL --> Exec
137
+ Exec --> Table
138
+
139
+ style Schema fill:#f0f0f0
140
+ style DDL fill:#e8f4e8
141
+ style Table fill:#e8f0f8
142
+ ```
143
+
144
+ Each Meadow column type maps to a SQLite storage class:
145
+
146
+ | Meadow DataType | SQLite Column Definition |
147
+ |-----------------|--------------------------|
148
+ | `ID` | `INTEGER PRIMARY KEY AUTOINCREMENT` |
149
+ | `GUID` | `TEXT DEFAULT '00000000-0000-0000-0000-000000000000'` |
150
+ | `ForeignKey` | `INTEGER NOT NULL DEFAULT 0` |
151
+ | `Numeric` | `INTEGER NOT NULL DEFAULT 0` |
152
+ | `Decimal` | `REAL` |
153
+ | `String` | `TEXT NOT NULL DEFAULT ''` |
154
+ | `Text` | `TEXT` |
155
+ | `DateTime` | `TEXT` |
156
+ | `Boolean` | `INTEGER NOT NULL DEFAULT 0` |
157
+
158
+ See [Schema & Table Creation](schema.md) for full details.
159
+
160
+ ---
161
+
162
+ ## Connection Safety
163
+
164
+ ```mermaid
165
+ flowchart TD
166
+ Start["connectAsync() called"]
167
+ CheckPath{{"SQLiteFilePath<br/>configured?"}}
168
+ CheckConn{{"Already<br/>connected?"}}
169
+ Connect["Open database file"]
170
+ WAL["Enable WAL journaling"]
171
+ Done["callback(null, db)"]
172
+ ErrPath["callback(error)"]
173
+ ErrConn["Log error, callback(null, existingDB)"]
174
+
175
+ Start --> CheckPath
176
+ CheckPath -->|No| ErrPath
177
+ CheckPath -->|Yes| CheckConn
178
+ CheckConn -->|Yes| ErrConn
179
+ CheckConn -->|No| Connect
180
+ Connect --> WAL
181
+ WAL --> Done
182
+
183
+ style ErrPath fill:#f8e0e0
184
+ style ErrConn fill:#f8f0e0
185
+ style Done fill:#e0f8e0
186
+ ```
187
+
188
+ The provider guards against:
189
+
190
+ - **Missing file path** -- Returns an error immediately if `SQLiteFilePath` is not configured
191
+ - **Double connect** -- Logs an error and returns the existing database if already connected
192
+ - **File creation** -- The database file is created automatically by better-sqlite3 if it does not exist
193
+
194
+ ---
195
+
196
+ ## Meadow Ecosystem Integration
197
+
198
+ ```mermaid
199
+ sequenceDiagram
200
+ participant App as Application
201
+ participant Meadow as Meadow ORM
202
+ participant FH as FoxHound
203
+ participant Provider as SQLite Provider
204
+ participant BS3 as better-sqlite3
205
+ participant File as .db File
206
+
207
+ App->>Provider: connectAsync()
208
+ Provider->>BS3: new Database(path)
209
+ BS3->>File: Open / create
210
+ Provider-->>App: Connected
211
+
212
+ App->>Meadow: new Meadow(fable, 'Entity')
213
+ App->>Meadow: setProvider('ALASQL')
214
+ App->>Meadow: setSchema(columns)
215
+
216
+ Note over App,Provider: For schema DDL
217
+ App->>Provider: createTable(schema)
218
+ Provider->>Provider: generateCreateTableStatement()
219
+ Provider->>BS3: db.exec(ddl)
220
+
221
+ Note over App,Provider: For direct queries
222
+ App->>Provider: .db getter
223
+ Provider-->>App: Database instance
224
+ App->>BS3: prepare(sql).all()
225
+ BS3-->>App: Results
226
+ ```
227
+
228
+ The SQLite connection provider serves two roles in the Meadow ecosystem:
229
+
230
+ 1. **Schema DDL** -- Generates and executes `CREATE TABLE` statements from Meadow table schemas
231
+ 2. **Direct query access** -- Exposes the `better-sqlite3` database for synchronous query execution
232
+
233
+ ---
234
+
235
+ ## Connector Comparison
236
+
237
+ | Feature | SQLite | MySQL | MSSQL | RocksDB |
238
+ |---------|--------|-------|-------|---------|
239
+ | **Server Required** | No | Yes | Yes | No |
240
+ | **Query API** | Synchronous | Async (callback) | Async (Promise) | Async (callback) |
241
+ | **File-based** | Yes | No | No | Yes |
242
+ | **In-memory mode** | `:memory:` | No | No | No |
243
+ | **WAL journaling** | Auto-enabled | N/A | N/A | Built-in |
244
+ | **Native driver** | better-sqlite3 | mysql2 | mssql (Tedious) | @nxtedition/rocksdb |
245
+ | **Connection pooling** | No (single file) | Yes | Yes | No (single handle) |
246
+ | **DDL generation** | Yes | Yes | Yes | No |
247
+ | **Prepared statements** | `db.prepare()` | Via pool | `ps.prepare()` | N/A |
248
+ | **Transactions** | `db.transaction(fn)` | Via pool | Via pool | Batch writes |
249
+ | **SQL support** | Full SQLite SQL | Full MySQL SQL | Full T-SQL | Key-value only |
250
+ | **Best for** | Local, embedded, test | Production servers | Enterprise | High-throughput KV |
@@ -0,0 +1,197 @@
1
+ # Quickstart
2
+
3
+ Get a SQLite database connected and running in five steps.
4
+
5
+ ---
6
+
7
+ ## Step 1 — Install
8
+
9
+ ```bash
10
+ npm install meadow-connection-sqlite fable
11
+ ```
12
+
13
+ `better-sqlite3` compiles a native addon at install time. A C/C++ toolchain must be available on the host (GCC, Clang, or MSVC).
14
+
15
+ ---
16
+
17
+ ## Step 2 — Configure and Connect
18
+
19
+ ```javascript
20
+ const libFable = require('fable');
21
+ const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
22
+
23
+ let _Fable = new libFable(
24
+ {
25
+ "Product": "BookstoreApp",
26
+ "ProductVersion": "1.0.0",
27
+ "SQLite":
28
+ {
29
+ "SQLiteFilePath": "./data/bookstore.db"
30
+ }
31
+ });
32
+
33
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
34
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
35
+
36
+ _Fable.MeadowSQLiteProvider.connectAsync(
37
+ (pError, pDatabase) =>
38
+ {
39
+ if (pError)
40
+ {
41
+ console.error('Connection failed:', pError);
42
+ return;
43
+ }
44
+
45
+ console.log('Connected:', _Fable.MeadowSQLiteProvider.connected);
46
+ // => Connected: true
47
+ });
48
+ ```
49
+
50
+ The database file is created automatically if it does not exist. WAL journal mode is enabled on connection.
51
+
52
+ For in-memory databases (useful in tests), set `SQLiteFilePath` to `":memory:"`.
53
+
54
+ ---
55
+
56
+ ## Step 3 — Run Queries
57
+
58
+ All queries use the synchronous `better-sqlite3` API via the `db` getter:
59
+
60
+ ```javascript
61
+ let tmpDB = _Fable.MeadowSQLiteProvider.db;
62
+
63
+ // Create a table with raw SQL
64
+ tmpDB.exec(`
65
+ CREATE TABLE IF NOT EXISTS Book (
66
+ IDBook INTEGER PRIMARY KEY AUTOINCREMENT,
67
+ Title TEXT DEFAULT '',
68
+ Author TEXT DEFAULT '',
69
+ Price REAL DEFAULT 0.0
70
+ )
71
+ `);
72
+
73
+ // Insert a row with a prepared statement
74
+ let tmpInsert = tmpDB.prepare(
75
+ 'INSERT INTO Book (Title, Author, Price) VALUES (?, ?, ?)'
76
+ );
77
+ let tmpResult = tmpInsert.run('Dune', 'Frank Herbert', 14.99);
78
+ console.log('Inserted ID:', tmpResult.lastInsertRowid);
79
+ // => Inserted ID: 1
80
+
81
+ // Query all rows
82
+ let tmpBooks = tmpDB.prepare('SELECT * FROM Book').all();
83
+ console.log(tmpBooks);
84
+ // => [{ IDBook: 1, Title: 'Dune', Author: 'Frank Herbert', Price: 14.99 }]
85
+
86
+ // Query a single row
87
+ let tmpBook = tmpDB.prepare('SELECT * FROM Book WHERE IDBook = ?').get(1);
88
+ console.log(tmpBook.Title);
89
+ // => Dune
90
+ ```
91
+
92
+ ### Key Methods
93
+
94
+ | Method | Returns | Purpose |
95
+ |--------|---------|---------|
96
+ | `db.exec(sql)` | nothing | Run DDL or multi-statement SQL |
97
+ | `db.prepare(sql).run(...)` | `{ changes, lastInsertRowid }` | INSERT, UPDATE, DELETE |
98
+ | `db.prepare(sql).get(...)` | object or `undefined` | SELECT single row |
99
+ | `db.prepare(sql).all(...)` | array of objects | SELECT all matching rows |
100
+ | `db.transaction(fn)` | wrapped function | Atomic batch operations |
101
+
102
+ ---
103
+
104
+ ## Step 4 — Create Tables from Schema
105
+
106
+ Instead of writing DDL by hand, pass a Meadow table schema to `createTable()`:
107
+
108
+ ```javascript
109
+ let tmpBookSchema =
110
+ {
111
+ TableName: 'Book',
112
+ Columns:
113
+ [
114
+ { Column: 'IDBook', DataType: 'ID' },
115
+ { Column: 'GUIDBook', DataType: 'GUID' },
116
+ { Column: 'Title', DataType: 'String', Size: '256' },
117
+ { Column: 'Author', DataType: 'String', Size: '128' },
118
+ { Column: 'YearPublished', DataType: 'Numeric' },
119
+ { Column: 'Price', DataType: 'Decimal', Size: '10,2' },
120
+ { Column: 'InPrint', DataType: 'Boolean' },
121
+ { Column: 'CreateDate', DataType: 'DateTime' },
122
+ { Column: 'UpdateDate', DataType: 'DateTime' }
123
+ ]
124
+ };
125
+
126
+ _Fable.MeadowSQLiteProvider.createTable(tmpBookSchema,
127
+ (pError) =>
128
+ {
129
+ if (pError) { console.error('Create table failed:', pError); return; }
130
+ console.log('Table created!');
131
+ });
132
+ ```
133
+
134
+ You can also generate the DDL string without executing it:
135
+
136
+ ```javascript
137
+ let tmpDDL = _Fable.MeadowSQLiteProvider.generateCreateTableStatement(tmpBookSchema);
138
+ console.log(tmpDDL);
139
+ ```
140
+
141
+ Output:
142
+
143
+ ```sql
144
+ CREATE TABLE IF NOT EXISTS Book (IDBook INTEGER PRIMARY KEY AUTOINCREMENT, GUIDBook TEXT DEFAULT '00000000-0000-0000-0000-000000000000', Title TEXT NOT NULL DEFAULT '', Author TEXT NOT NULL DEFAULT '', YearPublished INTEGER NOT NULL DEFAULT 0, Price REAL, InPrint INTEGER NOT NULL DEFAULT 0, CreateDate TEXT, UpdateDate TEXT);
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Step 5 — Meadow ORM Integration
150
+
151
+ Wire the SQLite connection into Meadow for full ORM capabilities:
152
+
153
+ ```javascript
154
+ const libMeadow = require('meadow');
155
+
156
+ let tmpBookMeadow = libMeadow.new(_Fable, 'FableTest')
157
+ .setProvider('ALASQL')
158
+ .setDefaultIdentifier('IDBook')
159
+ .loadFromPackage(
160
+ {
161
+ scope: 'Book',
162
+ jsonschema:
163
+ {
164
+ title: 'Book',
165
+ properties:
166
+ {
167
+ IDBook: { type: 'integer' },
168
+ GUIDBook: { type: 'string' },
169
+ Title: { type: 'string' },
170
+ Author: { type: 'string' }
171
+ }
172
+ }
173
+ });
174
+ ```
175
+
176
+ > **Note:** Meadow uses FoxHound dialects for query generation. For SQLite-specific workloads that bypass Meadow's query layer, use the `db` getter directly. The ALASQL provider is commonly paired with SQLite for local Meadow operations.
177
+
178
+ ---
179
+
180
+ ## Summary
181
+
182
+ | Step | What It Does |
183
+ |------|-------------|
184
+ | Install | `npm install meadow-connection-sqlite fable` |
185
+ | Configure | Set `SQLite.SQLiteFilePath` in Fable settings |
186
+ | Connect | `connectAsync()` opens the file and enables WAL |
187
+ | Query | `db.prepare().run/get/all()` for synchronous queries |
188
+ | Schema DDL | `createTable()` generates and executes SQLite DDL |
189
+
190
+ ---
191
+
192
+ ## Next Steps
193
+
194
+ - [Architecture & Design](architecture.md) -- Connection lifecycle and data flow diagrams
195
+ - [Full Pipeline Example](examples-pipeline.md) -- End-to-end CRUD pipeline with transactions
196
+ - [API Reference](api/reference.md) -- Complete reference for every property and method
197
+ - [Schema & Table Creation](schema.md) -- Column type mapping and DDL generation