retold-data-service 2.0.9 → 2.0.11

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.
@@ -0,0 +1,93 @@
1
+ # Configuration
2
+
3
+ Retold Data Service accepts options during instantiation that control model loading, storage provider selection, and server behavior.
4
+
5
+ ## Options Reference
6
+
7
+ | Option | Type | Default | Description |
8
+ |--------|------|---------|-------------|
9
+ | `StorageProvider` | String | `'MySQL'` | Meadow provider name (`MySQL`, `SQLite`, `MSSQL`, `ALASQL`) |
10
+ | `StorageProviderModule` | String | `'meadow-connection-mysql'` | npm module name for the storage provider |
11
+ | `FullMeadowSchemaPath` | String | `${process.cwd()}/model/` | Directory path where the compiled schema lives |
12
+ | `FullMeadowSchemaFilename` | String | `'MeadowModel-Extended.json'` | Filename of the compiled Stricture schema |
13
+ | `AutoInitializeDataService` | Boolean | `true` | Whether to auto-initialize on construction |
14
+ | `AutoStartOrator` | Boolean | `true` | Whether to start the Orator web server during initialization |
15
+
16
+ ## Fable Settings
17
+
18
+ The Fable instance configuration controls server port and database connection:
19
+
20
+ ```javascript
21
+ {
22
+ Product: 'MyApp',
23
+ APIServerPort: 8086,
24
+
25
+ // For MySQL
26
+ MySQL: {
27
+ Server: '127.0.0.1',
28
+ Port: 3306,
29
+ User: 'root',
30
+ Password: 'secret',
31
+ Database: 'mydb',
32
+ ConnectionPoolLimit: 20
33
+ },
34
+ MeadowConnectionMySQLAutoConnect: true,
35
+
36
+ // For SQLite
37
+ SQLite: {
38
+ SQLiteFilePath: './data/myapp.db'
39
+ }
40
+ }
41
+ ```
42
+
43
+ ## Example: MySQL Configuration
44
+
45
+ ```javascript
46
+ _Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
47
+ FullMeadowSchemaPath: `${__dirname}/model/`,
48
+ FullMeadowSchemaFilename: 'MeadowModel-Extended.json',
49
+ StorageProvider: 'MySQL',
50
+ StorageProviderModule: 'meadow-connection-mysql',
51
+ AutoStartOrator: true
52
+ });
53
+ ```
54
+
55
+ ## Example: SQLite Configuration
56
+
57
+ ```javascript
58
+ // Register the SQLite provider before creating the data service
59
+ const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
60
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
61
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
62
+
63
+ _Fable.MeadowSQLiteProvider.connectAsync(
64
+ (pError) =>
65
+ {
66
+ _Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
67
+ FullMeadowSchemaPath: `${__dirname}/model/`,
68
+ FullMeadowSchemaFilename: 'MeadowModel-Extended.json',
69
+ StorageProvider: 'SQLite',
70
+ StorageProviderModule: 'meadow-connection-sqlite',
71
+ AutoStartOrator: true
72
+ });
73
+ });
74
+ ```
75
+
76
+ ## Example: Disabling Auto-Start
77
+
78
+ ```javascript
79
+ _Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
80
+ FullMeadowSchemaPath: `${__dirname}/model/`,
81
+ FullMeadowSchemaFilename: 'MeadowModel-Extended.json',
82
+ AutoStartOrator: false
83
+ });
84
+
85
+ // Manually start later
86
+ _Fable.RetoldDataService.initializeService(
87
+ (pError) =>
88
+ {
89
+ // Service initialized without starting the web server
90
+ // Start it manually when ready:
91
+ _Fable.Orator.startService(() => console.log('Server started'));
92
+ });
93
+ ```
package/docs/cover.md ADDED
@@ -0,0 +1,11 @@
1
+ # Retold Data Service <small>2</small>
2
+
3
+ > All-in-one data service for the Retold ecosystem
4
+
5
+ - Schema-driven REST API generation from Stricture DDL models
6
+ - Automatic CRUD endpoints for every entity in your data model
7
+ - Pluggable storage providers: MySQL, SQLite, MSSQL, ALASQL
8
+ - Built on Fable, Meadow, and Orator with lifecycle hooks for customization
9
+
10
+ [GitHub](https://github.com/stevenvelozo/retold-data-service)
11
+ [Get Started](#retold-data-service)
@@ -0,0 +1,87 @@
1
+ # DAL Access
2
+
3
+ In addition to the REST endpoints, you can query your data directly through the Meadow DAL objects.
4
+
5
+ ## Accessing DAL Objects
6
+
7
+ After initialization, every entity in your model has a DAL object accessible via `fable.DAL`:
8
+
9
+ ```javascript
10
+ // Read a single record
11
+ let tmpQuery = _Fable.DAL.Book.query.addFilter('IDBook', 42);
12
+
13
+ _Fable.DAL.Book.doRead(tmpQuery,
14
+ (pError, pQuery, pRecord) =>
15
+ {
16
+ console.log('Found:', pRecord.Title);
17
+ });
18
+ ```
19
+
20
+ ## Available Operations
21
+
22
+ | Method | Description |
23
+ |--------|-------------|
24
+ | `doCreate(query, callback)` | Insert a new record |
25
+ | `doRead(query, callback)` | Read a single record |
26
+ | `doReads(query, callback)` | Read multiple records |
27
+ | `doUpdate(query, callback)` | Update an existing record |
28
+ | `doDelete(query, callback)` | Soft-delete a record |
29
+ | `doUndelete(query, callback)` | Restore a soft-deleted record |
30
+ | `doCount(query, callback)` | Count matching records |
31
+
32
+ ## Query Building
33
+
34
+ Each DAL has a `query` property (a FoxHound query instance) that you can configure with filters, sorting, and pagination:
35
+
36
+ ```javascript
37
+ // Read all Science Fiction books, newest first, page 1
38
+ let tmpQuery = _Fable.DAL.Book.query
39
+ .addFilter('Genre', 'Science Fiction')
40
+ .addSort({Column: 'PublicationYear', Direction: 'Descending'})
41
+ .setCap(25)
42
+ .setBegin(0);
43
+
44
+ _Fable.DAL.Book.doReads(tmpQuery,
45
+ (pError, pQuery, pRecords) =>
46
+ {
47
+ console.log(`Found ${pRecords.length} books`);
48
+ });
49
+ ```
50
+
51
+ ## Creating Records
52
+
53
+ ```javascript
54
+ let tmpQuery = _Fable.DAL.Author.query
55
+ .addRecord({Name: 'Frank Herbert'});
56
+
57
+ _Fable.DAL.Author.doCreate(tmpQuery,
58
+ (pError, pCreateQuery, pReadQuery, pRecord) =>
59
+ {
60
+ console.log('Created author with ID:', pRecord.IDAuthor);
61
+ });
62
+ ```
63
+
64
+ ## Counting Records
65
+
66
+ ```javascript
67
+ let tmpQuery = _Fable.DAL.Review.query;
68
+
69
+ _Fable.DAL.Review.doCount(tmpQuery,
70
+ (pError, pQuery, pCount) =>
71
+ {
72
+ console.log('Total reviews:', pCount);
73
+ });
74
+ ```
75
+
76
+ ## When to Use DAL vs Endpoints
77
+
78
+ Use the **REST endpoints** when:
79
+ - Building a web UI that communicates over HTTP
80
+ - Exposing an API for external consumers
81
+ - You need session management and authorization
82
+
83
+ Use **DAL access** when:
84
+ - Running server-side business logic
85
+ - Performing batch operations
86
+ - Writing behavior injection hooks that need to query related entities
87
+ - Running background tasks or workers
@@ -0,0 +1,121 @@
1
+ # Endpoints
2
+
3
+ Once initialized, Retold Data Service automatically creates RESTful endpoints for every entity in your Stricture model.
4
+
5
+ ## URL Pattern
6
+
7
+ All endpoints follow the Meadow Endpoints URL pattern:
8
+
9
+ ```
10
+ /{Version}/{Entity} — singular entity operations (Read, Create, Update, Delete)
11
+ /{Version}/{Entity}s — plural entity operations (Reads, Count)
12
+ ```
13
+
14
+ The version defaults to `1.0`.
15
+
16
+ ## Available Endpoints
17
+
18
+ For an entity named `Book`, these endpoints are created:
19
+
20
+ ### Read (Single Record)
21
+
22
+ ```
23
+ GET /1.0/Book/:IDRecord
24
+ ```
25
+
26
+ Returns a single record by primary key. Returns a 404 error object if not found.
27
+
28
+ ### Read (Multiple Records)
29
+
30
+ ```
31
+ GET /1.0/Books
32
+ GET /1.0/Books/:Begin/:Cap
33
+ GET /1.0/Books/FilteredTo/:Filter
34
+ GET /1.0/Books/FilteredTo/:Filter/:Begin/:Cap
35
+ ```
36
+
37
+ Returns an array of records. Supports pagination via `Begin` and `Cap` parameters, and filtering via the Meadow filter stanza format.
38
+
39
+ ### Create
40
+
41
+ ```
42
+ POST /1.0/Book
43
+ Body: { "Title": "Dune", "Genre": "Science Fiction" }
44
+ ```
45
+
46
+ Creates a new record and returns the created record (with auto-generated ID and GUID).
47
+
48
+ ### Update
49
+
50
+ ```
51
+ PUT /1.0/Book
52
+ Body: { "IDBook": 1, "Title": "Dune (Updated)" }
53
+ ```
54
+
55
+ Updates an existing record and returns the updated record. The request body must include the primary key.
56
+
57
+ ### Delete (Soft Delete)
58
+
59
+ ```
60
+ DELETE /1.0/Book/:IDRecord
61
+ ```
62
+
63
+ Soft-deletes a record (sets `Deleted = 1`). Returns the number of affected records.
64
+
65
+ ### Count
66
+
67
+ ```
68
+ GET /1.0/Books/Count
69
+ GET /1.0/Books/Count/FilteredTo/:Filter
70
+ GET /1.0/Books/Count/By/:ByField/:ByValue
71
+ ```
72
+
73
+ Returns the count of matching records as `{ "Count": N }`.
74
+
75
+ ### Schema
76
+
77
+ ```
78
+ GET /1.0/Book/Schema
79
+ ```
80
+
81
+ Returns the JSON Schema for the entity.
82
+
83
+ ### New Default Record
84
+
85
+ ```
86
+ GET /1.0/Book/Schema/New
87
+ ```
88
+
89
+ Returns a new default record with all fields set to their default values.
90
+
91
+ ## Filter Stanza Format
92
+
93
+ Filters use the Meadow filter stanza format in the URL:
94
+
95
+ ```
96
+ FBV~Column~Operator~Value
97
+ ```
98
+
99
+ | Code | Meaning |
100
+ |------|---------|
101
+ | `FBV` | Filter By Value |
102
+ | `EQ` | Equals |
103
+ | `NE` | Not Equals |
104
+ | `GT` | Greater Than |
105
+ | `GE` | Greater Than or Equal |
106
+ | `LT` | Less Than |
107
+ | `LE` | Less Than or Equal |
108
+ | `LK` | LIKE |
109
+
110
+ ### Examples
111
+
112
+ ```
113
+ # Filter by exact genre
114
+ GET /1.0/Books/FilteredTo/FBV~Genre~EQ~Science Fiction
115
+
116
+ # Filter by title pattern (URL-encode the % as %25)
117
+ GET /1.0/Books/FilteredTo/FBV~Title~LK~%25Dune%25
118
+
119
+ # Count filtered records
120
+ GET /1.0/Books/Count/FilteredTo/FBV~Genre~EQ~Fantasy
121
+ ```
@@ -0,0 +1,39 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7
+ <meta name="description" content="Documentation powered by pict-docuserve">
8
+
9
+ <title>Documentation</title>
10
+
11
+ <!-- Application Stylesheet -->
12
+ <link href="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/css/docuserve.css" rel="stylesheet">
13
+ <!-- KaTeX stylesheet for LaTeX equation rendering -->
14
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.css">
15
+ <!-- PICT Dynamic View CSS Container -->
16
+ <style id="PICT-CSS"></style>
17
+
18
+ <!-- Load the PICT library from jsDelivr CDN -->
19
+ <script src="https://cdn.jsdelivr.net/npm/pict@1/dist/pict.min.js" type="text/javascript"></script>
20
+ <!-- Bootstrap the Application -->
21
+ <script type="text/javascript">
22
+ //<![CDATA[
23
+ Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(PictDocuserve, 2)});
24
+ //]]>
25
+ </script>
26
+ </head>
27
+ <body>
28
+ <!-- The root container for the Pict application -->
29
+ <div id="Docuserve-Application-Container"></div>
30
+
31
+ <!-- Mermaid diagram rendering -->
32
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
33
+ <script>mermaid.initialize({ startOnLoad: false, theme: 'default' });</script>
34
+ <!-- KaTeX for LaTeX equation rendering -->
35
+ <script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.21/dist/katex.min.js"></script>
36
+ <!-- Load the Docuserve PICT Application Bundle from jsDelivr CDN -->
37
+ <script src="https://cdn.jsdelivr.net/npm/pict-docuserve@0/dist/pict-docuserve.min.js" type="text/javascript"></script>
38
+ </body>
39
+ </html>
@@ -0,0 +1,77 @@
1
+ # Initialization
2
+
3
+ Retold Data Service follows an ordered initialization sequence. Understanding this sequence is key to customizing the service behavior.
4
+
5
+ ## Basic Initialization
6
+
7
+ ```javascript
8
+ const libFable = require('fable');
9
+ const libRetoldDataService = require('retold-data-service');
10
+
11
+ const _Fable = new libFable(settings);
12
+
13
+ // 1. Register the service type
14
+ _Fable.serviceManager.addServiceType('RetoldDataService', libRetoldDataService);
15
+
16
+ // 2. Instantiate the service with options
17
+ _Fable.serviceManager.instantiateServiceProvider('RetoldDataService', options);
18
+
19
+ // 3. Initialize the service
20
+ _Fable.RetoldDataService.initializeService(
21
+ (pError) =>
22
+ {
23
+ if (pError) return console.error('Init failed:', pError);
24
+ console.log('Ready!');
25
+ });
26
+ ```
27
+
28
+ ## Initialization Sequence
29
+
30
+ When `initializeService()` is called, the following steps run in order:
31
+
32
+ ```
33
+ 1. onBeforeInitialize() ← your custom hook
34
+ 2. Start Orator web server ← if AutoStartOrator is true
35
+ 3. initializePersistenceEngine() ← loads the storage provider module
36
+ 4. onInitialize() ← your custom hook
37
+ 5. initializeDataEndpoints() ← loads model, creates DAL + endpoints
38
+ 6. onAfterInitialize() ← your custom hook
39
+ ```
40
+
41
+ ### Step 5: initializeDataEndpoints()
42
+
43
+ This is the core step where the model is loaded and endpoints are created:
44
+
45
+ 1. Load the compiled Stricture schema from `FullMeadowSchemaPath + FullMeadowSchemaFilename`
46
+ 2. Extract the list of table names from `model.Tables`
47
+ 3. For each table:
48
+ - Create a Meadow DAL from the table's `MeadowSchema` package
49
+ - Set the DAL's provider to the configured `StorageProvider`
50
+ - Create a Meadow Endpoints controller for the DAL
51
+ - Connect the endpoint routes to the Orator service server
52
+
53
+ ## Double-Initialization Protection
54
+
55
+ Calling `initializeService()` a second time returns an error:
56
+
57
+ ```javascript
58
+ _Fable.RetoldDataService.initializeService(
59
+ (pError) =>
60
+ {
61
+ // pError.message: "Retold Data Service Application is being
62
+ // initialized but has already been initialized..."
63
+ });
64
+ ```
65
+
66
+ ## Stopping the Service
67
+
68
+ ```javascript
69
+ _Fable.RetoldDataService.stopService(
70
+ (pError) =>
71
+ {
72
+ if (pError) return console.error('Stop failed:', pError);
73
+ console.log('Service stopped');
74
+ });
75
+ ```
76
+
77
+ Calling `stopService()` on an uninitialized service returns an error.
@@ -0,0 +1,81 @@
1
+ # Lifecycle Hooks
2
+
3
+ Retold Data Service provides three lifecycle hooks that you can override to customize initialization behavior.
4
+
5
+ ## Available Hooks
6
+
7
+ | Hook | Fires | Use Case |
8
+ |------|-------|----------|
9
+ | `onBeforeInitialize(fCallback)` | Before Orator starts and before the persistence engine loads | Environment checks, early configuration |
10
+ | `onInitialize(fCallback)` | After Orator starts and persistence engine loads, before data endpoints are created | Register additional services, run migrations |
11
+ | `onAfterInitialize(fCallback)` | After all data endpoints are created and routes are connected | Post-startup tasks, inject behaviors, warm caches |
12
+
13
+ ## Overriding Hooks
14
+
15
+ You can override the hooks by subclassing `RetoldDataService`:
16
+
17
+ ```javascript
18
+ const libRetoldDataService = require('retold-data-service');
19
+
20
+ class MyDataService extends libRetoldDataService
21
+ {
22
+ onBeforeInitialize(fCallback)
23
+ {
24
+ this.fable.log.info('Custom pre-initialization...');
25
+ // Perform environment validation, load configs, etc.
26
+ return fCallback();
27
+ }
28
+
29
+ onInitialize(fCallback)
30
+ {
31
+ this.fable.log.info('Custom initialization...');
32
+ // Run database migrations, register extra services, etc.
33
+ return fCallback();
34
+ }
35
+
36
+ onAfterInitialize(fCallback)
37
+ {
38
+ this.fable.log.info('Custom post-initialization...');
39
+ // Inject behaviors, seed data, start background tasks, etc.
40
+ this.fable.MeadowEndpoints.Book.controller.BehaviorInjection
41
+ .setBehavior('Read-PostOperation', myCustomHook);
42
+ return fCallback();
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Hook Execution Order
48
+
49
+ ```
50
+ initializeService() called
51
+
52
+ ├── onBeforeInitialize()
53
+
54
+ ├── Start Orator (if AutoStartOrator)
55
+
56
+ ├── initializePersistenceEngine()
57
+
58
+ ├── onInitialize()
59
+
60
+ ├── initializeDataEndpoints()
61
+ │ ├── Load schema model
62
+ │ ├── Create DAL for each entity
63
+ │ ├── Create Endpoints for each entity
64
+ │ └── Connect routes to Orator
65
+
66
+ ├── onAfterInitialize()
67
+
68
+ └── callback(error)
69
+ ```
70
+
71
+ ## Error Handling
72
+
73
+ If any hook or step passes an error to its callback, the initialization chain stops and the error is passed to the `initializeService` callback:
74
+
75
+ ```javascript
76
+ onInitialize(fCallback)
77
+ {
78
+ // Signal an error to stop initialization
79
+ return fCallback(new Error('Database migration failed'));
80
+ }
81
+ ```
@@ -0,0 +1,128 @@
1
+ # Schema Definition
2
+
3
+ Retold Data Service loads a compiled Stricture schema model to create its entities and endpoints.
4
+
5
+ ## The Stricture DDL
6
+
7
+ Schemas are defined using Stricture's DDL syntax, then compiled into a JSON model that Retold Data Service understands.
8
+
9
+ ### DDL Example
10
+
11
+ ```
12
+ !Book
13
+ @IDBook
14
+ %GUIDBook
15
+ &CreateDate
16
+ #CreatingIDUser
17
+ &UpdateDate
18
+ #UpdatingIDUser
19
+ ^Deleted
20
+ &DeleteDate
21
+ #DeletingIDUser
22
+ $Title 200
23
+ $Type 32
24
+ $Genre 128
25
+ $ISBN 64
26
+ $Language 12
27
+ #PublicationYear
28
+
29
+ !Author
30
+ @IDAuthor
31
+ %GUIDAuthor
32
+ &CreateDate
33
+ #CreatingIDUser
34
+ &UpdateDate
35
+ #UpdatingIDUser
36
+ ^Deleted
37
+ &DeleteDate
38
+ #DeletingIDUser
39
+ $Name 200
40
+ ```
41
+
42
+ ### DDL Symbols
43
+
44
+ | Symbol | Meaning | Meadow Type |
45
+ |--------|---------|-------------|
46
+ | `!` | Table/entity name | — |
47
+ | `@` | Auto-increment ID | `AutoIdentity` |
48
+ | `%` | Auto GUID | `AutoGUID` |
49
+ | `&` | DateTime column | `CreateDate`, `UpdateDate`, `DeleteDate`, or `DateTime` |
50
+ | `#` | Numeric column | `Integer`, `CreateIDUser`, `UpdateIDUser`, `DeleteIDUser` |
51
+ | `$` | String column (with size) | `String` |
52
+ | `^` | Boolean column | `Deleted` or `Boolean` |
53
+ | `.` | Decimal column (with precision) | `Decimal` |
54
+ | `*` | Text column | `String` (large) |
55
+
56
+ ## Compiling the Model
57
+
58
+ Use Stricture to compile the DDL into JSON:
59
+
60
+ ```bash
61
+ npx stricture -i model/ddl/BookStore.ddl
62
+ ```
63
+
64
+ This produces a `MeadowModel-Extended.json` file containing the full model with:
65
+ - Column definitions per table
66
+ - Meadow schema per table (with `AutoIdentity`, `AutoGUID`, `CreateDate`, etc.)
67
+ - JSON Schema per table
68
+ - Default objects per table
69
+ - Authorization rules per table
70
+
71
+ ## Model JSON Structure
72
+
73
+ ```json
74
+ {
75
+ "Tables": {
76
+ "Book": {
77
+ "TableName": "Book",
78
+ "Columns": [...],
79
+ "MeadowSchema": {
80
+ "Scope": "Book",
81
+ "DefaultIdentifier": "IDBook",
82
+ "Schema": [
83
+ {"Column": "IDBook", "Type": "AutoIdentity"},
84
+ {"Column": "GUIDBook", "Type": "AutoGUID"},
85
+ {"Column": "Title", "Type": "String", "Size": "200"},
86
+ ...
87
+ ],
88
+ "DefaultObject": {
89
+ "IDBook": 0,
90
+ "Title": "",
91
+ ...
92
+ },
93
+ "Authorization": { ... }
94
+ }
95
+ },
96
+ "Author": { ... }
97
+ }
98
+ }
99
+ ```
100
+
101
+ ## Build Script
102
+
103
+ The test model includes a build script for compiling the DDL:
104
+
105
+ ```bash
106
+ npm run build-test-model
107
+ ```
108
+
109
+ This runs `cd test && npx stricture -i model/ddl/BookStore.ddl` to regenerate the compiled model from the DDL.
110
+
111
+ ## Schema Types Reference
112
+
113
+ | Type | Description | Auto-Managed |
114
+ |------|-------------|-------------|
115
+ | `AutoIdentity` | Auto-increment primary key | On Create (NULL/omit) |
116
+ | `AutoGUID` | Unique identifier | On Create (UUID generated) |
117
+ | `CreateDate` | Creation timestamp | On Create |
118
+ | `CreateIDUser` | Creator user ID | On Create |
119
+ | `UpdateDate` | Last update timestamp | On Create and Update |
120
+ | `UpdateIDUser` | Last updater user ID | On Create and Update |
121
+ | `Deleted` | Soft-delete flag | On Delete (set to 1) |
122
+ | `DeleteDate` | Deletion timestamp | On Delete |
123
+ | `DeleteIDUser` | Deleter user ID | On Delete |
124
+ | `String` | Text data | — |
125
+ | `Integer` | Numeric data | — |
126
+ | `Decimal` | Decimal data | — |
127
+ | `Boolean` | Boolean data | — |
128
+ | `DateTime` | Date/time data | — |