meadow-integration 1.0.5 → 1.0.6
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/.dockerignore +11 -0
- package/Docker-Build.sh +2 -0
- package/Docker-Compose.sh +2 -0
- package/Docker-Push.sh +2 -0
- package/Docker-Tag.sh +2 -0
- package/Dockerfile +28 -0
- package/Dockerfile_LUXURYCode +23 -0
- package/README.md +139 -25
- package/docker-compose.yml +16 -0
- package/docs/README.md +65 -18
- package/docs/_cover.md +3 -2
- package/docs/_sidebar.md +52 -7
- package/docs/_topbar.md +2 -0
- package/docs/api/clone-rest-client.md +278 -0
- package/docs/api/connection-manager.md +179 -0
- package/docs/api/guid-map.md +234 -0
- package/docs/api/integration-adapter.md +283 -0
- package/docs/api/operation.md +241 -0
- package/docs/api/sync-entity-initial.md +227 -0
- package/docs/api/sync-entity-ongoing.md +244 -0
- package/docs/api/sync.md +213 -0
- package/docs/api/tabular-check.md +213 -0
- package/docs/api/tabular-transform.md +316 -0
- package/docs/architecture.md +423 -0
- package/docs/cli/comprehensionarray.md +111 -0
- package/docs/cli/comprehensionintersect.md +132 -0
- package/docs/cli/csvcheck.md +111 -0
- package/docs/cli/csvtransform.md +170 -0
- package/docs/cli/data-clone.md +277 -0
- package/docs/cli/jsonarraytransform.md +166 -0
- package/docs/cli/load-comprehension.md +129 -0
- package/docs/cli/objectarraytocsv.md +159 -0
- package/docs/cli/overview.md +96 -0
- package/docs/cli/serve.md +102 -0
- package/docs/cli/tsvtransform.md +144 -0
- package/docs/data-clone/configuration.md +357 -0
- package/docs/data-clone/connection-manager.md +206 -0
- package/docs/data-clone/docker.md +290 -0
- package/docs/data-clone/overview.md +173 -0
- package/docs/data-clone/sync-modes.md +186 -0
- package/docs/implementation-reference.md +311 -0
- package/docs/overview.md +156 -0
- package/docs/quickstart.md +233 -0
- package/docs/rest/comprehension-push.md +209 -0
- package/docs/rest/comprehension.md +506 -0
- package/docs/rest/csv.md +255 -0
- package/docs/rest/entity-generation.md +158 -0
- package/docs/rest/json-array.md +243 -0
- package/docs/rest/overview.md +120 -0
- package/docs/rest/status.md +63 -0
- package/docs/rest/tsv.md +241 -0
- package/docs/retold-catalog.json +93 -3
- package/docs/retold-keyword-index.json +23683 -1901
- package/package.json +6 -3
- package/scripts/run.sh +18 -0
- package/source/Meadow-Integration.js +15 -1
- package/source/cli/Default-Meadow-Integration-Configuration.json +37 -2
- package/source/cli/Meadow-Integration-CLI-Program.js +4 -1
- package/source/cli/commands/Meadow-Integration-Command-DataClone.js +284 -0
- package/source/services/clone/Meadow-Service-ConnectionManager.js +251 -0
- package/source/services/clone/Meadow-Service-Operation.js +196 -0
- package/source/services/clone/Meadow-Service-RestClient.js +364 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-Initial.js +367 -0
- package/source/services/clone/Meadow-Service-Sync-Entity-Ongoing.js +457 -0
- package/source/services/clone/Meadow-Service-Sync.js +142 -0
- /package/docs/examples/bookstore/{mapping_books_Author.json → mapping_books_author.json} +0 -0
- /package/docs/examples/bookstore/{mapping_books_Book.json → mapping_books_book.json} +0 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# tsvtransform
|
|
2
|
+
|
|
3
|
+
Transform a TSV (tab-separated values) file into a Comprehension JSON file. This command works identically to [csvtransform](csvtransform.md) but uses a tab character as the column delimiter instead of a comma.
|
|
4
|
+
|
|
5
|
+
**Aliases:** `tsv_t`, `tsv_transform`
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```shell
|
|
10
|
+
mdwint tsvtransform <file> [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Arguments
|
|
14
|
+
|
|
15
|
+
| Argument | Required | Description |
|
|
16
|
+
|----------|----------|-------------|
|
|
17
|
+
| `<file>` | Yes | Path to the TSV file to transform |
|
|
18
|
+
|
|
19
|
+
## Options
|
|
20
|
+
|
|
21
|
+
| Option | Description | Default |
|
|
22
|
+
|--------|-------------|---------|
|
|
23
|
+
| `-e, --entity <name>` | Entity name in the Comprehension | Auto-detected from filename |
|
|
24
|
+
| `-n, --guidname <name>` | Name of the GUID column in the generated Comprehension | `GUID<Entity>` |
|
|
25
|
+
| `-g, --guidtemplate <template>` | Pict template for generating the entity GUID | `GUID-<Entity>-{~Data:Record.<first_column>~}` |
|
|
26
|
+
| `-c, --columns <mappings>` | Inline column mappings in `Key={~D:col~}` format | Auto-detected 1:1 mapping |
|
|
27
|
+
| `-m, --mappingfile <path>` | Path to a JSON mapping file | -- |
|
|
28
|
+
| `-i, --incoming <path>` | Existing Comprehension file to merge into | -- |
|
|
29
|
+
| `-o, --output <path>` | Output file path | `./TSV-Comprehension-<filename>.json` |
|
|
30
|
+
| `-x, --extended` | Output full operation state, not just the Comprehension | `false` |
|
|
31
|
+
| `-q, --quotedelimiter <char>` | Quote delimiter character for TSV parsing | `"` |
|
|
32
|
+
|
|
33
|
+
## Configuration Priority
|
|
34
|
+
|
|
35
|
+
The same three-layer configuration priority applies as with `csvtransform`:
|
|
36
|
+
|
|
37
|
+
1. **Implicit** -- Auto-detected from the first TSV row
|
|
38
|
+
2. **Explicit** -- Loaded from a mapping file via `-m`
|
|
39
|
+
3. **User** -- Command-line options (`-e`, `-n`, `-g`, `-c`)
|
|
40
|
+
|
|
41
|
+
Each layer overrides the previous.
|
|
42
|
+
|
|
43
|
+
## Output Format
|
|
44
|
+
|
|
45
|
+
The output is a standard Comprehension JSON object, identical in format to `csvtransform` output:
|
|
46
|
+
|
|
47
|
+
```json
|
|
48
|
+
{
|
|
49
|
+
"Airport": {
|
|
50
|
+
"Airport-SEA": {
|
|
51
|
+
"GUIDAirport": "Airport-SEA",
|
|
52
|
+
"Code": "SEA",
|
|
53
|
+
"Name": "Seattle Tacoma International",
|
|
54
|
+
"City": "Seattle",
|
|
55
|
+
"State": "WA"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
### Basic TSV transform with a mapping file
|
|
64
|
+
|
|
65
|
+
Given a TSV file `airports.tsv` with columns `iata`, `name`, `city`, `state`, `country`, `lat`, `long`:
|
|
66
|
+
|
|
67
|
+
```shell
|
|
68
|
+
mdwint tsvtransform ./data/airports.tsv \
|
|
69
|
+
-m mapping_Airport.json \
|
|
70
|
+
-o airports.json
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Where `mapping_Airport.json` contains:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"Entity": "Airport",
|
|
78
|
+
"GUIDTemplate": "Airport-{~D:Record.iata~}",
|
|
79
|
+
"Mappings": {
|
|
80
|
+
"Code": "{~D:Record.iata~}",
|
|
81
|
+
"Name": "{~D:Record.name~}",
|
|
82
|
+
"Description": "{~D:Record.name~} airport in {~D:Record.city~}",
|
|
83
|
+
"City": "{~D:Record.city~}",
|
|
84
|
+
"State": "{~D:Record.state~}",
|
|
85
|
+
"Country": "{~D:Record.country~}",
|
|
86
|
+
"Latitude": "{~D:Record.lat~}",
|
|
87
|
+
"Longitude": "{~D:Record.long~}"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Transform with CLI options
|
|
93
|
+
|
|
94
|
+
```shell
|
|
95
|
+
mdwint tsvtransform ./data/airports.tsv \
|
|
96
|
+
-e Airport \
|
|
97
|
+
-n GUIDAirport \
|
|
98
|
+
-g "Airport-{~D:Record.iata~}" \
|
|
99
|
+
-c "Code={~D:Record.iata~},Name={~D:Record.name~},City={~D:Record.city~},State={~D:Record.state~},Country={~D:Record.country~},Latitude={~D:Record.lat~},Longitude={~D:Record.long~}" \
|
|
100
|
+
-o airports.json
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Implicit transform (auto-detect everything)
|
|
104
|
+
|
|
105
|
+
```shell
|
|
106
|
+
mdwint tsvtransform ./data/airports.tsv -o airports.json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Merge into an existing Comprehension
|
|
110
|
+
|
|
111
|
+
```shell
|
|
112
|
+
mdwint tsvtransform ./data/airports.tsv \
|
|
113
|
+
-m mapping_Airport.json \
|
|
114
|
+
-i existing-comprehension.json \
|
|
115
|
+
-o existing-comprehension.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Extended output for debugging
|
|
119
|
+
|
|
120
|
+
```shell
|
|
121
|
+
mdwint tsvtransform ./data/airports.tsv \
|
|
122
|
+
-m mapping_Airport.json \
|
|
123
|
+
-x \
|
|
124
|
+
-o debug-airports.json
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Tips
|
|
128
|
+
|
|
129
|
+
- TSV files are common exports from spreadsheet applications and database tools. The tab delimiter avoids issues with commas embedded in field values.
|
|
130
|
+
- The quote delimiter defaults to `"` but can be changed with `-q`. TSV files often do not use quote delimiters at all; if your file has no quoting, you can leave the default.
|
|
131
|
+
- All other behavior, including duplicate GUID merging, multi-entity support, and Solver expressions, works identically to `csvtransform`.
|
|
132
|
+
- Inline column mappings (`-c`) do not support commas or equal signs within template values. Use a mapping file for complex mappings.
|
|
133
|
+
|
|
134
|
+
## Notes
|
|
135
|
+
|
|
136
|
+
- The default output filename pattern is `./TSV-Comprehension-<filename>.json` (note the `TSV-` prefix rather than `CSV-`).
|
|
137
|
+
- The delimiter is set to `\t` internally. You do not need to specify it.
|
|
138
|
+
|
|
139
|
+
## See Also
|
|
140
|
+
|
|
141
|
+
- [csvtransform](csvtransform.md) -- Comma-delimited equivalent
|
|
142
|
+
- [jsonarraytransform](jsonarraytransform.md) -- JSON array equivalent
|
|
143
|
+
- [Mapping Files](../mapping-files.md) -- Full mapping file specification
|
|
144
|
+
- [Comprehensions](../comprehensions.md) -- Core data structure documentation
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
# Configuration Reference
|
|
2
|
+
|
|
3
|
+
The data clone system is configured through a `.meadow.config.json` file and/or CLI flags. This document covers the full configuration schema, cascading resolution behavior, and complete working examples.
|
|
4
|
+
|
|
5
|
+
## Configuration File
|
|
6
|
+
|
|
7
|
+
The configuration file is named `.meadow.config.json`. The CLI toolkit (`pict-service-commandlineutility`) automatically searches for this file using a cascading strategy.
|
|
8
|
+
|
|
9
|
+
### Cascading Resolution Order
|
|
10
|
+
|
|
11
|
+
The configuration file is resolved in the following order (first match wins):
|
|
12
|
+
|
|
13
|
+
1. **Current working directory** -- `.meadow.config.json` in the directory where the command is run.
|
|
14
|
+
2. **Parent directories** -- Walks up the directory tree searching for `.meadow.config.json`.
|
|
15
|
+
3. **Home directory** -- `~/.meadow.config.json` as a fallback.
|
|
16
|
+
|
|
17
|
+
Settings from the configuration file are merged with the built-in defaults. CLI flags override configuration file values.
|
|
18
|
+
|
|
19
|
+
## Full Configuration Schema
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"Source": {
|
|
24
|
+
"ServerURL": "https://api.example.com/1.0/",
|
|
25
|
+
"UserID": false,
|
|
26
|
+
"Password": false
|
|
27
|
+
},
|
|
28
|
+
"Destination": {
|
|
29
|
+
"Provider": "MySQL",
|
|
30
|
+
"MySQL": {
|
|
31
|
+
"server": "127.0.0.1",
|
|
32
|
+
"port": 3306,
|
|
33
|
+
"user": "root",
|
|
34
|
+
"password": "",
|
|
35
|
+
"database": "meadow",
|
|
36
|
+
"connectionLimit": 20
|
|
37
|
+
},
|
|
38
|
+
"MSSQL": {
|
|
39
|
+
"server": "127.0.0.1",
|
|
40
|
+
"port": 1433,
|
|
41
|
+
"user": "sa",
|
|
42
|
+
"password": "",
|
|
43
|
+
"database": "meadow",
|
|
44
|
+
"ConnectionPoolLimit": 20
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
"SchemaPath": "./schema/Model-Extended.json",
|
|
48
|
+
"Sync": {
|
|
49
|
+
"DefaultSyncMode": "Initial",
|
|
50
|
+
"PageSize": 100,
|
|
51
|
+
"SyncEntityList": [],
|
|
52
|
+
"SyncEntityOptions": {}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Section Reference
|
|
58
|
+
|
|
59
|
+
### Source
|
|
60
|
+
|
|
61
|
+
Configuration for the remote Meadow API server to clone data from.
|
|
62
|
+
|
|
63
|
+
| Property | Type | Default | Description |
|
|
64
|
+
|----------|------|---------|-------------|
|
|
65
|
+
| `ServerURL` | string | `"https://localhost:8080/1.0/"` | Base URL of the Meadow API (must include trailing `/1.0/`) |
|
|
66
|
+
| `UserID` | string or false | `false` | Username for API authentication; set to `false` to skip auth |
|
|
67
|
+
| `Password` | string or false | `false` | Password for API authentication; set to `false` to skip auth |
|
|
68
|
+
|
|
69
|
+
When `UserID` and `Password` are both `false`, the system skips authentication and makes unauthenticated requests.
|
|
70
|
+
|
|
71
|
+
### Destination
|
|
72
|
+
|
|
73
|
+
Configuration for the local database where cloned data is stored.
|
|
74
|
+
|
|
75
|
+
| Property | Type | Default | Description |
|
|
76
|
+
|----------|------|---------|-------------|
|
|
77
|
+
| `Provider` | string | `"MySQL"` | Database provider: `"MySQL"` or `"MSSQL"` |
|
|
78
|
+
| `MySQL` | object | See below | MySQL-specific connection settings |
|
|
79
|
+
| `MSSQL` | object | See below | MSSQL-specific connection settings |
|
|
80
|
+
|
|
81
|
+
Only the section matching the selected `Provider` is used.
|
|
82
|
+
|
|
83
|
+
#### MySQL Settings
|
|
84
|
+
|
|
85
|
+
| Property | Type | Default | Description |
|
|
86
|
+
|----------|------|---------|-------------|
|
|
87
|
+
| `server` | string | `"127.0.0.1"` | MySQL server hostname |
|
|
88
|
+
| `port` | number | `3306` | MySQL server port |
|
|
89
|
+
| `user` | string | `"root"` | Database username |
|
|
90
|
+
| `password` | string | `""` | Database password |
|
|
91
|
+
| `database` | string | `"meadow"` | Database name |
|
|
92
|
+
| `connectionLimit` | number | `20` | Connection pool size |
|
|
93
|
+
|
|
94
|
+
#### MSSQL Settings
|
|
95
|
+
|
|
96
|
+
| Property | Type | Default | Description |
|
|
97
|
+
|----------|------|---------|-------------|
|
|
98
|
+
| `server` | string | `"127.0.0.1"` | MSSQL server hostname |
|
|
99
|
+
| `port` | number | `1433` | MSSQL server port |
|
|
100
|
+
| `user` | string | `"sa"` | Database username |
|
|
101
|
+
| `password` | string | `""` | Database password |
|
|
102
|
+
| `database` | string | `"meadow"` | Database name |
|
|
103
|
+
| `ConnectionPoolLimit` | number | `20` | Connection pool size |
|
|
104
|
+
|
|
105
|
+
### SchemaPath
|
|
106
|
+
|
|
107
|
+
| Property | Type | Default | Description |
|
|
108
|
+
|----------|------|---------|-------------|
|
|
109
|
+
| `SchemaPath` | string | `"./schema/Model-Extended.json"` | Path to the Meadow extended schema JSON file (resolved relative to the config file or CWD) |
|
|
110
|
+
|
|
111
|
+
The schema file is a compiled Stricture model containing table definitions, column metadata, and Meadow schema information. It is generated by `stricture` during the build process.
|
|
112
|
+
|
|
113
|
+
### Sync
|
|
114
|
+
|
|
115
|
+
| Property | Type | Default | Description |
|
|
116
|
+
|----------|------|---------|-------------|
|
|
117
|
+
| `DefaultSyncMode` | string | `"Initial"` | Default sync mode: `"Initial"` or `"Ongoing"` |
|
|
118
|
+
| `PageSize` | number | `100` | Number of records to fetch per API request |
|
|
119
|
+
| `SyncEntityList` | array | `[]` | List of entity (table) names to sync. Empty array means sync all entities in the schema |
|
|
120
|
+
| `SyncEntityOptions` | object | `{}` | Per-entity configuration overrides (keyed by entity name) |
|
|
121
|
+
|
|
122
|
+
#### SyncEntityList
|
|
123
|
+
|
|
124
|
+
When `SyncEntityList` is an empty array `[]`, the system syncs every entity found in the loaded schema. To sync only specific entities, list them by their table name:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"Sync": {
|
|
129
|
+
"SyncEntityList": ["Book", "Author", "BookAuthorJoin"]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Entities are synced in the order they appear in this list.
|
|
135
|
+
|
|
136
|
+
#### SyncEntityOptions
|
|
137
|
+
|
|
138
|
+
Per-entity overrides, keyed by entity name:
|
|
139
|
+
|
|
140
|
+
```json
|
|
141
|
+
{
|
|
142
|
+
"Sync": {
|
|
143
|
+
"SyncEntityOptions": {
|
|
144
|
+
"AuditLog": {
|
|
145
|
+
"PageSize": 500
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## CLI Flag Overrides
|
|
153
|
+
|
|
154
|
+
All configuration values can be overridden via CLI flags. CLI flags take precedence over values from `.meadow.config.json`.
|
|
155
|
+
|
|
156
|
+
### Source (API) Flags
|
|
157
|
+
|
|
158
|
+
| Flag | Long Form | Description |
|
|
159
|
+
|------|-----------|-------------|
|
|
160
|
+
| `-a` | `--api_server` | Source API server URL |
|
|
161
|
+
| `-u` | `--api_username` | API username |
|
|
162
|
+
| `-p` | `--api_password` | API password |
|
|
163
|
+
|
|
164
|
+
### Destination (Database) Flags
|
|
165
|
+
|
|
166
|
+
| Flag | Long Form | Description |
|
|
167
|
+
|------|-----------|-------------|
|
|
168
|
+
| `-d` | `--db_provider` | Database provider (`MySQL` or `MSSQL`) |
|
|
169
|
+
| `-dh` | `--db_host` | Database server hostname |
|
|
170
|
+
| `-dp` | `--db_port` | Database server port |
|
|
171
|
+
| `-du` | `--db_username` | Database username |
|
|
172
|
+
| `-dw` | `--db_password` | Database password |
|
|
173
|
+
| `-dn` | `--db_name` | Database name |
|
|
174
|
+
|
|
175
|
+
### Other Flags
|
|
176
|
+
|
|
177
|
+
| Flag | Long Form | Default | Description |
|
|
178
|
+
|------|-----------|---------|-------------|
|
|
179
|
+
| `-sp` | `--schema_path` | From config | Path to Meadow extended schema JSON |
|
|
180
|
+
| `-s` | `--sync_mode` | `"Initial"` | Sync mode: `Initial` or `Ongoing` |
|
|
181
|
+
| `-w` | `--post_run_delay` | `0` | Minutes to wait after sync before exiting |
|
|
182
|
+
|
|
183
|
+
### Example with Full CLI Overrides
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
mdwint data-clone \
|
|
187
|
+
--api_server "https://api.prod.example.com/1.0/" \
|
|
188
|
+
--api_username "sync_user" \
|
|
189
|
+
--api_password "s3cret" \
|
|
190
|
+
--db_provider "MySQL" \
|
|
191
|
+
--db_host "db.local" \
|
|
192
|
+
--db_port 3306 \
|
|
193
|
+
--db_username "clone_user" \
|
|
194
|
+
--db_password "db_pass" \
|
|
195
|
+
--db_name "prod_clone" \
|
|
196
|
+
--schema_path "./schema/Model-Extended.json" \
|
|
197
|
+
--sync_mode "Initial"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Complete Working Examples
|
|
201
|
+
|
|
202
|
+
### Example 1: MySQL Initial Clone
|
|
203
|
+
|
|
204
|
+
`.meadow.config.json`:
|
|
205
|
+
|
|
206
|
+
```json
|
|
207
|
+
{
|
|
208
|
+
"Source": {
|
|
209
|
+
"ServerURL": "https://api.example.com/1.0/",
|
|
210
|
+
"UserID": "admin",
|
|
211
|
+
"Password": "admin_password"
|
|
212
|
+
},
|
|
213
|
+
"Destination": {
|
|
214
|
+
"Provider": "MySQL",
|
|
215
|
+
"MySQL": {
|
|
216
|
+
"server": "127.0.0.1",
|
|
217
|
+
"port": 3306,
|
|
218
|
+
"user": "root",
|
|
219
|
+
"password": "root_password",
|
|
220
|
+
"database": "app_clone",
|
|
221
|
+
"connectionLimit": 20
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
"SchemaPath": "./schema/Model-Extended.json",
|
|
225
|
+
"Sync": {
|
|
226
|
+
"DefaultSyncMode": "Initial",
|
|
227
|
+
"PageSize": 200,
|
|
228
|
+
"SyncEntityList": []
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Run:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
mdwint data-clone
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### Example 2: MSSQL Ongoing Sync with Specific Entities
|
|
240
|
+
|
|
241
|
+
`.meadow.config.json`:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"Source": {
|
|
246
|
+
"ServerURL": "https://api.example.com/1.0/",
|
|
247
|
+
"UserID": "sync_service",
|
|
248
|
+
"Password": "service_password"
|
|
249
|
+
},
|
|
250
|
+
"Destination": {
|
|
251
|
+
"Provider": "MSSQL",
|
|
252
|
+
"MSSQL": {
|
|
253
|
+
"server": "sql-server.local",
|
|
254
|
+
"port": 1433,
|
|
255
|
+
"user": "sa",
|
|
256
|
+
"password": "YourStrong!Passw0rd",
|
|
257
|
+
"database": "warehouse",
|
|
258
|
+
"ConnectionPoolLimit": 10
|
|
259
|
+
}
|
|
260
|
+
},
|
|
261
|
+
"SchemaPath": "/opt/schemas/Model-Extended.json",
|
|
262
|
+
"Sync": {
|
|
263
|
+
"DefaultSyncMode": "Ongoing",
|
|
264
|
+
"PageSize": 100,
|
|
265
|
+
"SyncEntityList": [
|
|
266
|
+
"Customer",
|
|
267
|
+
"Order",
|
|
268
|
+
"OrderItem",
|
|
269
|
+
"Product"
|
|
270
|
+
],
|
|
271
|
+
"SyncEntityOptions": {}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Run:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
mdwint data-clone
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### Example 3: No Authentication (Public API)
|
|
283
|
+
|
|
284
|
+
`.meadow.config.json`:
|
|
285
|
+
|
|
286
|
+
```json
|
|
287
|
+
{
|
|
288
|
+
"Source": {
|
|
289
|
+
"ServerURL": "http://public-api.example.com/1.0/",
|
|
290
|
+
"UserID": false,
|
|
291
|
+
"Password": false
|
|
292
|
+
},
|
|
293
|
+
"Destination": {
|
|
294
|
+
"Provider": "MySQL",
|
|
295
|
+
"MySQL": {
|
|
296
|
+
"server": "127.0.0.1",
|
|
297
|
+
"port": 3306,
|
|
298
|
+
"user": "root",
|
|
299
|
+
"password": "",
|
|
300
|
+
"database": "public_data",
|
|
301
|
+
"connectionLimit": 20
|
|
302
|
+
}
|
|
303
|
+
},
|
|
304
|
+
"SchemaPath": "./schema/PublicModel-Extended.json",
|
|
305
|
+
"Sync": {
|
|
306
|
+
"DefaultSyncMode": "Initial",
|
|
307
|
+
"PageSize": 500,
|
|
308
|
+
"SyncEntityList": []
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Example 4: CLI Overrides on Top of Config File
|
|
314
|
+
|
|
315
|
+
Given a minimal `.meadow.config.json`:
|
|
316
|
+
|
|
317
|
+
```json
|
|
318
|
+
{
|
|
319
|
+
"SchemaPath": "./schema/Model-Extended.json",
|
|
320
|
+
"Sync": {
|
|
321
|
+
"DefaultSyncMode": "Initial",
|
|
322
|
+
"PageSize": 100
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Override the source and destination at runtime:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
mdwint data-clone \
|
|
331
|
+
--api_server "https://staging.example.com/1.0/" \
|
|
332
|
+
--api_username "dev" \
|
|
333
|
+
--api_password "dev_pass" \
|
|
334
|
+
--db_host "localhost" \
|
|
335
|
+
--db_name "staging_clone" \
|
|
336
|
+
--sync_mode "Ongoing"
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## Configuration Validation
|
|
340
|
+
|
|
341
|
+
The `data-clone` command validates the following before starting:
|
|
342
|
+
|
|
343
|
+
1. `Source.ServerURL` must be set (via config or `--api_server`).
|
|
344
|
+
2. `SchemaPath` must be set (via config or `--schema_path`).
|
|
345
|
+
3. The destination database configuration for the selected provider must include at least `server` and `database`.
|
|
346
|
+
|
|
347
|
+
If any of these are missing, the command exits with an error message indicating which configuration is required.
|
|
348
|
+
|
|
349
|
+
## Using the Explanation Command
|
|
350
|
+
|
|
351
|
+
The CLI includes a built-in command to display the resolved configuration:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
mdwint config
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
This shows the merged result of default values, configuration file values, and CLI overrides, helping you verify what settings will be used before running a data clone.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# ConnectionManager
|
|
2
|
+
|
|
3
|
+
The `MeadowConnectionManager` service manages database connections for the data clone system. It supports MySQL and MSSQL providers, handles connection pooling, and provides automatic index creation on synced tables.
|
|
4
|
+
|
|
5
|
+
## Provider Selection
|
|
6
|
+
|
|
7
|
+
Set the `Provider` property to choose the database backend:
|
|
8
|
+
|
|
9
|
+
| Provider | Value | Required Module |
|
|
10
|
+
|----------|-------|-----------------|
|
|
11
|
+
| MySQL | `"MySQL"` | `meadow-connection-mysql` |
|
|
12
|
+
| MSSQL | `"MSSQL"` | `meadow-connection-mssql` |
|
|
13
|
+
|
|
14
|
+
Both modules are included as dependencies in `meadow-integration`.
|
|
15
|
+
|
|
16
|
+
## MySQL Configuration
|
|
17
|
+
|
|
18
|
+
### Options
|
|
19
|
+
|
|
20
|
+
| Property | Type | Default | Description |
|
|
21
|
+
|----------|------|---------|-------------|
|
|
22
|
+
| `server` | string | `"127.0.0.1"` | MySQL server hostname or IP address |
|
|
23
|
+
| `port` | number | `3306` | MySQL server port |
|
|
24
|
+
| `user` | string | `"root"` | Database username |
|
|
25
|
+
| `password` | string | `""` | Database password |
|
|
26
|
+
| `database` | string | `"meadow"` | Database name |
|
|
27
|
+
| `connectionLimit` | number | `20` | Maximum number of connections in the pool |
|
|
28
|
+
|
|
29
|
+
### Example
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
const meadowIntegration = require('meadow-integration');
|
|
33
|
+
const libFable = require('fable');
|
|
34
|
+
|
|
35
|
+
const fable = new libFable({});
|
|
36
|
+
|
|
37
|
+
fable.serviceManager.addServiceType('MeadowConnectionManager', meadowIntegration.ConnectionManager);
|
|
38
|
+
fable.serviceManager.instantiateServiceProvider('MeadowConnectionManager', {
|
|
39
|
+
Provider: 'MySQL',
|
|
40
|
+
MySQL: {
|
|
41
|
+
server: '127.0.0.1',
|
|
42
|
+
port: 3306,
|
|
43
|
+
user: 'app_user',
|
|
44
|
+
password: 'secure_password',
|
|
45
|
+
database: 'meadow_clone',
|
|
46
|
+
connectionLimit: 20
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
fable.MeadowConnectionManager.connect((pError, pConnectionPool) => {
|
|
51
|
+
if (pError) {
|
|
52
|
+
console.error('MySQL connection failed:', pError);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
console.log('Connected to MySQL. Pool ready.');
|
|
56
|
+
// pConnectionPool is the mysql2 pool instance
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### How MySQL Connection Works
|
|
61
|
+
|
|
62
|
+
1. The `meadow-connection-mysql` module is loaded dynamically.
|
|
63
|
+
2. The `connectionLimit` is propagated to `fable.settings` for the Meadow provider.
|
|
64
|
+
3. MySQL settings are applied to `fable.settings.MySQL`.
|
|
65
|
+
4. The provider is registered as `MeadowMySQLProvider` and connected via `connectAsync`.
|
|
66
|
+
5. The resulting connection pool is stored in `ConnectionManager.ConnectionPool`.
|
|
67
|
+
|
|
68
|
+
## MSSQL Configuration
|
|
69
|
+
|
|
70
|
+
### Options
|
|
71
|
+
|
|
72
|
+
| Property | Type | Default | Description |
|
|
73
|
+
|----------|------|---------|-------------|
|
|
74
|
+
| `server` | string | `"127.0.0.1"` | MSSQL server hostname or IP address |
|
|
75
|
+
| `port` | number | `1433` | MSSQL server port |
|
|
76
|
+
| `user` | string | `"sa"` | Database username |
|
|
77
|
+
| `password` | string | `""` | Database password |
|
|
78
|
+
| `database` | string | `"meadow"` | Database name |
|
|
79
|
+
| `ConnectionPoolLimit` | number | `20` | Maximum number of connections in the pool |
|
|
80
|
+
|
|
81
|
+
### Example
|
|
82
|
+
|
|
83
|
+
```javascript
|
|
84
|
+
const meadowIntegration = require('meadow-integration');
|
|
85
|
+
const libFable = require('fable');
|
|
86
|
+
|
|
87
|
+
const fable = new libFable({});
|
|
88
|
+
|
|
89
|
+
fable.serviceManager.addServiceType('MeadowConnectionManager', meadowIntegration.ConnectionManager);
|
|
90
|
+
fable.serviceManager.instantiateServiceProvider('MeadowConnectionManager', {
|
|
91
|
+
Provider: 'MSSQL',
|
|
92
|
+
MSSQL: {
|
|
93
|
+
server: 'sql-server.local',
|
|
94
|
+
port: 1433,
|
|
95
|
+
user: 'sa',
|
|
96
|
+
password: 'YourStrong!Passw0rd',
|
|
97
|
+
database: 'meadow_clone',
|
|
98
|
+
ConnectionPoolLimit: 20
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
fable.MeadowConnectionManager.connect((pError, pConnectionPool) => {
|
|
103
|
+
if (pError) {
|
|
104
|
+
console.error('MSSQL connection failed:', pError);
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log('Connected to MSSQL. Pool ready.');
|
|
108
|
+
});
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### How MSSQL Connection Works
|
|
112
|
+
|
|
113
|
+
1. The `meadow-connection-mssql` module is loaded dynamically.
|
|
114
|
+
2. MSSQL settings are applied to `fable.settings.MSSQL`.
|
|
115
|
+
3. The provider is registered as `MeadowMSSQLProvider` and connected via `connectAsync`.
|
|
116
|
+
4. The resulting connection pool is stored in `ConnectionManager.ConnectionPool`.
|
|
117
|
+
|
|
118
|
+
## Automatic Index Creation
|
|
119
|
+
|
|
120
|
+
During sync initialization, the `SyncEntity` (both Initial and Ongoing) automatically creates indexes on two column types:
|
|
121
|
+
|
|
122
|
+
### GUID Column Index
|
|
123
|
+
|
|
124
|
+
A **unique** index is created on any column with `DataType: "GUID"` in the Meadow schema. The index is named `AK_{TableName}_{ColumnName}`.
|
|
125
|
+
|
|
126
|
+
### Deleted Column Index
|
|
127
|
+
|
|
128
|
+
A **non-unique** index is created on the `Deleted` column if it exists. This speeds up queries that filter on soft-deleted records.
|
|
129
|
+
|
|
130
|
+
### Index Creation Behavior
|
|
131
|
+
|
|
132
|
+
- **MySQL**: Uses `INFORMATION_SCHEMA.STATISTICS` to check if the index already exists before creating it. Duplicate key errors (`ER_DUP_KEYNAME`) are silently ignored.
|
|
133
|
+
- **MSSQL**: Uses `sys.indexes` with `IF NOT EXISTS` to conditionally create the index.
|
|
134
|
+
- If no GUID or Deleted columns exist on a table, index creation is skipped entirely.
|
|
135
|
+
- If no `ConnectionManager` or connection pool is available, index creation is skipped with a log message.
|
|
136
|
+
|
|
137
|
+
### Programmatic Index Creation
|
|
138
|
+
|
|
139
|
+
You can also create indexes manually:
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
const entitySchema = {
|
|
143
|
+
TableName: 'Book',
|
|
144
|
+
Columns: [
|
|
145
|
+
{ Column: 'GUIDBook', DataType: 'GUID' }
|
|
146
|
+
]
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
fable.MeadowConnectionManager.createIndex(
|
|
150
|
+
entitySchema,
|
|
151
|
+
{ Column: 'GUIDBook' },
|
|
152
|
+
true, // unique
|
|
153
|
+
(pError) => {
|
|
154
|
+
if (pError) {
|
|
155
|
+
console.error('Index creation failed:', pError);
|
|
156
|
+
} else {
|
|
157
|
+
console.log('Index created successfully.');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
);
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Connection Pooling
|
|
164
|
+
|
|
165
|
+
Both MySQL and MSSQL use connection pooling to manage database connections efficiently:
|
|
166
|
+
|
|
167
|
+
- **MySQL**: Uses the `connectionLimit` property (default 20) via the `mysql2` pool.
|
|
168
|
+
- **MSSQL**: Uses the `ConnectionPoolLimit` property (default 20) via the `mssql` pool.
|
|
169
|
+
|
|
170
|
+
The pool is created once during `connect()` and reused for all subsequent queries within the sync process.
|
|
171
|
+
|
|
172
|
+
## Checking Connection State
|
|
173
|
+
|
|
174
|
+
```javascript
|
|
175
|
+
if (fable.MeadowConnectionManager.connected) {
|
|
176
|
+
console.log('Database is connected.');
|
|
177
|
+
} else {
|
|
178
|
+
console.log('Database is not connected.');
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Default Configuration
|
|
183
|
+
|
|
184
|
+
The default configuration is exported as `MeadowConnectionManager.default_configuration`:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"Provider": "MySQL",
|
|
189
|
+
"MySQL": {
|
|
190
|
+
"server": "127.0.0.1",
|
|
191
|
+
"port": 3306,
|
|
192
|
+
"user": "root",
|
|
193
|
+
"password": "",
|
|
194
|
+
"database": "meadow",
|
|
195
|
+
"connectionLimit": 20
|
|
196
|
+
},
|
|
197
|
+
"MSSQL": {
|
|
198
|
+
"server": "127.0.0.1",
|
|
199
|
+
"port": 1433,
|
|
200
|
+
"user": "sa",
|
|
201
|
+
"password": "",
|
|
202
|
+
"database": "meadow",
|
|
203
|
+
"ConnectionPoolLimit": 20
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
```
|