@friggframework/devtools 1.2.0-canary.293.5731c31.0 → 1.2.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 (51) hide show
  1. package/CHANGELOG.md +117 -0
  2. package/README.md +80 -0
  3. package/frigg-cli/backendJs.js +33 -0
  4. package/frigg-cli/backendPath.js +26 -0
  5. package/frigg-cli/commitChanges.js +16 -0
  6. package/frigg-cli/environmentVariables.js +134 -0
  7. package/frigg-cli/environmentVariables.test.js +86 -0
  8. package/frigg-cli/index.js +14 -0
  9. package/frigg-cli/index.test.js +109 -0
  10. package/frigg-cli/installCommand.js +57 -0
  11. package/frigg-cli/installPackage.js +13 -0
  12. package/frigg-cli/integrationFile.js +30 -0
  13. package/frigg-cli/logger.js +12 -0
  14. package/frigg-cli/template.js +90 -0
  15. package/frigg-cli/validatePackage.js +79 -0
  16. package/index.js +2 -6
  17. package/package.json +16 -6
  18. package/test/auther-definition-method-tester.js +45 -0
  19. package/test/auther-definition-tester.js +125 -0
  20. package/test/index.js +11 -0
  21. package/{test-environment → test}/mock-api.js +1 -1
  22. package/test/mock-integration.js +83 -0
  23. package/eslint-config/CHANGELOG.md +0 -17
  24. package/eslint-config/LICENSE.md +0 -9
  25. package/eslint-config/README.md +0 -3
  26. package/eslint-config/bump3.txt +0 -0
  27. package/eslint-config/index.js +0 -38
  28. package/migrations/README.md +0 -3
  29. package/migrations/bump3.txt +0 -0
  30. package/migrations/jest.config.js +0 -3
  31. package/prettier-config/.eslintrc.json +0 -3
  32. package/prettier-config/CHANGELOG.md +0 -17
  33. package/prettier-config/LICENSE.md +0 -9
  34. package/prettier-config/README.md +0 -3
  35. package/prettier-config/bump3.txt +0 -0
  36. package/prettier-config/index.js +0 -6
  37. package/test-environment/.eslintrc.json +0 -3
  38. package/test-environment/Authenticator.js +0 -74
  39. package/test-environment/CHANGELOG.md +0 -46
  40. package/test-environment/LICENSE.md +0 -9
  41. package/test-environment/README.md +0 -3
  42. package/test-environment/bump3.txt +0 -0
  43. package/test-environment/index.js +0 -21
  44. package/test-environment/jest-global-setup.js +0 -6
  45. package/test-environment/jest-global-teardown.js +0 -3
  46. package/test-environment/jest-preset.js +0 -14
  47. package/test-environment/mongodb.js +0 -22
  48. package/test-environment/override-environment.js +0 -11
  49. /package/{eslint-config/.eslintrc.json → .eslintrc.json} +0 -0
  50. /package/{test-environment → test}/integration-validator.js +0 -0
  51. /package/{test-environment → test}/mock-api-readme.md +0 -0
