retold-data-service 2.0.8 → 2.0.10
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/.vscode/settings.json +33 -14
- package/CONTRIBUTING.md +50 -0
- package/README.md +200 -56
- package/docs/.nojekyll +0 -0
- package/docs/README.md +76 -0
- package/docs/_sidebar.md +13 -0
- package/docs/architecture.md +94 -0
- package/docs/behavior-injection.md +111 -0
- package/docs/configuration.md +93 -0
- package/docs/cover.md +11 -0
- package/docs/dal-access.md +87 -0
- package/docs/endpoints.md +121 -0
- package/docs/index.html +39 -0
- package/docs/initialization.md +77 -0
- package/docs/lifecycle-hooks.md +81 -0
- package/docs/schema-definition.md +128 -0
- package/docs/storage-providers.md +109 -0
- package/package.json +10 -6
- package/source/Retold-Data-Service.js +22 -13
- package/test/RetoldDataService_tests.js +1315 -18
|
@@ -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 | — |
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Storage Providers
|
|
2
|
+
|
|
3
|
+
Retold Data Service supports any Meadow-compatible storage provider. The provider is configured through the `StorageProvider` and `StorageProviderModule` options.
|
|
4
|
+
|
|
5
|
+
## Available Providers
|
|
6
|
+
|
|
7
|
+
| Provider | Module | Best For |
|
|
8
|
+
|----------|--------|----------|
|
|
9
|
+
| MySQL | `meadow-connection-mysql` | Production web applications |
|
|
10
|
+
| SQLite | `meadow-connection-sqlite` | Embedded apps, testing, single-server deployments |
|
|
11
|
+
| MSSQL | `meadow-connection-mssql` | Enterprise SQL Server environments |
|
|
12
|
+
| ALASQL | Built into Meadow | In-memory / browser-side usage |
|
|
13
|
+
|
|
14
|
+
## MySQL Setup
|
|
15
|
+
|
|
16
|
+
MySQL is the default provider.
|
|
17
|
+
|
|
18
|
+
```javascript
|
|
19
|
+
const settings = {
|
|
20
|
+
APIServerPort: 8086,
|
|
21
|
+
MySQL: {
|
|
22
|
+
Server: '127.0.0.1',
|
|
23
|
+
Port: 3306,
|
|
24
|
+
User: 'root',
|
|
25
|
+
Password: 'secret',
|
|
26
|
+
Database: 'mydb',
|
|
27
|
+
ConnectionPoolLimit: 20
|
|
28
|
+
},
|
|
29
|
+
MeadowConnectionMySQLAutoConnect: true
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const _Fable = new libFable(settings);
|
|
33
|
+
|
|
34
|
+
_Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
|
|
35
|
+
StorageProvider: 'MySQL',
|
|
36
|
+
StorageProviderModule: 'meadow-connection-mysql',
|
|
37
|
+
FullMeadowSchemaPath: `${__dirname}/model/`,
|
|
38
|
+
FullMeadowSchemaFilename: 'MeadowModel-Extended.json'
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## SQLite Setup
|
|
43
|
+
|
|
44
|
+
SQLite requires pre-registering the connection provider before creating the data service:
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
|
|
48
|
+
|
|
49
|
+
const settings = {
|
|
50
|
+
APIServerPort: 8086,
|
|
51
|
+
SQLite: { SQLiteFilePath: './data/app.db' }
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const _Fable = new libFable(settings);
|
|
55
|
+
|
|
56
|
+
// Register and connect SQLite before creating the data service
|
|
57
|
+
_Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
|
|
58
|
+
_Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
|
|
59
|
+
|
|
60
|
+
_Fable.MeadowSQLiteProvider.connectAsync(
|
|
61
|
+
(pError) =>
|
|
62
|
+
{
|
|
63
|
+
_Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
|
|
64
|
+
StorageProvider: 'SQLite',
|
|
65
|
+
StorageProviderModule: 'meadow-connection-sqlite',
|
|
66
|
+
FullMeadowSchemaPath: `${__dirname}/model/`,
|
|
67
|
+
FullMeadowSchemaFilename: 'MeadowModel-Extended.json'
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
_Fable.RetoldDataService.initializeService(callback);
|
|
71
|
+
});
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
For in-memory testing, use `':memory:'` as the SQLite file path:
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
SQLite: { SQLiteFilePath: ':memory:' }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## MSSQL Setup
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const settings = {
|
|
84
|
+
APIServerPort: 8086,
|
|
85
|
+
MSSQL: {
|
|
86
|
+
Server: '127.0.0.1',
|
|
87
|
+
Port: 1433,
|
|
88
|
+
User: 'sa',
|
|
89
|
+
Password: 'YourPassword123',
|
|
90
|
+
Database: 'mydb'
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
_Fable.serviceManager.instantiateServiceProvider('RetoldDataService', {
|
|
95
|
+
StorageProvider: 'MSSQL',
|
|
96
|
+
StorageProviderModule: 'meadow-connection-mssql',
|
|
97
|
+
FullMeadowSchemaPath: `${__dirname}/model/`,
|
|
98
|
+
FullMeadowSchemaFilename: 'MeadowModel-Extended.json'
|
|
99
|
+
});
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Changing the Provider at Runtime
|
|
103
|
+
|
|
104
|
+
After initialization, each entity's provider can be changed individually:
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
_Fable.DAL.Book.setProvider('MySQL');
|
|
108
|
+
_Fable.DAL.Author.setProvider('SQLite');
|
|
109
|
+
```
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "retold-data-service",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.10",
|
|
4
4
|
"description": "Serve up a whole model!",
|
|
5
5
|
"main": "source/Retold-Data-Service.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "node source/Retold-Data-Service.js",
|
|
8
|
-
"coverage": "
|
|
9
|
-
"test": "
|
|
8
|
+
"coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
|
|
9
|
+
"test": "npx mocha -u tdd -R spec",
|
|
10
10
|
"build": "npx quack build",
|
|
11
11
|
"build-test-model": "cd test && npx stricture -i model/ddl/BookStore.ddl",
|
|
12
12
|
"docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t retold-data-service-image:local",
|
|
@@ -51,15 +51,19 @@
|
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://github.com/stevenvelozo/retold-data-service",
|
|
53
53
|
"devDependencies": {
|
|
54
|
+
"chai": "^6.2.2",
|
|
55
|
+
"meadow-connection-sqlite": "file:../meadow-connection-sqlite",
|
|
56
|
+
"mocha": "^11.7.5",
|
|
54
57
|
"quackage": "^1.0.41",
|
|
55
|
-
"stricture": "^1.0.37"
|
|
58
|
+
"stricture": "^1.0.37",
|
|
59
|
+
"supertest": "^7.2.2"
|
|
56
60
|
},
|
|
57
61
|
"dependencies": {
|
|
58
62
|
"fable": "^3.1.11",
|
|
59
63
|
"fable-serviceproviderbase": "^3.0.15",
|
|
60
|
-
"meadow": "
|
|
64
|
+
"meadow": "file:../meadow",
|
|
61
65
|
"meadow-connection-mysql": "^1.0.4",
|
|
62
|
-
"meadow-endpoints": "
|
|
66
|
+
"meadow-endpoints": "file:../meadow-endpoints",
|
|
63
67
|
"orator": "^5.0.1",
|
|
64
68
|
"orator-http-proxy": "^1.0.1",
|
|
65
69
|
"orator-serviceserver-restify": "^2.0.4",
|
|
@@ -110,19 +110,28 @@ class RetoldDataService extends libFableServiceProviderBase
|
|
|
110
110
|
{
|
|
111
111
|
// 4. Create the DAL for each entry (e.g. it would be at _DAL.Movie for the Movie entity)
|
|
112
112
|
let tmpDALEntityName = this.entityList[i];
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
113
|
+
try
|
|
114
|
+
{
|
|
115
|
+
let tmpDALSchema = this.fullModel.Tables[tmpDALEntityName];
|
|
116
|
+
let tmpDALMeadowSchema = tmpDALSchema.MeadowSchema;
|
|
117
|
+
|
|
118
|
+
//let tmpDALPackageFile = `${this.options.DALMeadowSchemaPath}${this.options.DALMeadowSchemaPrefix}${tmpDALEntityName}${this.options.DALMeadowSchemaPostfix}.json`
|
|
119
|
+
//this.fable.log.info(`Initializing the ${tmpDALEntityName} DAL from [${tmpDALPackageFile}]...`);
|
|
120
|
+
this._DAL[tmpDALEntityName] = this._Meadow.loadFromPackageObject(tmpDALMeadowSchema);
|
|
121
|
+
// 5. Tell this DAL object to use the configured storage provider
|
|
122
|
+
this.fable.log.info(`...defaulting the ${tmpDALEntityName} DAL to use ${this.options.StorageProvider}`);
|
|
123
|
+
this._DAL[tmpDALEntityName].setProvider(this.options.StorageProvider);
|
|
124
|
+
// 6. Create a Meadow Endpoints class for this DAL
|
|
125
|
+
this.fable.log.info(`...initializing the ${tmpDALEntityName} Meadow Endpoints`);
|
|
126
|
+
this._MeadowEndpoints[tmpDALEntityName] = libMeadowEndpoints.new(this._DAL[tmpDALEntityName]);
|
|
127
|
+
// 8. Expose the meadow endpoints on Orator
|
|
128
|
+
this.fable.log.info(`...mapping the ${tmpDALEntityName} Meadow Endpoints to Orator`);
|
|
129
|
+
this._MeadowEndpoints[tmpDALEntityName].connectRoutes(this.fable.OratorServiceServer);
|
|
130
|
+
}
|
|
131
|
+
catch (pError)
|
|
132
|
+
{
|
|
133
|
+
this.fable.log.error(`Error initializing DAL and Endpoints for entity [${tmpDALEntityName}]: ${pError}`);
|
|
134
|
+
}
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
return fCallback();
|