meadow 2.0.23 → 2.0.27

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.
Files changed (62) hide show
  1. package/README.md +110 -141
  2. package/docs/README.md +34 -230
  3. package/docs/_cover.md +14 -0
  4. package/docs/_sidebar.md +44 -12
  5. package/docs/_topbar.md +5 -0
  6. package/docs/api/doCount.md +109 -0
  7. package/docs/api/doCreate.md +132 -0
  8. package/docs/api/doDelete.md +101 -0
  9. package/docs/api/doRead.md +122 -0
  10. package/docs/api/doReads.md +136 -0
  11. package/docs/api/doUndelete.md +98 -0
  12. package/docs/api/doUpdate.md +129 -0
  13. package/docs/api/getRoleName.md +84 -0
  14. package/docs/api/loadFromPackage.md +153 -0
  15. package/docs/api/marshalRecordFromSourceToObject.md +92 -0
  16. package/docs/api/query.md +133 -0
  17. package/docs/api/rawQueries.md +197 -0
  18. package/docs/api/reference.md +117 -0
  19. package/docs/api/setAuthorizer.md +103 -0
  20. package/docs/api/setDefault.md +90 -0
  21. package/docs/api/setDefaultIdentifier.md +84 -0
  22. package/docs/api/setDomain.md +56 -0
  23. package/docs/api/setIDUser.md +91 -0
  24. package/docs/api/setJsonSchema.md +92 -0
  25. package/docs/api/setProvider.md +87 -0
  26. package/docs/api/setSchema.md +107 -0
  27. package/docs/api/setScope.md +68 -0
  28. package/docs/api/validateObject.md +119 -0
  29. package/docs/architecture.md +316 -0
  30. package/docs/audit-tracking.md +226 -0
  31. package/docs/configuration.md +317 -0
  32. package/docs/providers/meadow-endpoints.md +306 -0
  33. package/docs/providers/mongodb.md +319 -0
  34. package/docs/providers/postgresql.md +312 -0
  35. package/docs/providers/rocksdb.md +297 -0
  36. package/docs/query-dsl.md +269 -0
  37. package/docs/quick-start.md +384 -0
  38. package/docs/raw-queries.md +193 -0
  39. package/docs/retold-catalog.json +61 -1
  40. package/docs/retold-keyword-index.json +15860 -4839
  41. package/docs/soft-deletes.md +224 -0
  42. package/package.json +44 -13
  43. package/scripts/bookstore-seed-postgresql.sql +135 -0
  44. package/scripts/dgraph-test-db.sh +144 -0
  45. package/scripts/meadow-test-cleanup.sh +5 -1
  46. package/scripts/mongodb-test-db.sh +98 -0
  47. package/scripts/postgresql-test-db.sh +124 -0
  48. package/scripts/solr-test-db.sh +135 -0
  49. package/source/Meadow.js +5 -0
  50. package/source/providers/Meadow-Provider-DGraph.js +679 -0
  51. package/source/providers/Meadow-Provider-MeadowEndpoints.js +1 -1
  52. package/source/providers/Meadow-Provider-MongoDB.js +527 -0
  53. package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
  54. package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
  55. package/source/providers/Meadow-Provider-Solr.js +726 -0
  56. package/test/Meadow-Provider-DGraph_tests.js +741 -0
  57. package/test/Meadow-Provider-MongoDB_tests.js +661 -0
  58. package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
  59. package/test/Meadow-Provider-RocksDB_tests.js +887 -0
  60. package/test/Meadow-Provider-SQLiteBrowser-Headless_tests.js +657 -0
  61. package/test/Meadow-Provider-SQLiteBrowser_tests.js +895 -0
  62. package/test/Meadow-Provider-Solr_tests.js +679 -0
package/docs/_sidebar.md CHANGED
@@ -1,22 +1,21 @@
1
1
  - Getting Started
2
2
 
3
3
  - [Introduction](/)
4
+ - [Quick Start](quick-start.md)
4
5
  - [Architecture](architecture.md)
6
+ - [Configuration](configuration.md)
5
7
 
6
8
  - Core Concepts
7
9
 
8
10
  - [Schema](schema/README.md)
9
- - [CRUD Operations](crud-operations.md)
10
11
  - [Query DSL](query-dsl.md)
