@forzalabs/remora 0.0.30 → 0.0.31-nasco.3

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/LICENCE.md ADDED
@@ -0,0 +1,31 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: Forza Labs LLC
6
+
7
+ Licensed Work: Remora
8
+
9
+ Additional Use Grant: You may make use of the Licensed Work for any non-commercial purpose, including personal, academic, research, or open source projects.
10
+
11
+ Change Date: 02/07/2025
12
+
13
+ Terms
14
+
15
+ The Licensor hereby grants you the right to copy, modify, create derivative works, redistribute, and make other use of the Licensed Work. The rights granted are subject to the following conditions:
16
+
17
+ 1. **Commercial Use**: Any use of the Licensed Work for or on behalf of a company, organization, or any commercial purpose requires a separate commercial license from the Licensor.
18
+
19
+ 2. **Non-Commercial Use**: Non-commercial users may freely use, modify, and distribute the Licensed Work, provided that such use is not intended for commercial advantage or monetary compensation.
20
+
21
+ 3. **Change Date**: On the Change Date, the terms of this license will change to the Change License specified above.
22
+
23
+ 4. **Other Conditions**:
24
+ - This license does not grant trademark rights.
25
+ - You must include this license text with any distribution of the Licensed Work.
26
+ - You may not remove or modify this license notice.
27
+
28
+ Use Limitation: If your usage does not comply with the above terms (e.g., if it's for commercial purposes), you must contact the Licensor to purchase a commercial license.
29
+
30
+ To inquire about commercial licensing, contact: admin@forza-labs.com
31
+
package/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # 🐟 Remora CLI
2
+
3
+ A powerful CLI tool for seamless data translation and processing.
4
+
5
+ ## šŸ“– Overview
6
+
7
+ Remora is a comprehensive data processing CLI that enables efficient data transformation, translation, and management across various formats and sources. Whether you're working with CSV, JSON, XML, or other data formats, Remora provides the tools you need to process and transform your data with ease.
8
+
9
+ ## šŸš€ Features
10
+
11
+ - **Data Translation**: Convert between different data formats seamlessly
12
+ - **Multiple Data Sources**: Support for local files, S3, databases, and more
13
+ - **Flexible Processing**: Configure producers and consumers for custom data pipelines
14
+ - **Schema Validation**: Ensure data integrity with built-in schema validation
15
+ - **CLI Interface**: Easy-to-use command-line interface for all operations
16
+
17
+ ## šŸ“¦ Installation
18
+
19
+ ```bash
20
+ npm install -g @forzalabs/remora
21
+ ```
22
+
23
+ ## šŸ› ļø Usage
24
+
25
+ ```bash
26
+ # Initialize a new Remora project
27
+ remora init
28
+
29
+ # Run data processing
30
+ remora run
31
+
32
+ # Discover data sources
33
+ remora discover
34
+
35
+ # Compile configurations
36
+ remora compile
37
+
38
+ # Deploy to target environment
39
+ remora deploy
40
+ ```
41
+
42
+ ## šŸ·ļø NASCO Version
43
+
44
+ > **Important**: This specific version is for NASCO and has all AI features completely removed.
45
+
46
+ To manage different versions, we maintain a dedicated branch (called 'nasco') with a specific version of the package, which is the normal version with appended '-nasco.x'.
47
+
48
+ **Example**: `1.0.0-nasco.1`
49
+
50
+ **Publishing**: When publishing to npm, you must include the tag 'nasco' so the main version of the package is not overwritten:
51
+
52
+ ```bash
53
+ npm publish --tag nasco
54
+ ```
55
+
56
+ ## šŸ“„ License
57
+
58
+ BSL
59
+
60
+ ---
61
+
62
+ Built with ā¤ļø by Forza Labs
@@ -60,6 +60,7 @@ const Affirm_1 = __importDefault(require("../core/Affirm"));
60
60
  const Algo_1 = __importDefault(require("../core/Algo"));
61
61
  const xlsx_1 = __importDefault(require("xlsx"));
62
62
  const XMLParser_1 = __importDefault(require("../engines/parsing/XMLParser")); // Added XMLParser import
63
+ const Helper_1 = __importDefault(require("../helper/Helper"));
63
64
  class LocalSourceDriver {
64
65
  constructor() {
65
66
  this.init = (source) => __awaiter(this, void 0, void 0, function* () {
@@ -75,19 +76,15 @@ class LocalSourceDriver {
75
76
  (0, Affirm_1.default)(request, `Invalid download request`);
76
77
  (0, Affirm_1.default)(request.fileKey, `Invalid file key for download request`);
77
78
  (0, Affirm_1.default)(request.fileType, `Invalid file type for download request`);
78
- const { fileKey, options } = request;
79
- const fileUrl = path_1.default.join(this._path, fileKey);
80
- switch (request.fileType) {
81
- case 'CSV':
82
- case 'JSON':
83
- case 'JSONL':
84
- case 'TXT':
85
- return yield this._readLines(fileUrl);
86
- case 'XLS':
87
- case 'XLSX':
88
- return yield this._readExcelLines(fileUrl, options === null || options === void 0 ? void 0 : options.sheetName);
89
- case 'XML':
90
- return yield this._readXmlLines(fileUrl);
79
+ const { fileKey } = request;
80
+ if (fileKey.includes('%')) {
81
+ const allFileKeys = this.listFiles(fileKey);
82
+ const promises = allFileKeys.map(x => this._get(Object.assign(Object.assign({}, request), { fileKey: x })));
83
+ const results = yield Promise.all(promises);
84
+ return results.flat();
85
+ }
86
+ else {
87
+ return yield this._get(request);
91
88
  }
92
89
  });
93
90
  this.readLinesInRange = (request) => __awaiter(this, void 0, void 0, function* () {
@@ -98,19 +95,15 @@ class LocalSourceDriver {
98
95
  (0, Affirm_1.default)(request.options, `Invalid request options`);
99
96
  Affirm_1.default.hasValue(request.options.lineFrom, `Invalid request options line from`);
100
97
  Affirm_1.default.hasValue(request.options.lineTo, `Invalid request options line to`);
101
- const { fileKey, fileType, options: { lineFrom, lineTo, sheetName } } = request;
102
- const fileUrl = path_1.default.join(this._path, fileKey);
103
- switch (fileType) {
104
- case 'CSV':
105
- case 'JSON':
106
- case 'JSONL':
107
- case 'TXT':
108
- return yield this._readLines(fileUrl, lineFrom, lineTo);
109
- case 'XLS':
110
- case 'XLSX':
111
- return yield this._readExcelLines(fileUrl, sheetName, lineFrom, lineTo);
112
- case 'XML':
113
- return yield this._readXmlLines(fileUrl, lineFrom, lineTo);
98
+ const { fileKey } = request;
99
+ if (fileKey.includes('%')) {
100
+ const allFileKeys = this.listFiles(fileKey);
101
+ const promises = allFileKeys.map(x => this._get(Object.assign(Object.assign({}, request), { fileKey: x })));
102
+ const results = yield Promise.all(promises);
103
+ return results.flat();
104
+ }
105
+ else {
106
+ return yield this._get(request);
114
107
  }
115
108
  });
116
109
  this.exist = (producer) => __awaiter(this, void 0, void 0, function* () {
@@ -118,8 +111,14 @@ class LocalSourceDriver {
118
111
  (0, Affirm_1.default)(producer, `Invalid producer`);
119
112
  const fileKey = producer.settings.fileKey;
120
113
  (0, Affirm_1.default)(fileKey, `Invalid file key for download request`);
121
- const fileUrl = path_1.default.join(this._path, fileKey);
122
- return fs.existsSync(fileUrl);
114
+ if (fileKey.includes('%')) {
115
+ const allFileKeys = this.listFiles(fileKey);
116
+ return allFileKeys.length > 0;
117
+ }
118
+ else {
119
+ const fileUrl = path_1.default.join(this._path, fileKey);
120
+ return fs.existsSync(fileUrl);
121
+ }
123
122
  });
124
123
  this._readLines = (fileUri, lineFrom, lineTo) => __awaiter(this, void 0, void 0, function* () {
125
124
  var _a, e_1, _b, _c;
@@ -185,6 +184,65 @@ class LocalSourceDriver {
185
184
  }
186
185
  return lines;
187
186
  });
187
+ this._get = (request) => __awaiter(this, void 0, void 0, function* () {
188
+ const { fileKey, fileType, options } = request;
189
+ let lineFrom, lineTo, sheetName;
190
+ if (options) {
191
+ lineFrom = options.lineFrom;
192
+ lineTo = options.lineTo;
193
+ sheetName = options.sheetName;
194
+ }
195
+ const fileUrl = path_1.default.join(this._path, fileKey);
196
+ switch (fileType) {
197
+ case 'CSV':
198
+ case 'JSON':
199
+ case 'JSONL':
200
+ case 'TXT':
201
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
202
+ return yield this._readLines(fileUrl, lineFrom, lineTo);
203
+ else
204
+ return yield this._readLines(fileUrl);
205
+ case 'XLS':
206
+ case 'XLSX':
207
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
208
+ return yield this._readExcelLines(fileUrl, sheetName, lineFrom, lineTo);
209
+ else
210
+ return yield this._readExcelLines(fileUrl, sheetName);
211
+ case 'XML':
212
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
213
+ return yield this._readXmlLines(fileUrl, lineFrom, lineTo);
214
+ else
215
+ return yield this._readXmlLines(fileUrl);
216
+ }
217
+ });
218
+ this.listFiles = (filekeyPattern) => {
219
+ (0, Affirm_1.default)(this._path, 'Path not initialized');
220
+ try {
221
+ // Get all files in the directory (recursively if needed)
222
+ const getAllFiles = (dirPath, basePath = '') => {
223
+ const files = [];
224
+ const items = fs.readdirSync(dirPath);
225
+ for (const item of items) {
226
+ const fullPath = path_1.default.join(dirPath, item);
227
+ const relativePath = basePath ? path_1.default.join(basePath, item) : item;
228
+ const stats = fs.statSync(fullPath);
229
+ if (stats.isDirectory()) {
230
+ // Recursively get files from subdirectories
231
+ files.push(...getAllFiles(fullPath, relativePath));
232
+ }
233
+ else if (stats.isFile()) {
234
+ files.push(relativePath);
235
+ }
236
+ }
237
+ return files;
238
+ };
239
+ const allFiles = getAllFiles(this._path);
240
+ return Helper_1.default.matchPattern(filekeyPattern, allFiles);
241
+ }
242
+ catch (error) {
243
+ throw new Error(`Failed to list files in directory "${this._path}": ${error.message}`);
244
+ }
245
+ };
188
246
  }
189
247
  }
190
248
  exports.LocalSourceDriver = LocalSourceDriver;
@@ -27,6 +27,7 @@ const readline_1 = __importDefault(require("readline"));
27
27
  const Algo_1 = __importDefault(require("../core/Algo"));
28
28
  const xlsx_1 = __importDefault(require("xlsx"));
29
29
  const XMLParser_1 = __importDefault(require("../engines/parsing/XMLParser")); // Added XMLParser import
30
+ const Helper_1 = __importDefault(require("../helper/Helper"));
30
31
  class S3DestinationDriver {
31
32
  constructor() {
32
33
  this.init = (source) => __awaiter(this, void 0, void 0, function* () {
@@ -133,50 +134,31 @@ class S3SourceDriver {
133
134
  (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
134
135
  (0, Affirm_1.default)(request, `Invalid download request`);
135
136
  (0, Affirm_1.default)(request.fileKey, `Invalid file key for download request`);
136
- const { fileKey, fileType, options } = request;
137
- const bucket = this._bucketName;
138
- const response = yield this._client.send(new client_s3_1.GetObjectCommand({
139
- Bucket: bucket,
140
- Key: fileKey
141
- }));
142
- (0, Affirm_1.default)(response.Body, 'Failed to fetch object from S3');
143
- const stream = response.Body;
144
- switch (fileType) {
145
- case 'CSV':
146
- case 'JSON':
147
- case 'JSONL':
148
- case 'TXT':
149
- return yield this._readLines(stream);
150
- case 'XLS':
151
- case 'XLSX':
152
- return yield this._readExcelLines(stream, options === null || options === void 0 ? void 0 : options.sheetName);
153
- case 'XML':
154
- return yield this._readXmlLines(stream);
137
+ const { fileKey } = request;
138
+ if (fileKey.includes('%')) {
139
+ const allFileKeys = yield this.listFiles(fileKey);
140
+ (0, Affirm_1.default)(allFileKeys.length < 50, `Pattern ${fileKey} of producer requested to S3 matches more than 50 files (${allFileKeys.length}), this is more than the S3 allowed limit. Please refine your pattern, remove some files or use a separate bucket.`);
141
+ const promises = allFileKeys.map(x => this._get(Object.assign(Object.assign({}, request), { fileKey: x })));
142
+ const results = yield Promise.all(promises);
143
+ return results.flat();
144
+ }
145
+ else {
146
+ return yield this._get(request);
155
147
  }
156
148
  });
157
149
  this.readLinesInRange = (request) => __awaiter(this, void 0, void 0, function* () {
158
150
  (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
159
151
  (0, Affirm_1.default)(request, 'Invalid read request');
160
152
  (0, Affirm_1.default)(request.options, 'Invalid read request options');
161
- const { fileKey, fileType, options: { sheetName, lineFrom, lineTo } } = request;
162
- const bucket = this._bucketName;
163
- const response = yield this._client.send(new client_s3_1.GetObjectCommand({
164
- Bucket: bucket,
165
- Key: fileKey
166
- }));
167
- (0, Affirm_1.default)(response.Body, 'Failed to fetch object from S3');
168
- const stream = response.Body;
169
- switch (fileType) {
170
- case 'CSV':
171
- case 'JSON':
172
- case 'JSONL':
173
- case 'TXT':
174
- return yield this._readLines(stream, lineFrom, lineTo);
175
- case 'XLS':
176
- case 'XLSX':
177
- return yield this._readExcelLines(stream, sheetName, lineFrom, lineTo);
178
- case 'XML':
179
- return yield this._readXmlLines(stream, lineFrom, lineTo);
153
+ const { fileKey } = request;
154
+ if (fileKey.includes('%')) {
155
+ const allFileKeys = yield this.listFiles(fileKey);
156
+ const promises = allFileKeys.map(x => this._get(Object.assign(Object.assign({}, request), { fileKey: x })));
157
+ const results = yield Promise.all(promises);
158
+ return results.flat();
159
+ }
160
+ else {
161
+ return yield this._get(request);
180
162
  }
181
163
  });
182
164
  this.exist = (producer) => __awaiter(this, void 0, void 0, function* () {
@@ -186,14 +168,20 @@ class S3SourceDriver {
186
168
  const bucket = this._bucketName;
187
169
  const fileKey = producer.settings.fileKey;
188
170
  (0, Affirm_1.default)(fileKey, `Invalid file key for download request`);
189
- try {
190
- yield this._client.send(new client_s3_1.HeadObjectCommand({ Bucket: bucket, Key: fileKey }));
191
- return true;
171
+ if (fileKey.includes('%')) {
172
+ const allFileKeys = yield this.listFiles(fileKey);
173
+ return allFileKeys.length > 0;
192
174
  }
193
- catch (error) {
194
- if (((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404 || error.name === 'NotFound')
195
- return false;
196
- throw error;
175
+ else {
176
+ try {
177
+ yield this._client.send(new client_s3_1.HeadObjectCommand({ Bucket: bucket, Key: fileKey }));
178
+ return true;
179
+ }
180
+ catch (error) {
181
+ if (((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404 || error.name === 'NotFound')
182
+ return false;
183
+ throw error;
184
+ }
197
185
  }
198
186
  });
199
187
  this._readLines = (stream, lineFrom, lineTo) => __awaiter(this, void 0, void 0, function* () {
@@ -288,6 +276,94 @@ class S3SourceDriver {
288
276
  }
289
277
  return lines;
290
278
  });
279
+ this._get = (request) => __awaiter(this, void 0, void 0, function* () {
280
+ const { fileKey, fileType, options } = request;
281
+ const bucket = this._bucketName;
282
+ let lineFrom, lineTo, sheetName;
283
+ if (options) {
284
+ lineFrom = options.lineFrom;
285
+ lineTo = options.lineTo;
286
+ sheetName = options.sheetName;
287
+ }
288
+ const response = yield this._client.send(new client_s3_1.GetObjectCommand({
289
+ Bucket: bucket,
290
+ Key: fileKey
291
+ }));
292
+ (0, Affirm_1.default)(response.Body, 'Failed to fetch object from S3');
293
+ const stream = response.Body;
294
+ switch (fileType) {
295
+ case 'CSV':
296
+ case 'JSON':
297
+ case 'JSONL':
298
+ case 'TXT':
299
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
300
+ return yield this._readLines(stream, lineFrom, lineTo);
301
+ else
302
+ return yield this._readLines(stream);
303
+ case 'XLS':
304
+ case 'XLSX':
305
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
306
+ return yield this._readExcelLines(stream, sheetName, lineFrom, lineTo);
307
+ else
308
+ return yield this._readExcelLines(stream, sheetName);
309
+ case 'XML':
310
+ if (Algo_1.default.hasVal(lineFrom) && Algo_1.default.hasVal(lineTo))
311
+ return yield this._readXmlLines(stream, lineFrom, lineTo);
312
+ else
313
+ return yield this._readXmlLines(stream);
314
+ }
315
+ });
316
+ this._listFiles = (fileKeyPattern, maxKeys, continuationToken) => __awaiter(this, void 0, void 0, function* () {
317
+ var _a;
318
+ (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
319
+ // Convert SQL-like pattern to prefix and pattern parts for filtering
320
+ let prefix = '';
321
+ if (fileKeyPattern) {
322
+ if (fileKeyPattern.includes('%')) {
323
+ const parts = fileKeyPattern.split('%').filter(part => part.length > 0);
324
+ // If pattern starts with text before first %, use it as prefix for S3 optimization
325
+ if (!fileKeyPattern.startsWith('%') && parts[0]) {
326
+ prefix = parts[0];
327
+ }
328
+ }
329
+ else {
330
+ // No wildcard, use the entire pattern as prefix
331
+ prefix = fileKeyPattern;
332
+ }
333
+ }
334
+ const listParams = {
335
+ Bucket: this._bucketName,
336
+ Prefix: prefix || undefined,
337
+ MaxKeys: maxKeys || 10000,
338
+ ContinuationToken: continuationToken
339
+ };
340
+ try {
341
+ const response = yield this._client.send(new client_s3_1.ListObjectsV2Command(listParams));
342
+ const files = ((_a = response.Contents) === null || _a === void 0 ? void 0 : _a.map(obj => obj.Key).filter(key => key !== undefined)) || [];
343
+ const matchingFiles = Helper_1.default.matchPattern(fileKeyPattern, files);
344
+ return {
345
+ files: matchingFiles,
346
+ nextContinuationToken: response.NextContinuationToken
347
+ };
348
+ }
349
+ catch (error) {
350
+ throw new Error(`Failed to list files in bucket "${this._bucketName}": ${error.message}`);
351
+ }
352
+ });
353
+ this.listFiles = (fileKeyPattern, maxKeys) => __awaiter(this, void 0, void 0, function* () {
354
+ const allFiles = [];
355
+ let continuationToken = undefined;
356
+ do {
357
+ const result = yield this._listFiles(fileKeyPattern, maxKeys, continuationToken);
358
+ allFiles.push(...result.files);
359
+ continuationToken = result.nextContinuationToken;
360
+ // If maxKeys is specified and we've reached the limit, break
361
+ if (maxKeys && allFiles.length >= maxKeys) {
362
+ return allFiles.slice(0, maxKeys);
363
+ }
364
+ } while (continuationToken);
365
+ return allFiles;
366
+ });
291
367
  }
292
368
  }
293
369
  exports.S3SourceDriver = S3SourceDriver;
@@ -62,6 +62,9 @@ class ProducerEngineClass {
62
62
  }
63
63
  }
64
64
  });
65
+ /**
66
+ * @deprecated Nobody is using this anymore... prefer readFile
67
+ */
65
68
  this.execute = (producer) => __awaiter(this, void 0, void 0, function* () {
66
69
  (0, Affirm_1.default)(producer, 'Invalid producer');
67
70
  const source = Environment_1.default.getSource(producer.source);
package/helper/Helper.js CHANGED
@@ -66,6 +66,61 @@ const Helper = {
66
66
  const year = date.getFullYear();
67
67
  const month = ('0' + (date.getMonth() + 1)).slice(-2);
68
68
  return `${year}-${month}`;
69
+ },
70
+ matchPattern: (pattern, items) => {
71
+ let patternParts = [];
72
+ let hasWildcard = false;
73
+ let result = [...items];
74
+ if (pattern) {
75
+ if (pattern.includes('%')) {
76
+ hasWildcard = true;
77
+ const parts = pattern.split('%').filter(part => part.length > 0);
78
+ // Store all non-empty parts for pattern matching
79
+ patternParts = parts;
80
+ }
81
+ }
82
+ // Apply additional filtering for patterns with wildcards
83
+ if (hasWildcard && patternParts.length > 0) {
84
+ result = result.filter(key => {
85
+ // Create a function to check if the key matches the SQL-like pattern
86
+ const matchesPattern = (fileName, pattern) => {
87
+ if (!pattern.includes('%')) {
88
+ return fileName === pattern;
89
+ }
90
+ const parts = pattern.split('%');
91
+ let currentIndex = 0;
92
+ for (let i = 0; i < parts.length; i++) {
93
+ const part = parts[i];
94
+ if (part === '')
95
+ continue; // Skip empty parts from consecutive %% or leading/trailing %
96
+ if (i === 0 && !pattern.startsWith('%')) {
97
+ // First part must be at the beginning
98
+ if (!fileName.startsWith(part)) {
99
+ return false;
100
+ }
101
+ currentIndex = part.length;
102
+ }
103
+ else if (i === parts.length - 1 && !pattern.endsWith('%')) {
104
+ // Last part must be at the end
105
+ if (!fileName.endsWith(part)) {
106
+ return false;
107
+ }
108
+ }
109
+ else {
110
+ // Middle parts must exist somewhere after the current position
111
+ const foundIndex = fileName.indexOf(part, currentIndex);
112
+ if (foundIndex === -1) {
113
+ return false;
114
+ }
115
+ currentIndex = foundIndex + part.length;
116
+ }
117
+ }
118
+ return true;
119
+ };
120
+ return matchesPattern(key, pattern);
121
+ });
122
+ }
123
+ return result;
69
124
  }
70
125
  };
71
126
  exports.default = Helper;
package/index.js CHANGED
@@ -11,11 +11,10 @@ const debug_1 = require("./actions/debug");
11
11
  const deploy_1 = require("./actions/deploy");
12
12
  const init_1 = require("./actions/init");
13
13
  const run_1 = require("./actions/run");
14
- const Constants_1 = __importDefault(require("./Constants"));
15
14
  const discover_1 = require("./actions/discover");
16
- const automap_1 = require("./actions/automap");
17
15
  const create_producer_1 = require("./actions/create_producer");
18
16
  const create_consumer_1 = require("./actions/create_consumer");
17
+ const Constants_1 = __importDefault(require("./Constants"));
19
18
  const LicenceManager_1 = __importDefault(require("./licencing/LicenceManager"));
20
19
  dotenv_1.default.configDotenv();
21
20
  const program = new commander_1.Command();
@@ -63,12 +62,6 @@ program
63
62
  .description('Discover the data shape of a producer and automatically create the resource for it.')
64
63
  .argument('<producer>', 'The producer to discover')
65
64
  .action(discover_1.discover);
66
- program
67
- .command('automap')
68
- .description('Automatically map a producer to consumers using specified schemas.')
69
- .argument('<producer>', 'The producer to analyze')
70
- .argument('<schemas...>', 'One or more schema names to map against')
71
- .action(automap_1.automap);
72
65
  program
73
66
  .command('create-producer <name>')
74
67
  .description('Create a new producer configuration with default settings')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forzalabs/remora",
3
- "version": "0.0.30",
3
+ "version": "0.0.31-nasco.3",
4
4
  "description": "A powerful CLI tool for seamless data translation.",
5
5
  "main": "index.js",
6
6
  "private": false,
@@ -17,11 +17,10 @@
17
17
  "compile": "npx tsx ./src/index.ts compile",
18
18
  "deploy": "npx tsx ./src/index.ts deploy",
19
19
  "debug": "npx tsx ./src/index.ts debug",
20
- "automap": "npx tsx ./src/index.ts automap",
21
20
  "create-producer": "npx tsx ./src/index.ts create-producer",
22
21
  "copy-static-file": "npx tsx ./scripts/CopyStaticFile.js",
23
22
  "build": "npm i && npm run sync && tsc --outDir .build && npm run copy-static-file",
24
- "upload": "npm run build && cd .build && npm publish --access=public"
23
+ "upload": "npm run build && cd .build && npm publish --tag nasco --access=public"
25
24
  },
26
25
  "keywords": [
27
26
  "nextjs",
@@ -30,7 +29,7 @@
30
29
  "typescript"
31
30
  ],
32
31
  "author": "",
33
- "license": "ISC",
32
+ "license": "BSL",
34
33
  "dependencies": {
35
34
  "@aws-sdk/client-redshift-data": "^3.699.0",
36
35
  "@aws-sdk/client-s3": "^3.701.0",
@@ -51,7 +50,7 @@
51
50
  "knex": "^2.4.2",
52
51
  "mongodb": "^6.15.0",
53
52
  "next": "^13.4.1",
54
- "openai": "^4.91.1",
53
+
55
54
  "ora": "^5.4.1",
56
55
  "react": "^18.2.0",
57
56
  "react-dom": "^18.2.0",
@@ -1,77 +0,0 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
13
- };
14
- Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.automap = void 0;
16
- const chalk_1 = __importDefault(require("chalk"));
17
- const ora_1 = __importDefault(require("ora"));
18
- const compile_1 = require("./compile");
19
- const AutoMapperEngine_1 = __importDefault(require("../engines/ai/AutoMapperEngine"));
20
- const fs_1 = __importDefault(require("fs"));
21
- const path_1 = __importDefault(require("path"));
22
- const Environment_1 = __importDefault(require("../engines/Environment"));
23
- const ProducerEngine_1 = __importDefault(require("../engines/ProducerEngine"));
24
- /**
25
- * e.g. npm run automap -- myclaims Claim
26
- */
27
- const automap = (producerName, schemaNames) => __awaiter(void 0, void 0, void 0, function* () {
28
- try {
29
- (0, compile_1.compile)();
30
- const spinner = (0, ora_1.default)(chalk_1.default.blue('Auto-mapping producer data...\n')).start();
31
- // Get the producer
32
- const producer = Environment_1.default.getProducer(producerName);
33
- if (!producer) {
34
- throw new Error(`Producer ${producerName} not found`);
35
- }
36
- const source = Environment_1.default.getSource(producer.source);
37
- if (!source) {
38
- throw new Error(`Source ${producer.source} not found`);
39
- }
40
- // Get the specified schemas
41
- const schemas = [];
42
- for (const schemaName of schemaNames) {
43
- const schema = Environment_1.default.getSchema(schemaName);
44
- if (!schema) {
45
- throw new Error(`Schema ${schemaName} not found`);
46
- }
47
- schemas.push(schema);
48
- }
49
- // Read and convert sample data
50
- const sampleData = yield ProducerEngine_1.default.readSampleData(producer);
51
- // Convert sample data to strings for AutoMapperEngine
52
- const sampleStrings = sampleData.map(item => JSON.stringify(item));
53
- // Call the automapper
54
- const mapResult = yield AutoMapperEngine_1.default.map(sampleStrings, schemas, producer.settings.fileKey, [source]);
55
- // Create the producers based on the mapping
56
- for (const producer of mapResult.producers) {
57
- const producerPath = path_1.default.join('remora/producers', `${producer.name}.json`);
58
- fs_1.default.writeFileSync(producerPath, JSON.stringify(producer, null, 4));
59
- console.log(chalk_1.default.blue(`Created producer: ${producer.name}`));
60
- }
61
- // Create the consumers based on the mapping
62
- for (const consumer of mapResult.consumers) {
63
- const consumerPath = path_1.default.join('remora/consumers', `${consumer.name}.json`);
64
- fs_1.default.writeFileSync(consumerPath, JSON.stringify(consumer, null, 4));
65
- console.log(chalk_1.default.blue(`Created consumer: ${consumer.name}`));
66
- }
67
- spinner.succeed('Producer has been successfully mapped');
68
- console.log(chalk_1.default.green(`\nāœ… Created ${mapResult.producers.length} producers!`));
69
- console.log(chalk_1.default.green(`āœ… Created ${mapResult.consumers.length} consumers!`));
70
- process.exit(0);
71
- }
72
- catch (err) {
73
- console.error(chalk_1.default.red.bold('\nāŒ Unexpected error during automapping:'), err instanceof Error ? err.message : String(err));
74
- process.exit(1);
75
- }
76
- });
77
- exports.automap = automap;