@forzalabs/remora 0.0.16 → 0.0.18
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 +1 -1
- package/actions/create_consumer.js +75 -0
- package/actions/create_producer.js +41 -0
- package/actions/run.js +12 -5
- package/engines/ProducerEngine.js +2 -0
- package/engines/UserManager.js +11 -0
- package/engines/Validator.js +8 -5
- package/engines/consumer/PostProcessor.js +0 -1
- package/index.js +12 -1
- package/package.json +1 -1
package/Constants.js
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
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.create_consumer = void 0;
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const create_consumer = (name, producerName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
try {
|
|
21
|
+
if (!fs_1.default.existsSync('./remora/consumers')) {
|
|
22
|
+
throw new Error(chalk_1.default.red('Missing directory: ') + chalk_1.default.yellow('./remora/consumers'));
|
|
23
|
+
}
|
|
24
|
+
// Read the default consumer template
|
|
25
|
+
const defaultConsumerTemplate = fs_1.default.readFileSync(path_1.default.join(__dirname, '../documentation/default_resources/consumer.json'), 'utf-8');
|
|
26
|
+
const defaultConsumer = JSON.parse(defaultConsumerTemplate);
|
|
27
|
+
defaultConsumer.name = name;
|
|
28
|
+
// If a producer is specified, set up a one-to-one mapping
|
|
29
|
+
if (producerName) {
|
|
30
|
+
const producerPath = path_1.default.join('remora/producers', `${producerName}.json`);
|
|
31
|
+
if (!fs_1.default.existsSync(producerPath)) {
|
|
32
|
+
throw new Error(chalk_1.default.red('Producer not found: ') + chalk_1.default.yellow(producerPath));
|
|
33
|
+
}
|
|
34
|
+
const producerConfig = JSON.parse(fs_1.default.readFileSync(producerPath, 'utf-8'));
|
|
35
|
+
// Set up producer reference
|
|
36
|
+
defaultConsumer.producers = [{ name: producerName }];
|
|
37
|
+
// Set up fields to include all producer fields
|
|
38
|
+
defaultConsumer.fields = producerConfig.dimensions.map(dim => ({
|
|
39
|
+
key: dim.name,
|
|
40
|
+
from: producerName
|
|
41
|
+
}));
|
|
42
|
+
// If there are measures, include those too
|
|
43
|
+
if (producerConfig.measures && producerConfig.measures.length > 0) {
|
|
44
|
+
defaultConsumer.fields.push(...producerConfig.measures.map(measure => ({
|
|
45
|
+
key: measure.name,
|
|
46
|
+
from: producerName
|
|
47
|
+
})));
|
|
48
|
+
}
|
|
49
|
+
defaultConsumer.description = `Consumer for ${producerName} data`;
|
|
50
|
+
defaultConsumer.schema = undefined;
|
|
51
|
+
defaultConsumer.filters = undefined;
|
|
52
|
+
defaultConsumer.metadata = undefined;
|
|
53
|
+
}
|
|
54
|
+
const consumerPath = path_1.default.join('remora/consumers', `${name}.json`);
|
|
55
|
+
fs_1.default.writeFileSync(consumerPath, JSON.stringify(defaultConsumer, null, 4));
|
|
56
|
+
console.log(chalk_1.default.green(`✅ Created consumer config at ${consumerPath}`));
|
|
57
|
+
if (!producerName) {
|
|
58
|
+
console.log(chalk_1.default.blue('Remember to:'));
|
|
59
|
+
console.log(chalk_1.default.blue('1. Set the correct producer name'));
|
|
60
|
+
console.log(chalk_1.default.blue('2. Configure the fields you want to include'));
|
|
61
|
+
console.log(chalk_1.default.blue('3. Set up the desired output formats'));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
console.log(chalk_1.default.blue('Consumer is configured to match all fields from producer:'), chalk_1.default.yellow(producerName));
|
|
65
|
+
console.log(chalk_1.default.blue('Remember to:'));
|
|
66
|
+
console.log(chalk_1.default.blue('1. Review the included fields'));
|
|
67
|
+
console.log(chalk_1.default.blue('2. Set up the desired output formats'));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error(chalk_1.default.red('❌ Error creating consumer:'), error instanceof Error ? error.message : String(error));
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
exports.create_consumer = create_consumer;
|
|
@@ -0,0 +1,41 @@
|
|
|
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.create_producer = void 0;
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const create_producer = (name) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
+
try {
|
|
21
|
+
if (!fs_1.default.existsSync('./remora/producers')) {
|
|
22
|
+
throw new Error(chalk_1.default.red('Missing directory: ') + chalk_1.default.yellow('./remora/producers'));
|
|
23
|
+
}
|
|
24
|
+
// Read the default producer template
|
|
25
|
+
const defaultProducerTemplate = fs_1.default.readFileSync(path_1.default.join(__dirname, '../documentation/default_resources/producer.json'), 'utf-8');
|
|
26
|
+
const defaultProducer = JSON.parse(defaultProducerTemplate);
|
|
27
|
+
defaultProducer.name = name;
|
|
28
|
+
const producerPath = path_1.default.join('remora/producers', `${name}.json`);
|
|
29
|
+
fs_1.default.writeFileSync(producerPath, JSON.stringify(defaultProducer, null, 4));
|
|
30
|
+
console.log(chalk_1.default.green(`✅ Created producer config at ${producerPath}`));
|
|
31
|
+
console.log(chalk_1.default.blue('Remember to:'));
|
|
32
|
+
console.log(chalk_1.default.blue('1. Set the correct source name'));
|
|
33
|
+
console.log(chalk_1.default.blue('2. Configure the dimensions and measures (or use the "discover" command)'));
|
|
34
|
+
console.log(chalk_1.default.blue('3. Update the settings as needed'));
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(chalk_1.default.red('❌ Error creating producer:'), error instanceof Error ? error.message : String(error));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
exports.create_producer = create_producer;
|
package/actions/run.js
CHANGED
|
@@ -19,17 +19,24 @@ 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 run = (
|
|
22
|
+
const run = (consumerName) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
23
|
try {
|
|
24
24
|
(0, compile_1.compile)();
|
|
25
|
-
const spinner = (0, ora_1.default)(chalk_1.default.blue('
|
|
26
|
-
const consumersToExecute = (consumersName && consumersName.length > 0) ? [Environment_1.default.getConsumer(consumersName)] : Environment_1.default._env.consumers;
|
|
25
|
+
const spinner = (0, ora_1.default)(chalk_1.default.blue('Running consumer(s)...\n')).start();
|
|
27
26
|
const user = UserManager_1.default.getUser();
|
|
27
|
+
const consumersToExecute = (consumerName && consumerName.length > 0)
|
|
28
|
+
? [Environment_1.default.getConsumer(consumerName)]
|
|
29
|
+
: Environment_1.default._env.consumers;
|
|
28
30
|
const results = [];
|
|
29
31
|
for (let i = 0; i < consumersToExecute.length; i++) {
|
|
30
32
|
const consumer = consumersToExecute[i];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
try {
|
|
34
|
+
const response = yield ConsumerEngine_1.default.execute(consumer, {}, user);
|
|
35
|
+
results.push({ consumer, response });
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
console.error(chalk_1.default.red(`Failed to execute consumer ${consumer.name}:`, error instanceof Error ? error.message : String(error)));
|
|
39
|
+
}
|
|
33
40
|
}
|
|
34
41
|
spinner.succeed('All consumers have been successfully executed');
|
|
35
42
|
results.forEach(result => {
|
package/engines/UserManager.js
CHANGED
|
@@ -20,6 +20,8 @@ class UserManagerClass {
|
|
|
20
20
|
this.getUser = () => {
|
|
21
21
|
if (Helper_1.default.isDev())
|
|
22
22
|
return DEV_USER;
|
|
23
|
+
else
|
|
24
|
+
return MOCK_USER;
|
|
23
25
|
// TODO: figure out how to handle users
|
|
24
26
|
};
|
|
25
27
|
this.findOIDC = (oid) => __awaiter(this, void 0, void 0, function* () {
|
|
@@ -41,3 +43,12 @@ const DEV_USER = {
|
|
|
41
43
|
_signature: '',
|
|
42
44
|
lastLogin: new Date().toJSON()
|
|
43
45
|
};
|
|
46
|
+
const MOCK_USER = {
|
|
47
|
+
_id: '__mock__',
|
|
48
|
+
auth: { oid: '', provider: 'azure' },
|
|
49
|
+
email: '',
|
|
50
|
+
name: 'mock',
|
|
51
|
+
roles: ['user'],
|
|
52
|
+
_signature: '',
|
|
53
|
+
lastLogin: new Date().toJSON()
|
|
54
|
+
};
|
package/engines/Validator.js
CHANGED
|
@@ -121,7 +121,7 @@ class ValidatorClass {
|
|
|
121
121
|
const groupingFields = fields.filter(x => x.grouping);
|
|
122
122
|
if (groupingFields.length > 1)
|
|
123
123
|
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(
|
|
124
|
+
groupingFields.forEach(field => {
|
|
125
125
|
if (field.grouping)
|
|
126
126
|
errors = [...errors, ...validateGroupingLevels(field.grouping.subFields, level + 1)];
|
|
127
127
|
});
|
|
@@ -134,13 +134,16 @@ class ValidatorClass {
|
|
|
134
134
|
const duplicatesTypes = Algo_1.default.uniq(duplicatesOutputs.map(x => x.format));
|
|
135
135
|
errors.push(`There are outputs with the same type. (duplicates type: ${duplicatesTypes.join(' and ')})`);
|
|
136
136
|
}
|
|
137
|
-
for (
|
|
138
|
-
const output = consumer.outputs[i];
|
|
137
|
+
for (const output of consumer.outputs) {
|
|
139
138
|
const format = output.format.toUpperCase();
|
|
140
139
|
if (format === 'SQL' && output.accellerated && output.direct)
|
|
141
140
|
errors.push(`An output SQL cannot be both direct and accelerated (output: ${format})`);
|
|
142
|
-
if ((format === 'CSV' || format === 'JSON' || format === 'PARQUET')
|
|
143
|
-
|
|
141
|
+
if ((format === 'CSV' || format === 'JSON' || format === 'PARQUET')) {
|
|
142
|
+
if (!output.exportDestination)
|
|
143
|
+
errors.push(`A static file output must have an export destination set (${format})`);
|
|
144
|
+
else if (!Environment_1.default.getSource(output.exportDestination))
|
|
145
|
+
errors.push(`The export destination "${output.exportDestination}" was not found in the sources.`);
|
|
146
|
+
}
|
|
144
147
|
}
|
|
145
148
|
}
|
|
146
149
|
catch (e) {
|
|
@@ -74,7 +74,6 @@ class PostProcessorClass {
|
|
|
74
74
|
(0, Affirm_1.default)(data, 'Invalid data');
|
|
75
75
|
(0, Affirm_1.default)(Array.isArray(data), 'Invalid data type, must be an array');
|
|
76
76
|
(0, Affirm_1.default)(producer, 'Invalid producer');
|
|
77
|
-
console.log('BBBBBBBBB');
|
|
78
77
|
const source = Environment_1.default.getSource(producer.source);
|
|
79
78
|
(0, Affirm_1.default)(source, `No source found for producer "${producer.name}" with name "${producer.source}"`);
|
|
80
79
|
const columns = FileCompiler_1.default.compileProducer(producer, source);
|
package/index.js
CHANGED
|
@@ -14,6 +14,8 @@ const run_1 = require("./actions/run");
|
|
|
14
14
|
const Constants_1 = __importDefault(require("./Constants"));
|
|
15
15
|
const discover_1 = require("./actions/discover");
|
|
16
16
|
const automap_1 = require("./actions/automap");
|
|
17
|
+
const create_producer_1 = require("./actions/create_producer");
|
|
18
|
+
const create_consumer_1 = require("./actions/create_consumer");
|
|
17
19
|
dotenv_1.default.configDotenv();
|
|
18
20
|
const program = new commander_1.Command();
|
|
19
21
|
program
|
|
@@ -46,7 +48,7 @@ program
|
|
|
46
48
|
.option('--build-only', 'Build without deploying')
|
|
47
49
|
.action(deploy_1.deploy);
|
|
48
50
|
program
|
|
49
|
-
.command('run [
|
|
51
|
+
.command('run [name]')
|
|
50
52
|
.description('Execute consumers. Optionally specify a single consumers name to run.')
|
|
51
53
|
.action(run_1.run);
|
|
52
54
|
program
|
|
@@ -60,4 +62,13 @@ program
|
|
|
60
62
|
.argument('<producer>', 'The producer to analyze')
|
|
61
63
|
.argument('<schemas...>', 'One or more schema names to map against')
|
|
62
64
|
.action(automap_1.automap);
|
|
65
|
+
program
|
|
66
|
+
.command('create-producer <name>')
|
|
67
|
+
.description('Create a new producer configuration with default settings')
|
|
68
|
+
.action(create_producer_1.create_producer);
|
|
69
|
+
program
|
|
70
|
+
.command('create-consumer <name>')
|
|
71
|
+
.description('Create a new consumer configuration with default settings')
|
|
72
|
+
.option('-p, --producer <name>', 'Producer to create a one-to-one mapping from')
|
|
73
|
+
.action((name, options) => (0, create_consumer_1.create_consumer)(name, options.producer));
|
|
63
74
|
program.parse(process.argv);
|