meadow-integration 1.0.4 → 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.
Files changed (67) hide show
  1. package/.dockerignore +11 -0
  2. package/Docker-Build.sh +2 -0
  3. package/Docker-Compose.sh +2 -0
  4. package/Docker-Push.sh +2 -0
  5. package/Docker-Tag.sh +2 -0
  6. package/Dockerfile +28 -0
  7. package/Dockerfile_LUXURYCode +23 -0
  8. package/README.md +139 -25
  9. package/docker-compose.yml +16 -0
  10. package/docs/README.md +65 -18
  11. package/docs/{cover.md → _cover.md} +3 -2
  12. package/docs/_sidebar.md +52 -7
  13. package/docs/_topbar.md +2 -0
  14. package/docs/api/clone-rest-client.md +278 -0
  15. package/docs/api/connection-manager.md +179 -0
  16. package/docs/api/guid-map.md +234 -0
  17. package/docs/api/integration-adapter.md +283 -0
  18. package/docs/api/operation.md +241 -0
  19. package/docs/api/sync-entity-initial.md +227 -0
  20. package/docs/api/sync-entity-ongoing.md +244 -0
  21. package/docs/api/sync.md +213 -0
  22. package/docs/api/tabular-check.md +213 -0
  23. package/docs/api/tabular-transform.md +316 -0
  24. package/docs/architecture.md +423 -0
  25. package/docs/cli/comprehensionarray.md +111 -0
  26. package/docs/cli/comprehensionintersect.md +132 -0
  27. package/docs/cli/csvcheck.md +111 -0
  28. package/docs/cli/csvtransform.md +170 -0
  29. package/docs/cli/data-clone.md +277 -0
  30. package/docs/cli/jsonarraytransform.md +166 -0
  31. package/docs/cli/load-comprehension.md +129 -0
  32. package/docs/cli/objectarraytocsv.md +159 -0
  33. package/docs/cli/overview.md +96 -0
  34. package/docs/cli/serve.md +102 -0
  35. package/docs/cli/tsvtransform.md +144 -0
  36. package/docs/data-clone/configuration.md +357 -0
  37. package/docs/data-clone/connection-manager.md +206 -0
  38. package/docs/data-clone/docker.md +290 -0
  39. package/docs/data-clone/overview.md +173 -0
  40. package/docs/data-clone/sync-modes.md +186 -0
  41. package/docs/implementation-reference.md +311 -0
  42. package/docs/overview.md +156 -0
  43. package/docs/quickstart.md +233 -0
  44. package/docs/rest/comprehension-push.md +209 -0
  45. package/docs/rest/comprehension.md +506 -0
  46. package/docs/rest/csv.md +255 -0
  47. package/docs/rest/entity-generation.md +158 -0
  48. package/docs/rest/json-array.md +243 -0
  49. package/docs/rest/overview.md +120 -0
  50. package/docs/rest/status.md +63 -0
  51. package/docs/rest/tsv.md +241 -0
  52. package/docs/retold-catalog.json +93 -3
  53. package/docs/retold-keyword-index.json +23683 -1901
  54. package/package.json +13 -10
  55. package/scripts/run.sh +18 -0
  56. package/source/Meadow-Integration.js +15 -1
  57. package/source/cli/Default-Meadow-Integration-Configuration.json +37 -2
  58. package/source/cli/Meadow-Integration-CLI-Program.js +4 -1
  59. package/source/cli/commands/Meadow-Integration-Command-DataClone.js +284 -0
  60. package/source/services/clone/Meadow-Service-ConnectionManager.js +251 -0
  61. package/source/services/clone/Meadow-Service-Operation.js +196 -0
  62. package/source/services/clone/Meadow-Service-RestClient.js +364 -0
  63. package/source/services/clone/Meadow-Service-Sync-Entity-Initial.js +367 -0
  64. package/source/services/clone/Meadow-Service-Sync-Entity-Ongoing.js +457 -0
  65. package/source/services/clone/Meadow-Service-Sync.js +142 -0
  66. /package/docs/examples/bookstore/{mapping_books_Author.json → mapping_books_author.json} +0 -0
  67. /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
+ ```