@forzalabs/remora 1.0.21 → 1.1.1

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 (111) hide show
  1. package/actions/automap.js +26 -42
  2. package/actions/compile.js +27 -43
  3. package/actions/create_consumer.js +24 -40
  4. package/actions/create_producer.js +16 -32
  5. package/actions/debug.js +18 -34
  6. package/actions/deploy.js +30 -46
  7. package/actions/discover.js +13 -29
  8. package/actions/init.js +29 -45
  9. package/actions/mock.js +16 -32
  10. package/actions/run.js +34 -52
  11. package/actions/sample.js +42 -58
  12. package/index.js +38 -43
  13. package/package.json +4 -4
  14. package/workers/ExecutorWorker.js +18 -32
  15. package/Constants.js +0 -34
  16. package/core/Affirm.js +0 -42
  17. package/core/Algo.js +0 -160
  18. package/core/dste/DSTE.js +0 -113
  19. package/core/logger/DebugLogService.js +0 -48
  20. package/core/logger/DevelopmentLogService.js +0 -70
  21. package/core/logger/LocalLogService.js +0 -70
  22. package/core/logger/Logger.js +0 -54
  23. package/database/DatabaseEngine.js +0 -149
  24. package/database/DatabaseStructure.js +0 -27
  25. package/definitions/DatasetDefinitions.js +0 -2
  26. package/definitions/ExecutorDefinitions.js +0 -2
  27. package/definitions/ProcessENV.js +0 -2
  28. package/definitions/agents/DestinationDriver.js +0 -2
  29. package/definitions/agents/SourceDriver.js +0 -2
  30. package/definitions/cli.js +0 -2
  31. package/definitions/database/ApiKeys.js +0 -2
  32. package/definitions/database/Stored.js +0 -7
  33. package/definitions/database/UsageStat.js +0 -2
  34. package/definitions/database/User.js +0 -2
  35. package/definitions/json_schemas/consumer-schema.json +0 -1226
  36. package/definitions/json_schemas/producer-schema.json +0 -308
  37. package/definitions/json_schemas/project-schema.json +0 -100
  38. package/definitions/json_schemas/source-schema.json +0 -249
  39. package/definitions/requests/ConsumerRequest.js +0 -2
  40. package/definitions/requests/Developer.js +0 -2
  41. package/definitions/requests/Mapping.js +0 -2
  42. package/definitions/requests/ProducerRequest.js +0 -2
  43. package/definitions/requests/Request.js +0 -2
  44. package/definitions/resources/Compiled.js +0 -2
  45. package/definitions/resources/Consumer.js +0 -2
  46. package/definitions/resources/Environment.js +0 -2
  47. package/definitions/resources/Library.js +0 -2
  48. package/definitions/resources/Producer.js +0 -2
  49. package/definitions/resources/Project.js +0 -2
  50. package/definitions/resources/Schema.js +0 -2
  51. package/definitions/resources/Source.js +0 -2
  52. package/definitions/temp.js +0 -2
  53. package/definitions/transform/Transformations.js +0 -2
  54. package/drivers/DeltaShareDriver.js +0 -186
  55. package/drivers/DriverFactory.js +0 -72
  56. package/drivers/DriverHelper.js +0 -248
  57. package/drivers/HttpApiDriver.js +0 -208
  58. package/drivers/RedshiftDriver.js +0 -184
  59. package/drivers/files/LocalDestinationDriver.js +0 -146
  60. package/drivers/files/LocalSourceDriver.js +0 -405
  61. package/drivers/s3/S3DestinationDriver.js +0 -197
  62. package/drivers/s3/S3SourceDriver.js +0 -495
  63. package/engines/CryptoEngine.js +0 -75
  64. package/engines/Environment.js +0 -170
  65. package/engines/ProcessENVManager.js +0 -83
  66. package/engines/RandomEngine.js +0 -47
  67. package/engines/SecretManager.js +0 -23
  68. package/engines/UserManager.js +0 -66
  69. package/engines/ai/AutoMapperEngine.js +0 -37
  70. package/engines/ai/DeveloperEngine.js +0 -497
  71. package/engines/ai/LLM.js +0 -255
  72. package/engines/consumer/ConsumerManager.js +0 -218
  73. package/engines/consumer/ConsumerOnFinishManager.js +0 -202
  74. package/engines/dataset/Dataset.js +0 -824
  75. package/engines/dataset/DatasetManager.js +0 -211
  76. package/engines/dataset/DatasetRecord.js +0 -120
  77. package/engines/dataset/DatasetRecordPool.js +0 -77
  78. package/engines/execution/RequestExecutor.js +0 -67
  79. package/engines/parsing/CSVParser.js +0 -60
  80. package/engines/parsing/LineParser.js +0 -71
  81. package/engines/parsing/ParseCompression.js +0 -101
  82. package/engines/parsing/ParseHelper.js +0 -18
  83. package/engines/parsing/ParseManager.js +0 -54
  84. package/engines/parsing/XLSParser.js +0 -87
  85. package/engines/parsing/XMLParser.js +0 -115
  86. package/engines/producer/ProducerEngine.js +0 -127
  87. package/engines/producer/ProducerManager.js +0 -43
  88. package/engines/scheduler/CronScheduler.js +0 -222
  89. package/engines/scheduler/QueueManager.js +0 -314
  90. package/engines/schema/SchemaValidator.js +0 -67
  91. package/engines/transform/JoinEngine.js +0 -232
  92. package/engines/transform/TransformationEngine.js +0 -277
  93. package/engines/transform/TypeCaster.js +0 -59
  94. package/engines/usage/DataframeManager.js +0 -55
  95. package/engines/usage/UsageDataManager.js +0 -151
  96. package/engines/usage/UsageManager.js +0 -65
  97. package/engines/validation/Validator.js +0 -216
  98. package/executors/ConsumerExecutor.js +0 -280
  99. package/executors/Executor.js +0 -177
  100. package/executors/ExecutorOrchestrator.js +0 -331
  101. package/executors/ExecutorPerformance.js +0 -17
  102. package/executors/ExecutorProgress.js +0 -54
  103. package/executors/ExecutorScope.js +0 -52
  104. package/executors/OutputExecutor.js +0 -118
  105. package/executors/ProducerExecutor.js +0 -108
  106. package/helper/Helper.js +0 -149
  107. package/helper/Logger.js +0 -84
  108. package/helper/Runtime.js +0 -20
  109. package/helper/Settings.js +0 -13
  110. package/licencing/LicenceManager.js +0 -64
  111. package/settings.js +0 -12
