@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,80 @@
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 AdminManager_1 = __importDefault(require("../auth/AdminManager"));
16
+ const Affirm_1 = __importDefault(require("../core/Affirm"));
17
+ const UserManager_1 = __importDefault(require("../engines/UserManager"));
18
+ const Helper_1 = __importDefault(require("../helper/Helper"));
19
+ const DatabaseEngine_1 = __importDefault(require("./DatabaseEngine"));
20
+ const DatabaseStructure_1 = __importDefault(require("./DatabaseStructure"));
21
+ const bcryptjs_1 = __importDefault(require("bcryptjs"));
22
+ class DatabaseInitializerClass {
23
+ constructor() {
24
+ this.initialize = () => __awaiter(this, void 0, void 0, function* () {
25
+ try {
26
+ yield DatabaseEngine_1.default.connect();
27
+ yield this.createCollections();
28
+ yield this.primeCollections();
29
+ }
30
+ catch (error) {
31
+ console.error('Error initializing database:', error);
32
+ throw error;
33
+ }
34
+ });
35
+ this.createCollections = () => __awaiter(this, void 0, void 0, function* () {
36
+ const db = DatabaseEngine_1.default.db();
37
+ // Get list of existing collections
38
+ const collections = yield db.listCollections().toArray();
39
+ const existingCollections = collections.map(col => col.name);
40
+ // Check and create required collections from SETTINGS
41
+ for (const collection of DatabaseStructure_1.default.collections) {
42
+ const name = collection.name;
43
+ if (!existingCollections.includes(name)) {
44
+ console.log(`Creating collection: ${name}`);
45
+ yield db.createCollection(name);
46
+ for (const index of collection.indexes) {
47
+ console.log(`Setting up index ${JSON.stringify(index)}`);
48
+ yield db.collection(name).createIndex(index);
49
+ }
50
+ }
51
+ }
52
+ console.log('Collections creation completed');
53
+ });
54
+ this.primeCollections = () => __awaiter(this, void 0, void 0, function* () {
55
+ // Create the default user of the system
56
+ (0, Affirm_1.default)(process.env.ROOT_TEMP_PASSWORD, 'Wrong system config: missing root user temp password');
57
+ const rootUser = yield DatabaseEngine_1.default.findOne(AdminManager_1.default.COLLECTION, { isRoot: true });
58
+ if (!rootUser) {
59
+ const salt = yield bcryptjs_1.default.genSalt(10);
60
+ const passHash = yield bcryptjs_1.default.hash(process.env.ROOT_TEMP_PASSWORD, salt);
61
+ const newRootUser = {
62
+ _id: Helper_1.default.uuid(),
63
+ _signature: '',
64
+ auth: { oid: null, provider: 'password' },
65
+ email: 'root@remora.com',
66
+ lastLogin: new Date().toJSON(),
67
+ name: 'Root',
68
+ roles: ['root'],
69
+ isRoot: true,
70
+ rootPasswordHash: passHash
71
+ };
72
+ console.log('Creating the default root user');
73
+ yield UserManager_1.default.update(newRootUser);
74
+ }
75
+ console.log('Collections priming completed');
76
+ });
77
+ }
78
+ }
79
+ const DatabaseInitializer = new DatabaseInitializerClass();
80
+ exports.default = DatabaseInitializer;
@@ -0,0 +1,27 @@
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 Settings_1 = __importDefault(require("../helper/Settings"));
7
+ const DATABASE_STRUCTURE = {
8
+ collections: [
9
+ {
10
+ name: Settings_1.default.db.collections.usage,
11
+ indexes: [
12
+ { consumer: 1 },
13
+ { startedAt: 1 },
14
+ { status: 1 }
15
+ ]
16
+ },
17
+ {
18
+ name: Settings_1.default.db.collections.users,
19
+ indexes: []
20
+ },
21
+ {
22
+ name: Settings_1.default.db.collections.apiKeys,
23
+ indexes: []
24
+ }
25
+ ]
26
+ };
27
+ exports.default = DATABASE_STRUCTURE;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ /**
3
+ * TODO: these are the documents that are stored in the database.
4
+ * TODO: I need to register all the events and usage around these resources (producers and consumers).
5
+ * Like all the executions, who executed, for how long and others...
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,423 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Consumer Schema",
4
+ "description": "Schema for defining data consumers",
5
+ "type": "object",
6
+ "properties": {
7
+ "$schema": {
8
+ "type": "string",
9
+ "format": "uri"
10
+ },
11
+ "name": {
12
+ "type": "string",
13
+ "description": "The name of the consumer"
14
+ },
15
+ "description": {
16
+ "type": "string",
17
+ "description": "Optional description of the consumer"
18
+ },
19
+ "producers": {
20
+ "type": "array",
21
+ "description": "The 'FROM' elements of the SQL query (only the first one is in the FROM clause, others are joined in)",
22
+ "items": {
23
+ "type": "object",
24
+ "properties": {
25
+ "name": {
26
+ "type": "string",
27
+ "description": "The name of an available producer/consumer"
28
+ },
29
+ "joins": {
30
+ "type": "array",
31
+ "items": {
32
+ "type": "object",
33
+ "properties": {
34
+ "otherName": {
35
+ "type": "string",
36
+ "description": "The name of the other producer to JOIN with from the list of producers"
37
+ },
38
+ "relationship": {
39
+ "type": "string",
40
+ "enum": [
41
+ "one-to-one",
42
+ "one-to-many",
43
+ "many-to-one"
44
+ ],
45
+ "description": "The type of join relationship"
46
+ },
47
+ "sql": {
48
+ "type": "string",
49
+ "description": "The SQL to use to perform the join"
50
+ }
51
+ },
52
+ "required": [
53
+ "otherName",
54
+ "relationship",
55
+ "sql"
56
+ ],
57
+ "additionalProperties": false
58
+ }
59
+ },
60
+ "custom": {
61
+ "type": "object",
62
+ "description": "Custom code to extract fields from producers, transform them, and return results",
63
+ "properties": {
64
+ "language": {
65
+ "type": "string",
66
+ "enum": [
67
+ "js",
68
+ "python"
69
+ ],
70
+ "description": "The language of the custom code"
71
+ },
72
+ "code": {
73
+ "type": "string",
74
+ "description": "The custom code to execute"
75
+ }
76
+ },
77
+ "required": [
78
+ "language",
79
+ "code"
80
+ ],
81
+ "additionalProperties": false
82
+ }
83
+ },
84
+ "required": [
85
+ "name"
86
+ ],
87
+ "additionalProperties": false
88
+ },
89
+ "minItems": 1
90
+ },
91
+ "fields": {
92
+ "type": "array",
93
+ "description": "The fields to include in the consumer",
94
+ "items": {
95
+ "type": "object",
96
+ "properties": {
97
+ "key": {
98
+ "type": "string",
99
+ "description": "The dimension/measure of the producer OR '*'. If '*' then return all dimensions"
100
+ },
101
+ "alias": {
102
+ "type": "string",
103
+ "description": "If set, changes the key returned by the consumer to this alias"
104
+ },
105
+ "from": {
106
+ "type": "string",
107
+ "description": "If the key is ambiguous, set a 'from' with the name of the producer/consumer to get the key from"
108
+ },
109
+ "grouping": {
110
+ "type": "object",
111
+ "description": "If set, group resulting items that have the same value for the 'groupingKey'",
112
+ "properties": {
113
+ "groupingKey": {
114
+ "type": "string",
115
+ "description": "Used to create hierarchical data structure (parent -> children)"
116
+ },
117
+ "subFields": {
118
+ "type": "array",
119
+ "description": "Recursive structure defining fields that should be pulled inside this grouped field",
120
+ "items": {
121
+ "$ref": "#/definitions/consumerField"
122
+ }
123
+ }
124
+ },
125
+ "required": [
126
+ "groupingKey",
127
+ "subFields"
128
+ ],
129
+ "additionalProperties": false
130
+ }
131
+ },
132
+ "required": [
133
+ "key"
134
+ ],
135
+ "additionalProperties": false
136
+ },
137
+ "minItems": 1
138
+ },
139
+ "outputs": {
140
+ "type": "array",
141
+ "description": "Output formats and configurations for the consumer",
142
+ "items": {
143
+ "type": "object",
144
+ "properties": {
145
+ "format": {
146
+ "type": "string",
147
+ "enum": [
148
+ "SQL",
149
+ "API",
150
+ "CSV",
151
+ "PARQUET",
152
+ "JSON"
153
+ ],
154
+ "description": "The output format of the consumer"
155
+ },
156
+ "accellerated": {
157
+ "type": "boolean",
158
+ "description": "If true and supported, the consumer will be materialized to improve query performance"
159
+ },
160
+ "direct": {
161
+ "type": "boolean",
162
+ "description": "If true, no view is created on the consumer side due to permission limitations"
163
+ },
164
+ "exportDestination": {
165
+ "type": "string",
166
+ "description": "The name of the source where the consumer will export its data when deployed/run"
167
+ },
168
+ "trigger": {
169
+ "type": "object",
170
+ "description": "Triggers to perform the export (not just the usual 'Deploy')",
171
+ "properties": {
172
+ "type": {
173
+ "type": "string",
174
+ "enum": [
175
+ "CRON",
176
+ "API"
177
+ ],
178
+ "description": "The type of trigger schedule"
179
+ },
180
+ "value": {
181
+ "type": "string",
182
+ "description": "The value for the trigger (e.g., cron expression or API endpoint)"
183
+ }
184
+ },
185
+ "required": [
186
+ "type",
187
+ "value"
188
+ ],
189
+ "additionalProperties": false
190
+ }
191
+ },
192
+ "required": [
193
+ "format"
194
+ ],
195
+ "additionalProperties": false
196
+ },
197
+ "minItems": 1
198
+ },
199
+ "filters": {
200
+ "type": "array",
201
+ "description": "Filters to apply to the consumer data",
202
+ "items": {
203
+ "type": "object",
204
+ "properties": {
205
+ "sql": {
206
+ "type": "string",
207
+ "description": "The SQL to use to filter on the included dimension"
208
+ },
209
+ "rule": {
210
+ "type": "object",
211
+ "description": "Non-SQL based filtering logic",
212
+ "properties": {
213
+ "member": {
214
+ "type": "string",
215
+ "description": "The field to filter on"
216
+ },
217
+ "operator": {
218
+ "type": "string",
219
+ "enum": [
220
+ "equals",
221
+ "notEquals",
222
+ "contains",
223
+ "notContains",
224
+ "startsWith",
225
+ "endsWith",
226
+ "greaterThan",
227
+ "greaterThanOrEquals",
228
+ "lessThan",
229
+ "lessThanOrEquals",
230
+ "in",
231
+ "notIn",
232
+ "between",
233
+ "notBetween",
234
+ "isNull",
235
+ "isNotNull",
236
+ "true",
237
+ "false",
238
+ "matches",
239
+ "notMatches",
240
+ "sql"
241
+ ],
242
+ "description": "The filter operator to apply"
243
+ },
244
+ "values": {
245
+ "type": "array",
246
+ "items": {
247
+ "type": "string"
248
+ },
249
+ "description": "The values to filter against"
250
+ }
251
+ },
252
+ "required": [
253
+ "member",
254
+ "operator",
255
+ "values"
256
+ ],
257
+ "additionalProperties": false
258
+ }
259
+ },
260
+ "additionalProperties": false
261
+ }
262
+ },
263
+ "metadata": {
264
+ "type": "object",
265
+ "description": "Any tags to add to this consumer for sorting and organizing",
266
+ "additionalProperties": {
267
+ "type": "string"
268
+ }
269
+ },
270
+ "project": {
271
+ "type": "string",
272
+ "description": "Tag that groups consumers together to make them accessible by a singular api_key"
273
+ },
274
+ "schema": {
275
+ "type": "string",
276
+ "description": "The name of the JSON schema in this project that this consumer needs to adhere to"
277
+ },
278
+ "_version": {
279
+ "type": "number",
280
+ "description": "Version number of the consumer configuration"
281
+ }
282
+ },
283
+ "required": [
284
+ "name",
285
+ "producers",
286
+ "fields",
287
+ "outputs",
288
+ "_version"
289
+ ],
290
+ "additionalProperties": false,
291
+ "definitions": {
292
+ "consumerField": {
293
+ "type": "object",
294
+ "properties": {
295
+ "key": {
296
+ "type": "string",
297
+ "description": "The dimension/measure of the producer OR '*'. If '*' then return all dimensions"
298
+ },
299
+ "alias": {
300
+ "type": "string",
301
+ "description": "If set, changes the key returned by the consumer to this alias"
302
+ },
303
+ "from": {
304
+ "type": "string",
305
+ "description": "If the key is ambiguous, set a 'from' with the name of the producer/consumer to get the key from"
306
+ },
307
+ "grouping": {
308
+ "type": "object",
309
+ "description": "If set, group resulting items that have the same value for the 'groupingKey'",
310
+ "properties": {
311
+ "groupingKey": {
312
+ "type": "string",
313
+ "description": "Used to create hierarchical data structure (parent -> children)"
314
+ },
315
+ "subFields": {
316
+ "type": "array",
317
+ "description": "Recursive structure defining fields that should be pulled inside this grouped field",
318
+ "items": {
319
+ "$ref": "#/definitions/consumerField"
320
+ }
321
+ }
322
+ },
323
+ "required": [
324
+ "groupingKey",
325
+ "subFields"
326
+ ],
327
+ "additionalProperties": false
328
+ }
329
+ },
330
+ "required": [
331
+ "key"
332
+ ],
333
+ "additionalProperties": false
334
+ }
335
+ },
336
+ "examples": [
337
+ {
338
+ "name": "UserOrderAnalytics",
339
+ "description": "Consumer that combines user data with their order history",
340
+ "producers": [
341
+ {
342
+ "name": "UserData",
343
+ "joins": [
344
+ {
345
+ "otherName": "OrderData",
346
+ "relationship": "one-to-many",
347
+ "sql": "${P.id} = ${OrderData.user_id}"
348
+ }
349
+ ]
350
+ },
351
+ {
352
+ "name": "OrderData"
353
+ }
354
+ ],
355
+ "fields": [
356
+ {
357
+ "key": "id",
358
+ "from": "UserData"
359
+ },
360
+ {
361
+ "key": "name",
362
+ "alias": "user_name",
363
+ "from": "UserData"
364
+ },
365
+ {
366
+ "key": "email",
367
+ "from": "UserData"
368
+ },
369
+ {
370
+ "key": "orders",
371
+ "grouping": {
372
+ "groupingKey": "order_items",
373
+ "subFields": [
374
+ {
375
+ "key": "id",
376
+ "from": "OrderData",
377
+ "alias": "order_id"
378
+ },
379
+ {
380
+ "key": "created_at",
381
+ "from": "OrderData"
382
+ },
383
+ {
384
+ "key": "total_amount",
385
+ "from": "OrderData"
386
+ }
387
+ ]
388
+ }
389
+ }
390
+ ],
391
+ "outputs": [
392
+ {
393
+ "format": "API"
394
+ },
395
+ {
396
+ "format": "JSON",
397
+ "exportDestination": "Data Lake",
398
+ "trigger": {
399
+ "type": "CRON",
400
+ "value": "0 0 * * *"
401
+ }
402
+ }
403
+ ],
404
+ "filters": [
405
+ {
406
+ "rule": {
407
+ "member": "total_amount",
408
+ "operator": "greaterThan",
409
+ "values": [
410
+ "100"
411
+ ]
412
+ }
413
+ }
414
+ ],
415
+ "metadata": {
416
+ "department": "Sales",
417
+ "owner": "analytics-team"
418
+ },
419
+ "project": "sales-analytics",
420
+ "_version": 1
421
+ }
422
+ ]
423
+ }