@friggframework/core 2.0.0--canary.397.6ecf8f5.0 → 2.0.0--canary.397.05c9b19.0

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.
@@ -61,21 +61,7 @@ class IntegrationBase {
61
61
  static getCurrentVersion() {
62
62
  return this.Definition.version;
63
63
  }
64
- loadModules() {
65
- // Load all the modules defined in Definition.modules
66
- const moduleNames = Object.keys(this.constructor.Definition.modules);
67
- for (const moduleName of moduleNames) {
68
- const { definition } =
69
- this.constructor.Definition.modules[moduleName];
70
- if (typeof definition.API === 'function') {
71
- this[moduleName] = { api: new definition.API({}) };
72
- } else {
73
- throw new Error(
74
- `Module ${moduleName} must be a function that extends IntegrationModule`
75
- );
76
- }
77
- }
78
- }
64
+
79
65
  registerEventHandlers() {
80
66
  this.on = {
81
67
  ...this.defaultEvents,
@@ -119,7 +105,6 @@ class IntegrationBase {
119
105
  handler: this.refreshActionOptions,
120
106
  },
121
107
  };
122
- this.loadModules();
123
108
  }
124
109
 
125
110
  async send(event, object) {
@@ -51,9 +51,11 @@ function createIntegrationRouter(params) {
51
51
  moduleService,
52
52
  moduleRepository,
53
53
  });
54
+
54
55
  const getCredentialForUser = new GetCredentialForUser({
55
56
  credentialRepository,
56
57
  });
58
+
57
59
  const createIntegration = new CreateIntegration({
58
60
  integrationRepository,
59
61
  integrationClasses,
@@ -62,8 +62,14 @@ class Integration {
62
62
  // Integration behavior (strategy pattern)
63
63
  this.integrationClass = integrationClass;
64
64
 
65
- // Loaded modules
66
- this.modules = modules;
65
+ // Preserve the provided Module instances (array). We'll attach them
66
+ // as keyed modules after the behaviour instance is created so that
67
+ // `this.hubspot`, `this.salesforce`, etc. reference the fully-
68
+ // initialised objects with credentials.
69
+ this._moduleInstances = Array.isArray(modules) ? modules : [];
70
+
71
+ // Normalised map of modules keyed by module name (filled later)
72
+ this.modules = {};
67
73
 
68
74
  // Initialize basic behavior (sync parts only)
69
75
  this._initializeBasicBehavior();
@@ -110,10 +116,17 @@ class Integration {
110
116
  this.events = this.behavior.events || {};
111
117
  this.defaultEvents = this.behavior.defaultEvents || {};
112
118
 
119
+ // -----------------------------------------------------------------
120
+ // Inject the real Module instances (with credentials) so that any
121
+ // behaviour code accessing `this.<moduleName>.api` hits the
122
+ // correctly authenticated requester created by ModuleService.
123
+ // -----------------------------------------------------------------
124
+ for (const mod of this._moduleInstances) {
125
+ const key = typeof mod.getName === 'function' ? mod.getName() : mod.name;
126
+ if (!key) continue;
127
+ this.setModule(key, mod);
128
+ }
113
129
 
114
- // Expose behaviour instance methods directly on the wrapper so that
115
- // early-bound handlers (created before behaviour existed) can still
116
- // access them without falling back through the Proxy. This prevents
117
130
  // `undefined` errors for methods like `loadDynamicUserActions` that
118
131
  // may be invoked inside default event-handlers.
119
132
  let proto = Object.getPrototypeOf(this.behavior);
@@ -217,4 +230,4 @@ class Integration {
217
230
  }
218
231
  }
219
232
 
220
- module.exports = { Integration };
233
+ module.exports = { Integration };
@@ -40,24 +40,35 @@ class ModuleRepository {
40
40
  }
41
41
 
42
42
  async findEntitiesByUserId(userId) {
43
- return Entity.find(
43
+ const entitiesRecords = await Entity.find(
44
44
  { user: userId },
45
45
  '-dateCreated -dateUpdated -user -credentials -credential -__t -__v',
46
46
  { lean: true }
47
- );
47
+ ).populate('credential');
48
+
49
+ return entitiesRecords.map(e => ({
50
+ id: e._id.toString(),
51
+ accountId: e.accountId,
52
+ credential: e.credential,
53
+ userId: e.user.toString(),
54
+ name: e.name,
55
+ externalId: e.externalId,
56
+ type: e.__t,
57
+ moduleName: e.moduleName,
58
+ }));
48
59
  }
49
60
 
50
- async findEntitiesByIds(entityIds) {
51
- const entities = await Entity.find(
52
- { _id: { $in: entityIds } },
61
+ async findEntitiesByIds(entitiesIds) {
62
+ const entitiesRecords = await Entity.find(
63
+ { _id: { $in: entitiesIds } },
53
64
  '',
54
65
  { lean: true }
55
- );
66
+ ).populate('credential');
56
67
 
57
- return entities.map(e => ({
68
+ return entitiesRecords.map(e => ({
58
69
  id: e._id.toString(),
59
70
  accountId: e.accountId,
60
- credentialId: e.credential.toString(),
71
+ credential: e.credential,
61
72
  userId: e.user.toString(),
62
73
  name: e.name,
63
74
  externalId: e.externalId,
@@ -27,10 +27,9 @@ class ModuleService {
27
27
  );
28
28
  }
29
29
 
30
- const entityType = entity.type;
30
+ const moduleName = entity.moduleName;
31
31
  const moduleDefinition = this.moduleDefinitions.find((def) => {
32
- const modelName = Module.getEntityModelFromDefinition(def).modelName;
33
- return entityType === modelName;
32
+ return moduleName === def.modelName;
34
33
  });
35
34
 
36
35
  if (!moduleDefinition) {
package/modules/module.js CHANGED
@@ -1,10 +1,6 @@
1
1
  const { Delegate } = require('../core');
2
- const { get } = require('../assertions');
3
2
  const _ = require('lodash');
4
3
  const { flushDebugLog } = require('../logs');
5
- const { Credential } = require('./credential');
6
- const { Entity } = require('./entity');
7
- const { mongoose } = require('../database/mongoose');
8
4
  const { ModuleConstants } = require('./ModuleConstants');
9
5
 
10
6
  class Module extends Delegate {
@@ -33,10 +29,6 @@ class Module extends Delegate {
33
29
 
34
30
  Object.assign(this, this.definition.requiredAuthMethods);
35
31
 
36
- this.CredentialModel = this.getCredentialModel();
37
- this.EntityModel = this.getEntityModel();
38
-
39
-
40
32
  const apiParams = {
41
33
  ...this.definition.env,
42
34
  delegate: this,
@@ -46,11 +38,6 @@ class Module extends Delegate {
46
38
  this.api = new this.apiClass(apiParams);
47
39
  }
48
40
 
49
- static getEntityModelFromDefinition(definition) {
50
- const partialModule = new this({ definition });
51
- return partialModule.getEntityModel();
52
- }
53
-
54
41
  getName() {
55
42
  return this.name;
56
43
  }
@@ -72,45 +59,6 @@ class Module extends Delegate {
72
59
  return _.pick(entity, ...this.apiPropertiesToPersist?.entity);
73
60
  }
74
61
 
75
- getEntityModel() {
76
- if (!this.EntityModel) {
77
- const prefix = this.modelName ?? _.upperFirst(this.getName());
78
- const arrayToDefaultObject = (array, defaultValue) =>
79
- _.mapValues(_.keyBy(array), () => defaultValue);
80
- const schema = new mongoose.Schema(
81
- arrayToDefaultObject(this.apiPropertiesToPersist.entity, {
82
- type: mongoose.Schema.Types.Mixed,
83
- trim: true,
84
- })
85
- );
86
- const name = `${prefix}Entity`;
87
- this.EntityModel =
88
- Entity.discriminators?.[name] ||
89
- Entity.discriminator(name, schema);
90
- }
91
- return this.EntityModel;
92
- }
93
-
94
- getCredentialModel() {
95
- if (!this.CredentialModel) {
96
- const arrayToDefaultObject = (array, defaultValue) =>
97
- _.mapValues(_.keyBy(array), () => defaultValue);
98
- const schema = new mongoose.Schema(
99
- arrayToDefaultObject(this.apiPropertiesToPersist.credential, {
100
- type: mongoose.Schema.Types.Mixed,
101
- trim: true,
102
- lhEncrypt: true,
103
- })
104
- );
105
- const prefix = this.modelName ?? _.upperFirst(this.getName());
106
- const name = `${prefix}Credential`;
107
- this.CredentialModel =
108
- Credential.discriminators?.[name] ||
109
- Credential.discriminator(name, schema);
110
- }
111
- return this.CredentialModel;
112
- }
113
-
114
62
  async validateAuthorizationRequirements() {
115
63
  const requirements = await this.getAuthorizationRequirements();
116
64
  let valid = true;
@@ -190,58 +138,6 @@ class Module extends Delegate {
190
138
  }
191
139
  }
192
140
 
193
- async findOrCreateEntity(entityDetails) {
194
- const identifiers = get(entityDetails, 'identifiers');
195
- const details = get(entityDetails, 'details');
196
- const search = await this.EntityModel.find(identifiers);
197
- if (search.length > 1) {
198
- throw new Error(
199
- 'Multiple entities found with the same identifiers: ' +
200
- JSON.stringify(identifiers)
201
- );
202
- } else if (search.length === 0) {
203
- this.entity = await this.EntityModel.create({
204
- credential: this.credential.id,
205
- ...details,
206
- ...identifiers,
207
- });
208
- } else if (search.length === 1) {
209
- this.entity = search[0];
210
- }
211
- if (this.entity.credential === undefined) {
212
- this.entity.credential = this.credential.id;
213
- await this.entity.save();
214
- }
215
- }
216
-
217
- async updateOrCreateCredential(credentialDetails) {
218
- const identifiers = get(credentialDetails, 'identifiers');
219
- const details = get(credentialDetails, 'details');
220
-
221
- if (!this.credential) {
222
- const credentialSearch = await this.CredentialModel.find(
223
- identifiers
224
- );
225
- if (credentialSearch.length > 1) {
226
- throw new Error(
227
- `Multiple credentials found with same identifiers: ${identifiers}`
228
- );
229
- } else if (credentialSearch.length === 1) {
230
- // found exactly one credential with these identifiers
231
- this.credential = credentialSearch[0];
232
- } else {
233
- // found no credential with these identifiers (match none for insert)
234
- this.credential = { $exists: false };
235
- }
236
- }
237
- // update credential or create if none was found
238
- this.credential = await this.CredentialModel.findOneAndUpdate(
239
- { _id: this.credential },
240
- { $set: { ...identifiers, ...details } },
241
- { useFindAndModify: true, new: true, upsert: true }
242
- );
243
- }
244
-
245
141
  async markCredentialsInvalid() {
246
142
  if (this.credential) {
247
143
  this.credential.auth_is_valid = false;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@friggframework/core",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "2.0.0--canary.397.6ecf8f5.0",
4
+ "version": "2.0.0--canary.397.05c9b19.0",
5
5
  "dependencies": {
6
6
  "@hapi/boom": "^10.0.1",
7
7
  "aws-sdk": "^2.1200.0",
@@ -22,9 +22,9 @@
22
22
  "uuid": "^9.0.1"
23
23
  },
24
24
  "devDependencies": {
25
- "@friggframework/eslint-config": "2.0.0--canary.397.6ecf8f5.0",
26
- "@friggframework/prettier-config": "2.0.0--canary.397.6ecf8f5.0",
27
- "@friggframework/test": "2.0.0--canary.397.6ecf8f5.0",
25
+ "@friggframework/eslint-config": "2.0.0--canary.397.05c9b19.0",
26
+ "@friggframework/prettier-config": "2.0.0--canary.397.05c9b19.0",
27
+ "@friggframework/test": "2.0.0--canary.397.05c9b19.0",
28
28
  "@types/lodash": "4.17.15",
29
29
  "@typescript-eslint/eslint-plugin": "^8.0.0",
30
30
  "chai": "^4.3.6",
@@ -53,5 +53,5 @@
53
53
  },
54
54
  "homepage": "https://github.com/friggframework/frigg#readme",
55
55
  "description": "",
56
- "gitHead": "6ecf8f59b4e8e90f6a83c19af86c437504e776d6"
56
+ "gitHead": "05c9b19a8f1f2d8e7ef49983786c1fd622fa376a"
57
57
  }