package/engines/ai/LLM.js DELETED
@@ -1,255 +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
- const openai_1 = __importDefault(require("openai"));
16
- const zod_1 = require("openai/helpers/zod");
17
- const zod_2 = require("zod");
18
- const ProcessENVManager_1 = __importDefault(require("../ProcessENVManager"));
19
- const baseProducersSystemPrompt = `
20
- # TASK
21
- You are an agent tasked with creating the mapping between an INPUT DATA SPEC and one or more OUTPUT DATA SPEC.
22
- The mapping between the two is made by creating PRODUCERS and CONSUMERS.
23
- You are tasked with creating the PRODUCER(S) that will then be used.
24
-
25
- # PRODUCERS
26
- A producer maps directly to a dataset and exposes it's dimensions.
27
-
28
- ## FIELDS
29
- - classification: make your best guess if the field falls under any of these regulations
30
-
31
- # RULES
32
- - Add only the required fields to comply with the OUTPUT DATA SPEC
33
- - Add fields that you think are important
34
- - The name of the producer must be the same as the name of the dataset.
35
- - Avoid creating multiple providers with similar data.
36
- - Try to create the least number of providers
37
- - Awlays include this exact property as the first -> "$schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/producer-schema.json"
38
- - Based on the producer select the source that makes the most sense to connect otherwise leave the string "<source_name>"
39
-
40
- # FORMAT
41
- The INPUT DATA SPEC will be the first 10 rows from the dataset that the producer needs to map to.
42
- The OUTPUT DATA SPEC is a JSON of the desired output that the consumer needs to return.
43
- The result must be returned as a JSON object.
44
-
45
- # INPUT DATA SPEC
46
- {{input data spec}}
47
-
48
- # OUTPUT DATA SPEC
49
- {{output data spec}}
50
-
51
- # File name
52
- {{file name}}
53
-
54
- # SOURCES
55
- {{sources}}
56
- `;
57
- const baseConsumersSystemPrompt = `
58
- # TASK
59
- You are an agent tasked with creating the mapping between a list of PRODUCERS and one or more OUTPUT DATA SPEC.
60
- You are going to receive a list of PRODUCERS that expose some dimensions, and you will create the CONSUMERS that comply with the provided OUTPUT DATA SPEC.
61
-
62
- # CONSUMERS
63
- A consumer takes the data from one or more producers and changes it's shape to transform it into the required output schema.
64
-
65
- ## FIELDS
66
- - fields.from: used to distinct between the producers imported by the consumer. The value is the name of the producer.
67
-
68
- # RULES
69
- - If a field is not needed, do not add it e.g.
70
- - Only import a producer once
71
- - Awlays include this exact property as the first -> $schema": "https://raw.githubusercontent.com/ForzaLabs/remora-public/refs/heads/main/json_schemas/consumer-schema.json",
72
- - Use "API" as the only valid output format.
73
- - The "from" must contain only the name of the producer
74
-
75
- # FORMAT
76
- The INPUT DATA SPEC will be the first 10 rows from the dataset that the producer needs to map to.
77
- The OUTPUT DATA SPEC is a JSON of the desired output that the consumer needs to return.
78
- The result must be returned as a JSON object.
79
-
80
- # PRODUCERS
81
- {{producers}}
82
-
83
- # OUTPUT DATA SPEC
84
- {{output data spec}}
85
-
86
- # EXAMPLES
87
- producers: """
88
- {
89
- "name": "claim",
90
- "dimensions": [
91
- {
92
- "name": "id",
93
- "type": "string",
94
- "pk": true
95
- },
96
- {
97
- "name": "amount",
98
- "type": "number"
99
- },
100
- {
101
- "name": "provider",
102
- "type": "string"
103
- },
104
- {
105
- "name": "date",
106
- "type": "datetime"
107
- }
108
- ]
109
- }
110
- """
111
-
112
- output data spec: """
113
- {
114
- "name": "claim",
115
- "fields": [
116
- {
117
- "name": "id",
118
- "type": "string",
119
- "pk": true
120
- },
121
- {
122
- "name": "amount",
123
- "type": "number"
124
- },
125
- {
126
- "name": "provider",
127
- "type": "string"
128
- },
129
- {
130
- "name": "date",
131
- "type": "datetime"
132
- }
133
- ]
134
- }
135
- """
136
-
137
- resulting consumer: """
138
- {
139
- "name": "claims",
140
- "fields": [
141
- {
142
- "key": "id"
143
- },
144
- {
145
- "key": "amount"
146
- },
147
- {
148
- "key": "provider"
149
- },
150
- {
151
- "key": "date",
152
- "alias": "Creation date"
153
- }
154
- ],
155
- "outputs": [
156
- {
157
- "format": "API"
158
- }
159
- ],
160
- "producers": [
161
- {
162
- "name": "claim"
163
- }
164
- ]
165
- }
166
- """
167
- `;
168
- class LLM {
169
- constructor() {
170
- this.inferProducers = (input, outputs, fileName, sources) => __awaiter(this, void 0, void 0, function* () {
171
- let systemPrompt = baseProducersSystemPrompt;
172
- systemPrompt = systemPrompt.replace('{{input data spec}}', input.map(x => `- ${JSON.stringify(x)}`).join('\n'));
173
- systemPrompt = systemPrompt.replace('{{output data spec}}', outputs.map(x => `- ${JSON.stringify(x)}`).join('\n'));
174
- systemPrompt = systemPrompt.replace('{{file name}}', fileName);
175
- systemPrompt = systemPrompt.replace('{{sources}}', sources.map(x => `- ${JSON.stringify(x)}`).join('\n'));
176
- const res = yield this._client.chat.completions.create({
177
- model: 'gpt-4o',
178
- messages: [
179
- { role: 'system', content: systemPrompt }
180
- ],
181
- response_format: (0, zod_1.zodResponseFormat)(zod_2.z.object({
182
- producers: zod_2.z.array(zod_2.z.object({
183
- $schema: zod_2.z.string().describe('The schema of the producer. This should always be the same.'),
184
- name: zod_2.z.string(),
185
- description: zod_2.z.string(),
186
- source: zod_2.z.string().describe('The name of the source linked to this producer.'),
187
- settings: zod_2.z.object({
188
- fileKey: zod_2.z.string().describe('The name of the file'),
189
- fileType: zod_2.z.string().describe('The file extension (CSV | JSONL | JSON)')
190
- }),
191
- dimensions: zod_2.z.array(zod_2.z.object({
192
- name: zod_2.z.string(),
193
- // alias: z.string().optional(),
194
- description: zod_2.z.string().optional(),
195
- type: zod_2.z.enum(['string', 'number', 'datetime']),
196
- pk: zod_2.z.boolean().optional(),
197
- classification: zod_2.z.array(zod_2.z.enum(['PHI', 'PII', 'GDPR'])).optional()
198
- }))
199
- }))
200
- }), 'environment')
201
- });
202
- const msg = res.choices[0].message;
203
- return JSON.parse(msg.content);
204
- });
205
- this.inferConsumers = (producers, outputs) => __awaiter(this, void 0, void 0, function* () {
206
- let systemPrompt = baseConsumersSystemPrompt;
207
- systemPrompt = systemPrompt.replace('{{producers}}', producers.map(x => `- ${JSON.stringify(x)}`).join('\n'));
208
- systemPrompt = systemPrompt.replace('{{output data spec}}', outputs.map(x => `- ${JSON.stringify(x)}`).join('\n'));
209
- const item = {
210
- model: 'gpt-4o',
211
- messages: [
212
- { role: 'system', content: systemPrompt }
213
- ],
214
- response_format: (0, zod_1.zodResponseFormat)(zod_2.z.object({
215
- consumers: zod_2.z.array(zod_2.z.object({
216
- $schema: zod_2.z.string().describe('The schema of the consumer. This should always be the same.'),
217
- name: zod_2.z.string(),
218
- description: zod_2.z.string(),
219
- producers: zod_2.z.array(zod_2.z.object({
220
- name: zod_2.z.string().describe('References one of the producers. Must be unique, there can\'t be two entry with the same name.'),
221
- joins: zod_2.z.array(zod_2.z.object({
222
- otherName: zod_2.z.string(),
223
- relationship: zod_2.z.enum(['one-to-one', 'one-to-many', 'many-to-one']),
224
- sql: zod_2.z.string()
225
- })).optional().describe('Which other producer to join this one with. Omit if empty.')
226
- })),
227
- fields: zod_2.z.array(zod_2.z.object({
228
- key: zod_2.z.string(),
229
- from: zod_2.z.string().optional(),
230
- alias: zod_2.z.string().optional()
231
- // grouping: z.object({
232
- // groupingKey: z.string(),
233
- // subFields: z.array(z.lazy(() => z.object({
234
- // key: z.string(),
235
- // from: z.string().optional()
236
- // })))
237
- // }).optional()
238
- })),
239
- outputs: zod_2.z.array(zod_2.z.object({
240
- format: zod_2.z.enum(['SQL', 'API', 'CSV', 'PARQUET', 'JSON'])
241
- }))
242
- }))
243
- }), 'environment')
244
- };
245
- const res = yield this._client.chat.completions.create(item);
246
- const msg = res.choices[0].message;
247
- const finalDraft = JSON.parse(msg.content);
248
- return finalDraft;
249
- });
250
- this._client = new openai_1.default({
251
- apiKey: ProcessENVManager_1.default.getEnvVariable('OPENAI_API_KEY')
252
- });
253
- }
254
- }
255
- exports.default = LLM;
@@ -1,218 +0,0 @@
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 Algo_1 = __importDefault(require("../../core/Algo"));
8
- const Environment_1 = __importDefault(require("../Environment"));
9
- const ProducerManager_1 = __importDefault(require("../producer/ProducerManager"));
10
- class ConsumerManagerClass {
11
- constructor() {
12
- /**
13
- * Returns the full list of fields that are used by a consumer, while keeping the nested structure of fields.
14
- * If there are *, then replace them with the actual fields found in the underlying producer/consumer
15
- */
16
- this.getExpandedFields = (consumer) => {
17
- (0, Affirm_1.default)(consumer, 'Invalid consumer');
18
- const availableColumns = this.getAvailableColumns(consumer);
19
- const convertedFields = consumer.fields.map(x => {
20
- var _a;
21
- return ({
22
- cField: x,
23
- finalKey: (_a = x.alias) !== null && _a !== void 0 ? _a : x.key
24
- });
25
- });
26
- const expandedFields = convertedFields.flatMap(x => this.expandField(consumer, x, availableColumns));
27
- return expandedFields;
28
- };
29
- /**
30
- * Return all the available columns (dimensions and measures) to the consumer given its producers
31
- */
32
- this.getAvailableColumns = (consumer) => {
33
- const availableColumns = consumer.producers.flatMap(cProd => {
34
- var _a, _b;
35
- const producer = Environment_1.default.getProducer(cProd.name);
36
- if (!producer) {
37
- const subConsumer = Environment_1.default.getConsumer(cProd.name);
38
- (0, Affirm_1.default)(subConsumer, `No producer found with name "${cProd.name}"`);
39
- return this.getAvailableColumns(subConsumer);
40
- }
41
- else {
42
- const dims = producer.dimensions.map(x => ({
43
- consumerAlias: null,
44
- consumerKey: null,
45
- nameInProducer: x.name,
46
- aliasInProducer: x.alias,
47
- dimension: x,
48
- owner: cProd.name
49
- }));
50
- const meas = (_b = (_a = producer.measures) === null || _a === void 0 ? void 0 : _a.map(x => ({
51
- consumerAlias: null,
52
- consumerKey: null,
53
- nameInProducer: x.name,
54
- aliasInProducer: x.name,
55
- measure: x,
56
- owner: cProd.name
57
- }))) !== null && _b !== void 0 ? _b : [];
58
- return [...dims, ...meas];
59
- }
60
- });
61
- return availableColumns;
62
- };
63
- /**
64
- * If the field is '*' then replace them with the actual fields found in the underlying producer/consumer
65
- */
66
- this.expandField = (consumer, field, availableColumns) => {
67
- var _a;
68
- (0, Affirm_1.default)(consumer, 'Invalid consumer');
69
- (0, Affirm_1.default)(field, 'Invalid consumer field');
70
- const expandedFields = [];
71
- if (field.cField.key === '*') {
72
- // If the producers are "union" then they have the same dimensions, meaning that I can use the "*"
73
- if (consumer.producers.length > 1 && consumer.producers.every(x => x.union)) {
74
- const first = consumer.producers[0];
75
- const firstColumns = availableColumns.filter(x => x.owner === first.name);
76
- expandedFields.push(...firstColumns.map(x => ({
77
- cField: {
78
- key: x.nameInProducer,
79
- alias: x.nameInProducer,
80
- from: x.owner
81
- },
82
- finalKey: x.nameInProducer,
83
- dimension: x.dimension,
84
- measure: x.measure
85
- })));
86
- }
87
- else {
88
- const from = (_a = field.cField.from) !== null && _a !== void 0 ? _a : (consumer.producers.length === 1 ? consumer.producers[0].name : null);
89
- availableColumns.filter(x => x.owner === from).forEach(col => {
90
- expandedFields.push({
91
- cField: {
92
- key: col.nameInProducer,
93
- alias: col.nameInProducer,
94
- from: col.owner
95
- },
96
- finalKey: col.nameInProducer,
97
- dimension: col.dimension,
98
- measure: col.measure
99
- });
100
- });
101
- }
102
- }
103
- else {
104
- const col = ConsumerManager.searchFieldInColumns(field.cField, availableColumns, consumer);
105
- (0, Affirm_1.default)(col, `Consumer "${consumer.name}" misconfiguration: the requested field "${field.cField.key}" is not found in any of the specified producers ("${consumer.producers.map(x => x.name).join(', ')}")`);
106
- expandedFields.push(Object.assign(Object.assign({}, field), { dimension: col.dimension, measure: col.measure }));
107
- }
108
- return expandedFields;
109
- };
110
- this.searchFieldInColumns = (field, columns, consumer) => {
111
- var _a, _b;
112
- (0, Affirm_1.default)(field, 'Invalid field');
113
- (0, Affirm_1.default)(columns, 'Invalid columns');
114
- (0, Affirm_1.default)(consumer, 'Invalid consumer');
115
- let column = null;
116
- if (field.from) {
117
- column = columns.find(x => x.owner === field.from && x.nameInProducer === field.key);
118
- }
119
- else if (consumer.producers.length === 1 && !field.from) {
120
- column = columns.find(x => x.nameInProducer === field.key);
121
- }
122
- else if (!field.fixed) {
123
- const matches = columns.filter(x => x.nameInProducer === field.key);
124
- (0, Affirm_1.default)(matches.length > 0, `Consumer "${consumer.name}" misconfiguration: the field "${field.key}" is not found in any of the included producers (${consumer.producers.map(x => x.name).join(', ')})`);
125
- if (matches.length === 1) {
126
- // Need to check if the producers have "union" if they do, I don't care about this check
127
- const cProd = consumer.producers.find(x => x.name === matches[0].owner);
128
- if (!cProd.union)
129
- (0, Affirm_1.default)(matches.length === 1, `Consumer "${consumer.name}" misconfiguration: the field "${field.key}" is ambiguos between the fields with same name from the producers: ${matches.map(x => x.owner).join(', ')}`);
130
- }
131
- column = matches[0];
132
- }
133
- if (!column) {
134
- // If the consumer doesn't find the field in the producer but has a default value AND set_default onError
135
- // then instead of failing, create a placeholder column for the producer
136
- if (field.fixed === true && Algo_1.default.hasVal(field.default)) {
137
- column = {
138
- aliasInProducer: field.key,
139
- nameInProducer: (_a = field.alias) !== null && _a !== void 0 ? _a : field.key,
140
- consumerAlias: (_b = field.alias) !== null && _b !== void 0 ? _b : field.key,
141
- consumerKey: field.key,
142
- owner: field.from,
143
- dimension: { name: field.key, type: typeof field.default }
144
- };
145
- }
146
- }
147
- return column;
148
- };
149
- this.getSource = (consumer) => {
150
- const producers = consumer.producers.map(x => Environment_1.default.getProducer(x.name));
151
- (0, Affirm_1.default)(producers.length > 0, 'No producers found');
152
- (0, Affirm_1.default)(producers.every(x => x), `Invalid producer found in consumer "${consumer.name}"`);
153
- const sources = producers.map(x => Environment_1.default.getSource(x.source));
154
- (0, Affirm_1.default)(sources.length > 0, 'No sources found');
155
- (0, Affirm_1.default)(sources.every(x => x), `Invalid source found in consumer "${consumer.name}"`);
156
- // For now we only support connecting producers of the same engine type to a consumer, so we give an error if we detect different ones
157
- const uniqEngines = Algo_1.default.uniqBy(sources, 'engine');
158
- (0, Affirm_1.default)(uniqEngines.length === 1, `Sources with different engines were used in the consumer "${consumer.name}" (${uniqEngines.join(', ')})`);
159
- // For now we also only support consumers that have producers ALL having the same exact source
160
- const uniqNames = Algo_1.default.uniqBy(sources, 'name');
161
- (0, Affirm_1.default)(uniqNames.length === 1, `Producers with different sources were used in the consumer "${consumer.name}" (${uniqNames.join(', ')})`);
162
- return [sources[0], producers[0]];
163
- };
164
- this.compile = (consumer) => {
165
- var _a, _b;
166
- (0, Affirm_1.default)(consumer, `Invalid consumer`);
167
- const availableColumns = this.getAvailableColumns(consumer);
168
- const selectedColumns = [];
169
- const flat = consumer.fields;
170
- for (let i = 0; i < flat.length; i++) {
171
- const field = flat[i];
172
- // TODO: replace with the new funcitons in the consumermanager to reduce diplicate code
173
- if (field.key === '*') {
174
- const from = (_a = field.from) !== null && _a !== void 0 ? _a : (consumer.producers.length === 1 ? consumer.producers[0].name : null);
175
- availableColumns.filter(x => x.owner === from).forEach(col => {
176
- col.consumerKey = col.nameInProducer;
177
- col.consumerAlias = col.nameInProducer;
178
- selectedColumns.push(col);
179
- });
180
- }
181
- else {
182
- const col = ConsumerManager.searchFieldInColumns(field, availableColumns, consumer);
183
- (0, Affirm_1.default)(col, `Consumer "${consumer.name}" misconfiguration: the requested field "${field.key}" is not found in any of the specified producers ("${consumer.producers.map(x => x.name).join(', ')}")`);
184
- col.consumerKey = field.key;
185
- col.consumerAlias = (_b = field.alias) !== null && _b !== void 0 ? _b : field.key;
186
- selectedColumns.push(col);
187
- }
188
- }
189
- const columnsWithNoAlias = selectedColumns.filter(x => !x.consumerAlias || !x.consumerKey);
190
- (0, Affirm_1.default)(columnsWithNoAlias.length === 0, `Consumer "${consumer.name}" compilation error: some selected fields don't have a correct alias or key (${columnsWithNoAlias.map(x => x.nameInProducer).join(', ')})`);
191
- return selectedColumns;
192
- };
193
- this.getOutputShape = (consumer) => {
194
- (0, Affirm_1.default)(consumer, `Invalid consumer`);
195
- const compiled = this.compile(consumer);
196
- const outDimensions = compiled.map(x => {
197
- var _a, _b, _c, _d, _e, _f, _g;
198
- return ({
199
- name: (_a = x.consumerAlias) !== null && _a !== void 0 ? _a : x.consumerKey,
200
- type: (_b = x.dimension) === null || _b === void 0 ? void 0 : _b.type,
201
- classification: (_c = x.dimension) === null || _c === void 0 ? void 0 : _c.classification,
202
- description: (_e = (_d = x.dimension) === null || _d === void 0 ? void 0 : _d.description) !== null && _e !== void 0 ? _e : (_f = x.measure) === null || _f === void 0 ? void 0 : _f.description,
203
- mask: ProducerManager_1.default.getMask(x.dimension),
204
- pk: (_g = x.dimension) === null || _g === void 0 ? void 0 : _g.pk
205
- });
206
- });
207
- return {
208
- _version: consumer._version,
209
- name: consumer.name,
210
- description: consumer.description,
211
- metadata: consumer.metadata,
212
- dimensions: outDimensions
213
- };
214
- };
215
- }
216
- }
217
- const ConsumerManager = new ConsumerManagerClass();
218
- exports.default = ConsumerManager;
@@ -1,202 +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
- const Affirm_1 = __importDefault(require("../../core/Affirm"));
16
- const Environment_1 = __importDefault(require("../Environment"));
17
- const DriverFactory_1 = __importDefault(require("../../drivers/DriverFactory"));
18
- class ConsumerOnFinishManagerClass {
19
- constructor() {
20
- this.onConsumerSuccess = (consumer, executionId) => __awaiter(this, void 0, void 0, function* () {
21
- void executionId;
22
- for (const output of consumer.outputs) {
23
- if (output.onSuccess)
24
- yield this.performOnSuccessActions(consumer, output);
25
- }
26
- });
27
- this.onConsumerError = (consumer, executionId) => __awaiter(this, void 0, void 0, function* () {
28
- void executionId;
29
- for (const output of consumer.outputs) {
30
- if (output.onError)
31
- yield this.performOnSuccessActions(consumer, output);
32
- }
33
- });
34
- this.performOnSuccessActions = (consumer, output) => __awaiter(this, void 0, void 0, function* () {
35
- (0, Affirm_1.default)(consumer, 'Invalid consumer');
36
- (0, Affirm_1.default)(output, 'Invalid output');
37
- if (!output.onSuccess || output.onSuccess.length === 0)
38
- return;
39
- for (const onSuccess of output.onSuccess) {
40
- switch (onSuccess.action) {
41
- case 'move-file': {
42
- yield this.moveSourceFiles(consumer, onSuccess.moveToDestination);
43
- break;
44
- }
45
- default:
46
- throw new Error(`On success action "${onSuccess.action}" is not implemented yet.`);
47
- }
48
- }
49
- });
50
- this.moveSourceFiles = (consumer, moveDestination) => __awaiter(this, void 0, void 0, function* () {
51
- (0, Affirm_1.default)(moveDestination, 'Move destination is required for move-file action');
52
- const destinationSource = Environment_1.default.getSource(moveDestination);
53
- (0, Affirm_1.default)(destinationSource, `Destination source "${moveDestination}" not found`);
54
- // Get all unique source files from all producers used by this consumer
55
- const sourceFilesToMove = [];
56
- for (const consumerProducer of consumer.producers) {
57
- const producer = Environment_1.default.getProducer(consumerProducer.name);
58
- (0, Affirm_1.default)(producer, `Producer "${consumerProducer.name}" not found`);
59
- const source = Environment_1.default.getSource(producer.source);
60
- (0, Affirm_1.default)(source, `Source "${producer.source}" not found`);
61
- // Only handle file-based sources that have fileKey
62
- if (producer.settings.fileKey) {
63
- // Handle wildcard patterns (files with %)
64
- if (producer.settings.fileKey.includes('%')) {
65
- // Get all files matching the pattern
66
- const matchingFiles = yield this.getMatchingFiles(source, producer.settings.fileKey);
67
- for (const fileKey of matchingFiles) {
68
- sourceFilesToMove.push({
69
- sourceName: producer.source,
70
- filePath: this.getSourceFilePath(source, fileKey),
71
- fileKey
72
- });
73
- }
74
- }
75
- else {
76
- // Single file
77
- sourceFilesToMove.push({
78
- sourceName: producer.source,
79
- filePath: this.getSourceFilePath(source, producer.settings.fileKey),
80
- fileKey: producer.settings.fileKey
81
- });
82
- }
83
- }
84
- }
85
- // Move all files to destination
86
- yield this.moveFiles(sourceFilesToMove, destinationSource);
87
- });
88
- this.getMatchingFiles = (source, fileKeyPattern) => __awaiter(this, void 0, void 0, function* () {
89
- const sourceDriver = yield DriverFactory_1.default.instantiateSource(source);
90
- if (source.engine === 'aws-s3') {
91
- // S3 driver has a public listFiles method that handles patterns
92
- const s3Driver = sourceDriver;
93
- return yield s3Driver.listFiles(fileKeyPattern);
94
- }
95
- else if (source.engine === 'local') {
96
- // Local driver now has a public listFiles method consistent with S3
97
- const localDriver = sourceDriver;
98
- return localDriver.listFiles(fileKeyPattern);
99
- }
100
- throw new Error(`Unsupported source engine for file listing: ${source.engine}`);
101
- });
102
- this.getSourceFilePath = (source, fileKey) => {
103
- if (source.engine === 'local') {
104
- return `${source.authentication['path']}/${fileKey}`;
105
- }
106
- else if (source.engine === 'aws-s3') {
107
- // For S3, we return the key as the path since S3 uses keys instead of file paths
108
- return fileKey;
109
- }
110
- throw new Error(`Unsupported source engine for file move: ${source.engine}`);
111
- };
112
- this.moveFiles = (files, destinationSource) => __awaiter(this, void 0, void 0, function* () {
113
- for (const file of files) {
114
- const sourceSource = Environment_1.default.getSource(file.sourceName);
115
- if (sourceSource.engine === 'local' && destinationSource.engine === 'local') {
116
- // Local to Local move
117
- yield this.moveLocalToLocal(file.filePath, destinationSource, file.fileKey);
118
- }
119
- else if (sourceSource.engine === 'local' && destinationSource.engine === 'aws-s3') {
120
- // Local to S3 move
121
- yield this.moveLocalToS3(file.filePath, destinationSource, file.fileKey);
122
- }
123
- else if (sourceSource.engine === 'aws-s3' && destinationSource.engine === 'local') {
124
- // S3 to Local move
125
- yield this.moveS3ToLocal(sourceSource, file.fileKey, destinationSource);
126
- }
127
- else if (sourceSource.engine === 'aws-s3' && destinationSource.engine === 'aws-s3') {
128
- // S3 to S3 move
129
- yield this.moveS3ToS3(sourceSource, file.fileKey, destinationSource);
130
- }
131
- else {
132
- throw new Error(`Unsupported move operation from ${sourceSource.engine} to ${destinationSource.engine}`);
133
- }
134
- }
135
- });
136
- this.moveLocalToLocal = (sourceFilePath, destinationSource, fileKey) => __awaiter(this, void 0, void 0, function* () {
137
- const sourceDriver = yield DriverFactory_1.default.instantiateSource(this.findSourceForPath(sourceFilePath));
138
- const destinationDriver = yield DriverFactory_1.default.instantiateDestination(destinationSource);
139
- // Read file from source
140
- const fileContent = sourceDriver.readFile(fileKey);
141
- // Save to destination
142
- yield destinationDriver.saveFile(fileKey, fileContent);
143
- // Delete from source
144
- sourceDriver.deleteFile(fileKey);
145
- });
146
- this.findSourceForPath = (filePath) => {
147
- // Extract directory from file path for source creation
148
- const directory = filePath.substring(0, filePath.lastIndexOf('/'));
149
- return {
150
- name: 'temp-source',
151
- engine: 'local',
152
- authentication: { path: directory }
153
- };
154
- };
155
- this.moveLocalToS3 = (sourceFilePath, destinationSource, fileKey) => __awaiter(this, void 0, void 0, function* () {
156
- const sourceDriver = yield DriverFactory_1.default.instantiateSource(this.findSourceForPath(sourceFilePath));
157
- const destinationDriver = yield DriverFactory_1.default.instantiateDestination(destinationSource);
158
- // Read file from local source
159
- const fileContent = sourceDriver.readFile(fileKey);
160
- // Upload to S3 destination
161
- yield destinationDriver.saveFile(fileKey, fileContent);
162
- // Remove source file after successful upload
163
- sourceDriver.deleteFile(fileKey);
164
- });
165
- this.moveS3ToLocal = (sourceSource, fileKey, destinationSource) => __awaiter(this, void 0, void 0, function* () {
166
- const sourceDriver = yield DriverFactory_1.default.instantiateSource(sourceSource);
167
- const destinationDriver = yield DriverFactory_1.default.instantiateDestination(destinationSource);
168
- // Download from S3
169
- const content = yield sourceDriver.downloadFile(fileKey);
170
- // Save to local destination
171
- yield destinationDriver.saveFile(fileKey, content);
172
- // Delete from S3 source
173
- yield sourceDriver.deleteFile(fileKey);
174
- });
175
- this.moveS3ToS3 = (sourceSource, fileKey, destinationSource) => __awaiter(this, void 0, void 0, function* () {
176
- const sourceDriver = yield DriverFactory_1.default.instantiateSource(sourceSource);
177
- const destinationDriver = yield DriverFactory_1.default.instantiateDestination(destinationSource);
178
- // Copy from source S3 to destination S3
179
- yield destinationDriver.copyFromS3(sourceSource.authentication['bucket'], fileKey, fileKey);
180
- // Delete from source S3
181
- yield sourceDriver.deleteFile(fileKey);
182
- });
183
- this.performOnErrorActions = (consumer, output) => __awaiter(this, void 0, void 0, function* () {
184
- (0, Affirm_1.default)(consumer, 'Invalid consumer');
185
- (0, Affirm_1.default)(output, 'Invalid output');
186
- if (!output.onError || output.onError.length === 0)
187
- return;
188
- for (const onError of output.onError) {
189
- switch (onError.action) {
190
- case 'move-file': {
191
- yield this.moveSourceFiles(consumer, onError.moveToDestination);
192
- break;
193
- }
194
- default:
195
- throw new Error(`On success action "${onError.action}" is not implemented yet.`);
196
- }
197
- }
198
- });
199
- }
200
- }
201
- const ConsumerOnFinishManager = new ConsumerOnFinishManagerClass();
202
- exports.default = ConsumerOnFinishManager;