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.
- package/.claude/launch.json +11 -0
- package/bin/retold-data-service-clone.js +286 -0
- package/package.json +18 -9
- package/source/Retold-Data-Service.js +275 -73
- package/source/services/Retold-Data-Service-ConnectionManager.js +277 -0
- package/source/services/Retold-Data-Service-MeadowEndpoints.js +217 -0
- package/source/services/Retold-Data-Service-ModelManager.js +335 -0
- package/source/services/data-cloner/DataCloner-Command-Connection.js +138 -0
- package/source/services/data-cloner/DataCloner-Command-Headless.js +357 -0
- package/source/services/data-cloner/DataCloner-Command-Schema.js +367 -0
- package/source/services/data-cloner/DataCloner-Command-Session.js +229 -0
- package/source/services/data-cloner/DataCloner-Command-Sync.js +491 -0
- package/source/services/data-cloner/DataCloner-Command-WebUI.js +40 -0
- package/source/services/data-cloner/DataCloner-ProviderRegistry.js +20 -0
- package/source/services/data-cloner/Retold-Data-Service-DataCloner.js +751 -0
- package/source/services/data-cloner/data-cloner-web.html +2706 -0
- package/source/services/integration-telemetry/IntegrationTelemetry-Command-Dashboard.js +60 -0
- package/source/services/integration-telemetry/IntegrationTelemetry-Command-Integrations.js +132 -0
- package/source/services/integration-telemetry/IntegrationTelemetry-Command-Runs.js +93 -0
- package/source/services/integration-telemetry/IntegrationTelemetry-StorageProvider-Base.js +116 -0
- package/source/services/integration-telemetry/IntegrationTelemetry-StorageProvider-Bibliograph.js +495 -0
- package/source/services/integration-telemetry/Retold-Data-Service-IntegrationTelemetry.js +224 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-CSVCheck.js +85 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-CSVTransform.js +180 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionIntersect.js +153 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionPush.js +190 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionToArray.js +113 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-ComprehensionToCSV.js +211 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-EntityFromTabularFolder.js +244 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-JSONArrayTransform.js +213 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-TSVCheck.js +80 -0
- package/source/services/meadow-integration/MeadowIntegration-Command-TSVTransform.js +166 -0
- package/source/services/meadow-integration/Retold-Data-Service-MeadowIntegration.js +113 -0
- package/source/services/migration-manager/MigrationManager-Command-Connections.js +220 -0
- package/source/services/migration-manager/MigrationManager-Command-DiffMigrate.js +169 -0
- package/source/services/migration-manager/MigrationManager-Command-Schemas.js +532 -0
- package/source/services/migration-manager/MigrationManager-Command-WebUI.js +123 -0
- package/source/services/migration-manager/Retold-Data-Service-MigrationManager.js +357 -0
- package/source/services/stricture/Retold-Data-Service-Stricture.js +303 -0
- package/source/services/stricture/Stricture-Command-Compile.js +39 -0
- package/source/services/stricture/Stricture-Command-Generate-AuthorizationChart.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-DictionaryCSV.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-LaTeX.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-Markdown.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-Meadow.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-ModelGraph.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-MySQL.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-MySQLMigrate.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-Pict.js +14 -0
- package/source/services/stricture/Stricture-Command-Generate-TestObjectContainers.js +14 -0
- package/test/RetoldDataService_tests.js +161 -1
- package/debug/data/books.csv +0 -10001
|
@@ -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.
|
|
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.
|
|
55
|
-
"quackage": "^1.0.
|
|
56
|
-
"stricture": "^
|
|
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.
|
|
63
|
-
"meadow-connection-mysql": "^1.0.
|
|
64
|
-
"meadow-endpoints": "^4.0.
|
|
65
|
-
"orator": "^6.0.
|
|
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
|
-
"
|
|
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
|
}
|