@forzalabs/remora 0.0.18 → 0.0.20

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/Constants.js CHANGED
@@ -1,8 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const CONSTANTS = {
4
- cliVersion: '0.0.18',
4
+ cliVersion: '0.0.20',
5
5
  lambdaVersion: 1,
6
- port: 5069
6
+ port: 5069,
7
+ defaults: {
8
+ SQL_MAX_QUERY_ROWS: 10000,
9
+ STRING_MAX_CHARACTERS_LENGTH: 10000000
10
+ }
7
11
  };
8
12
  exports.default = CONSTANTS;
@@ -39,7 +39,7 @@ const compile = () => __awaiter(void 0, void 0, void 0, function* () {
39
39
  errors = [...errors, ...envErrors];
40
40
  if (errors.length === 0) {
41
41
  spinner.succeed(chalk_1.default.green('Project structure validated successfully'));
42
- console.log(chalk_1.default.green.bold('\n✅ Compilation complete!'));
42
+ console.log(chalk_1.default.blueBright.bold('✅ Compilation complete!'));
43
43
  }
44
44
  else {
45
45
  spinner.fail(chalk_1.default.red('Validation failed with errors:'));
package/actions/run.js CHANGED
@@ -19,9 +19,11 @@ const Environment_1 = __importDefault(require("../engines/Environment"));
19
19
  const UserManager_1 = __importDefault(require("../engines/UserManager"));
20
20
  const ConsumerEngine_1 = __importDefault(require("../engines/consumer/ConsumerEngine"));
21
21
  const compile_1 = require("./compile");
22
+ const Helper_1 = __importDefault(require("../helper/Helper"));
22
23
  const run = (consumerName) => __awaiter(void 0, void 0, void 0, function* () {
23
24
  try {
24
25
  (0, compile_1.compile)();
26
+ console.log();
25
27
  const spinner = (0, ora_1.default)(chalk_1.default.blue('Running consumer(s)...\n')).start();
26
28
  const user = UserManager_1.default.getUser();
27
29
  const consumersToExecute = (consumerName && consumerName.length > 0)
@@ -32,26 +34,38 @@ const run = (consumerName) => __awaiter(void 0, void 0, void 0, function* () {
32
34
  const consumer = consumersToExecute[i];
33
35
  try {
34
36
  const response = yield ConsumerEngine_1.default.execute(consumer, {}, user);
35
- results.push({ consumer, response });
37
+ results.push({ success: true, consumer, response });
36
38
  }
37
39
  catch (error) {
38
- console.error(chalk_1.default.red(`Failed to execute consumer ${consumer.name}:`, error instanceof Error ? error.message : String(error)));
40
+ const myErr = Helper_1.default.asError(error);
41
+ results.push({ success: false, consumer, error: myErr.message });
42
+ if (Helper_1.default.isDev())
43
+ console.log(myErr.stack);
39
44
  }
40
45
  }
41
- spinner.succeed('All consumers have been successfully executed');
42
- results.forEach(result => {
43
- if (result.response.fileUri) {
44
- console.log(chalk_1.default.green(`• Consumer ${result.consumer.name} -> ${result.response.fileUri}`));
46
+ spinner.succeed('All consumers have been executed:');
47
+ results.forEach(({ response, consumer, success, error }) => {
48
+ if (success) {
49
+ if (response.fileUri)
50
+ console.log(chalk_1.default.green(`• Consumer ${consumer.name} -> ${response.fileUri}`));
51
+ else
52
+ console.log(chalk_1.default.green(`• Consumer ${consumer.name} -> ${response.data.slice(0, 5).join('\n')}`));
45
53
  }
46
54
  else {
47
- console.log(chalk_1.default.green(`• Consumer ${result.consumer.name} -> ${result.response.data.slice(0, 5).join('\n')}`));
55
+ console.log(chalk_1.default.red(`• Consumer ${consumer.name} -> Failed: ${error}`));
48
56
  }
49
57
  });
50
- console.log(chalk_1.default.green('\n✅ Initialization complete!'));
58
+ if (results.some(x => !x.success))
59
+ console.log(chalk_1.default.blueBright('\nℹ️ Run completed with errors'));
60
+ else
61
+ console.log(chalk_1.default.green('\n✅ Run complete!'));
51
62
  process.exit(1);
52
63
  }
53
64
  catch (err) {
54
- console.error(chalk_1.default.red.bold('\n❌ Unexpected error during run:'), err instanceof Error ? err.message : String(err));
65
+ const myErr = Helper_1.default.asError(err);
66
+ console.error(chalk_1.default.red.bold('\n❌ Unexpected error during run:'), myErr.message);
67
+ if (Helper_1.default.isDev())
68
+ console.log(myErr.stack);
55
69
  process.exit(1);
56
70
  }
57
71
  });
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -12,7 +45,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
45
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
46
  };
14
47
  Object.defineProperty(exports, "__esModule", { value: true });
15
- const LocalDriver_1 = __importDefault(require("./LocalDriver"));
48
+ const LocalDriver_1 = __importStar(require("./LocalDriver"));
16
49
  const RedshiftDriver_1 = __importDefault(require("./RedshiftDriver"));
17
50
  const S3Driver_1 = __importDefault(require("./S3Driver"));
18
51
  const S3SourceDriver_1 = __importDefault(require("./S3SourceDriver"));
@@ -47,6 +80,11 @@ class DriverFactoryClass {
47
80
  yield driver.init(source);
48
81
  return driver;
49
82
  }
83
+ case 'local': {
84
+ const driver = new LocalDriver_1.LocalDriverDestination();
85
+ yield driver.init(source);
86
+ return driver;
87
+ }
50
88
  default: throw new Error(`Invalid driver type "${source.engine}". This driver is not implemented yet`);
51
89
  }
52
90
  });
@@ -52,6 +52,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
52
52
  return (mod && mod.__esModule) ? mod : { "default": mod };
53
53
  };
54
54
  Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.LocalDriverDestination = void 0;
55
56
  const fs = __importStar(require("fs"));
56
57
  const path_1 = __importDefault(require("path"));
57
58
  const readline_1 = __importDefault(require("readline"));
@@ -60,9 +61,9 @@ class LocalDriver {
60
61
  constructor() {
61
62
  this.init = (source) => __awaiter(this, void 0, void 0, function* () {
62
63
  const fileURL = source.authentication['path'];
63
- (0, Affirm_1.default)(fileURL, 'file path is not entered in configuration');
64
+ (0, Affirm_1.default)(fileURL, `Missing file path in the authentication of source "${source.name}"`);
64
65
  const exist = fs.existsSync(fileURL);
65
- (0, Affirm_1.default)(exist, 'The path entered is incorrect: ' + fileURL);
66
+ (0, Affirm_1.default)(exist, `The path (${fileURL}) for source "${source.name}" does NOT exist.`);
66
67
  this._path = source.authentication['path'];
67
68
  return this;
68
69
  });
@@ -119,4 +120,71 @@ class LocalDriver {
119
120
  });
120
121
  }
121
122
  }
123
+ class LocalDriverDestination {
124
+ constructor() {
125
+ this.init = (source) => __awaiter(this, void 0, void 0, function* () {
126
+ (0, Affirm_1.default)(source, `Invalid source`);
127
+ const fileURL = source.authentication['path'];
128
+ (0, Affirm_1.default)(fileURL, `Missing file path in the authentication of source "${source.name}"`);
129
+ const exist = fs.existsSync(fileURL);
130
+ (0, Affirm_1.default)(exist, `The path (${fileURL}) for source "${source.name}" does NOT exist.`);
131
+ this._path = source.authentication['path'];
132
+ return this;
133
+ });
134
+ this.uploadFile = (options) => __awaiter(this, void 0, void 0, function* () {
135
+ (0, Affirm_1.default)(this._path, 'Path not initialized');
136
+ (0, Affirm_1.default)(options, 'Invalid upload options');
137
+ (0, Affirm_1.default)(options.name, 'File name is required');
138
+ (0, Affirm_1.default)(options.content != null, 'File content is required');
139
+ const folder = this._path;
140
+ try {
141
+ if (!fs.existsSync(folder))
142
+ fs.mkdirSync(folder, { recursive: true });
143
+ const filePath = path_1.default.join(folder, options.name);
144
+ fs.writeFileSync(filePath, options.content);
145
+ return { bucket: folder, key: filePath, res: true };
146
+ }
147
+ catch (error) {
148
+ throw new Error(`Failed to upload local file "${options.name}": ${error.message}`);
149
+ }
150
+ });
151
+ this.multipartUpload = (options) => __awaiter(this, void 0, void 0, function* () {
152
+ (0, Affirm_1.default)(this._path, 'Path not initialized');
153
+ (0, Affirm_1.default)(options, 'Invalid upload options');
154
+ (0, Affirm_1.default)(options.name, 'File name is required');
155
+ (0, Affirm_1.default)(options.contents && Array.isArray(options.contents), 'Contents must be an array');
156
+ (0, Affirm_1.default)(options.contents.length > 0, 'Contents array cannot be empty');
157
+ const folder = this._path;
158
+ try {
159
+ if (!fs.existsSync(folder)) {
160
+ fs.mkdirSync(folder, { recursive: true });
161
+ }
162
+ const filePath = path_1.default.join(folder, options.name);
163
+ // Create or truncate the file first
164
+ fs.writeFileSync(filePath, '');
165
+ // Append each chunk
166
+ for (const chunk of options.contents) {
167
+ (0, Affirm_1.default)(typeof chunk === 'string', 'Each chunk must be a string');
168
+ fs.appendFileSync(filePath, chunk);
169
+ }
170
+ return { bucket: folder, key: filePath, res: true };
171
+ }
172
+ catch (error) {
173
+ // Clean up the partial file if it exists
174
+ const filePath = path_1.default.join(folder, options.name);
175
+ if (fs.existsSync(filePath)) {
176
+ try {
177
+ fs.unlinkSync(filePath);
178
+ }
179
+ catch (cleanupError) {
180
+ console.error(`Failed to clean up partial file after error: ${cleanupError.message}`);
181
+ throw cleanupError;
182
+ }
183
+ }
184
+ throw new Error(`Failed to complete local multipart upload for "${options.name}": ${error.message}`);
185
+ }
186
+ });
187
+ }
188
+ }
189
+ exports.LocalDriverDestination = LocalDriverDestination;
122
190
  exports.default = LocalDriver;
@@ -45,6 +45,58 @@ class S3Driver {
45
45
  (0, Affirm_1.default)(res.$metadata.httpStatusCode === 200, `Failed to upload the file "${name}" to the bucket "${this._bucketName}": status code ${res.$metadata.httpStatusCode}`);
46
46
  return { res: true, key: name, bucket: this._bucketName };
47
47
  });