@@ -0,0 +1,57 @@
1
+ const { installPackage } = require('./installPackage');
2
+ const { createIntegrationFile } = require('./integrationFile');
3
+ const { resolve } = require('node:path');
4
+ const { updateBackendJsFile } = require('./backendJs');
5
+ const { logInfo, logError } = require('./logger');
6
+ const { commitChanges } = require('./commitChanges');
7
+ const {
8
+ findNearestBackendPackageJson,
9
+ validateBackendPath,
10
+ } = require('./backendPath');
11
+ const { handleEnvVariables } = require('./environmentVariables');
12
+ const {
13
+ validatePackageExists,
14
+ searchAndSelectPackage,
15
+ } = require('./validatePackage');
16
+
17
+ const installCommand = async (apiModuleName) => {
18
+ try {
19
+ const packageNames = await searchAndSelectPackage(apiModuleName);
20
+ if (!packageNames || packageNames.length === 0) return;
21
+
22
+ const backendPath = findNearestBackendPackageJson();
23
+ validateBackendPath(backendPath);
24
+
25
+ for (const packageName of packageNames) {
26
+ await validatePackageExists(packageName);
27
+ installPackage(backendPath, packageName);
28
+
29
+ const modulePath = resolve(
30
+ backendPath,
31
+ `../../node_modules/${packageName}`
32
+ );
33
+ const {
34
+ Config: { label },
35
+ Api: ApiClass,
36
+ } = require(modulePath);
37
+
38
+ const sanitizedLabel = label.replace(
39
+ /[<>:"/\\|?*\x00-\x1F\s]/g,
40
+ ''
41
+ ); // Remove invalid characters and spaces console.log('Installing integration for:', sanitizedLabel);
42
+ createIntegrationFile(backendPath, sanitizedLabel, ApiClass);
43
+ updateBackendJsFile(backendPath, sanitizedLabel);
44
+ commitChanges(backendPath, sanitizedLabel);
45
+ logInfo(
46
+ `Successfully installed ${packageName} and updated the project.`
47
+ );
48
+
49
+ await handleEnvVariables(backendPath, modulePath);
50
+ }
51
+ } catch (error) {
52
+ logError('An error occurred:', error);
53
+ process.exit(1);
54
+ }
55
+ };
56
+
57
+ module.exports = { installCommand };
@@ -0,0 +1,13 @@
1
+ const { execSync } = require('child_process');
2
+ const path = require('path');
3
+
4
+ function installPackage(backendPath, packageName) {
5
+ execSync(`npm install ${packageName}`, {
6
+ cwd: path.dirname(backendPath),
7
+ stdio: 'inherit',
8
+ });
9
+ }
10
+
11
+ module.exports = {
12
+ installPackage,
13
+ };
@@ -0,0 +1,30 @@
1
+ const fs = require('fs-extra');
2
+ const path = require('path');
3
+ const { logInfo } = require('./logger');
4
+ const { getIntegrationTemplate } = require('./template');
5
+ const INTEGRATIONS_DIR = 'src/integrations';
6
+
7
+ function createIntegrationFile(backendPath, apiModuleName, ApiClass) {
8
+ const integrationDir = path.join(
9
+ path.dirname(backendPath),
10
+ INTEGRATIONS_DIR
11
+ );
12
+ logInfo(`Ensuring directory exists: ${integrationDir}`);
13
+ fs.ensureDirSync(integrationDir);
14
+
15
+ const integrationFilePath = path.join(
16
+ integrationDir,
17
+ `${apiModuleName}Integration.js`
18
+ );
19
+ logInfo(`Writing integration file: ${integrationFilePath}`);
20
+ const integrationTemplate = getIntegrationTemplate(
21
+ apiModuleName,
22
+ backendPath,
23
+ ApiClass
24
+ );
25
+ fs.writeFileSync(integrationFilePath, integrationTemplate);
26
+ }
27
+
28
+ module.exports = {
29
+ createIntegrationFile,
30
+ };
@@ -0,0 +1,12 @@
1
+ function logInfo(message) {
2
+ console.log(message);
3
+ }
4
+
5
+ function logError(message, error) {
6
+ console.error(message, error);
7
+ }
8
+
9
+ module.exports = {
10
+ logInfo,
11
+ logError,
12
+ };
@@ -0,0 +1,90 @@
1
+ const path = require('path');
2
+
3
+ function getIntegrationTemplate(apiModuleName, backendPath, ApiClass) {
4
+ // Find the sample data method
5
+ const apiMethods = Object.getOwnPropertyNames(ApiClass.prototype);
6
+ const sampleDataMethod =
7
+ apiMethods.find(
8
+ (method) =>
9
+ method.toLowerCase().includes('search') ||
10
+ method.toLowerCase().includes('list') ||
11
+ method.toLowerCase().includes('get')
12
+ ) || 'searchDeals';
13
+
14
+ return `const { get, IntegrationBase, Options } = require('@friggframework/core');
15
+ const { Definition: ${apiModuleName}Module, Config: defaultConfig } = require('@friggframework/api-module-${apiModuleName.toLowerCase()}');
16
+
17
+ class ${apiModuleName}Integration extends IntegrationBase {
18
+ static Config = {
19
+ name: defaultConfig.name || '${apiModuleName.toLowerCase()}',
20
+ version: '1.0.0',
21
+ supportedVersions: ['1.0.0'],
22
+ events: ['SEARCH_DEALS'],
23
+ };
24
+
25
+ static Options =
26
+ new Options({
27
+ module: ${apiModuleName}Module,
28
+ integrations: [${apiModuleName}Module],
29
+ display: {
30
+ name: defaultConfig.displayName || '${apiModuleName}',
31
+ description: defaultConfig.description || 'Sales & CRM, Marketing',
32
+ category: defaultConfig.category || 'Sales & CRM, Marketing',
33
+ detailsUrl: defaultConfig.detailsUrl || 'https://www.${apiModuleName.toLowerCase()}.com',
34
+ icon: defaultConfig.icon || 'https://friggframework.org/assets/img/${apiModuleName.toLowerCase()}.jpeg',
35
+ },
36
+ hasUserConfig: true,
37
+ });
38
+
39
+ static modules = {
40
+ ${apiModuleName.toLowerCase()}: ${apiModuleName}Module,
41
+ }
42
+
43
+ /**
44
+ * HANDLE EVENTS
45
+ */
46
+ async receiveNotification(notifier, event, object = null) {
47
+ if (event === 'SEARCH_DEALS') {
48
+ return this.target.api.searchDeals(object);
49
+ }
50
+ }
51
+
52
+ /**
53
+ * ALL CUSTOM/OPTIONAL METHODS FOR AN INTEGRATION MANAGER
54
+ */
55
+ async getSampleData() {
56
+ const res = await this.target.api.${sampleDataMethod}();
57
+ return { data: res };
58
+ }
59
+
60
+ /**
61
+ * ALL REQUIRED METHODS FOR AN INTEGRATION MANAGER
62
+ */
63
+ async onCreate(params) {
64
+ // Validate that we have all of the data we need
65
+ // Set integration status as makes sense. Default ENABLED
66
+ // TODO turn this into a validateConfig method/function
67
+ this.record.status = 'ENABLED';
68
+ await this.record.save();
69
+ return this.record;
70
+ }
71
+
72
+ async onUpdate(params) {
73
+ const newConfig = get(params, 'config');
74
+ const oldConfig = this.record.config;
75
+ // Just save whatever
76
+ this.record.markModified('config');
77
+ await this.record.save();
78
+ return this.validateConfig();
79
+ }
80
+
81
+ async getConfigOptions() {
82
+ const options = {}
83
+ return options;
84
+ }
85
+ }
86
+
87
+ module.exports = ${apiModuleName}Integration;`;
88
+ }
89
+
90
+ module.exports = { getIntegrationTemplate };
@@ -0,0 +1,79 @@
1
+ const { execSync } = require('child_process');
2
+ const axios = require('axios');
3
+ const { logError } = require('./logger');
4
+ const inquirer = require('inquirer');
5
+
6
+ async function searchPackages(apiModuleName) {
7
+ const searchCommand = `npm search @friggframework/api-module-${apiModuleName} --json`;
8
+ const result = execSync(searchCommand, { encoding: 'utf8' });
9
+ return JSON.parse(result);
10
+ }
11
+
12
+ async function checkPackageExists(packageName) {
13
+ try {
14
+ const response = await axios.get(
15
+ `https://registry.npmjs.org/${packageName}`
16
+ );
17
+ return response.status === 200;
18
+ } catch (error) {
19
+ return false;
20
+ }
21
+ }
22
+
23
+ async function validatePackageExists(packageName) {
24
+ const packageExists = await checkPackageExists(packageName);
25
+ if (!packageExists) {
26
+ throw new Error(`Package ${packageName} does not exist on npm.`);
27
+ }
28
+ }
29
+
30
+ const searchAndSelectPackage = async (apiModuleName) => {
31
+ const searchResults = await searchPackages(apiModuleName || '');
32
+
33
+ if (searchResults.length === 0) {
34
+ logError(`No packages found matching ${apiModuleName}`);
35
+ process.exit(1);
36
+ }
37
+
38
+ const filteredResults = searchResults.filter((pkg) => {
39
+ const version = pkg.version
40
+ ? pkg.version.split('.').map(Number)
41
+ : [];
42
+ return version[0] >= 1;
43
+ });
44
+
45
+ if (filteredResults.length === 0) {
46
+ const earlierVersions = searchResults
47
+ .map((pkg) => `${pkg.name} (${pkg.version})`)
48
+ .join(', ');
49
+ logError(
50
+ `No packages found with version 1.0.0 or above for ${apiModuleName}. Found earlier versions: ${earlierVersions}`
51
+ );
52
+ process.exit(1);
53
+ }
54
+
55
+ const choices = filteredResults.map((pkg) => {
56
+ return {
57
+ name: `${pkg.name} (${pkg.version})`,
58
+ checked: filteredResults.length === 1, // Automatically select if only one result
59
+ };
60
+ });
61
+
62
+ const { selectedPackages } = await inquirer.prompt([
63
+ {
64
+ type: 'checkbox',
65
+ name: 'selectedPackages',
66
+ message: 'Select the packages to install:',
67
+ choices,
68
+ },
69
+ ]);
70
+
71
+ return selectedPackages.map(choice => choice.split(' ')[0]);
72
+ };
73
+
74
+ module.exports = {
75
+ validatePackageExists,
76
+ checkPackageExists,
77
+ searchPackages,
78
+ searchAndSelectPackage,
79
+ };
package/index.js CHANGED
@@ -1,9 +1,5 @@
1
- const eslintConfig = require('./eslint-config')
2
- const prettierConfig = require('./prettier-config')
3
- const testEnvironment = require('./test-environment/index');
1
+ const test = require('./test');
4
2
 
5
3
  module.exports = {
6
- eslintConfig,
7
- prettierConfig,
8
- ...testEnvironment
4
+ ...test
9
5
  }
package/package.json CHANGED
@@ -1,26 +1,36 @@
1
1
  {
2
2
  "name": "@friggframework/devtools",
3
3
  "prettier": "@friggframework/prettier-config",
4
- "version": "1.2.0-canary.293.5731c31.0",
4
+ "version": "1.2.1",
5
5
  "dependencies": {
6
6
  "@babel/eslint-parser": "^7.18.9",
7
+ "@babel/parser": "^7.25.3",
8
+ "@babel/traverse": "^7.25.3",
9
+ "@friggframework/core": "^1.2.1",
10
+ "@friggframework/test": "^1.2.1",
11
+ "axios": "^1.7.2",
12
+ "commander": "^12.1.0",
13
+ "dotenv": "^16.4.5",
7
14
  "eslint": "^8.22.0",
8
15
  "eslint-config-prettier": "^8.5.0",
9
16
  "eslint-plugin-json": "^3.1.0",
10
17
  "eslint-plugin-markdown": "^3.0.0",
11
18
  "eslint-plugin-no-only-tests": "^3.0.0",
12
19
  "eslint-plugin-yaml": "^0.5.0",
13
- "jest-runner-groups": "^2.2.0",
14
- "mongodb-memory-server": "^8.9.0"
20
+ "fs-extra": "^11.2.0",
21
+ "inquirer": "^10.1.6"
15
22
  },
16
23
  "devDependencies": {
17
- "jest": "^28.1.3",
18
- "prettier": "^2.7.1"
24
+ "@friggframework/eslint-config": "^1.2.1",
25
+ "@friggframework/prettier-config": "^1.2.1"
19
26
  },
20
27
  "scripts": {
21
28
  "lint:fix": "prettier --write --loglevel error . && eslint . --fix",
22
29
  "test": "jest --passWithNoTests # TODO"
23
30
  },
31
+ "bin": {
32
+ "frigg": "./frigg-cli/index.js"
33
+ },
24
34
  "author": "",
25
35
  "license": "MIT",
26
36
  "main": "index.js",
@@ -36,5 +46,5 @@
36
46
  "publishConfig": {
37
47
  "access": "public"
38
48
  },
39
- "gitHead": "5731c31f2ef22a9b47b43a626cd8ff0e849bd561"
49
+ "gitHead": "3c2bb949c71be314cf44e326e618b3e16b787e8c"
40
50
  }
@@ -0,0 +1,45 @@
1
+ const {flushDebugLog} = require('@friggframework/core');
2
+
3
+ async function testDefinitionRequiredAuthMethods(api, definition, authCallbackParams, tokenResponse, userId) {
4
+
5
+ // const response = await definition.getToken(api, authCallbackParams);
6
+ // expect(api.setTokens).toHaveBeenCalled();
7
+ // if (tokenResponse) {
8
+ // expect(response).toMatchObject(tokenResponse);
9
+ // }
10
+
11
+ const entityDetails = await definition.requiredAuthMethods.getEntityDetails(api, authCallbackParams, tokenResponse, userId);
12
+ expect(entityDetails).toHaveProperty('identifiers');
13
+ expect(Object.values(entityDetails.identifiers).length).toBeGreaterThan(0);
14
+ for (const key of Object.keys(entityDetails.identifiers)){
15
+ expect(key).toBeDefined();
16
+ expect(entityDetails.identifiers[key]).toBeDefined();
17
+ }
18
+
19
+
20
+ const credentialDetails = await definition.requiredAuthMethods.getCredentialDetails(api);
21
+ expect(credentialDetails).toHaveProperty('identifiers');
22
+ expect(Object.values(entityDetails.identifiers).length).toBeGreaterThan(0);
23
+ for (const key of Object.keys(entityDetails.identifiers)){
24
+ expect(key).toBeDefined();
25
+ expect(entityDetails.identifiers[key]).toBeDefined();
26
+ }
27
+
28
+ const successResponse = await definition.requiredAuthMethods.testAuthRequest(api);
29
+ expect(successResponse).toBeTruthy();
30
+ const savedKeys = {};
31
+ for (const key of definition.requiredAuthMethods.apiPropertiesToPersist.credential){
32
+ savedKeys[key] = api[key];
33
+ delete api[key];
34
+ }
35
+ let validAuth = false;
36
+ try {
37
+ if (await definition.requiredAuthMethods.testAuthRequest(api)) validAuth = true;
38
+ } catch (e) {
39
+ flushDebugLog(e);
40
+ }
41
+ expect(validAuth).not.toBeTruthy();
42
+ Object.assign(api, savedKeys);
43
+ }
44
+
45
+ module.exports = { testDefinitionRequiredAuthMethods }
@@ -0,0 +1,125 @@
1
+ const {
2
+ Auther,
3
+ ModuleConstants,
4
+ createObjectId,
5
+ connectToDatabase,
6
+ disconnectFromDatabase,
7
+ } = require('@friggframework/core');
8
+ const { createMockApiObject } = require("./mock-integration");
9
+
10
+
11
+ function testAutherDefinition(definition, mocks) {
12
+ const getModule = async (params) => {
13
+ const module = await Auther.getInstance({
14
+ definition,
15
+ userId: createObjectId(),
16
+ ...params,
17
+ });
18
+ if (mocks.tokenResponse) {
19
+ mocks.getTokenFrom = async function(code) {
20
+ await this.setTokens(mocks.tokenResponse);
21
+ return mocks.tokenResponse
22
+ }
23
+ mocks.getTokenFromCode = mocks.getTokenFromCode || mocks.getTokenFrom
24
+ mocks.getTokenFromCodeBasicAuthHeader = mocks.getTokenFromCodeBasicAuthHeader || mocks.getTokenFrom
25
+ mocks.getTokenFromClientCredentials = mocks.getTokenFromClientCredentials || mocks.getTokenFrom
26
+ mocks.getTokenFromUsernamePassword = mocks.getTokenFromUsernamePassword || mocks.getTokenFrom
27
+ }
28
+ if (mocks.refreshResponse) {
29
+ mocks.refreshAccessToken = async function(code) {
30
+ await this.setTokens(mocks.refreshResponse);
31
+ return mocks.refreshResponse
32
+ }
33
+ }
34
+ module.api = createMockApiObject(jest, module.api, mocks);
35
+ return module
36
+ }
37
+
38
+
39
+ describe(`${definition.moduleName} Module Tests`, () => {
40
+ let module, authUrl;
41
+ beforeAll(async () => {
42
+ await connectToDatabase();
43
+ module = await getModule();
44
+ });
45
+
46
+ afterAll(async () => {
47
+ await disconnectFromDatabase();
48
+ });
49
+
50
+ let requirements, authCallbackParams;
51
+ if (definition.API.requesterType === ModuleConstants.authType.oauth2) {
52
+ authCallbackParams = mocks.authorizeResponse || mocks.authorizeParams;
53
+ describe('getAuthorizationRequirements() test', () => {
54
+ it('should return auth requirements', async () => {
55
+ requirements = await module.getAuthorizationRequirements();
56
+ expect(requirements).toBeDefined();
57
+ expect(requirements.type).toEqual(ModuleConstants.authType.oauth2);
58
+ expect(requirements.url).toBeDefined();
59
+ authUrl = requirements.url;
60
+ });
61
+ });
62
+ } else if (definition.API.requesterType === ModuleConstants.authType.basic) {
63
+ // could also confirm authCallbackParams against the auth requirements
64
+ authCallbackParams = mocks.authorizeParams
65
+ describe('getAuthorizationRequirements() test', () => {
66
+ it('should return auth requirements', async () => {
67
+ requirements = module.getAuthorizationRequirements();
68
+ expect(requirements).toBeDefined();
69
+ expect(requirements.type).toEqual(ModuleConstants.authType.basic);
70
+ });
71
+ });
72
+ } else if (definition.API.requesterType === ModuleConstants.authType.apiKey) {
73
+ // could also confirm authCallbackParams against the auth requirements
74
+ authCallbackParams = mocks.authorizeParams
75
+ describe('getAuthorizationRequirements() test', () => {
76
+ it('should return auth requirements', async () => {
77
+ requirements = module.getAuthorizationRequirements();
78
+ expect(requirements).toBeDefined();
79
+ expect(requirements.type).toEqual(ModuleConstants.authType.apiKey);
80
+ });
81
+ });
82
+ }
83
+
84
+ describe('Authorization requests', () => {
85
+ let firstRes;
86
+ it('processAuthorizationCallback()', async () => {
87
+ firstRes = await module.processAuthorizationCallback(authCallbackParams);
88
+ expect(firstRes).toBeDefined();
89
+ expect(firstRes.entity_id).toBeDefined();
90
+ expect(firstRes.credential_id).toBeDefined();
91
+ });
92
+ it('retrieves existing entity on subsequent calls', async () => {
93
+ const res = await module.processAuthorizationCallback(authCallbackParams);
94
+ expect(res).toEqual(firstRes);
95
+ });
96
+ });
97
+
98
+ describe('Test credential retrieval and module instantiation', () => {
99
+ it('retrieve by entity id', async () => {
100
+ const newModule = await getModule({
101
+ userId: module.userId,
102
+ entityId: module.entity.id
103
+ });
104
+ expect(newModule).toBeDefined();
105
+ expect(newModule.entity).toBeDefined();
106
+ expect(newModule.credential).toBeDefined();
107
+ expect(await newModule.testAuth()).toBeTruthy();
108
+
109
+ });
110
+
111
+ it('retrieve by credential id', async () => {
112
+ const newModule = await getModule({
113
+ userId: module.userId,
114
+ credentialId: module.credential.id
115
+ });
116
+ expect(newModule).toBeDefined();
117
+ expect(newModule.credential).toBeDefined();
118
+ expect(await newModule.testAuth()).toBeTruthy();
119
+ });
120
+ });
121
+ });
122
+ }
123
+
124
+ module.exports = { testAutherDefinition }
125
+
package/test/index.js ADDED
@@ -0,0 +1,11 @@
1
+ const {testDefinitionRequiredAuthMethods} = require('./auther-definition-method-tester');
2
+ const {createMockIntegration, createMockApiObject} = require('./mock-integration');
3
+ const { testAutherDefinition } = require('./auther-definition-tester');
4
+
5
+
6
+ module.exports = {
7
+ createMockIntegration,
8
+ createMockApiObject,
9
+ testDefinitionRequiredAuthMethods,
10
+ testAutherDefinition,
11
+ };
@@ -1,5 +1,5 @@
1
1
  const nock = require('nock');
2
- const Authenticator = require('./Authenticator');
2
+ const { Authenticator } = require('@friggframework/test');
3
3
  const { join: joinPath } = require('path');
4
4
  const { parse: parseUrl } = require('url');
5
5
  const { mkdir, readFile, rename, rm, writeFile } = require('fs/promises');
@@ -0,0 +1,83 @@
1
+ const { Auther, Credential, Entity, IntegrationFactory, createObjectId } = require('@friggframework/core');
2
+
3
+
4
+ async function createMockIntegration(IntegrationClassDef, userId = null, config = {},) {
5
+ const integrationFactory = new IntegrationFactory([IntegrationClassDef]);
6
+ userId = userId || createObjectId();
7
+
8
+ const insertOptions = {
9
+ new: true,
10
+ upsert: true,
11
+ setDefaultsOnInsert: true,
12
+ }
13
+ const user = {user: userId}
14
+
15
+ const credential = await Credential.findOneAndUpdate(
16
+ user,
17
+ { $set: user },
18
+ insertOptions
19
+ );
20
+ const entity1 = await Entity.findOneAndUpdate(
21
+ user,
22
+ {
23
+ $set: {
24
+ credential: credential.id,
25
+ user: userId,
26
+ name: 'Test user',
27
+ externalId: '1234567890123456',
28
+ },
29
+ },
30
+ insertOptions
31
+ );
32
+ const entity2 = await Entity.findOneAndUpdate(
33
+ user,
34
+ {
35
+ $set: {
36
+ credential: credential.id,
37
+ user: userId,
38
+ },
39
+ },
40
+ insertOptions
41
+ );
42
+
43
+ const entities = [entity1, entity2]
44
+
45
+ const integration =
46
+ await integrationFactory.createIntegration(
47
+ entities,
48
+ userId,
49
+ config,
50
+ );
51
+
52
+ integration.id = integration.record._id
53
+
54
+ for (const i in entities){
55
+ if (Object.entries(IntegrationClassDef.modules).length <= i) break
56
+ const [moduleName, ModuleDef] = Object.entries(IntegrationClassDef.modules)[i];
57
+ const module = await Auther.getInstance({definition: ModuleDef, userId: userId})
58
+ module.entity = entities[i];
59
+ integration[moduleName] = module;
60
+ }
61
+
62
+ return integration
63
+ }
64
+
65
+ function createMockApiObject(jest, api = {}, mockMethodMap) {
66
+ // take in an api class and object with keys that are method names
67
+ // and values which are the mock response (or implementation)
68
+ const clone = (data) => JSON.parse(JSON.stringify(data));
69
+
70
+ for (const [methodName, mockDataOrImplementation] of Object.entries(mockMethodMap)) {
71
+ if (mockDataOrImplementation instanceof Function) {
72
+ api[methodName] = jest.fn(mockDataOrImplementation);
73
+ }
74
+ else if (api[methodName]?.constructor?.name === "AsyncFunction") {
75
+ api[methodName] = jest.fn().mockResolvedValue(clone(mockDataOrImplementation));
76
+ } else {
77
+ api[methodName] = jest.fn().mockReturnValue(clone(mockDataOrImplementation));
78
+ }
79
+ }
80
+ return api;
81
+ }
82
+
83
+ module.exports = {createMockIntegration, createMockApiObject};
@@ -1,17 +0,0 @@
1
- # v1.0.8 (Mon Jan 09 2023)
2
-
3
- #### 🐛 Bug Fix
4
-
5
- - Merge remote-tracking branch 'origin/main' into gitbook-updates [#48](https://github.com/friggframework/frigg/pull/48) ([@seanspeaks](https://github.com/seanspeaks))
6
- - Bump independent versions \[skip ci\] ([@seanspeaks](https://github.com/seanspeaks))
7
- - Merge remote-tracking branch 'origin/main' into simplify-mongoose-models ([@seanspeaks](https://github.com/seanspeaks))
8
- - Add READMEs for all packages and api-modules [#20](https://github.com/friggframework/frigg/pull/20) ([@seanspeaks](https://github.com/seanspeaks))
9
- - Add READMEs for all packages and api-modules ([@seanspeaks](https://github.com/seanspeaks))
10
-
11
- #### ⚠️ Pushed to `main`
12
-
13
- - Refactored for more conventional naming (at least for packages) ([@seanspeaks](https://github.com/seanspeaks))
14
-
15
- #### Authors: 1
16
-
17
- - Sean Matthews ([@seanspeaks](https://github.com/seanspeaks))
@@ -1,9 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 Left Hook Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
-
7
- The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.
8
-
9
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,3 +0,0 @@
1
- # eslint-config
2
-
3
- This package exports the default `eslint-config` settings used in [Frigg](https://friggframework.org). You can find its documentation [on Frigg's website](https://docs.friggframework.org/packages/eslint-config).
File without changes