@forzalabs/remora 0.0.12

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 (85) hide show
  1. package/Constants.js +8 -0
  2. package/actions/automap.js +73 -0
  3. package/actions/compile.js +57 -0
  4. package/actions/debug.js +61 -0
  5. package/actions/deploy.js +95 -0
  6. package/actions/discover.js +36 -0
  7. package/actions/init.js +78 -0
  8. package/actions/run.js +51 -0
  9. package/auth/AdminManager.js +48 -0
  10. package/auth/ApiKeysManager.js +45 -0
  11. package/auth/JWTManager.js +56 -0
  12. package/core/Affirm.js +42 -0
  13. package/core/Algo.js +155 -0
  14. package/core/dste/DSTE.js +113 -0
  15. package/core/logger/DebugLogService.js +48 -0
  16. package/core/logger/DevelopmentLogService.js +70 -0
  17. package/core/logger/LocalLogService.js +70 -0
  18. package/core/logger/Logger.js +54 -0
  19. package/database/DatabaseEngine.js +119 -0
  20. package/database/DatabaseInitializer.js +80 -0
  21. package/database/DatabaseStructure.js +27 -0
  22. package/definitions/agents/DestinationDriver.js +2 -0
  23. package/definitions/agents/SourceDriver.js +2 -0
  24. package/definitions/cli.js +2 -0
  25. package/definitions/database/ApiKeys.js +2 -0
  26. package/definitions/database/Stored.js +7 -0
  27. package/definitions/database/UsageStat.js +2 -0
  28. package/definitions/database/User.js +2 -0
  29. package/definitions/json_schemas/consumer-schema.json +423 -0
  30. package/definitions/json_schemas/producer-schema.json +236 -0
  31. package/definitions/json_schemas/project-schema.json +59 -0
  32. package/definitions/json_schemas/source-schema.json +109 -0
  33. package/definitions/requests/ConsumerRequest.js +2 -0
  34. package/definitions/requests/Developer.js +2 -0
  35. package/definitions/requests/Mapping.js +2 -0
  36. package/definitions/requests/ProducerRequest.js +2 -0
  37. package/definitions/requests/Request.js +2 -0
  38. package/definitions/resources/Compiled.js +2 -0
  39. package/definitions/resources/Consumer.js +2 -0
  40. package/definitions/resources/Environment.js +2 -0
  41. package/definitions/resources/Library.js +2 -0
  42. package/definitions/resources/Producer.js +2 -0
  43. package/definitions/resources/Project.js +2 -0
  44. package/definitions/resources/Schema.js +2 -0
  45. package/definitions/resources/Source.js +2 -0
  46. package/documentation/README.md +123 -0
  47. package/documentation/default_resources/consumer.json +52 -0
  48. package/documentation/default_resources/producer.json +32 -0
  49. package/documentation/default_resources/project.json +14 -0
  50. package/documentation/default_resources/schema.json +36 -0
  51. package/documentation/default_resources/source.json +15 -0
  52. package/drivers/DriverFactory.js +56 -0
  53. package/drivers/LocalDriver.js +122 -0
  54. package/drivers/RedshiftDriver.js +179 -0
  55. package/drivers/S3Driver.js +47 -0
  56. package/drivers/S3SourceDriver.js +127 -0
  57. package/engines/CryptoEngine.js +46 -0
  58. package/engines/Environment.js +139 -0
  59. package/engines/ParseManager.js +38 -0
  60. package/engines/ProducerEngine.js +150 -0
  61. package/engines/UsageManager.js +61 -0
  62. package/engines/UserManager.js +43 -0
  63. package/engines/Validator.js +154 -0
  64. package/engines/ai/AutoMapperEngine.js +37 -0
  65. package/engines/ai/DeveloperEngine.js +70 -0
  66. package/engines/ai/LLM.js +299 -0
  67. package/engines/consumer/ConsumerEngine.js +204 -0
  68. package/engines/consumer/ConsumerManager.js +155 -0
  69. package/engines/consumer/PostProcessor.js +143 -0
  70. package/engines/deployment/DeploymentPlanner.js +46 -0
  71. package/engines/execution/ExecutionEnvironment.js +114 -0
  72. package/engines/execution/ExecutionPlanner.js +92 -0
  73. package/engines/execution/RequestExecutor.js +100 -0
  74. package/engines/file/FileCompiler.js +28 -0
  75. package/engines/file/FileExporter.js +116 -0
  76. package/engines/schema/SchemaEngine.js +33 -0
  77. package/engines/schema/SchemaValidator.js +67 -0
  78. package/engines/sql/SQLBuilder.js +96 -0
  79. package/engines/sql/SQLCompiler.js +140 -0
  80. package/engines/sql/SQLUtils.js +22 -0
  81. package/engines/validation/Validator.js +151 -0
  82. package/helper/Helper.js +64 -0
  83. package/helper/Settings.js +13 -0
  84. package/index.js +63 -0
  85. package/package.json +77 -0
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "PROJECT_NAME_EXAMPLE",
3
+ "version": "1.0.0",
4
+ "description": "DESCRIPTION_OF_THIS_PROJECT",
5
+ "consumers": ["/consumers"],
6
+ "producers": ["/producers"],
7
+ "sources": ["/sources"],
8
+ "schemas": ["/schemas"],
9
+ "settings": {
10
+ "SQL_MAX_QUERY_ROWS": 10000,
11
+ "DEFAULT_TIMEOUT_SECONDS": 300,
12
+ "LOG_LEVEL": "INFO"
13
+ }
14
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "$schema": "<http://json-schema.org/draft-07/schema#>",
3
+ "title": "<schema title>",
4
+ "type": "<object>",
5
+ "version": 1,
6
+ "description": "<schema description>",
7
+ "properties": {
8
+ "<required id field>": {
9
+ "type": "<number | string | etc.>",
10
+ "description": "<field description>"
11
+ },
12
+ "<required name field>": {
13
+ "type": "<string>",
14
+ "description": "<field description>"
15
+ },
16
+ "<status field with enum>": {
17
+ "type": "<string>",
18
+ "description": "<field description>",
19
+ "enum": [
20
+ "<example status 1>",
21
+ "<example status 2>",
22
+ "<example status 3>"
23
+ ]
24
+ },
25
+ "<datetime field example>": {
26
+ "type": "<string>",
27
+ "format": "<date-time>",
28
+ "description": "<field description>"
29
+ }
30
+ },
31
+ "required": [
32
+ "<required id field>",
33
+ "<required name field>"
34
+ ],
35
+ "additionalProperties": false
36
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "<source name>",
3
+ "description": "<source description>",
4
+ "_version": 1,
5
+ "authentication": {
6
+ "method": "<iam | username-password | access-secret-key | arn | implicit>",
7
+ "schema": "<database_schema_name - db schema>",
8
+ "accessKey": "<access key var from env>",
9
+ "secretKey": "<secret key var from env>",
10
+ "region": "<aws region>",
11
+ "database": "<db name>",
12
+ "workgroup": "<db workgroup>"
13
+ },
14
+ "engine": "<aws-redshift | aws-dynamodb | aws-s3 | postgres | local>"
15
+ }
@@ -0,0 +1,56 @@
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 LocalDriver_1 = __importDefault(require("./LocalDriver"));
16
+ const RedshiftDriver_1 = __importDefault(require("./RedshiftDriver"));
17
+ const S3Driver_1 = __importDefault(require("./S3Driver"));
18
+ const S3SourceDriver_1 = __importDefault(require("./S3SourceDriver"));
19
+ class DriverFactoryClass {
20
+ constructor() {
21
+ this.instantiateSource = (source) => __awaiter(this, void 0, void 0, function* () {
22
+ switch (source.engine) {
23
+ // TODO: implement all the other engines
24
+ case 'aws-redshift': {
25
+ const driver = new RedshiftDriver_1.default();
26
+ yield driver.init(source);
27
+ return driver;
28
+ }
29
+ case 'aws-s3': {
30
+ const driver = new S3SourceDriver_1.default();
31
+ yield driver.init(source);
32
+ return driver;
33
+ }
34
+ case 'local': {
35
+ const driver = new LocalDriver_1.default();
36
+ yield driver.init(source);
37
+ return driver;
38
+ }
39
+ default: throw new Error(`Invalid driver type "${source.engine}". This driver is not implemented yet`);
40
+ }
41
+ });
42
+ this.instantiateDestination = (source) => __awaiter(this, void 0, void 0, function* () {
43
+ switch (source.engine) {
44
+ // TODO: implement all the other engines
45
+ case 'aws-s3': {
46
+ const driver = new S3Driver_1.default();
47
+ yield driver.init(source);
48
+ return driver;
49
+ }
50
+ default: throw new Error(`Invalid driver type "${source.engine}". This driver is not implemented yet`);
51
+ }
52
+ });
53
+ }
54
+ }
55
+ const DriverFactory = new DriverFactoryClass();
56
+ exports.default = DriverFactory;
@@ -0,0 +1,122 @@
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
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __asyncValues = (this && this.__asyncValues) || function (o) {
45
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
46
+ var m = o[Symbol.asyncIterator], i;
47
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
48
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
49
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
50
+ };
51
+ var __importDefault = (this && this.__importDefault) || function (mod) {
52
+ return (mod && mod.__esModule) ? mod : { "default": mod };
53
+ };
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ const fs = __importStar(require("fs"));
56
+ const path_1 = __importDefault(require("path"));
57
+ const readline_1 = __importDefault(require("readline"));
58
+ const Affirm_1 = __importDefault(require("../core/Affirm"));
59
+ class LocalDriver {
60
+ constructor() {
61
+ this.init = (source) => __awaiter(this, void 0, void 0, function* () {
62
+ const fileURL = source.authentication['path'];
63
+ (0, Affirm_1.default)(fileURL, 'file path is not entered in configuration');
64
+ const exist = fs.existsSync(fileURL);
65
+ (0, Affirm_1.default)(exist, 'The path entered is incorrect: ' + fileURL);
66
+ this._path = source.authentication['path'];
67
+ return this;
68
+ });
69
+ this.download = (request) => __awaiter(this, void 0, void 0, function* () {
70
+ (0, Affirm_1.default)(this._path, `Invalid path`);
71
+ (0, Affirm_1.default)(request, `Invalid download request`);
72
+ (0, Affirm_1.default)(request.fileKey, `Invalid file key for download request`);
73
+ const fileUrl = path_1.default.join(this._path, request.fileKey);
74
+ const data = yield fs.promises.readFile(fileUrl, 'utf-8');
75
+ return data;
76
+ });
77
+ this.readLinesInRange = (readOptions) => __awaiter(this, void 0, void 0, function* () {
78
+ var _a, e_1, _b, _c;
79
+ (0, Affirm_1.default)(this._path, `Invalid path`);
80
+ (0, Affirm_1.default)(readOptions, 'Invalid read options');
81
+ (0, Affirm_1.default)(readOptions.fileKey, 'Invalid file key');
82
+ const fileUrl = path_1.default.join(this._path, readOptions.fileKey);
83
+ const { lineFrom, lineTo } = readOptions;
84
+ const stream = fs.createReadStream(fileUrl);
85
+ const reader = readline_1.default.createInterface({ input: stream, crlfDelay: Infinity });
86
+ const lines = [];
87
+ let lineCounter = 0;
88
+ try {
89
+ for (var _d = true, reader_1 = __asyncValues(reader), reader_1_1; reader_1_1 = yield reader_1.next(), _a = reader_1_1.done, !_a; _d = true) {
90
+ _c = reader_1_1.value;
91
+ _d = false;
92
+ const line = _c;
93
+ if (lineCounter >= lineFrom && lineCounter < lineTo) {
94
+ lines.push(line);
95
+ }
96
+ lineCounter++;
97
+ if (lineCounter >= lineTo)
98
+ break;
99
+ }
100
+ }
101
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
102
+ finally {
103
+ try {
104
+ if (!_d && !_a && (_b = reader_1.return)) yield _b.call(reader_1);
105
+ }
106
+ finally { if (e_1) throw e_1.error; }
107
+ }
108
+ reader.close();
109
+ stream.close();
110
+ return lines;
111
+ });
112
+ this.exist = (producer) => __awaiter(this, void 0, void 0, function* () {
113
+ (0, Affirm_1.default)(this._path, `Invalid path`);
114
+ (0, Affirm_1.default)(producer, `Invalid producer`);
115
+ const fileKey = producer.settings.fileKey;
116
+ (0, Affirm_1.default)(fileKey, `Invalid file key for download request`);
117
+ const fileUrl = path_1.default.join(this._path, fileKey);
118
+ return fs.existsSync(fileUrl);
119
+ });
120
+ }
121
+ }
122
+ exports.default = LocalDriver;
@@ -0,0 +1,179 @@
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 client_redshift_data_1 = require("@aws-sdk/client-redshift-data");
16
+ const Affirm_1 = __importDefault(require("../core/Affirm"));
17
+ const Algo_1 = __importDefault(require("../core/Algo"));
18
+ const Environment_1 = __importDefault(require("../engines/Environment"));
19
+ class RedshiftDriver {
20
+ constructor() {
21
+ this.init = (source) => __awaiter(this, void 0, void 0, function* () {
22
+ (0, Affirm_1.default)(source, `Invalid source`);
23
+ this._SQL_MAX_QUERY_ROWS = parseInt(Environment_1.default.get('SQL_MAX_QUERY_ROWS'));
24
+ this._dbName = source.authentication['database'];
25
+ this._workgroup = source.authentication['workgroup'];
26
+ const config = {
27
+ region: source.authentication['region'],
28
+ credentials: {
29
+ accessKeyId: source.authentication['accessKey'],
30
+ secretAccessKey: source.authentication['secretKey']
31
+ // sessionToken: 'IQoJb3JpZ2luX2VjEDQaCXVzLWVhc3QtMSJIMEYCIQDXHjVYaGyCWCMgYWmnYt652z02H+w0jia8l/ckgu+gSAIhAOaKqkWbitaywpIy4l3lXQfQqW/fYhd187jRsL0kkm+wKokDCCwQABoMNzMwMzM1MTgwOTE5Igz36Yz4UuTQ6KuP5lcq5gKi1zczRVbAI6fnKQGNqg2k18/wJFpQgINNW+Ae9BoFofarAlOkXO5qeloP/5dGMufPVu/hy4tqaDi0Jpz8Zpa1JJjj6Q4l7XZi0+SpCkWwoVRsM/8ojMzowTWnUzan17I0jnG4TQKVEABQjQEACbJMbPwHNm1cN+dEY14cTyA36yJ0ma+8GDLECYnBM4klHKxzYJbD2tdwSgW4KAZ2ttk9+AnrKJUVH4hDI4cPBRv8uIUKGGfzD8cRpMGCByYeLVPc0o5IFCZGqkHncRlAU7dH0xZyGyCeDo3Z3819Ll8vJ41RN4RQOwcWrmL1Ne73KRgH32Ya9xH5j052WxERJPouCk+Lj307XmL0YwpkiQtV7cK5bQQRHtihviGkiK4maZLXXy7aUPQQG57xc0Q3HJXdI6LiXhvKvPKQm2iwAQS+FUZeekf1msT6MkVWd1ibYyhMzFeHBBPvVDlc4NFtLH6rGKAGgkuaMLGunrwGOqUB+nVvTAgcT7amelZRma0TRJsfFezBCAXXWNurD/6qAAKpKgmP+ouE+gH+SmG67IbQqIzK/5dc53sMV7dXDdG4/XGvmWfTph1iHZN/c1bd/rYPfVzy3K3ybTe2Djj0IaTbNndxVPfWIU6cC6cJ6ahEMvzokNnKNUqdDnu/Z1S2xiOfV4P/9vTg7O1XuLUylsCzveeYWRoZJPY4XCUnOgNlqQ/ZwKTC'
32
+ }
33
+ };
34
+ try {
35
+ this._client = new client_redshift_data_1.RedshiftData(config);
36
+ // This is just to check that the connection was successful and warm up the connection
37
+ yield this.query('SELECT :diss AS number', [{ name: ':diss', value: '1' }]);
38
+ }
39
+ catch (error) {
40
+ const myError = error;
41
+ if (myError.__type === 'UnrecognizedClientException')
42
+ throw new Error(`Invalid AWS credentials for source "${source.name}": ${myError.message}`);
43
+ else
44
+ throw error;
45
+ }
46
+ return this;
47
+ });
48
+ this.execute = (sql) => __awaiter(this, void 0, void 0, function* () {
49
+ var _a;
50
+ (0, Affirm_1.default)(sql, `Invalid SQL`);
51
+ const input = {
52
+ Sql: sql,
53
+ Database: this._dbName,
54
+ WorkgroupName: this._workgroup
55
+ };
56
+ const executeStatementRes = yield this._client.executeStatement(input);
57
+ const queryId = (_a = executeStatementRes.Id) !== null && _a !== void 0 ? _a : '';
58
+ const res = (yield this.executeStatement(queryId, { retry: 5 }))[0];
59
+ console.log(res);
60
+ return {
61
+ rows: res.result
62
+ };
63
+ });
64
+ this.query = (sql, values) => __awaiter(this, void 0, void 0, function* () {
65
+ var _a, _b;
66
+ (0, Affirm_1.default)(sql, `Invalid SQL`);
67
+ const wrapperSql = `SELECT * FROM (${sql}) LIMIT ${this._SQL_MAX_QUERY_ROWS}`;
68
+ const input = {
69
+ Sql: wrapperSql,
70
+ Database: this._dbName,
71
+ WorkgroupName: this._workgroup,
72
+ Parameters: (_a = values === null || values === void 0 ? void 0 : values.map(x => ({ name: Algo_1.default.replaceAll(x.name, ':', ''), value: x.value }))) !== null && _a !== void 0 ? _a : undefined
73
+ };
74
+ const executeStatementRes = yield this._client.executeStatement(input);
75
+ const queryId = (_b = executeStatementRes.Id) !== null && _b !== void 0 ? _b : '';
76
+ // TODO: handle errors (permission, wrong query, ...)
77
+ const res = (yield this.executeStatement(queryId, { retry: 5 }))[0];
78
+ console.log(res);
79
+ return {
80
+ rows: res.result
81
+ };
82
+ });
83
+ this.exist = (producer) => __awaiter(this, void 0, void 0, function* () {
84
+ var _a;
85
+ (0, Affirm_1.default)(producer, `Invalid producer`);
86
+ const sql = `SELECT * FROM "${producer.settings.sqlTable}" LIMIT 1`;
87
+ const input = {
88
+ Sql: sql,
89
+ Database: this._dbName,
90
+ WorkgroupName: this._workgroup
91
+ };
92
+ const executeStatementRes = yield this._client.executeStatement(input);
93
+ const queryId = (_a = executeStatementRes.Id) !== null && _a !== void 0 ? _a : '';
94
+ try {
95
+ yield this.executeStatement(queryId, { retry: 5 });
96
+ return true;
97
+ }
98
+ catch (e) {
99
+ return false;
100
+ }
101
+ });
102
+ this.executeStatement = (queryId, options) => __awaiter(this, void 0, void 0, function* () {
103
+ const MAX_WAIT_CYCLES = 20;
104
+ for (let i = 0; i < MAX_WAIT_CYCLES; i++) {
105
+ const statement = yield this._client.describeStatement({ Id: queryId });
106
+ (0, Affirm_1.default)(statement, 'SQL query failed: describe statement call failed.');
107
+ (0, Affirm_1.default)(statement.Status !== 'FAILED', `SQL query failed: ${queryId}:\n\tSQL: ${statement.QueryString}\n\tError: ${statement.Error}.`);
108
+ const { Status: status, SubStatements: subStatements } = statement;
109
+ if (status === 'FINISHED') {
110
+ if (subStatements && subStatements.length > 0) {
111
+ const result = [];
112
+ for (let i = 0; i < subStatements.length; i++) {
113
+ const subStatement = subStatements[i];
114
+ result.push({
115
+ statement: { hasResultSet: statement.HasResultSet, queryString: statement.QueryString, resultRows: statement.ResultRows, resultSize: statement.ResultSize },
116
+ subStatement: { hasResultSet: subStatement.HasResultSet, queryString: subStatement.QueryString, resultRows: subStatement.ResultRows, resultSize: subStatement.ResultSize },
117
+ result: yield this.getStatementResult(subStatement)
118
+ });
119
+ }
120
+ return result;
121
+ }
122
+ else {
123
+ return [{
124
+ statement: { hasResultSet: statement.HasResultSet, queryString: statement.QueryString, resultRows: statement.ResultRows, resultSize: statement.ResultSize },
125
+ result: yield this.getStatementResult(statement)
126
+ }];
127
+ }
128
+ }
129
+ yield Algo_1.default.sleep(1);
130
+ }
131
+ if (options && options.retry > 0)
132
+ return yield this.executeStatement(queryId, Object.assign(Object.assign({}, options), { retry: options.retry - 1 }));
133
+ else
134
+ throw new Error('SQL timeout: query failed because timeout exceeded max wait cycles');
135
+ });
136
+ this.getStatementResult = (statement) => __awaiter(this, void 0, void 0, function* () {
137
+ (0, Affirm_1.default)(statement, `SQL failed: can't extract result from invalid statement`);
138
+ if (statement.HasResultSet) {
139
+ const result = yield this._client.getStatementResult({ Id: statement.Id });
140
+ (0, Affirm_1.default)(result, 'SQL failed: invalid result statement');
141
+ (0, Affirm_1.default)(result.Records, 'SQL failed: no records in result statement');
142
+ return this.parseQueryResult(result);
143
+ }
144
+ else {
145
+ return [];
146
+ }
147
+ });
148
+ this.parseQueryResult = (queryResult) => {
149
+ (0, Affirm_1.default)(queryResult, `Parse SQL failed: invalid query result`);
150
+ (0, Affirm_1.default)(queryResult.ColumnMetadata, `Parse SQL failed: invalid column metadata in query result`);
151
+ (0, Affirm_1.default)(queryResult.Records, `Parse SQL failed: invalid records in query result`);
152
+ const columnNames = queryResult.ColumnMetadata.map(column => column.name);
153
+ const records = [];
154
+ for (const record of queryResult.Records) {
155
+ const recordData = {};
156
+ for (let i = 0; i < columnNames.length; i++) {
157
+ const columnName = columnNames[i];
158
+ (0, Affirm_1.default)(columnName, `Parse SQL failed: invalid column name`);
159
+ const value = record[i];
160
+ if (value.longValue !== undefined)
161
+ recordData[columnName] = value.longValue;
162
+ else if (value.stringValue !== undefined)
163
+ recordData[columnName] = value.stringValue;
164
+ else if (value.booleanValue !== undefined)
165
+ recordData[columnName] = value.booleanValue;
166
+ else if (value.doubleValue !== undefined)
167
+ recordData[columnName] = value.doubleValue;
168
+ else if (value.isNull === true)
169
+ recordData[columnName] = null;
170
+ else
171
+ recordData[columnName] = null;
172
+ }
173
+ records.push(recordData);
174
+ }
175
+ return records;
176
+ };
177
+ }
178
+ }
179
+ exports.default = RedshiftDriver;
@@ -0,0 +1,47 @@
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 client_s3_1 = require("@aws-sdk/client-s3");
16
+ const Affirm_1 = __importDefault(require("../core/Affirm"));
17
+ class S3Driver {
18
+ constructor() {
19
+ this.init = (source) => __awaiter(this, void 0, void 0, function* () {
20
+ this._bucketName = source.authentication['bucketName'];
21
+ const config = {
22
+ region: source.authentication['region'],
23
+ credentials: {
24
+ accessKeyId: source.authentication['accessKey'],
25
+ secretAccessKey: source.authentication['secretKey']
26
+ }
27
+ };
28
+ this._client = new client_s3_1.S3Client(config);
29
+ // TODO: is there a way to test if the connection was successful? like a query or scan that I can do?
30
+ return this;
31
+ });
32
+ this.uploadFile = (options) => __awaiter(this, void 0, void 0, function* () {
33
+ (0, Affirm_1.default)(options, `Invalid upload options`);
34
+ const { content, name } = options;
35
+ const commandParams = {
36
+ Bucket: this._bucketName,
37
+ Key: name,
38
+ Body: content
39
+ };
40
+ const command = new client_s3_1.PutObjectCommand(commandParams);
41
+ const res = yield this._client.send(command);
42
+ (0, Affirm_1.default)(res.$metadata.httpStatusCode === 200, `Failed to upload the file "${name}" to the bucket "${this._bucketName}": status code ${res.$metadata.httpStatusCode}`);
43
+ return { res: true, key: name, bucket: this._bucketName };
44
+ });
45
+ }
46
+ }
47
+ exports.default = S3Driver;
@@ -0,0 +1,127 @@
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 __asyncValues = (this && this.__asyncValues) || function (o) {
12
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
13
+ var m = o[Symbol.asyncIterator], i;
14
+ return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
15
+ function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
16
+ function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
+ };
18
+ var __importDefault = (this && this.__importDefault) || function (mod) {
19
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
+ };
21
+ Object.defineProperty(exports, "__esModule", { value: true });
22
+ const client_s3_1 = require("@aws-sdk/client-s3");
23
+ const readline_1 = __importDefault(require("readline"));
24
+ const Affirm_1 = __importDefault(require("../core/Affirm"));
25
+ class S3SourceDriver {
26
+ constructor() {
27
+ this.init = (source) => __awaiter(this, void 0, void 0, function* () {
28
+ this._bucketName = source.authentication['bucketName'];
29
+ const config = {
30
+ region: source.authentication['region'],
31
+ credentials: {
32
+ accessKeyId: source.authentication['accessKey'],
33
+ secretAccessKey: source.authentication['secretKey']
34
+ }
35
+ };
36
+ this._client = new client_s3_1.S3Client(config);
37
+ // TODO: is there a way to test if the connection was successful? like a query or scan that I can do?
38
+ return this;
39
+ });
40
+ this.download = (request) => __awaiter(this, void 0, void 0, function* () {
41
+ var _a, e_1, _b, _c;
42
+ (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
43
+ (0, Affirm_1.default)(request, `Invalid download request`);
44
+ (0, Affirm_1.default)(request.fileKey, `Invalid file key for download request`);
45
+ const { fileKey } = request;
46
+ const bucket = this._bucketName;
47
+ const response = yield this._client.send(new client_s3_1.GetObjectCommand({
48
+ Bucket: bucket,
49
+ Key: fileKey
50
+ }));
51
+ (0, Affirm_1.default)(response.Body, 'Failed to fetch object from S3');
52
+ const stream = response.Body;
53
+ const chunks = [];
54
+ try {
55
+ for (var _d = true, stream_1 = __asyncValues(stream), stream_1_1; stream_1_1 = yield stream_1.next(), _a = stream_1_1.done, !_a; _d = true) {
56
+ _c = stream_1_1.value;
57
+ _d = false;
58
+ const chunk = _c;
59
+ chunks.push(chunk);
60
+ }
61
+ }
62
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
63
+ finally {
64
+ try {
65
+ if (!_d && !_a && (_b = stream_1.return)) yield _b.call(stream_1);
66
+ }
67
+ finally { if (e_1) throw e_1.error; }
68
+ }
69
+ return Buffer.concat(chunks).toString('utf-8');
70
+ });
71
+ this.readLinesInRange = (readOptions) => __awaiter(this, void 0, void 0, function* () {
72
+ var _a, e_2, _b, _c;
73
+ (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
74
+ (0, Affirm_1.default)(readOptions, 'Invalid read options');
75
+ const { fileKey, lineFrom, lineTo } = readOptions;
76
+ const bucket = this._bucketName;
77
+ const response = yield this._client.send(new client_s3_1.GetObjectCommand({
78
+ Bucket: bucket,
79
+ Key: fileKey
80
+ }));
81
+ (0, Affirm_1.default)(response.Body, 'Failed to fetch object from S3');
82
+ const stream = response.Body;
83
+ const reader = readline_1.default.createInterface({ input: stream, crlfDelay: Infinity });
84
+ const lines = [];
85
+ let lineCounter = 0;
86
+ try {
87
+ for (var _d = true, reader_1 = __asyncValues(reader), reader_1_1; reader_1_1 = yield reader_1.next(), _a = reader_1_1.done, !_a; _d = true) {
88
+ _c = reader_1_1.value;
89
+ _d = false;
90
+ const line = _c;
91
+ if (lineCounter >= lineFrom && lineCounter < lineTo)
92
+ lines.push(line);
93
+ if (lineCounter > lineTo)
94
+ break;
95
+ lineCounter++;
96
+ }
97
+ }
98
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
99
+ finally {
100
+ try {
101
+ if (!_d && !_a && (_b = reader_1.return)) yield _b.call(reader_1);
102
+ }
103
+ finally { if (e_2) throw e_2.error; }
104
+ }
105
+ reader.close();
106
+ return lines;
107
+ });
108
+ this.exist = (producer) => __awaiter(this, void 0, void 0, function* () {
109
+ var _a;
110
+ (0, Affirm_1.default)(this._client, 'S3 client not yet initialized, call "connect()" first');
111
+ (0, Affirm_1.default)(producer, 'Invalid read producer');
112
+ const bucket = this._bucketName;
113
+ const fileKey = producer.settings.fileKey;
114
+ (0, Affirm_1.default)(fileKey, `Invalid file key for download request`);
115
+ try {
116
+ yield this._client.send(new client_s3_1.HeadObjectCommand({ Bucket: bucket, Key: fileKey }));
117
+ return true;
118
+ }
119
+ catch (error) {
120
+ if (((_a = error.$metadata) === null || _a === void 0 ? void 0 : _a.httpStatusCode) === 404 || error.name === 'NotFound')
121
+ return false;
122
+ throw error;
123
+ }
124
+ });
125
+ }
126
+ }
127
+ exports.default = S3SourceDriver;
@@ -0,0 +1,46 @@
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 crypto_1 = __importDefault(require("crypto"));
7
+ const Algo_1 = __importDefault(require("../core/Algo"));
8
+ class CryptoEngineClass {
9
+ constructor() {
10
+ this.hashQuery = (maskType, fieldReference, fieldName) => {
11
+ if (!Algo_1.default.hasVal(maskType))
12
+ return;
13
+ switch (maskType) {
14
+ case 'hash':
15
+ return `SHA2(${fieldReference}, 256) AS "${fieldName}"`;
16
+ case 'crypt':
17
+ throw new Error('Not implemented yet');
18
+ case 'mask':
19
+ throw new Error('Not implemented yet');
20
+ default:
21
+ throw new Error('This type is not ');
22
+ }
23
+ };
24
+ this.valueToHash = (value) => {
25
+ return crypto_1.default.createHash('sha256').update(JSON.stringify(value)).digest('hex');
26
+ };
27
+ this.hashValue = (maskType, value) => {
28
+ if (!Algo_1.default.hasVal(value))
29
+ return value;
30
+ if (!Algo_1.default.hasVal(maskType))
31
+ return value;
32
+ switch (maskType) {
33
+ case 'hash':
34
+ return this.valueToHash(value);
35
+ case 'crypt':
36
+ throw new Error('Not implemented yet');
37
+ case 'mask':
38
+ throw new Error('Not implemented yet');
39
+ default:
40
+ throw new Error(`This type doesn't exist`);
41
+ }
42
+ };
43
+ }
44
+ }
45
+ const CryptoEngine = new CryptoEngineClass();
46
+ exports.default = CryptoEngine;