48
+ this.multipartUpload = (options) => __awaiter(this, void 0, void 0, function* () {
49
+ (0, Affirm_1.default)(options, `Invalid upload options`);
50
+ (0, Affirm_1.default)(options.contents && options.contents.length > 0, 'No contents provided for multipart upload');
51
+ (0, Affirm_1.default)(options.name, 'No filename provided for multipart upload');
52
+ try {
53
+ // Create the multipart upload
54
+ const createMultipartUploadRes = yield this._client.send(new client_s3_1.CreateMultipartUploadCommand({
55
+ Bucket: this._bucketName,
56
+ Key: options.name
57
+ }));
58
+ const uploadId = createMultipartUploadRes.UploadId;
59
+ (0, Affirm_1.default)(uploadId, 'Failed to initiate multipart upload');
60
+ // Upload each part
61
+ const uploadPromises = options.contents.map((content, index) => __awaiter(this, void 0, void 0, function* () {
62
+ const partNumber = index + 1;
63
+ const uploadPartRes = yield this._client.send(new client_s3_1.UploadPartCommand({
64
+ Bucket: this._bucketName,
65
+ Key: options.name,
66
+ UploadId: uploadId,
67
+ PartNumber: partNumber,
68
+ Body: Buffer.from(content)
69
+ }));
70
+ return {
71
+ PartNumber: partNumber,
72
+ ETag: uploadPartRes.ETag
73
+ };
74
+ }));
75
+ const uploadedParts = yield Promise.all(uploadPromises);
76
+ // Complete the multipart upload
77
+ const completeRes = yield this._client.send(new client_s3_1.CompleteMultipartUploadCommand({
78
+ Bucket: this._bucketName,
79
+ Key: options.name,
80
+ UploadId: uploadId,
81
+ MultipartUpload: {
82
+ Parts: uploadedParts
83
+ }
84
+ }));
85
+ (0, Affirm_1.default)(completeRes.$metadata.httpStatusCode === 200, `Failed to complete multipart upload for "${options.name}": status code ${completeRes.$metadata.httpStatusCode}`);
86
+ return { res: true, key: options.name, bucket: this._bucketName };
87
+ }
88
+ catch (error) {
89
+ // If anything fails, make sure to abort the multipart upload
90
+ if (error.UploadId) {
91
+ yield this._client.send(new client_s3_1.AbortMultipartUploadCommand({
92
+ Bucket: this._bucketName,
93
+ Key: options.name,
94
+ UploadId: error.UploadId
95
+ }));
96
+ }
97
+ throw error;
98
+ }
99
+ });
48
100
  }