11
12
  - [Raw Queries](raw-queries.md)
13
+ - [Audit Tracking](audit-tracking.md)
14
+ - [Soft Deletes](soft-deletes.md)
12
15
 
13
- - Schema
14
-
15
- - [Schema Overview](schema/README.md)
16
-
17
- - Query Operations
16
+ - CRUD Operations
18
17
 
19
- - [Query Overview](query/README.md)
18
+ - [Overview](query/README.md)
20
19
  - [Create](query/create.md)
21
20
  - [Read](query/read.md)
22
21
  - [Update](query/update.md)
@@ -25,14 +24,47 @@
25
24
 
26
25
  - Providers
27
26
 
28
- - [Providers Overview](providers/README.md)
27
+ - [Overview](providers/README.md)
29
28
  - [MySQL](providers/mysql.md)
30
29
  - [MSSQL](providers/mssql.md)
30
+ - [PostgreSQL](providers/postgresql.md)
31
31
  - [SQLite](providers/sqlite.md)
32
+ - [MongoDB](providers/mongodb.md)
33
+ - [RocksDB](providers/rocksdb.md)
32
34
  - [ALASQL](providers/alasql.md)
35
+ - [MeadowEndpoints](providers/meadow-endpoints.md)
33
36
 
34
- - Advanced
37
+ - API Reference
35
38
 
