retold-data-service 2.0.13 → 2.0.16

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 (52) hide show
  1. package/.claude/launch.json +11 -0
  2. package/bin/retold-data-service-clone.js +286 -0
  3. package/package.json +18 -9
  4. package/source/Retold-Data-Service.js +275 -73
  5. package/source/services/Retold-Data-Service-ConnectionManager.js +277 -0
  6. package/source/services/Retold-Data-Service-MeadowEndpoints.js +217 -0
  7. package/source/services/Retold-Data-Service-ModelManager.js +335 -0
  8. package/source/services/data-cloner/DataCloner-Command-Connection.js +138 -0
  9. package/source/services/data-cloner/DataCloner-Command-Headless.js +357 -0
  10. package/source/services/data-cloner/DataCloner-Command-Schema.js +367 -0
  11. package/source/services/data-cloner/DataCloner-Command-Session.js +229 -0
  12. package/source/services/data-cloner/DataCloner-Command-Sync.js +491 -0
  13. package/source/services/data-cloner/DataCloner-Command-WebUI.js +40 -0
  14. package/source/services/data-cloner/DataCloner-ProviderRegistry.js +20 -0
  15. package/source/services/data-cloner/Retold-Data-Service-DataCloner.js +751 -0
  16. package/source/services/data-cloner/data-cloner-web.html +2706 -0
  17. package/source/services/integration-telemetry/IntegrationTelemetry-Command-Dashboard.js +60 -0
  18. package/source/services/integration-telemetry/IntegrationTelemetry-Command-Integrations.js +132 -0
  19. package/source/services/integration-telemetry/IntegrationTelemetry-Command-Runs.js +93 -0
  20. package/source/services/integration-telemetry/IntegrationTelemetry-StorageProvider-Base.js +116 -0
  21. package/source/services/integration-telemetry/IntegrationTelemetry-StorageProvider-Bibliograph.js +495 -0
  22. package/source/services/integration-telemetry/Retold-Data-Service-IntegrationTelemetry.js +224 -0
  23. package/source/services/meadow-integration/MeadowIntegration-Command-CSVCheck.js +85 -0
  24. package/source/services/meadow-integration/MeadowIntegration-Command-CSVTransform.js +180 -0
  25. package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionIntersect.js +153 -0
  26. package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionPush.js +190 -0
  27. package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionToArray.js +113 -0
  28. package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionToCSV.js +211 -0
  29. package/source/services/meadow-integration/MeadowIntegration-Command-EntityFromTabularFolder.js +244 -0
  30. package/source/services/meadow-integration/MeadowIntegration-Command-JSONArrayTransform.js +213 -0
  31. package/source/services/meadow-integration/MeadowIntegration-Command-TSVCheck.js +80 -0
  32. package/source/services/meadow-integration/MeadowIntegration-Command-TSVTransform.js +166 -0
  33. package/source/services/meadow-integration/Retold-Data-Service-MeadowIntegration.js +113 -0
  34. package/source/services/migration-manager/MigrationManager-Command-Connections.js +220 -0
  35. package/source/services/migration-manager/MigrationManager-Command-DiffMigrate.js +169 -0
  36. package/source/services/migration-manager/MigrationManager-Command-Schemas.js +532 -0
  37. package/source/services/migration-manager/MigrationManager-Command-WebUI.js +123 -0
  38. package/source/services/migration-manager/Retold-Data-Service-MigrationManager.js +357 -0
  39. package/source/services/stricture/Retold-Data-Service-Stricture.js +303 -0
  40. package/source/services/stricture/Stricture-Command-Compile.js +39 -0
  41. package/source/services/stricture/Stricture-Command-Generate-AuthorizationChart.js +14 -0
  42. package/source/services/stricture/Stricture-Command-Generate-DictionaryCSV.js +14 -0
  43. package/source/services/stricture/Stricture-Command-Generate-LaTeX.js +14 -0
  44. package/source/services/stricture/Stricture-Command-Generate-Markdown.js +14 -0
  45. package/source/services/stricture/Stricture-Command-Generate-Meadow.js +14 -0
  46. package/source/services/stricture/Stricture-Command-Generate-ModelGraph.js +14 -0
  47. package/source/services/stricture/Stricture-Command-Generate-MySQL.js +14 -0
  48. package/source/services/stricture/Stricture-Command-Generate-MySQLMigrate.js +14 -0
  49. package/source/services/stricture/Stricture-Command-Generate-Pict.js +14 -0
  50. package/source/services/stricture/Stricture-Command-Generate-TestObjectContainers.js +14 -0
  51. package/test/RetoldDataService_tests.js +161 -1
  52. package/debug/data/books.csv +0 -10001
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": "0.0.1",
3
+ "configurations": [
4
+ {
5
+ "name": "data-cloner",
6
+ "runtimeExecutable": "node",
7
+ "runtimeArgs": ["bin/retold-data-service-clone.js"],
8
+ "port": 8095
9
+ }
10
+ ]
11
+ }
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Retold Data Cloner — CLI Entry Point
4
+ *
5
+ * Starts a retold-data-service instance with the DataCloner execution mode enabled.
6
+ * Supports both a web UI for interactive cloning and a headless pipeline mode
7
+ * (--config + --run) for automated cloning.
8
+ *
9
+ * Usage:
10
+ * retold-data-clone Start web UI only
11
+ * retold-data-clone --config <path> --run Headless clone from config file
12
+ * retold-data-clone --config-json '{}' --run Headless clone from inline JSON
13
+ *
14
+ * @author Steven Velozo <steven@velozo.com>
15
+ */
16
+ const libFable = require('fable');
17
+ const libMeadowConnectionSQLite = require('meadow-connection-sqlite');
18
+ const libRetoldDataService = require('../source/Retold-Data-Service.js');
19
+
20
+ const libMeadowCloneRestClient = require('meadow-integration/source/services/clone/Meadow-Service-RestClient');
21
+ const libMeadowSync = require('meadow-integration/source/services/clone/Meadow-Service-Sync');
22
+
23
+ const libFs = require('fs');
24
+ const libPath = require('path');
25
+
26
+ // ================================================================
27
+ // CLI Arguments
28
+ // ================================================================
29
+
30
+ let _CLIConfig = null;
31
+ let _CLIRunHeadless = false;
32
+ let _CLILogPath = null;
33
+ let _CLIMaxRecords = 0;
34
+ let _CLISchemaPath = null;
35
+ let _CLIReportPath = null;
36
+
37
+ for (let i = 2; i < process.argv.length; i++)
38
+ {
39
+ if ((process.argv[i] === '--config' || process.argv[i] === '-c') && process.argv[i + 1])
40
+ {
41
+ let tmpConfigPath = libPath.resolve(process.argv[i + 1]);
42
+ try
43
+ {
44
+ let tmpRaw = libFs.readFileSync(tmpConfigPath, 'utf8');
45
+ _CLIConfig = JSON.parse(tmpRaw);
46
+ console.log(`Data Cloner: Loaded config from ${tmpConfigPath}`);
47
+ }
48
+ catch (pConfigError)
49
+ {
50
+ console.error(`Data Cloner: Failed to load config from ${tmpConfigPath}: ${pConfigError.message}`);
51
+ process.exit(1);
52
+ }
53
+ i++;
54
+ }
55
+ else if (process.argv[i] === '--config-json' && process.argv[i + 1])
56
+ {
57
+ try
58
+ {
59
+ _CLIConfig = JSON.parse(process.argv[i + 1]);
60
+ console.log('Data Cloner: Loaded config from inline JSON');
61
+ }
62
+ catch (pParseError)
63
+ {
64
+ console.error(`Data Cloner: Failed to parse inline JSON: ${pParseError.message}`);
65
+ process.exit(1);
66
+ }
67
+ i++;
68
+ }
69
+ else if (process.argv[i] === '--run' || process.argv[i] === '-r')
70
+ {
71
+ _CLIRunHeadless = true;
72
+ }
73
+ else if ((process.argv[i] === '--port' || process.argv[i] === '-p') && process.argv[i + 1])
74
+ {
75
+ process.env.PORT = process.argv[i + 1];
76
+ i++;
77
+ }
78
+ else if (process.argv[i] === '--log' || process.argv[i] === '-l')
79
+ {
80
+ if (process.argv[i + 1] && !process.argv[i + 1].startsWith('-'))
81
+ {
82
+ _CLILogPath = libPath.resolve(process.argv[i + 1]);
83
+ i++;
84
+ }
85
+ else
86
+ {
87
+ _CLILogPath = `${process.cwd()}/DataCloner-Run-${libFable.generateFileNameDateStamp()}.log`;
88
+ }
89
+ }
90
+ else if ((process.argv[i] === '--max' || process.argv[i] === '-m') && process.argv[i + 1])
91
+ {
92
+ _CLIMaxRecords = parseInt(process.argv[i + 1], 10) || 0;
93
+ i++;
94
+ }
95
+ else if ((process.argv[i] === '--schema' || process.argv[i] === '-s') && process.argv[i + 1])
96
+ {
97
+ _CLISchemaPath = libPath.resolve(process.argv[i + 1]);
98
+ i++;
99
+ }
100
+ else if (process.argv[i] === '--report')
101
+ {
102
+ if (process.argv[i + 1] && !process.argv[i + 1].startsWith('-'))
103
+ {
104
+ _CLIReportPath = libPath.resolve(process.argv[i + 1]);
105
+ i++;
106
+ }
107
+ else
108
+ {
109
+ _CLIReportPath = `${process.cwd()}/DataCloner-Report-${libFable.generateFileNameDateStamp()}.json`;
110
+ }
111
+ }
112
+ else if (process.argv[i] === '--help' || process.argv[i] === '-h')
113
+ {
114
+ console.log(`
115
+ Retold Data Cloner
116
+
117
+ Usage:
118
+ retold-data-clone Start web UI only
119
+ retold-data-clone --config <path> --run Headless clone from config file
120
+ retold-data-clone --config-json '{}' --run Headless clone from inline JSON
121
+
122
+ Options:
123
+ --config, -c <path> Path to a JSON config file (generate from the web UI)
124
+ --config-json <json> Inline JSON config string (for one-liner commands)
125
+ --run, -r Auto-run the clone pipeline (requires --config or --config-json)
126
+ --port, -p <port> Override the API server port (default: 8095)
127
+ --log, -l [path] Write log output to a file (default: ./DataCloner-Run-<timestamp>.log)
128
+ --max, -m <n> Limit sync to first n records per entity (for testing)
129
+ --schema, -s <path> Path to a local schema JSON file (skip remote schema fetch)
130
+ --report [path] Write sync report JSON file (default: auto-named; auto-enabled with --log)
131
+ --help, -h Show this help
132
+ `);
133
+ process.exit(0);
134
+ }
135
+ }
136
+
137
+ if (_CLIRunHeadless && !_CLIConfig)
138
+ {
139
+ console.error('Data Cloner: --run requires --config <path> or --config-json <json>');
140
+ process.exit(1);
141
+ }
142
+
143
+ // ================================================================
144
+ // Configuration
145
+ // ================================================================
146
+
147
+ let _Settings = (
148
+ {
149
+ Product: 'RetoldDataCloner',
150
+ ProductVersion: '1.0.0',
151
+ APIServerPort: parseInt(process.env.PORT, 10) || 8095,
152
+ LogStreams:
153
+ [
154
+ {
155
+ streamtype: 'console'
156
+ }
157
+ ],
158
+
159
+ SQLite:
160
+ {
161
+ SQLiteFilePath: libPath.join(process.cwd(), 'data', 'cloned.sqlite')
162
+ }
163
+ });
164
+
165
+ if (_CLILogPath)
166
+ {
167
+ _Settings.LogStreams.push(
168
+ {
169
+ loggertype: 'simpleflatfile',
170
+ outputloglinestoconsole: false,
171
+ showtimestamps: true,
172
+ formattedtimestamps: true,
173
+ level: 'trace',
174
+ path: _CLILogPath
175
+ });
176
+ }
177
+
178
+ // Ensure the data directory exists
179
+ let _DataDir = libPath.join(process.cwd(), 'data');
180
+ if (!libFs.existsSync(_DataDir))
181
+ {
182
+ libFs.mkdirSync(_DataDir, { recursive: true });
183
+ }
184
+
185
+ let _Fable = new libFable(_Settings);
186
+
187
+ // ================================================================
188
+ // SQLite Setup (default — connects automatically)
189
+ // ================================================================
190
+
191
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
192
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
193
+
194
+ _Fable.MeadowSQLiteProvider.connectAsync(
195
+ (pError) =>
196
+ {
197
+ if (pError)
198
+ {
199
+ _Fable.log.error(`SQLite connection error: ${pError}`);
200
+ process.exit(1);
201
+ }
202
+
203
+ // Set default Meadow provider to SQLite
204
+ _Fable.settings.MeadowProvider = 'SQLite';
205
+
206
+ // Register meadow-integration services for clone sync
207
+ _Fable.serviceManager.addServiceType('MeadowCloneRestClient', libMeadowCloneRestClient);
208
+ _Fable.serviceManager.addServiceType('MeadowSync', libMeadowSync);
209
+
210
+ _Fable.serviceManager.addServiceType('RetoldDataService', libRetoldDataService);
211
+ let tmpDataService = _Fable.serviceManager.instantiateServiceProvider('RetoldDataService',
212
+ {
213
+ StorageProvider: 'SQLite',
214
+ StorageProviderModule: 'meadow-connection-sqlite',
215
+
216
+ // No default schema — models loaded at runtime after fetch
217
+ FullMeadowSchemaFilename: false,
218
+
219
+ Endpoints:
220
+ {
221
+ ConnectionManager: true,
222
+ ModelManagerWrite: true,
223
+ Stricture: false,
224
+ MeadowIntegration: false,
225
+ MeadowEndpoints: true,
226
+ MigrationManager: true,
227
+ MigrationManagerWebUI: true,
228
+ DataCloner: true,
229
+ DataClonerWebUI: true,
230
+ IntegrationTelemetry: true
231
+ }
232
+ });
233
+
234
+ // Enable JSON body parsing for POST/PUT requests
235
+ tmpDataService.onBeforeInitialize = (fCallback) =>
236
+ {
237
+ _Fable.OratorServiceServer.server.use(_Fable.OratorServiceServer.bodyParser());
238
+ return fCallback();
239
+ };
240
+
241
+ // SQLite is available but don't presume it's the user's desired provider.
242
+ // The web UI will connect via the auto chain or manual "go" click.
243
+ tmpDataService.onAfterInitialize = (fCallback) =>
244
+ {
245
+ return fCallback();
246
+ };
247
+
248
+ // ================================================================
249
+ // Start the service
250
+ // ================================================================
251
+
252
+ tmpDataService.initializeService(
253
+ (pInitError) =>
254
+ {
255
+ if (pInitError)
256
+ {
257
+ _Fable.log.error(`Initialization error: ${pInitError}`);
258
+ process.exit(1);
259
+ }
260
+ _Fable.log.info(`Data Cloner running on port ${_Settings.APIServerPort}`);
261
+ _Fable.log.info(`Web UI: http://localhost:${_Settings.APIServerPort}/clone/`);
262
+ _Fable.log.info(`Migration Mgr: http://localhost:${_Settings.APIServerPort}/meadow-migrationmanager/`);
263
+
264
+ // ---- Headless auto-run from config file ----
265
+ if (_CLIConfig && _CLIRunHeadless)
266
+ {
267
+ _Fable.RetoldDataServiceDataCloner.runHeadlessPipeline(_CLIConfig,
268
+ {
269
+ logPath: _CLILogPath,
270
+ maxRecords: _CLIMaxRecords,
271
+ schemaPath: _CLISchemaPath,
272
+ serverPort: _Settings.APIServerPort,
273
+ reportPath: _CLIReportPath
274
+ },
275
+ (pPipelineError) =>
276
+ {
277
+ if (pPipelineError)
278
+ {
279
+ _Fable.log.error(`Pipeline error: ${pPipelineError}`);
280
+ process.exit(1);
281
+ }
282
+ process.exit(0);
283
+ });
284
+ }
285
+ });
286
+ });
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "retold-data-service",
3
- "version": "2.0.13",
3
+ "version": "2.0.16",
4
4
  "description": "Serve up a whole model!",