49
101
  }
50
102
  exports.default = S3Driver;
@@ -8,6 +8,7 @@ const path_1 = __importDefault(require("path"));
8
8
  const Affirm_1 = __importDefault(require("../core/Affirm"));
9
9
  const SchemaValidator_1 = __importDefault(require("./schema/SchemaValidator"));
10
10
  const Validator_1 = __importDefault(require("./Validator"));
11
+ const Constants_1 = __importDefault(require("../Constants"));
11
12
  class EnvironmentClass {
12
13
  constructor() {
13
14
  this._env = null;
@@ -71,9 +72,16 @@ class EnvironmentClass {
71
72
  if (!SchemaValidator_1.default.validate('consumer-schema', consumer))
72
73
  throw new Error(`Invalid consumer configuration: ${consumer.name}`);
73
74
  });
75
+ // Load the project settings
76
+ const envSettings = new Map(Object.entries(Object.assign({}, projectConfig.settings))
77
+ .map(([key, value]) => [key, String(value)]));
78
+ if (!envSettings.has('SQL_MAX_QUERY_ROWS'))
79
+ envSettings.set('SQL_MAX_QUERY_ROWS', Constants_1.default.defaults.SQL_MAX_QUERY_ROWS.toString());
80
+ if (!envSettings.has('STRING_MAX_CHARACTERS_LENGTH'))
81
+ envSettings.set('STRING_MAX_CHARACTERS_LENGTH', Constants_1.default.defaults.STRING_MAX_CHARACTERS_LENGTH.toString());
74
82
  // Initialize environment
75
83
  this.init({
76
- settings: new Map(Object.entries(Object.assign({}, projectConfig.settings)).map(([key, value]) => [key, String(value)])),
84
+ settings: envSettings,
77
85
  sources,
78
86
  producers,
79
87
  consumers,
@@ -93,7 +101,7 @@ class EnvironmentClass {
93
101
  */
94
102
  this.getFirstProducer = (producerName) => {
95
103
  (0, Affirm_1.default)(producerName, `Invalid producer name`);
96
- const prod = this._env.producers.find(x => x.name === producerName);
104
+ const prod = this._env.producers.find(x => x.name.toLocaleLowerCase() === producerName.toLowerCase());
97
105
  if (!prod) {
98
106
  const consumer = this.getConsumer(producerName);
99
107
  (0, Affirm_1.default)(consumer, `Invalid producer name`);
@@ -103,11 +111,11 @@ class EnvironmentClass {
103
111
  };
104
112
  this.getProducer = (producerName) => {
105
113
  (0, Affirm_1.default)(producerName, `Invalid producer name`);
106
- return this._env.producers.find(x => x.name === producerName);
114
+ return this._env.producers.find(x => x.name.toLowerCase() === producerName.toLowerCase());
107
115
  };
108
116
  this.getConsumer = (consumerName) => {
109
117
  (0, Affirm_1.default)(consumerName, `Invalid consumer name`);
110
- return this._env.consumers.find(x => x.name === consumerName);
118
+ return this._env.consumers.find(x => x.name.toLowerCase() === consumerName.toLowerCase());
111
119
  };
112
120
  this.getSchema = (schemaName) => {
113
121
  (0, Affirm_1.default)(schemaName, 'Invalid schema name');
@@ -123,7 +131,17 @@ class EnvironmentClass {
123
131
  try {
124
132
  errors = [...errors, ...Validator_1.default.validateSources(this._env.sources)];
125
133
  errors = [...errors, ...Validator_1.default.validateProducers(this._env.producers)];
134
+ this._env.producers.forEach(prod => {
135
+ const ce = Validator_1.default.validateProducer(prod);
136
+ if (ce.length > 0)
137
+ errors.push(`Producer "${prod.name}" errors:\n${ce.map(x => `\t-${x}\n`)}`);
138
+ });
126
139
  errors = [...errors, ...Validator_1.default.validateConsumers(this._env.consumers)];
140
+ this._env.consumers.forEach(cons => {
141
+ const ce = Validator_1.default.validateConsumer(cons);
142
+ if (ce.length > 0)
143
+ errors.push(`Consumer "${cons.name}" errors:\n${ce.map(x => `\t-${x}\n`)}`);
144
+ });
127
145
  }
128
146
  catch (e) {
129
147
  if (errors.length === 0)
@@ -82,6 +82,7 @@ class ProducerEngineClass {
82
82
  }
83
83
  });
84
84
  this.readFile = (producer, options) => __awaiter(this, void 0, void 0, function* () {
85
+ var _a;
85
86
  (0, Affirm_1.default)(producer, 'Invalid producer');
86
87
  (0, Affirm_1.default)(options, 'Invalid options');
87
88
  if (options.readmode === 'lines')
@@ -95,7 +96,7 @@ class ProducerEngineClass {
95
96
  lines = yield driver.readLinesInRange({ fileKey: producer.settings.fileKey, lineFrom: options.lines.from, lineTo: options.lines.to });
96
97
  else
97
98
  lines = [(yield driver.download({ fileKey: producer.settings.fileKey }))];
98
- switch (producer.settings.fileType.toUpperCase()) {
99
+ switch ((_a = producer.settings.fileType) === null || _a === void 0 ? void 0 : _a.toUpperCase()) {
99
100
  case 'CSV': {
100
101
  return { data: lines, dataType: 'lines-of-text' };
101
102
  }
@@ -65,7 +65,6 @@ class ValidatorClass {
65
65
  const dupes = Algo_1.default.duplicatesObject(consumers, 'name');
66
66
  if (dupes.length > 0)
67
67
  errors.push(`Duplicate name(s) found in consumers: "${dupes.map(x => x.name).join(', ')}"`);
68
- errors.push(...consumers.flatMap(x => this.validateConsumer(x)));
69
68
  }
70
69
  catch (e) {
71
70
  if (errors.length === 0)
@@ -121,7 +120,7 @@ class ValidatorClass {
121
120
  const groupingFields = fields.filter(x => x.grouping);
122
121
  if (groupingFields.length > 1)
123
122
  errors.push(`There can't be 2 fields with grouping defined at the same level (${groupingFields.map(x => x.key).join(', ')}). Level: ${level}`);
124
- groupingFields.forEach(field => {
123
+ groupingFields.forEach((field) => {
125
124
  if (field.grouping)
126
125
  errors = [...errors, ...validateGroupingLevels(field.grouping.subFields, level + 1)];
127
126
  });
@@ -18,7 +18,7 @@ class ExecutionPlannerClas {
18
18
  }
19
19
  };
20
20
  this.plan = (consumer, options) => {
21
- var _a;
21
+ var _a, _b;
22
22
  (0, Affirm_1.default)(consumer, 'Invalid consumer');
23
23
  const [source, producer] = ConsumerManager_1.default.getSource(consumer);
24
24
  const producerEngine = source.engine;
@@ -39,7 +39,7 @@ class ExecutionPlannerClas {
39
39
  plan.push({ type: 'read-file-lines', producer: prod, lines: { from: (_a = options.offset) !== null && _a !== void 0 ? _a : 0, to: options.limit ? (options.offset + options.limit) : undefined } });
40
40
  else
41
41
  plan.push({ type: 'read-file-whole', producer: prod });
42
- if (prod.settings.fileType.toUpperCase() === 'CSV') {
42
+ if (((_b = prod.settings.fileType) === null || _b === void 0 ? void 0 : _b.toUpperCase()) === 'CSV') {
43
43
  plan.push({ type: 'csv-to-json', producer: prod });
44
44
  }
45
45
  if (prod.dimensions.some(x => { var _a, _b; return ((_a = x.alias) === null || _a === void 0 ? void 0 : _a.includes('{')) || ((_b = x.alias) === null || _b === void 0 ? void 0 : _b.includes('[')); }))
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const Affirm_1 = __importDefault(require("../../core/Affirm"));
7
+ const Environment_1 = __importDefault(require("../Environment"));
8
+ class FileContentBuilderClass {
9
+ constructor() {
10
+ /**
11
+ * Converts an array of string to a single string separated with the separator.
12
+ * In the V8 engine there is a maximum length to a string so I can't just join it all.
13
+ * I use this to create chunks that are not too long.
14
+ */
15
+ this.compose = (lines, separator) => {
16
+ Affirm_1.default.hasValue(lines, 'Invalid lines');
17
+ Affirm_1.default.hasValue(lines, 'Invalid separator');
18
+ const maxStringLength = parseInt(Environment_1.default.get('STRING_MAX_CHARACTERS_LENGTH'));
19
+ const chunks = [];
20
+ let currentChunk = '';
21
+ for (const line of lines) {
22
+ currentChunk += (line + separator);
23
+ if (currentChunk.length >= maxStringLength) {
24
+ chunks.push(currentChunk);
25
+ currentChunk = '';
26
+ }
27
+ }
28
+ chunks.push(currentChunk);
29
+ return chunks;
30
+ };
31
+ }
32
+ }
33
+ const FileContentBuilder = new FileContentBuilderClass();
34
+ exports.default = FileContentBuilder;
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -50,14 +17,22 @@ const Algo_1 = __importDefault(require("../../core/Algo"));
50
17
  const DSTE_1 = __importDefault(require("../../core/dste/DSTE"));
51
18
  const DriverFactory_1 = __importDefault(require("../../drivers/DriverFactory"));
52
19
  const Environment_1 = __importDefault(require("../Environment"));
53
- const fs = __importStar(require("fs"));
20
+ const FileContentBuilder_1 = __importDefault(require("./FileContentBuilder"));
54
21
  class FileExporterClass {
55
22
  constructor() {
56
23
  this.export = (consumer, output, data) => __awaiter(this, void 0, void 0, function* () {
57
24
  (0, Affirm_1.default)(consumer, `Invalid consumer`);
58
25
  (0, Affirm_1.default)(output, `Invalid output`);
59
26
  (0, Affirm_1.default)(data, `Invalid export data`);
60
- let exportData = null;
27
+ const preparedData = this._prepareData(consumer, output, data);
28
+ const writeRes = yield this._writeData(consumer, output, preparedData);
29
+ return writeRes;
30
+ });
31
+ this._prepareData = (consumer, output, data) => {
32
+ (0, Affirm_1.default)(consumer, `Invalid consumer`);
33
+ (0, Affirm_1.default)(output, `Invalid output`);
34
+ (0, Affirm_1.default)(data, `Invalid export data`);
35
+ let exportDataChunks = null;
61
36
  let extension = null;
62
37
  // build the actual file in the requested format
63
38
  switch (output.format.toUpperCase()) {
@@ -71,8 +46,7 @@ class FileExporterClass {
71
46
  const rowValues = columns.map(c => { var _a; return Algo_1.default.replaceAll((_a = c === null || c === void 0 ? void 0 : c.toString()) !== null && _a !== void 0 ? _a : '', '"', '""'); }).map(c => `"${c}"`).join(',');
72
47
  lines.push(rowValues);
73
48
  }
74
- const csv = lines.join('\n');
75
- exportData = csv;
49
+ exportDataChunks = FileContentBuilder_1.default.compose(lines, '\n');
76
50
  extension = 'csv';
77
51
  break;
78
52
  }
@@ -82,8 +56,7 @@ class FileExporterClass {
82
56
  const row = data[i];
83
57
  lines.push(JSON.stringify(row));
84
58
  }
85
- const jsonl = lines.join('\n');
86
- exportData = jsonl;
59
+ exportDataChunks = FileContentBuilder_1.default.compose(lines, '\n');
87
60
  extension = 'jsonl';
88
61
  break;
89
62
  }
@@ -91,27 +64,37 @@ class FileExporterClass {
91
64
  throw new Error(`Consumer output "${output.format}" not implemented yet`);
92
65
  }
93
66
  }
67
+ return { textChunks: exportDataChunks, extension };
68
+ };
69
+ this._writeData = (consumer, output, preparedData) => __awaiter(this, void 0, void 0, function* () {
70
+ (0, Affirm_1.default)(consumer, `Invalid consumer`);
71
+ (0, Affirm_1.default)(output, `Invalid output`);
72
+ (0, Affirm_1.default)(preparedData, `Invalid prepared data`);
94
73
  // export it where it needs to go
95
74
  const source = Environment_1.default.getSource(output.exportDestination);
96
75
  (0, Affirm_1.default)(source, `Invalid consumer "${consumer.name}" export location source. Make sure that the export location is an available source.`);
76
+ const { extension, textChunks } = preparedData;
77
+ const name = this._composeFileName(consumer, extension);
97
78
  switch (source.engine) {
98
79
  case 'local': {
99
- const folder = source.authentication.path;
100
- if (!fs.existsSync(folder))
101
- fs.mkdirSync(folder);
102
- const date = DSTE_1.default.now().toISOString().split('.')[0];
103
- const path = `${folder}/${consumer.name}_${Algo_1.default.replaceAll(date, ':', '-')}.${extension}`;
104
- fs.writeFileSync(path, exportData);
105
- return path;
80
+ const driver = yield DriverFactory_1.default.instantiateDestination(source);
81
+ const res = yield driver.multipartUpload({ contents: textChunks, name });
82
+ return res.key;
106
83
  }
107
84
  case 'aws-s3': {
108
85
  const driver = yield DriverFactory_1.default.instantiateDestination(source);
109
- const date = DSTE_1.default.now().toISOString().split('.')[0];
110
- const res = yield driver.uploadFile({ content: exportData, name: `${consumer.name}_${Algo_1.default.replaceAll(date, ':', '-')}.${extension}` });
111
- return res.key;
86
+ if (textChunks.length === 1) {
87
+ const res = yield driver.uploadFile({ content: textChunks[0], name });
88
+ return res.key;
89
+ }
90
+ else {
91
+ const res = yield driver.multipartUpload({ contents: textChunks, name });
92
+ return res.key;
93
+ }
112
94
  }
113
95
  }
114
96
  });
97
+ this._composeFileName = (consumer, extension) => `${consumer.name}_${Algo_1.default.replaceAll(DSTE_1.default.now().toISOString().split('.')[0], ':', '-')}.${extension}`;
115
98
  }
116
99
  }
117
100
  const FileExporter = new FileExporterClass();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@forzalabs/remora",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "A powerful CLI tool for seamless data translation.",
5
5
  "main": "index.js",
6
6
  "private": false,