meadow 2.0.16 → 2.0.18
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/.config/configstore/update-notifier-npm.json +1 -1
- package/Dockerfile_LUXURYCode +1 -42
- package/README.md +174 -112
- package/docs/README.md +276 -0
- package/docs/_sidebar.md +38 -0
- package/docs/providers/README.md +253 -0
- package/docs/providers/alasql.md +271 -0
- package/docs/providers/mssql.md +296 -0
- package/docs/providers/mysql.md +260 -0
- package/docs/providers/sqlite.md +173 -0
- package/docs/query/README.md +175 -0
- package/docs/query/count.md +228 -0
- package/docs/query/create.md +226 -0
- package/docs/query/delete.md +264 -0
- package/docs/query/read.md +350 -0
- package/docs/query/update.md +250 -0
- package/docs/schema/README.md +408 -0
- package/package.json +16 -3
- package/scripts/mssql-test-db.sh +111 -0
- package/scripts/mysql-test-db.sh +108 -0
- package/source/Meadow.js +1 -0
- package/source/providers/Meadow-Provider-MSSQL.js +21 -0
- package/source/providers/Meadow-Provider-SQLite.js +235 -155
- package/test/Meadow-Provider-SQLite-AnimalReadQuery.sql +5 -0
- package/test/Meadow-Provider-SQLite_tests.js +931 -0
package/docs/_sidebar.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
- Getting Started
|
|
2
|
+
|
|
3
|
+
- [Introduction](/)
|
|
4
|
+
- [Architecture](architecture.md)
|
|
5
|
+
|
|
6
|
+
- Core Concepts
|
|
7
|
+
|
|
8
|
+
- [Schema](schema/README.md)
|
|
9
|
+
- [CRUD Operations](crud-operations.md)
|
|
10
|
+
- [Query DSL](query-dsl.md)
|
|
11
|
+
- [Raw Queries](raw-queries.md)
|
|
12
|
+
|
|
13
|
+
- Schema
|
|
14
|
+
|
|
15
|
+
- [Schema Overview](schema/README.md)
|
|
16
|
+
|
|
17
|
+
- Query Operations
|
|
18
|
+
|
|
19
|
+
- [Query Overview](query/README.md)
|
|
20
|
+
- [Create](query/create.md)
|
|
21
|
+
- [Read](query/read.md)
|
|
22
|
+
- [Update](query/update.md)
|
|
23
|
+
- [Delete](query/delete.md)
|
|
24
|
+
- [Count](query/count.md)
|
|
25
|
+
|
|
26
|
+
- Providers
|
|
27
|
+
|
|
28
|
+
- [Providers Overview](providers/README.md)
|
|
29
|
+
- [MySQL](providers/mysql.md)
|
|
30
|
+
- [MSSQL](providers/mssql.md)
|
|
31
|
+
- [SQLite](providers/sqlite.md)
|
|
32
|
+
- [ALASQL](providers/alasql.md)
|
|
33
|
+
|
|
34
|
+
- Advanced
|
|
35
|
+
|
|
36
|
+
- [Audit Tracking](audit-tracking.md)
|
|
37
|
+
- [Soft Deletes](soft-deletes.md)
|
|
38
|
+
- [Configuration Reference](configuration.md)
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# Providers
|
|
2
|
+
|
|
3
|
+
> Pluggable database backends through a consistent interface
|
|
4
|
+
|
|
5
|
+
Meadow's provider system abstracts database communication behind a unified CRUD interface. You write your data access code once, then swap providers to target MySQL, MSSQL, SQLite, an in-browser IndexedDB store, or even a remote REST API — all without changing your application logic.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Meadow (Data Access Layer)
|
|
11
|
+
└── Provider Interface
|
|
12
|
+
├── MySQL → mysql2 connection pool, named placeholders
|
|
13
|
+
├── MSSQL → mssql prepared statements, SCOPE_IDENTITY()
|
|
14
|
+
├── SQLite → Lightweight embedded SQL
|
|
15
|
+
├── ALASQL → In-memory JavaScript SQL engine (browser/Node)
|
|
16
|
+
├── MeadowEndpoints → HTTP proxy to remote Meadow REST API
|
|
17
|
+
└── None → No-op stub for testing
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Every provider implements the same operation set:
|
|
21
|
+
|
|
22
|
+
| Operation | Description |
|
|
23
|
+
|-----------|-------------|
|
|
24
|
+
| `Create` | Insert a new record, return the identity value |
|
|
25
|
+
| `Read` | Execute a SELECT query, return result rows |
|
|
26
|
+
| `Update` | Execute an UPDATE query |
|
|
27
|
+
| `Delete` | Execute a DELETE query (soft delete), return affected rows |
|
|
28
|
+
| `Undelete` | Reverse a soft delete, return affected rows |
|
|
29
|
+
| `Count` | Execute a COUNT query, return the row count |
|
|
30
|
+
|
|
31
|
+
## Choosing a Provider
|
|
32
|
+
|
|
33
|
+
| Provider | Best For | Connection Module |
|
|
34
|
+
|----------|----------|-------------------|
|
|
35
|
+
| [MySQL](providers/mysql.md) | Production web applications, MySQL/MariaDB | [meadow-connection-mysql](https://github.com/stevenvelozo/meadow-connection-mysql) |
|
|
36
|
+
| [MSSQL](providers/mssql.md) | Enterprise environments, SQL Server | [meadow-connection-mssql](https://github.com/stevenvelozo/meadow-connection-mssql) |
|
|
37
|
+
| [SQLite](providers/sqlite.md) | Embedded applications, local development | [meadow-connection-sqlite](https://github.com/stevenvelozo/meadow-connection-sqlite) |
|
|
38
|
+
| [ALASQL](providers/alasql.md) | Browser applications, unit testing, prototyping | Built-in (no external connection) |
|
|
39
|
+
| MeadowEndpoints | Client-side proxy to remote Meadow APIs | Built-in (HTTP via simple-get) |
|
|
40
|
+
| None | Unit testing stubs, development scaffolding | None required |
|
|
41
|
+
|
|
42
|
+
## Setting a Provider
|
|
43
|
+
|
|
44
|
+
```javascript
|
|
45
|
+
const libFable = require('fable').new();
|
|
46
|
+
const libMeadow = require('meadow');
|
|
47
|
+
|
|
48
|
+
const meadow = libMeadow.new(libFable, 'Book')
|
|
49
|
+
.setProvider('MySQL')
|
|
50
|
+
.setDefaultIdentifier('IDBook')
|
|
51
|
+
.setSchema([
|
|
52
|
+
{ Column: 'IDBook', Type: 'AutoIdentity' },
|
|
53
|
+
{ Column: 'Title', Type: 'String', Size: '255' }
|
|
54
|
+
]);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The provider name is a string matching one of: `'MySQL'`, `'MSSQL'`, `'SQLite'`, `'ALASQL'`, `'MeadowEndpoints'`, or `'None'`.
|
|
58
|
+
|
|
59
|
+
## How Providers Work
|
|
60
|
+
|
|
61
|
+
### Query Flow
|
|
62
|
+
|
|
63
|
+
Every CRUD operation follows the same flow through the provider:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Application Code
|
|
67
|
+
│
|
|
68
|
+
▼
|
|
69
|
+
Meadow Behavior (e.g., doCreate)
|
|
70
|
+
│ 1. Build query object via FoxHound
|
|
71
|
+
│ 2. Apply auto-stamps and GUID generation
|
|
72
|
+
│ 3. Merge default object with submitted record
|
|
73
|
+
│
|
|
74
|
+
▼
|
|
75
|
+
FoxHound Query DSL
|
|
76
|
+
│ 4. Set dialect for target database
|
|
77
|
+
│ 5. Generate dialect-specific SQL
|
|
78
|
+
│ 6. Bind parameters
|
|
79
|
+
│
|
|
80
|
+
▼
|
|
81
|
+
Provider
|
|
82
|
+
│ 7. Get database connection
|
|
83
|
+
│ 8. Execute generated SQL
|
|
84
|
+
│ 9. Marshal results into result object
|
|
85
|
+
│
|
|
86
|
+
▼
|
|
87
|
+
Callback
|
|
88
|
+
10. Return (pError, pQuery, pRecord/pRecords)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### FoxHound Dialect Integration
|
|
92
|
+
|
|
93
|
+
Each provider sets the appropriate FoxHound dialect before building queries:
|
|
94
|
+
|
|
95
|
+
```javascript
|
|
96
|
+
// MySQL provider internally calls:
|
|
97
|
+
pQuery.setDialect('MySQL').buildReadQuery();
|
|
98
|
+
|
|
99
|
+
// MSSQL provider internally calls:
|
|
100
|
+
pQuery.setDialect('MSSQL').buildReadQuery();
|
|
101
|
+
|
|
102
|
+
// ALASQL provider internally calls:
|
|
103
|
+
pQuery.setDialect('ALASQL').buildReadQuery();
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
This ensures the generated SQL matches the target database's syntax.
|
|
107
|
+
|
|
108
|
+
### Result Object
|
|
109
|
+
|
|
110
|
+
All providers store their results in a consistent structure on the query object:
|
|
111
|
+
|
|
112
|
+
```javascript
|
|
113
|
+
pQuery.parameters.result =
|
|
114
|
+
{
|
|
115
|
+
error: null, // Error object if operation failed, null on success
|
|
116
|
+
value: false, // Result value (varies by operation — see below)
|
|
117
|
+
executed: true // Whether the provider attempted execution
|
|
118
|
+
};
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Operation | `result.value` |
|
|
122
|
+
|-----------|----------------|
|
|
123
|
+
| Create | Identity value of the new record (e.g., `42`) |
|
|
124
|
+
| Read | Array of record objects |
|
|
125
|
+
| Update | Query result object |
|
|
126
|
+
| Delete | Number of affected rows |
|
|
127
|
+
| Undelete | Number of affected rows |
|
|
128
|
+
| Count | Integer count of matching records |
|
|
129
|
+
|
|
130
|
+
### Record Marshalling
|
|
131
|
+
|
|
132
|
+
All providers implement `marshalRecordFromSourceToObject(pObject, pRecord)` to copy database field values onto a result object:
|
|
133
|
+
|
|
134
|
+
```javascript
|
|
135
|
+
// Provider copies each column from the database result to the output object
|
|
136
|
+
for (var tmpColumn in pRecord)
|
|
137
|
+
{
|
|
138
|
+
pObject[tmpColumn] = pRecord[tmpColumn];
|
|
139
|
+
}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Meadow's `marshalRecordFromSourceToObject` method combines this with default object merging:
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
// Internally:
|
|
146
|
+
// 1. Create object from default template
|
|
147
|
+
// 2. Provider copies database values over defaults
|
|
148
|
+
const tmpRecord = fable.Utility.extend({}, schema.defaultObject, pRecord);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Schema Synchronization
|
|
152
|
+
|
|
153
|
+
When you call `setSchema()` on Meadow, it automatically updates the provider:
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// Meadow internally calls:
|
|
157
|
+
provider.setSchema(scope, schema, defaultIdentifier, defaultGUIdentifier);
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This is critical for providers like ALASQL that dynamically create tables from schema definitions.
|
|
161
|
+
|
|
162
|
+
## Connection Management
|
|
163
|
+
|
|
164
|
+
Each SQL provider requires a connection module registered as a Fable service. The connection modules handle pooling, configuration, and lifecycle management.
|
|
165
|
+
|
|
166
|
+
### MySQL Connection
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
const libMeadowConnectionMySQL = require('meadow-connection-mysql');
|
|
170
|
+
|
|
171
|
+
// Register the connection service
|
|
172
|
+
libFable.serviceManager.addServiceType('MeadowMySQLProvider', libMeadowConnectionMySQL);
|
|
173
|
+
libFable.serviceManager.instantiateServiceProvider('MeadowMySQLProvider');
|
|
174
|
+
|
|
175
|
+
// Or auto-connect on init:
|
|
176
|
+
libFable.serviceManager.instantiateServiceProvider('MeadowMySQLProvider',
|
|
177
|
+
{ MeadowConnectionMySQLAutoConnect: true });
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### MSSQL Connection
|
|
181
|
+
|
|
182
|
+
```javascript
|
|
183
|
+
const libMeadowConnectionMSSQL = require('meadow-connection-mssql');
|
|
184
|
+
|
|
185
|
+
// Register and connect asynchronously
|
|
186
|
+
libFable.serviceManager.addServiceType('MeadowMSSQLProvider', libMeadowConnectionMSSQL);
|
|
187
|
+
const tmpConnection = libFable.serviceManager.instantiateServiceProvider('MeadowMSSQLProvider');
|
|
188
|
+
tmpConnection.connectAsync(
|
|
189
|
+
(pError) =>
|
|
190
|
+
{
|
|
191
|
+
if (pError)
|
|
192
|
+
{
|
|
193
|
+
return console.error('Connection failed:', pError);
|
|
194
|
+
}
|
|
195
|
+
// Ready for CRUD operations
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## MeadowEndpoints Provider
|
|
200
|
+
|
|
201
|
+
The MeadowEndpoints provider is unique — it doesn't connect to a database directly. Instead, it acts as an HTTP proxy to a remote Meadow REST API. This enables client-side code to use the same Meadow interface while the actual data operations happen on a server.
|
|
202
|
+
|
|
203
|
+
```javascript
|
|
204
|
+
meadow.setProvider('MeadowEndpoints');
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Configuration is read from Fable settings:
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"MeadowEndpoints": {
|
|
212
|
+
"ServerProtocol": "http",
|
|
213
|
+
"ServerAddress": "127.0.0.1",
|
|
214
|
+
"ServerPort": 8086,
|
|
215
|
+
"ServerEndpointPrefix": "1.0/"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
| HTTP Method | CRUD Operation |
|
|
221
|
+
|-------------|----------------|
|
|
222
|
+
| `POST` | Create |
|
|
223
|
+
| `GET` | Read / Reads / Count |
|
|
224
|
+
| `PUT` | Update |
|
|
225
|
+
| `DELETE` | Delete |
|
|
226
|
+
|
|
227
|
+
## None Provider
|
|
228
|
+
|
|
229
|
+
The None provider is a no-op stub that marks every operation as executed without doing anything. Useful for testing application logic without a database connection.
|
|
230
|
+
|
|
231
|
+
```javascript
|
|
232
|
+
meadow.setProvider('None');
|
|
233
|
+
|
|
234
|
+
// All operations succeed immediately with empty results
|
|
235
|
+
meadow.doRead(meadow.query.addFilter('IDBook', 1),
|
|
236
|
+
(pError, pQuery, pRecord) =>
|
|
237
|
+
{
|
|
238
|
+
// pRecord will be minimal/empty — no actual data
|
|
239
|
+
});
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## Provider-Specific Documentation
|
|
243
|
+
|
|
244
|
+
- [MySQL](providers/mysql.md) — Connection pooling, named placeholders, configuration
|
|
245
|
+
- [MSSQL](providers/mssql.md) — Prepared statements, type mapping, identity handling
|
|
246
|
+
- [SQLite](providers/sqlite.md) — Embedded database, lightweight deployment
|
|
247
|
+
- [ALASQL](providers/alasql.md) — In-memory SQL, dynamic table creation, browser support
|
|
248
|
+
|
|
249
|
+
## Related Documentation
|
|
250
|
+
|
|
251
|
+
- [Schema](schema/README.md) — How schema definitions drive provider behavior
|
|
252
|
+
- [Query Overview](query/README.md) — FoxHound query DSL and dialect generation
|
|
253
|
+
- [Meadow-Endpoints](https://github.com/stevenvelozo/meadow-endpoints) — REST API generation on top of Meadow providers
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# ALASQL Provider
|
|
2
|
+
|
|
3
|
+
> In-memory JavaScript SQL engine for browser applications, unit testing, and rapid prototyping
|
|
4
|
+
|
|
5
|
+
The ALASQL provider connects Meadow to [AlaSQL](https://github.com/AlaSQL/alasql), a JavaScript SQL database that runs entirely in memory. It requires no external database server, supports dynamic table creation from Meadow schemas, and works in both Node.js and browser environments. This makes it ideal for unit tests, browser-based applications, and prototyping.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Install Dependencies
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install meadow alasql
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Initialize ALASQL on Fable
|
|
16
|
+
|
|
17
|
+
```javascript
|
|
18
|
+
const libFable = require('fable').new();
|
|
19
|
+
const libALASQL = require('alasql');
|
|
20
|
+
|
|
21
|
+
// Attach ALASQL to the Fable instance
|
|
22
|
+
libFable.ALASQL = libALASQL;
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Create a Meadow DAL
|
|
26
|
+
|
|
27
|
+
```javascript
|
|
28
|
+
const libMeadow = require('meadow');
|
|
29
|
+
|
|
30
|
+
const meadow = libMeadow.new(libFable, 'Book')
|
|
31
|
+
.setProvider('ALASQL')
|
|
32
|
+
.setDefaultIdentifier('IDBook')
|
|
33
|
+
.setSchema([
|
|
34
|
+
{ Column: 'IDBook', Type: 'AutoIdentity' },
|
|
35
|
+
{ Column: 'GUIDBook', Type: 'AutoGUID' },
|
|
36
|
+
{ Column: 'Title', Type: 'String', Size: '255' },
|
|
37
|
+
{ Column: 'Author', Type: 'String', Size: '128' },
|
|
38
|
+
{ Column: 'PageCount', Type: 'Numeric' },
|
|
39
|
+
{ Column: 'InPrint', Type: 'Boolean' },
|
|
40
|
+
{ Column: 'CreateDate', Type: 'CreateDate' },
|
|
41
|
+
{ Column: 'CreatingIDUser', Type: 'CreateIDUser' },
|
|
42
|
+
{ Column: 'UpdateDate', Type: 'UpdateDate' },
|
|
43
|
+
{ Column: 'UpdatingIDUser', Type: 'UpdateIDUser' },
|
|
44
|
+
{ Column: 'DeleteDate', Type: 'DeleteDate' },
|
|
45
|
+
{ Column: 'DeletingIDUser', Type: 'DeleteIDUser' },
|
|
46
|
+
{ Column: 'Deleted', Type: 'Deleted' }
|
|
47
|
+
]);
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Dynamic Table Creation
|
|
51
|
+
|
|
52
|
+
Unlike SQL-server-based providers, ALASQL dynamically creates tables from your Meadow schema. When the first CRUD operation is executed, the provider checks whether the table exists and creates it if needed.
|
|
53
|
+
|
|
54
|
+
### Schema-to-SQL Type Mapping
|
|
55
|
+
|
|
56
|
+
| Meadow Type | ALASQL Column Definition |
|
|
57
|
+
|-------------|--------------------------|
|
|
58
|
+
| `AutoIdentity` | `INT AUTOINCREMENT` |
|
|
59
|
+
| `AutoGUID` | `STRING` |
|
|
60
|
+
| `Boolean` | `BOOLEAN` |
|
|
61
|
+
| `Numeric` | `INT` |
|
|
62
|
+
| `Integer` | `INT` |
|
|
63
|
+
| `Decimal` | `DECIMAL` |
|
|
64
|
+
| `String` | `STRING` |
|
|
65
|
+
| `Text` | `STRING` |
|
|
66
|
+
| `DateTime` | `STRING` |
|
|
67
|
+
| `CreateDate` | `STRING` |
|
|
68
|
+
| `CreateIDUser` | `INT` |
|
|
69
|
+
| `UpdateDate` | `STRING` |
|
|
70
|
+
| `UpdateIDUser` | `INT` |
|
|
71
|
+
| `DeleteDate` | `STRING` |
|
|
72
|
+
| `DeleteIDUser` | `INT` |
|
|
73
|
+
| `Deleted` | `BOOLEAN` |
|
|
74
|
+
|
|
75
|
+
### Automatic Table Check
|
|
76
|
+
|
|
77
|
+
Before each CRUD operation, the provider calls `checkDataExists(pParameters)` to verify the table exists. If not, it generates and executes a `CREATE TABLE` statement based on the schema:
|
|
78
|
+
|
|
79
|
+
```sql
|
|
80
|
+
-- Generated automatically from schema:
|
|
81
|
+
CREATE TABLE Book (
|
|
82
|
+
IDBook INT AUTOINCREMENT,
|
|
83
|
+
GUIDBook STRING,
|
|
84
|
+
Title STRING,
|
|
85
|
+
Author STRING,
|
|
86
|
+
PageCount INT,
|
|
87
|
+
InPrint BOOLEAN,
|
|
88
|
+
CreateDate STRING,
|
|
89
|
+
CreatingIDUser INT,
|
|
90
|
+
UpdateDate STRING,
|
|
91
|
+
UpdatingIDUser INT,
|
|
92
|
+
DeleteDate STRING,
|
|
93
|
+
DeletingIDUser INT,
|
|
94
|
+
Deleted BOOLEAN
|
|
95
|
+
)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## CRUD Operations
|
|
99
|
+
|
|
100
|
+
All ALASQL operations are **synchronous** internally (wrapped in callbacks for API consistency). Queries are compiled via `libALASQL.compile()` for efficient execution.
|
|
101
|
+
|
|
102
|
+
### Create
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
meadow.doCreate(
|
|
106
|
+
meadow.query.addRecord({ Title: 'Dune', Author: 'Frank Herbert' }),
|
|
107
|
+
(pError, pCreateQuery, pReadQuery, pRecord) =>
|
|
108
|
+
{
|
|
109
|
+
console.log('New ID:', pRecord.IDBook);
|
|
110
|
+
});
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Internally:**
|
|
114
|
+
- Builds query: `pQuery.setDialect('ALASQL').buildCreateQuery()`
|
|
115
|
+
- Compiles: `libALASQL.compile(queryBody)`
|
|
116
|
+
- Extracts identity: `libALASQL.autoval(scope, defaultIdentifier)`
|
|
117
|
+
|
|
118
|
+
### Read
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
meadow.doRead(
|
|
122
|
+
meadow.query.addFilter('IDBook', 1),
|
|
123
|
+
(pError, pQuery, pRecord) =>
|
|
124
|
+
{
|
|
125
|
+
console.log('Title:', pRecord.Title);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
meadow.doReads(
|
|
129
|
+
meadow.query.setCap(10),
|
|
130
|
+
(pError, pQuery, pRecords) =>
|
|
131
|
+
{
|
|
132
|
+
pRecords.forEach((pBook) => console.log(pBook.Title));
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Update
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
meadow.doUpdate(
|
|
140
|
+
meadow.query
|
|
141
|
+
.addFilter('IDBook', 1)
|
|
142
|
+
.addRecord({ Title: 'Updated Title' }),
|
|
143
|
+
(pError, pUpdateQuery, pReadQuery, pRecord) =>
|
|
144
|
+
{
|
|
145
|
+
console.log('Updated:', pRecord.Title);
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Delete
|
|
150
|
+
|
|
151
|
+
```javascript
|
|
152
|
+
meadow.doDelete(
|
|
153
|
+
meadow.query.addFilter('IDBook', 1),
|
|
154
|
+
(pError, pQuery, pResult) =>
|
|
155
|
+
{
|
|
156
|
+
console.log('Deleted rows:', pResult);
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Count
|
|
161
|
+
|
|
162
|
+
```javascript
|
|
163
|
+
meadow.doCount(
|
|
164
|
+
meadow.query,
|
|
165
|
+
(pError, pQuery, pCount) =>
|
|
166
|
+
{
|
|
167
|
+
console.log('Total books:', pCount);
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Data Binding
|
|
172
|
+
|
|
173
|
+
The ALASQL provider offers special methods for directly binding JavaScript data to tables, which is useful for initializing state or importing datasets.
|
|
174
|
+
|
|
175
|
+
### Bind an Array to a Table
|
|
176
|
+
|
|
177
|
+
```javascript
|
|
178
|
+
// Directly assign an array as the table's data
|
|
179
|
+
meadow.provider.bindObject(
|
|
180
|
+
[
|
|
181
|
+
{ IDBook: 1, Title: 'Dune', Author: 'Frank Herbert' },
|
|
182
|
+
{ IDBook: 2, Title: 'Foundation', Author: 'Isaac Asimov' },
|
|
183
|
+
{ IDBook: 3, Title: 'Neuromancer', Author: 'William Gibson' }
|
|
184
|
+
]);
|
|
185
|
+
// ALASQL.tables['Book'].data now contains these records
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Construct from Object
|
|
189
|
+
|
|
190
|
+
The `constructFromObject` method builds a complete Meadow entity from a JavaScript object prototype, optionally including audit columns and importing data:
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
meadow.provider.constructFromObject(
|
|
194
|
+
{
|
|
195
|
+
Meadow: meadow,
|
|
196
|
+
Scope: 'Book',
|
|
197
|
+
ObjectPrototype:
|
|
198
|
+
{
|
|
199
|
+
Title: 'String',
|
|
200
|
+
Author: 'String',
|
|
201
|
+
PageCount: 'Numeric'
|
|
202
|
+
},
|
|
203
|
+
AuditData: true, // Auto-generate audit columns
|
|
204
|
+
Import: true, // Import the Data array via doCreate
|
|
205
|
+
Data:
|
|
206
|
+
[
|
|
207
|
+
{ Title: 'Dune', Author: 'Frank Herbert', PageCount: 412 },
|
|
208
|
+
{ Title: 'Foundation', Author: 'Isaac Asimov', PageCount: 244 }
|
|
209
|
+
]
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
| Parameter | Type | Description |
|
|
214
|
+
|-----------|------|-------------|
|
|
215
|
+
| `Meadow` | object | The Meadow instance to configure |
|
|
216
|
+
| `Scope` | string | Entity name for the table |
|
|
217
|
+
| `ObjectPrototype` | object | Column name to type mapping |
|
|
218
|
+
| `AuditData` | boolean | Add Create/Update/Delete audit columns |
|
|
219
|
+
| `Import` | boolean | Import Data array via `doCreate` operations |
|
|
220
|
+
| `Data` | array | Records to import (when `Import` is `true`) |
|
|
221
|
+
|
|
222
|
+
## Browser Usage
|
|
223
|
+
|
|
224
|
+
ALASQL is the recommended provider for browser-based Meadow applications. When bundled with Browserify or another bundler, Meadow with ALASQL provides a full SQL database in the browser.
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
// In a browser bundle:
|
|
228
|
+
const libFable = require('fable').new();
|
|
229
|
+
const libALASQL = require('alasql');
|
|
230
|
+
const libMeadow = require('meadow');
|
|
231
|
+
|
|
232
|
+
libFable.ALASQL = libALASQL;
|
|
233
|
+
|
|
234
|
+
const meadow = libMeadow.new(libFable, 'Task')
|
|
235
|
+
.setProvider('ALASQL')
|
|
236
|
+
.setDefaultIdentifier('IDTask')
|
|
237
|
+
.setSchema([
|
|
238
|
+
{ Column: 'IDTask', Type: 'AutoIdentity' },
|
|
239
|
+
{ Column: 'Description', Type: 'String', Size: '255' },
|
|
240
|
+
{ Column: 'Complete', Type: 'Boolean' }
|
|
241
|
+
]);
|
|
242
|
+
|
|
243
|
+
// Full CRUD operations in the browser
|
|
244
|
+
meadow.doCreate(
|
|
245
|
+
meadow.query.addRecord({ Description: 'Buy groceries', Complete: false }),
|
|
246
|
+
(pError, pCreateQuery, pReadQuery, pRecord) =>
|
|
247
|
+
{
|
|
248
|
+
console.log('Created task:', pRecord.IDTask);
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
## When to Use ALASQL
|
|
253
|
+
|
|
254
|
+
| Use Case | Recommendation |
|
|
255
|
+
|----------|---------------|
|
|
256
|
+
| Unit testing | Excellent — no database setup, fast, deterministic |
|
|
257
|
+
| Browser applications | Excellent — full SQL in the browser |
|
|
258
|
+
| Rapid prototyping | Excellent — start coding immediately |
|
|
259
|
+
| Production server | Consider MySQL or MSSQL instead |
|
|
260
|
+
| Data persistence | Data is in-memory only (lost on refresh/restart) |
|
|
261
|
+
|
|
262
|
+
## Error Handling
|
|
263
|
+
|
|
264
|
+
All operations are wrapped in try-catch blocks. Errors are stored in `pQuery.parameters.result.error` and the `executed` flag is always set to `true`.
|
|
265
|
+
|
|
266
|
+
## Related Documentation
|
|
267
|
+
|
|
268
|
+
- [Providers Overview](providers/README.md) — Comparison of all providers
|
|
269
|
+
- [MySQL Provider](providers/mysql.md) — Production MySQL alternative
|
|
270
|
+
- [SQLite Provider](providers/sqlite.md) — Lightweight embedded alternative
|
|
271
|
+
- [Schema](schema/README.md) — Schema definitions that drive table creation
|