36
- - [Audit Tracking](audit-tracking.md)
37
- - [Soft Deletes](soft-deletes.md)
38
- - [Configuration Reference](configuration.md)
39
+ - [Overview](api/reference.md)
40
+
41
+ - CRUD Methods
42
+
43
+ - [doCreate()](api/doCreate.md)
44
+ - [doRead()](api/doRead.md)
45
+ - [doReads()](api/doReads.md)
46
+ - [doUpdate()](api/doUpdate.md)
47
+ - [doDelete()](api/doDelete.md)
48
+ - [doUndelete()](api/doUndelete.md)
49
+ - [doCount()](api/doCount.md)
50
+
51
+ - Configuration
52
+
53
+ - [setProvider()](api/setProvider.md)
54
+ - [setScope()](api/setScope.md)
55
+ - [setSchema()](api/setSchema.md)
56
+ - [setDefaultIdentifier()](api/setDefaultIdentifier.md)
57
+ - [setIDUser()](api/setIDUser.md)
58
+ - [setJsonSchema()](api/setJsonSchema.md)
59
+ - [setDefault()](api/setDefault.md)
60
+ - [setAuthorizer()](api/setAuthorizer.md)
61
+ - [setDomain()](api/setDomain.md)
62
+ - [loadFromPackage()](api/loadFromPackage.md)
63
+
64
+ - Utility
65
+
66
+ - [query (property)](api/query.md)
67
+ - [rawQueries](api/rawQueries.md)
68
+ - [validateObject()](api/validateObject.md)
69
+ - [marshalRecordFromSourceToObject()](api/marshalRecordFromSourceToObject.md)
70
+ - [getRoleName()](api/getRoleName.md)
@@ -0,0 +1,5 @@
1
+ [Home](/)
2
+ [Quick Start](quick-start.md)
3
+ [Schema](schema/README.md)
4
+ [API Reference](api/reference.md)
5
+ [GitHub](https://github.com/stevenvelozo/meadow)
@@ -0,0 +1,109 @@
1
+ # doCount
2
+
3
+ Count records matching the query filters.
4
+
5
+ ## Signature
6
+
7
+ ```javascript
8
+ meadow.doCount(pQuery, fCallBack)
9
+ ```
10
+
11
+ ## Parameters
12
+
13
+ | Name | Type | Description |
14
+ |------|------|-------------|
15
+ | `pQuery` | `Object` | A FoxHound query object with optional filters |
16
+ | `fCallBack` | `Function` | Callback invoked when the operation completes |
17
+
18
+ ## Callback
19
+
20
+ ```javascript
21
+ function (pError, pQuery, pCount)
22
+ ```
23
+
24
+ | Name | Type | Description |
25
+ |------|------|-------------|
26
+ | `pError` | `string\|null` | Error message, or falsy on success |
27
+ | `pQuery` | `Object` | The FoxHound query used for the count operation |
28
+ | `pCount` | `number\|false` | The integer count of matching records, or `false` on failure |
29
+
30
+ ## Returns
31
+
32
+ Returns the Meadow instance for chaining.
33
+
34
+ ## Description
35
+
36
+ `doCount` executes a two-step asynchronous waterfall:
37
+
38
+ 1. **Count** -- If a `Count` raw query override is set via
39
+ `rawQueries.setQuery('Count', ...)`, it is used. Otherwise, the provider's
40
+ `Count` method executes the query.
41
+
42
+ 2. **Validate and profile** -- The result is verified to be a number. If the
43
+ provider returned a non-numeric value, the callback receives
44
+ `'Count did not return valid results.'`. The elapsed time is checked against
45
+ the `QueryThresholdWarnTime` setting (default 200ms). If the query exceeded
46
+ the threshold, `logSlowQuery` emits a warning.
47
+
48
+ Soft-deleted records are excluded by default unless delete tracking is disabled
49
+ on the query.
50
+
51
+ ## Examples
52
+
53
+ ### Count all records
54
+
55
+ ```javascript
56
+ var tmpQuery = meadow.query;
57
+
58
+ meadow.doCount(tmpQuery,
59
+ function (pError, pQuery, pCount)
60
+ {
61
+ if (pError)
62
+ {
63
+ console.error('Count error:', pError);
64
+ return;
65
+ }
66
+ console.log('Total books:', pCount);
67
+ });
68
+ ```
69
+
70
+ ### Count with filters
71
+
72
+ ```javascript
73
+ var tmpQuery = meadow.query
74
+ .addFilter('Author', 'Tolkien');
75
+
76
+ meadow.doCount(tmpQuery,
77
+ function (pError, pQuery, pCount)
78
+ {
79
+ console.log('Books by Tolkien:', pCount);
80
+ });
81
+ ```
82
+
83
+ ### Count including soft-deleted records
84
+
85
+ ```javascript
86
+ var tmpQuery = meadow.query
87
+ .setDisableDeleteTracking(true);
88
+
89
+ meadow.doCount(tmpQuery,
90
+ function (pError, pQuery, pCount)
91
+ {
92
+ console.log('Total including deleted:', pCount);
93
+ });
94
+ ```
95
+
96
+ ## Notes
97
+
98
+ - The `Count` raw query override applies to this method. Set it via
99
+ `meadow.rawQueries.setQuery('Count', pQueryString)`.
100
+
101
+ - Slow query profiling measures elapsed wall time from the start of `doCount`
102
+ through provider completion. The threshold defaults to 200ms and can be
103
+ configured via the `QueryThresholdWarnTime` Fable setting.
104
+
105
+ - The result is always an integer. If the provider returns a non-number, the
106
+ callback receives an error and `pCount` is `false`.
107
+
108
+ - Soft-deleted records are excluded by default. Use
109
+ `setDisableDeleteTracking(true)` on the query to include them in the count.
@@ -0,0 +1,132 @@
1
+ # doCreate
2
+
3
+ Insert a new record into the data source, read it back, and return the
4
+ marshalled result.
5
+
6
+ ## Signature
7
+
8
+ ```javascript
9
+ meadow.doCreate(pQuery, fCallBack)
10
+ ```
11
+
12
+ ## Parameters
13
+
14
+ | Name | Type | Description |
15
+ |------|------|-------------|
16
+ | `pQuery` | `Object` | A FoxHound query object with at least one record added via `addRecord()` |
17
+ | `fCallBack` | `Function` | Callback invoked when the operation completes |
18
+
19
+ ## Callback
20
+
21
+ ```javascript
22
+ function (pError, pCreateQuery, pReadQuery, pRecord)
23
+ ```
24
+
25
+ | Name | Type | Description |
26
+ |------|------|-------------|
27
+ | `pError` | `string\|null` | Error message, or falsy on success |
28
+ | `pCreateQuery` | `Object` | The FoxHound query used for the INSERT operation |
29
+ | `pReadQuery` | `Object` | The FoxHound query used for the read-back operation |
30
+ | `pRecord` | `Object\|false` | The marshalled record, or `false` on failure |
31
+
32
+ ## Returns
33
+
34
+ Returns the Meadow instance for chaining.
35
+
36
+ ## Description
37
+
38
+ `doCreate` executes a four-step asynchronous waterfall:
39
+
40
+ 1. **GUID uniqueness check** -- If the record contains a GUID column value
41
+ (the `defaultGUIdentifier`, e.g. `GUIDBook`) that is at least 5 characters
42
+ long, Meadow reads the data source to confirm no existing record has that
43
+ GUID. If a duplicate is found, the callback receives an error.
44
+
45
+ 2. **Insert** -- The record is merged with the default object template so that
46
+ all schema columns have values. The `IDUser` is set automatically from
47
+ either `pQuery.userID` or `meadow.userIdentifier` when not already present
48
+ on the query. The provider's `Create` method executes the insert.
49
+
50
+ 3. **Read back** -- After a successful insert, the newly created record is read
51
+ from the data source using the returned primary key value. If a `Read` raw
52
+ query override is set, it is used for this step.
53
+
54
+ 4. **Marshal** -- The raw database row is converted to a plain JavaScript
55
+ object via `marshalRecordFromSourceToObject`.
56
+
57
+ ## Examples
58
+
59
+ ### Basic create
60
+
61
+ ```javascript
62
+ var tmpQuery = meadow.query
63
+ .addRecord({ Title: 'The Hobbit', Author: 'Tolkien' });
64
+
65
+ meadow.doCreate(tmpQuery,
66
+ function (pError, pCreateQuery, pReadQuery, pRecord)
67
+ {
68
+ if (pError)
69
+ {
70
+ console.error('Create failed:', pError);
71
+ return;
72
+ }
73
+ console.log('New record ID:', pRecord.IDBook);
74
+ });
75
+ ```
76
+
77
+ ### Create with a specific GUID
78
+
79
+ ```javascript
80
+ var tmpQuery = meadow.query
81
+ .addRecord({
82
+ GUIDBook: '0x12345-abcde-67890',
83
+ Title: 'Dune'
84
+ });
85
+
86
+ meadow.doCreate(tmpQuery,
87
+ function (pError, pCreateQuery, pReadQuery, pRecord)
88
+ {
89
+ if (pError)
90
+ {
91
+ // Error if GUID already exists
92
+ console.error(pError);
93
+ return;
94
+ }
95
+ console.log('Created with GUID:', pRecord.GUIDBook);
96
+ });
97
+ ```
98
+
99
+ ### Create with explicit user ID on the query
100
+
101
+ ```javascript
102
+ var tmpQuery = meadow.query
103
+ .setIDUser(42)
104
+ .addRecord({ Title: 'Neuromancer' });
105
+
106
+ meadow.doCreate(tmpQuery,
107
+ function (pError, pCreateQuery, pReadQuery, pRecord)
108
+ {
109
+ // CreatingIDUser will be 42
110
+ console.log(pRecord);
111
+ });
112
+ ```
113
+
114
+ ## Notes
115
+
116
+ - The query **must** have a record added via `addRecord()` before calling
117
+ `doCreate`. If `pQuery.query.records` is falsy, the callback receives
118
+ `'No record submitted'`.
119
+
120
+ - GUID uniqueness is only checked when the GUID value is at least 5 characters
121
+ long. Shorter values or empty strings skip the check.
122
+
123
+ - The default object template (set via `setDefault`) is merged into the record
124
+ before insert, ensuring all schema columns have initial values.
125
+
126
+ - `Create` raw query overrides are **not** supported. The comment in the source
127
+ notes that create overrides are too complex. However, `Read` raw query
128
+ overrides **are** used during the read-back step.
129
+
130
+ - The `IDUser` resolution order is: `pQuery.query.IDUser` (if already set) >
131
+ `pQuery.userID` (if a non-negative integer) > `meadow.userIdentifier`
132
+ (fallback).
@@ -0,0 +1,101 @@
1
+ # doDelete
2
+
3
+ Delete a record from the data source. Uses soft delete when the schema includes
4
+ a `Deleted` column, otherwise performs a hard delete.
5
+
6
+ ## Signature
7
+
8
+ ```javascript
9
+ meadow.doDelete(pQuery, fCallBack)
10
+ ```
11
+
12
+ ## Parameters
13
+
14
+ | Name | Type | Description |
15
+ |------|------|-------------|
16
+ | `pQuery` | `Object` | A FoxHound query object with filters identifying the record(s) to delete |
17
+ | `fCallBack` | `Function` | Callback invoked when the operation completes |
18
+
19
+ ## Callback
20
+
21
+ ```javascript
22
+ function (pError, pQuery, pCount)
23
+ ```
24
+
25
+ | Name | Type | Description |
26
+ |------|------|-------------|
27
+ | `pError` | `string\|null` | Error message, or falsy on success |
28
+ | `pQuery` | `Object` | The FoxHound query used for the delete operation |
29
+ | `pCount` | `number` | The number of affected records |
30
+
31
+ ## Returns
32
+
33
+ Returns the Meadow instance for chaining.
34
+
35
+ ## Description
36
+
37
+ `doDelete` executes a single-step asynchronous waterfall:
38
+
39
+ 1. **Delete** -- If a `Delete` raw query override is set via
40
+ `rawQueries.setQuery('Delete', ...)`, it is used. Otherwise, the provider's
41
+ `Delete` method executes the query. The provider determines the actual SQL
42
+ based on the schema:
43
+
44
+ - **Soft delete**: If the schema contains a column with type `Deleted`, the
45
+ provider issues `UPDATE {Scope} SET Deleted=1, DeleteDate=NOW(),
46
+ DeletingIDUser={IDUser} WHERE ...`.
47
+ - **Hard delete**: If no `Deleted` column exists, the provider issues
48
+ `DELETE FROM {Scope} WHERE ...`.
49
+
50
+ ## Examples
51
+
52
+ ### Delete by primary key
53
+
54
+ ```javascript
55
+ var tmpQuery = meadow.query
56
+ .addFilter('IDBook', 42);
57
+
58
+ meadow.doDelete(tmpQuery,
59
+ function (pError, pQuery, pCount)
60
+ {
61
+ if (pError)
62
+ {
63
+ console.error('Delete failed:', pError);
64
+ return;
65
+ }
66
+ console.log('Deleted', pCount, 'record(s)');
67
+ });
68
+ ```
69
+
70
+ ### Delete with a custom raw query
71
+
72
+ ```javascript
73
+ meadow.rawQueries.setQuery('Delete',
74
+ 'UPDATE Book SET Deleted=1, DeleteDate=NOW() WHERE IDBook = :IDBook AND OwnerIDUser = :IDUser');
75
+
76
+ var tmpQuery = meadow.query
77
+ .addFilter('IDBook', 42);
78
+
79
+ meadow.doDelete(tmpQuery,
80
+ function (pError, pQuery, pCount)
81
+ {
82
+ console.log('Custom delete affected', pCount, 'record(s)');
83
+ });
84
+ ```
85
+
86
+ ## Notes
87
+
88
+ - Soft delete is automatic when the schema includes `{ Column: 'Deleted',
89
+ Type: 'Deleted' }`. No configuration is needed beyond the schema definition.
90
+
91
+ - After a soft delete, the record still exists in the database with
92
+ `Deleted = 1`. Subsequent `doRead` and `doReads` calls will exclude it by
93
+ default (unless `setDisableDeleteTracking(true)` is set on the query).
94
+
95
+ - Use [doUndelete](doUndelete.md) to restore a soft-deleted record.
96
+
97
+ - The `Delete` raw query override applies to this method. Set it via
98
+ `meadow.rawQueries.setQuery('Delete', pQueryString)`.
99
+
100
+ - Hard deletes are irreversible. Only schemas without a `Deleted` column
101
+ trigger hard deletes.
@@ -0,0 +1,122 @@
1
+ # doRead
2
+
3
+ Read a single record from the data source and return it as a marshalled plain
4
+ object.
5
+
6
+ ## Signature
7
+
8
+ ```javascript
9
+ meadow.doRead(pQuery, fCallBack)
10
+ ```
11
+
12
+ ## Parameters
13
+
14
+ | Name | Type | Description |
15
+ |------|------|-------------|
16
+ | `pQuery` | `Object` | A FoxHound query object with filters set to identify the target record |
17
+ | `fCallBack` | `Function` | Callback invoked when the operation completes |
18
+
19
+ ## Callback
20
+
21
+ ```javascript
22
+ function (pError, pQuery, pRecord)
23
+ ```
24
+
25
+ | Name | Type | Description |
26
+ |------|------|-------------|
27
+ | `pError` | `string\|null` | Error message, or falsy on success |
28
+ | `pQuery` | `Object` | The FoxHound query used for the read operation |
29
+ | `pRecord` | `Object\|false` | The marshalled record, or `false` if no record was found |
30
+
31
+ ## Returns
32
+
33
+ Returns the Meadow instance for chaining.
34
+
35
+ ## Description
36
+
37
+ `doRead` executes a two-step asynchronous waterfall:
38
+
39
+ 1. **Read** -- The provider's `Read` method executes the query. If a `Read`
40
+ raw query override is set via `rawQueries.setQuery('Read', ...)`, it is
41
+ used instead of the auto-generated query.
42
+
43
+ 2. **Marshal** -- If at least one record is returned, the first row is
44
+ converted to a plain JavaScript object via `marshalRecordFromSourceToObject`.
45
+ If no rows match, `pRecord` is `false` (not an error).
46
+
47
+ Soft-deleted records (those with `Deleted = 1`) are excluded by default unless
48
+ delete tracking has been explicitly disabled on the query via
49
+ `setDisableDeleteTracking(true)`.
50
+
51
+ ## Examples
52
+
53
+ ### Read by primary key
54
+
55
+ ```javascript
56
+ var tmpQuery = meadow.query
57
+ .addFilter('IDBook', 42);
58
+
59
+ meadow.doRead(tmpQuery,
60
+ function (pError, pQuery, pRecord)
61
+ {
62
+ if (pError)
63
+ {
64
+ console.error('Read error:', pError);
65
+ return;
66
+ }
67
+ if (!pRecord)
68
+ {
69
+ console.log('No record found');
70
+ return;
71
+ }
72
+ console.log('Title:', pRecord.Title);
73
+ });
74
+ ```
75
+
76
+ ### Read by GUID
77
+
78
+ ```javascript
79
+ var tmpQuery = meadow.query
80
+ .addFilter('GUIDBook', '0x12345-abcde-67890');
81
+
82
+ meadow.doRead(tmpQuery,
83
+ function (pError, pQuery, pRecord)
84
+ {
85
+ if (pRecord)
86
+ {
87
+ console.log('Found:', pRecord.Title);
88
+ }
89
+ });
90
+ ```
91
+
92
+ ### Read including soft-deleted records
93
+
94
+ ```javascript
95
+ var tmpQuery = meadow.query
96
+ .addFilter('IDBook', 99)
97
+ .setDisableDeleteTracking(true);
98
+
99
+ meadow.doRead(tmpQuery,
100
+ function (pError, pQuery, pRecord)
101
+ {
102
+ if (pRecord)
103
+ {
104
+ console.log('Deleted?', pRecord.Deleted);
105
+ }
106
+ });
107
+ ```
108
+
109
+ ## Notes
110
+
111
+ - When no record is found, `pRecord` is `false` and `pError` is `undefined`
112
+ (not an error condition). Always check for a falsy record.
113
+
114
+ - `doRead` returns only the **first** matching record. To read multiple records,
115
+ use [doReads](doReads.md).
116
+
117
+ - The `Read` raw query override applies to this method. Set it via
118
+ `meadow.rawQueries.setQuery('Read', pQueryString)`.
119
+
120
+ - The returned object is built from the default object template overlaid with
121
+ provider-marshalled values, so all schema columns are present even if the
122
+ database row has nulls.
@@ -0,0 +1,136 @@
1
+ # doReads
2
+
3
+ Read multiple records from the data source and return them as an array of
4
+ marshalled plain objects.
5
+
6
+ ## Signature
7
+
8
+ ```javascript
9
+ meadow.doReads(pQuery, fCallBack)
10
+ ```
11
+
12
+ ## Parameters
13
+
14
+ | Name | Type | Description |
15
+ |------|------|-------------|
16
+ | `pQuery` | `Object` | A FoxHound query object with filters, pagination, and sort options |
17
+ | `fCallBack` | `Function` | Callback invoked when the operation completes |
18
+
19
+ ## Callback
20
+
21
+ ```javascript
22
+ function (pError, pQuery, pRecords)
23
+ ```
24
+
25
+ | Name | Type | Description |
26
+ |------|------|-------------|
27
+ | `pError` | `string\|null` | Error message, or falsy on success |
28
+ | `pQuery` | `Object` | The FoxHound query used for the read operation |
29
+ | `pRecords` | `Array` | Array of marshalled record objects (empty array if none found) |
30
+
31
+ ## Returns
32
+
33
+ Returns the Meadow instance for chaining.
34
+
35
+ ## Description
36
+
37
+ `doReads` executes a two-step asynchronous waterfall:
38
+
39
+ 1. **Read** -- The provider's `Read` method executes the query. If a `Reads`
40
+ raw query override is set via `rawQueries.setQuery('Reads', ...)`, it is
41
+ used instead of the auto-generated query.
42
+
43
+ 2. **Marshal and profile** -- Each returned row is converted to a plain
44
+ JavaScript object via `marshalRecordFromSourceToObject` and pushed into an
45
+ array. After the provider returns, the elapsed time is checked against the
46
+ `QueryThresholdWarnTime` setting (default 200ms). If the query exceeded the
47
+ threshold, `logSlowQuery` emits a warning.
48
+
49
+ Soft-deleted records are excluded by default unless delete tracking is disabled
50
+ on the query.
51
+
52
+ ## Examples
53
+
54
+ ### Read all records (with default cap)
55
+
56
+ ```javascript
57
+ var tmpQuery = meadow.query;
58
+
59
+ meadow.doReads(tmpQuery,
60
+ function (pError, pQuery, pRecords)
61
+ {
62
+ if (pError)
63
+ {
64
+ console.error('Reads error:', pError);
65
+ return;
66
+ }
67
+ console.log('Found', pRecords.length, 'records');
68
+ pRecords.forEach(function (pRecord)
69
+ {
70
+ console.log('-', pRecord.Title);
71
+ });
72
+ });
73
+ ```
74
+
75
+ ### Read with filters and pagination
76
+
77
+ ```javascript
78
+ var tmpQuery = meadow.query
79
+ .addFilter('Author', 'Tolkien')
80
+ .setCap(10)
81
+ .setBegin(0)
82
+ .addSort({ Column: 'Title', Direction: 'ASC' });
83
+
84
+ meadow.doReads(tmpQuery,
85
+ function (pError, pQuery, pRecords)
86
+ {
87
+ console.log('Page 1:', pRecords.length, 'results');
88
+ });
89
+ ```
90
+
91
+ ### Read with specific data elements
92
+
93
+ ```javascript
94
+ var tmpQuery = meadow.query
95
+ .setDataElements(['IDBook', 'Title', 'Author']);
96
+
97
+ meadow.doReads(tmpQuery,
98
+ function (pError, pQuery, pRecords)
99
+ {
100
+ // Each record will have only the requested columns
101
+ // (plus any columns derived from the default object)
102
+ console.log(pRecords);
103
+ });
104
+ ```
105
+
106
+ ### Read with custom slow query threshold
107
+
108
+ ```javascript
109
+ // In Fable settings:
110
+ // { QueryThresholdWarnTime: 500 }
111
+
112
+ var tmpQuery = meadow.query
113
+ .addFilter('Genre', 'Fantasy');
114
+
115
+ meadow.doReads(tmpQuery,
116
+ function (pError, pQuery, pRecords)
117
+ {
118
+ // Queries taking longer than 500ms will trigger a warning log
119
+ console.log(pRecords.length, 'records');
120
+ });
121
+ ```
122
+
123
+ ## Notes
124
+
125
+ - The `Reads` raw query override is **separate** from the `Read` override. Set
126
+ it via `meadow.rawQueries.setQuery('Reads', pQueryString)`.
127
+
128
+ - Slow query profiling measures elapsed wall time from the start of `doReads`
129
+ through provider completion. The threshold defaults to 200ms and can be
130
+ configured via the `QueryThresholdWarnTime` Fable setting.
131
+
132
+ - Each record in the result array is independently marshalled through the
133
+ default object template, so all schema columns are present on every record.
134
+
135
+ - An empty result set returns an empty array `[]`, not `false`. This differs
136
+ from `doRead` which returns `false` for no results.