5
5
  "main": "source/Retold-Data-Service.js",
6
+ "bin": {
7
+ "retold-data-service-clone": "bin/retold-data-service-clone.js"
8
+ },
6
9
  "scripts": {
7
10
  "start": "node source/Retold-Data-Service.js",
8
11
  "coverage": "npx quack coverage",
@@ -51,20 +54,26 @@
51
54
  },
52
55
  "homepage": "https://github.com/stevenvelozo/retold-data-service",
53
56
  "devDependencies": {
54
- "meadow-connection-sqlite": "^1.0.11",
55
- "quackage": "^1.0.59",
56
- "stricture": "^1.0.37",
57
+ "meadow-connection-sqlite": "^1.0.18",
58
+ "quackage": "^1.0.63",
59
+ "stricture": "^4.0.2",
57
60
  "supertest": "^7.2.2"
58
61
  },
59
62
  "dependencies": {
63
+ "bibliograph": "^0.1.4",
60
64
  "fable": "^3.1.63",
61
65
  "fable-serviceproviderbase": "^3.0.19",
62
- "meadow": "^2.0.23",
63
- "meadow-connection-mysql": "^1.0.9",
64
- "meadow-endpoints": "^4.0.10",
65
- "orator": "^6.0.3",
66
+ "meadow": "^2.0.31",
67
+ "meadow-connection-mysql": "^1.0.14",
68
+ "meadow-endpoints": "^4.0.14",
69
+ "orator": "^6.0.4",
66
70
  "orator-http-proxy": "^1.0.5",
67
71
  "orator-serviceserver-restify": "^2.0.9",
68
- "orator-static-server": "^2.0.4"
72
+ "meadow-integration": "^1.0.14",
73
+ "meadow-migrationmanager": "^0.0.4",
74
+ "orator-static-server": "^2.0.4",
75
+ "pict": "^1.0.357",
76
+ "pict-sessionmanager": "^1.0.2",
77
+ "stricture": "^4.0.2"
69
78
  }
70
79
  }