@unito/integration-cli 0.57.2 → 0.58.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.
Files changed (88) hide show
  1. package/dist/.eslintrc.d.ts +6 -0
  2. package/dist/.eslintrc.js +9 -2
  3. package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/src/index.ts +1 -3
  4. package/dist/src/commands/dev.d.ts +4 -0
  5. package/dist/src/commands/dev.js +40 -4
  6. package/dist/src/commands/init.js +2 -2
  7. package/dist/src/commands/login.js +1 -1
  8. package/dist/src/commands/oauth2.js +15 -10
  9. package/dist/src/commands/test.js +28 -6
  10. package/dist/src/errors.d.ts +8 -0
  11. package/dist/src/errors.js +35 -18
  12. package/dist/src/resources/configuration.js +0 -2
  13. package/dist/src/resources/credentials.d.ts +3 -0
  14. package/dist/src/resources/credentials.js +26 -0
  15. package/dist/src/resources/integrations.d.ts +1 -0
  16. package/dist/src/resources/integrations.js +37 -2
  17. package/dist/src/resources/oauth2Helper.d.ts +4 -0
  18. package/dist/src/resources/oauth2Helper.js +30 -0
  19. package/dist/src/services/integrationsPlatform.d.ts +1 -0
  20. package/dist/src/services/integrationsPlatform.js +5 -1
  21. package/dist/src/services/oauth2Helper.d.ts +77 -3
  22. package/dist/src/services/oauth2Helper.js +228 -29
  23. package/dist/test/commands/dev.test.js +21 -0
  24. package/dist/test/commands/init.test.js +4 -4
  25. package/dist/test/commands/login.test.js +1 -0
  26. package/dist/test/commands/oauth2.test.js +2 -1
  27. package/dist/test/commands/publish.test.js +1 -0
  28. package/dist/test/commands/test.test.js +22 -0
  29. package/dist/test/commands/upgrade.test.js +1 -0
  30. package/dist/test/oauth2Helper/oauth2Helper.test.js +111 -127
  31. package/dist/test/resources/integrations.test.js +37 -0
  32. package/dist/test/{services → resources}/oauth2Helper.test.js +12 -42
  33. package/oclif.manifest.json +64 -9
  34. package/package.json +8 -8
  35. package/dist/integrationGenerator/errors.d.ts +0 -2
  36. package/dist/integrationGenerator/errors.js +0 -6
  37. package/dist/integrationGenerator/index.d.ts +0 -2
  38. package/dist/integrationGenerator/index.js +0 -5
  39. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.dockerignore +0 -3
  40. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.eslintrc.js +0 -74
  41. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.nvmrc +0 -1
  42. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.prettierignore +0 -1
  43. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.prettierrc +0 -7
  44. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.unito.json +0 -1
  45. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/Dockerfile +0 -38
  46. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/README.md +0 -21
  47. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/index.ts +0 -94
  48. package/dist/integrationGenerator/integrationBoilerplate/package.json +0 -43
  49. package/dist/integrationGenerator/integrationBoilerplate/src/logger.ts +0 -55
  50. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +0 -22
  51. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/correlationId.ts +0 -13
  52. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/credentials.ts +0 -38
  53. package/dist/integrationGenerator/integrationBoilerplate/src/request.ts +0 -59
  54. package/dist/integrationGenerator/integrationBoilerplate/src/routes/index.ts +0 -11
  55. package/dist/integrationGenerator/integrationBoilerplate/src/routes/me.ts +0 -15
  56. package/dist/integrationGenerator/integrationBoilerplate/src/routes/root.ts +0 -12
  57. package/dist/integrationGenerator/integrationBoilerplate/tsconfig.json +0 -37
  58. package/dist/integrationGenerator/src/index.d.ts +0 -1
  59. package/dist/integrationGenerator/src/index.js +0 -5
  60. package/dist/integrationGenerator/src/resources/index.d.ts +0 -1
  61. package/dist/integrationGenerator/src/resources/index.js +0 -5
  62. package/dist/integrationGenerator/src/resources/integration.d.ts +0 -9
  63. package/dist/integrationGenerator/src/resources/integration.js +0 -60
  64. package/dist/integrationGenerator/test/resources/integration.test.js +0 -50
  65. package/dist/src/oauth2Helper/oauth2Helper.d.ts +0 -65
  66. package/dist/src/oauth2Helper/oauth2Helper.js +0 -255
  67. package/dist/src/oauth2Helper/types.d.ts +0 -22
  68. package/dist/src/oauth2Helper/types.js +0 -2
  69. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.dockerignore +0 -0
  70. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.eslintrc.js +0 -0
  71. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.nvmrc +0 -0
  72. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.prettierignore +0 -0
  73. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.prettierrc +0 -0
  74. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/.unito.json +0 -0
  75. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/Dockerfile +0 -0
  76. /package/dist/{integrationGenerator/integrationBoilerplate → boilerplate}/README.md +0 -0
  77. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/package.json +0 -0
  78. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/logger.ts +0 -0
  79. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/middlewares/additionalLoggingContext.ts +0 -0
  80. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/middlewares/correlationId.ts +0 -0
  81. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/middlewares/credentials.ts +0 -0
  82. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/request.ts +0 -0
  83. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/routes/index.ts +0 -0
  84. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/routes/me.ts +0 -0
  85. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/src/routes/root.ts +0 -0
  86. /package/dist/{integrationGenerator/integrationBoilerplate/integrationBoilerplate → boilerplate}/tsconfig.json +0 -0
  87. /package/dist/{integrationGenerator/test/resources/integration.test.d.ts → test/resources/integrations.test.d.ts} +0 -0
  88. /package/dist/test/{services → resources}/oauth2Helper.test.d.ts +0 -0
@@ -8,3 +8,9 @@ export declare let rules: {
8
8
  'no-console': string;
9
9
  };
10
10
  export declare let ignorePatterns: string[];
11
+ export declare let overrides: {
12
+ files: string[];
13
+ rules: {
14
+ '@typescript-eslint/no-floating-promises': string;
15
+ };
16
+ }[];
package/dist/.eslintrc.js CHANGED
@@ -14,7 +14,14 @@ module.exports = {
14
14
  'no-console': 'off',
15
15
  },
16
16
  ignorePatterns: [
17
- 'integrationGenerator/integrationBoilerplate',
18
- 'integrationGenerator/templates',
17
+ 'boilerplate',
18
+ ],
19
+ overrides: [
20
+ {
21
+ 'files': ['test/**/*.test.ts'],
22
+ 'rules': {
23
+ '@typescript-eslint/no-floating-promises': 'off'
24
+ }
25
+ }
19
26
  ],
20
27
  };
@@ -70,9 +70,7 @@ app.use((req: express.Request, res: express.Response, _next: express.NextFunctio
70
70
  });
71
71
 
72
72
  // eslint-disable-next-line
73
- const instance = app.listen(process.env.PORT || 9200, () =>
74
- console.log(`Server started on port ${process.env.PORT || 9200}.`),
75
- );
73
+ const instance = app.listen(process.env.PORT || 9200, () => console.log(`Server started on port ${process.env.PORT || 9200}.`));
76
74
 
77
75
  // Trap exit signals.
78
76
  ['SIGTERM', 'SIGINT', 'SIGUSR2'].forEach(signalType => {
@@ -7,6 +7,10 @@ export default class Dev extends BaseCommand<typeof Dev> {
7
7
  static flags: {
8
8
  environment: import("@oclif/core/lib/interfaces").OptionFlag<GlobalConfiguration.Environment, import("@oclif/core/lib/interfaces").CustomOptions>;
9
9
  verbose: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
+ 'credential-payload': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
11
+ 'credential-id': import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
12
+ 'test-account': import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
13
+ 'read-only': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
10
14
  crawlMode: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
11
15
  checks: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
12
16
  'config-path': import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
@@ -9,6 +9,7 @@ const GlobalConfiguration = tslib_1.__importStar(require("../resources/globalCon
9
9
  const integrations_1 = require("../resources/integrations");
10
10
  const configuration_1 = require("../resources/configuration");
11
11
  const decryption_1 = require("../resources/decryption");
12
+ const credentials_1 = require("../resources/credentials");
12
13
  class Dev extends baseCommand_1.BaseCommand {
13
14
  static description = 'Develop your integration';
14
15
  static examples = ['<%= config.bin %> <%= command.id %>'];
@@ -29,6 +30,23 @@ class Dev extends baseCommand_1.BaseCommand {
29
30
  description: 'output more (debug) information',
30
31
  default: false,
31
32
  }),
33
+ 'credential-payload': core_1.Flags.string({
34
+ description: '(advanced) credential payload to use.',
35
+ exclusive: ['credential-id'],
36
+ }),
37
+ 'credential-id': core_1.Flags.integer({
38
+ description: '(advanced) credential to use.',
39
+ exclusive: ['credential-payload'],
40
+ }),
41
+ 'test-account': core_1.Flags.string({
42
+ description: 'test account to use.',
43
+ options: Object.values(configuration_1.CredentialScope),
44
+ default: configuration_1.CredentialScope.DEVELOPMENT,
45
+ }),
46
+ 'read-only': core_1.Flags.boolean({
47
+ description: 'whether or not to only perform read operations',
48
+ allowNo: true,
49
+ }),
32
50
  crawlMode: core_1.Flags.string({
33
51
  description: 'mode to use while crawling the integration graph',
34
52
  options: Object.values(configuration_1.CrawlMode),
@@ -63,9 +81,24 @@ class Dev extends baseCommand_1.BaseCommand {
63
81
  // Resolve the configuration.
64
82
  const environment = flags.environment ?? GlobalConfiguration.Environment.Production;
65
83
  const configuration = await (0, configuration_1.getConfiguration)(environment, flags['config-path']);
66
- let credentials = configuration.testAccounts?.[configuration_1.CredentialScope.DEVELOPMENT];
67
- if (credentials) {
68
- credentials = (await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, credentials)).entries;
84
+ let credentialPayload;
85
+ let readOnly = flags['read-only'] ?? false;
86
+ if (flags['credential-id']) {
87
+ const credential = await (0, credentials_1.fetchCredential)(environment, this.config.configDir, flags['credential-id']);
88
+ credentialPayload = JSON.stringify(credential.payload);
89
+ // When "credential-id" is provided, the default value of "read-only" is false.
90
+ readOnly = flags['read-only'] ?? true;
91
+ }
92
+ else if (flags['credential-payload']) {
93
+ credentialPayload = flags['credential-payload'];
94
+ }
95
+ else {
96
+ let credentials = configuration.testAccounts?.[flags['test-account']];
97
+ if (credentials) {
98
+ credentials = (await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, credentials))
99
+ .entries;
100
+ }
101
+ credentialPayload = JSON.stringify(credentials);
69
102
  }
70
103
  let secrets = {};
71
104
  // Decrypt secrets, if necessary.
@@ -78,9 +111,12 @@ class Dev extends baseCommand_1.BaseCommand {
78
111
  `${process.env.NODE_MODULES_FOLDER}/@unito/integration-debugger/dist/src/index.js`,
79
112
  '--integration-url=http://localhost:9200',
80
113
  `--spawn-process=npm run dev`,
81
- `--credential-payload=${JSON.stringify(credentials)}`,
114
+ `--credential-payload=${credentialPayload}`,
82
115
  `--secrets-payload=${JSON.stringify(secrets)}`,
83
116
  ];
117
+ if (readOnly) {
118
+ commandArguments.push('--read-only');
119
+ }
84
120
  if (configuration.graphRelativeUrl) {
85
121
  commandArguments.push(`--graph-relative-url=${configuration.graphRelativeUrl}`);
86
122
  }
@@ -5,7 +5,7 @@ const core_1 = require("@oclif/core");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
6
  const inquirer_1 = tslib_1.__importDefault(require("inquirer"));
7
7
  const Configuration = tslib_1.__importStar(require("../resources/configuration"));
8
- const integrationGenerator_1 = require("../../integrationGenerator");
8
+ const integrations_1 = require("../resources/integrations");
9
9
  const baseCommand_1 = require("../baseCommand");
10
10
  const errors_1 = require("../errors");
11
11
  class Init extends baseCommand_1.BaseCommand {
@@ -41,7 +41,7 @@ class Init extends baseCommand_1.BaseCommand {
41
41
  },
42
42
  ])).name;
43
43
  core_1.ux.action.start('\nInitializing integration', undefined, { stdout: true });
44
- const generatedPath = await integrationGenerator_1.Resources.Integration.generateIntegrationSkeleton(name, process.cwd());
44
+ const generatedPath = await (0, integrations_1.copyBoilerplate)(name, process.cwd());
45
45
  process.chdir(generatedPath);
46
46
  await Configuration.writeConfiguration({ name });
47
47
  core_1.ux.action.stop();
@@ -46,7 +46,7 @@ class Login extends baseCommand_1.BaseCommand {
46
46
  this.exit(-1);
47
47
  }
48
48
  // Retrieve the user's profile.
49
- core_1.ux.action.start('Log in...', undefined, { stdout: true });
49
+ core_1.ux.action.start('Log in', undefined, { stdout: true });
50
50
  let profile = undefined;
51
51
  IntegrationsPlatform.setEnvironment(environment);
52
52
  IntegrationsPlatform.setApiKey(apiKey);
@@ -4,16 +4,22 @@ const tslib_1 = require("tslib");
4
4
  const core_1 = require("@oclif/core");
5
5
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
6
6
  const configuration_1 = require("../resources/configuration");
7
- const Oauth2Helper = tslib_1.__importStar(require("../services/oauth2Helper"));
7
+ const Oauth2Helper = tslib_1.__importStar(require("../resources/oauth2Helper"));
8
8
  const IntegrationsPlatform = tslib_1.__importStar(require("../services/integrationsPlatform"));
9
9
  const configurationTypes_1 = require("../configurationTypes");
10
10
  const errors_1 = require("../errors");
11
11
  const globalConfiguration_1 = require("../resources/globalConfiguration");
12
12
  const decryption_1 = require("../resources/decryption");
13
13
  class Oauth2 extends core_1.Command {
14
- static summary = 'Perform an OAuth2 workflow locally';
15
- static description = 'The Oauth2 command allows you to perform an OAuth2 workflow locally, either to create a new test account or to refresh an existing one.';
16
- static examples = ['<%= config.bin %> <%= command.id %>'];
14
+ static summary = `Perform an OAuth2 workflow to either populate or refresh a test account's credentials.`;
15
+ static description = `The Oauth2 command allows you to perform an OAuth2 workflow to populate the specified test account's accessToken and refreshToken to be used by the 'test' and 'dev' commands.
16
+
17
+ If the test-account is already populated, the command will refresh the credentials if the refresh token is available.
18
+ If you want to force a new OAuth2 flow to change the connected account or something else, use the --reauth flag.`;
19
+ static examples = [
20
+ '<%= config.bin %> <%= command.id %>',
21
+ '<%= config.bin %> <%= command.id %> --reauth --test-account=compliance',
22
+ ];
17
23
  static flags = {
18
24
  'test-account': core_1.Flags.string({
19
25
  description: 'Test account to use.',
@@ -24,9 +30,10 @@ class Oauth2 extends core_1.Command {
24
30
  description: 'the environment of the platform',
25
31
  options: Object.values(globalConfiguration_1.Environment),
26
32
  default: globalConfiguration_1.Environment.Production,
33
+ hidden: true,
27
34
  })(),
28
35
  reauth: core_1.Flags.boolean({
29
- description: 'triggers a new oauth2 flow to collect credentials and overwrite the current one',
36
+ description: `triggers a new oauth2 flow to overwrite the test account's current credentials`,
30
37
  default: false,
31
38
  }),
32
39
  'config-path': core_1.Flags.string({
@@ -76,14 +83,12 @@ class Oauth2 extends core_1.Command {
76
83
  return;
77
84
  }
78
85
  const decryptionResult = await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, account);
86
+ const refreshToken = decryptionResult.entries?.refreshToken;
79
87
  core_1.ux.action.start(`Refreshing test account ${testAccount}`, undefined, { stdout: true });
80
- credentials = await Oauth2Helper.updateToken({
81
- ...oauth2,
82
- refreshToken: decryptionResult.entries?.refreshToken,
83
- });
88
+ credentials = await Oauth2Helper.updateToken(oauth2, refreshToken);
84
89
  // If provider response doesn't contain a new refresh token, use the one we already have
85
90
  if (!credentials.refreshToken) {
86
- credentials.refreshToken = account?.refreshToken;
91
+ credentials.refreshToken = refreshToken;
87
92
  }
88
93
  if (decryptionResult.decryptedKeys.includes('accessToken')) {
89
94
  credentials.accessToken = (await IntegrationsPlatform.encryptData(configuration.name, credentials.accessToken)).encryptedData;
@@ -10,6 +10,7 @@ const GlobalConfiguration = tslib_1.__importStar(require("../resources/globalCon
10
10
  const integrations_1 = require("../resources/integrations");
11
11
  const configuration_1 = require("../resources/configuration");
12
12
  const decryption_1 = require("../resources/decryption");
13
+ const credentials_1 = require("../resources/credentials");
13
14
  class Test extends baseCommand_1.BaseCommand {
14
15
  static description = 'Test your integration';
15
16
  static examples = ['<%= config.bin %> <%= command.id %>'];
@@ -36,13 +37,22 @@ class Test extends baseCommand_1.BaseCommand {
36
37
  description: 'output report in JSON format at the specified path',
37
38
  }),
38
39
  'credential-payload': core_1.Flags.string({
40
+ description: '(advanced) credential payload to use.',
41
+ exclusive: ['credential-id'],
42
+ }),
43
+ 'credential-id': core_1.Flags.integer({
39
44
  description: '(advanced) credential to use.',
45
+ exclusive: ['credential-payload'],
40
46
  }),
41
47
  'test-account': core_1.Flags.string({
42
- description: 'Test account to use.',
48
+ description: 'test account to use.',
43
49
  options: Object.values(configuration_1.CredentialScope),
44
50
  default: configuration_1.CredentialScope.DEVELOPMENT,
45
51
  }),
52
+ 'read-only': core_1.Flags.boolean({
53
+ description: 'whether or not to only perform read operations',
54
+ allowNo: true,
55
+ }),
46
56
  crawlMode: core_1.Flags.string({
47
57
  description: 'mode to use while crawling the integration graph',
48
58
  options: Object.values(configuration_1.CrawlMode),
@@ -54,13 +64,13 @@ class Test extends baseCommand_1.BaseCommand {
54
64
  default: [],
55
65
  }),
56
66
  debug: core_1.Flags.boolean({
57
- description: 'Log launch command to console before running it - including decrypted values - for debugging only',
67
+ description: 'log launch command to console before running it - including decrypted values - for debugging only',
58
68
  hidden: true,
59
69
  default: false,
60
70
  }),
61
71
  'config-path': core_1.Flags.string({
62
72
  summary: 'relative path to a custom ".unito.json" file',
63
- description: `Use a custom configuration file instead of the default '.unito.json' or other environment specific
73
+ description: `use a custom configuration file instead of the default '.unito.json' or other environment specific
64
74
  ones.
65
75
 
66
76
  If you want to force the CLI to use a specific configuration file, you can use this flag to specify the relative
@@ -89,9 +99,18 @@ class Test extends baseCommand_1.BaseCommand {
89
99
  // Resolve the configuration.
90
100
  const environment = flags.environment ?? GlobalConfiguration.Environment.Production;
91
101
  const configuration = await (0, configuration_1.getConfiguration)(environment, flags['config-path']);
92
- let credentialPayload = flags['credential-payload'];
93
- // Default to test account's credentials if none are specifically provided
94
- if (credentialPayload === null || credentialPayload === undefined) {
102
+ let credentialPayload;
103
+ let readOnly = flags['read-only'] ?? false;
104
+ if (flags['credential-id']) {
105
+ const credential = await (0, credentials_1.fetchCredential)(environment, this.config.configDir, flags['credential-id']);
106
+ credentialPayload = JSON.stringify(credential.payload);
107
+ // When "credential-id" is provided, the default value of "read-only" is false.
108
+ readOnly = flags['read-only'] ?? true;
109
+ }
110
+ else if (flags['credential-payload']) {
111
+ credentialPayload = flags['credential-payload'];
112
+ }
113
+ else {
95
114
  let credentials = configuration.testAccounts?.[flags['test-account']];
96
115
  if (credentials) {
97
116
  credentials = (await (0, decryption_1.decryptEntries)(configuration.name, environment, this.config.configDir, credentials))
@@ -116,6 +135,9 @@ class Test extends baseCommand_1.BaseCommand {
116
135
  `--starting-path=${flags['starting-path']}`,
117
136
  `--starting-operation=${flags['starting-operation']}`,
118
137
  ];
138
+ if (readOnly) {
139
+ commandArguments.push('--read-only');
140
+ }
119
141
  if (configuration.graphRelativeUrl) {
120
142
  commandArguments.push(`--graph-relative-url=${configuration.graphRelativeUrl}`);
121
143
  }
@@ -21,6 +21,14 @@ export declare class AuthenticationFailed extends Error {
21
21
  }
22
22
  export declare class DecryptionAuthenticationError extends Error {
23
23
  }
24
+ export declare class UnsupportedContentTypeError extends Error {
25
+ }
26
+ export declare class CredentialAuthenticationError extends Error {
27
+ }
28
+ export declare class CredentialAccessDenied extends Error {
29
+ }
30
+ export declare class IntegrationAlreadyExistsError extends Error {
31
+ }
24
32
  export declare class EntryDecryptionError extends Error {
25
33
  key: string;
26
34
  value: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.handleError = exports.ConfigurationInvalid = exports.EntryDecryptionError = exports.DecryptionAuthenticationError = exports.AuthenticationFailed = exports.MissingApiKey = exports.FileSizeExceeded = exports.MissingAuth2AuthorizationError = exports.InvalidRequestContentTypeError = exports.FailedToRetrieveAccessTokenError = exports.NoRefreshTokenError = exports.ConfigurationMalformed = exports.NoConfigurationFileError = exports.NoIntegrationFoundError = void 0;
3
+ exports.handleError = exports.ConfigurationInvalid = exports.EntryDecryptionError = exports.IntegrationAlreadyExistsError = exports.CredentialAccessDenied = exports.CredentialAuthenticationError = exports.UnsupportedContentTypeError = exports.DecryptionAuthenticationError = exports.AuthenticationFailed = exports.MissingApiKey = exports.FileSizeExceeded = exports.MissingAuth2AuthorizationError = exports.InvalidRequestContentTypeError = exports.FailedToRetrieveAccessTokenError = exports.NoRefreshTokenError = exports.ConfigurationMalformed = exports.NoConfigurationFileError = exports.NoIntegrationFoundError = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const core_1 = require("@oclif/core");
6
6
  const chalk_1 = tslib_1.__importDefault(require("chalk"));
@@ -41,6 +41,18 @@ exports.AuthenticationFailed = AuthenticationFailed;
41
41
  class DecryptionAuthenticationError extends Error {
42
42
  }
43
43
  exports.DecryptionAuthenticationError = DecryptionAuthenticationError;
44
+ class UnsupportedContentTypeError extends Error {
45
+ }
46
+ exports.UnsupportedContentTypeError = UnsupportedContentTypeError;
47
+ class CredentialAuthenticationError extends Error {
48
+ }
49
+ exports.CredentialAuthenticationError = CredentialAuthenticationError;
50
+ class CredentialAccessDenied extends Error {
51
+ }
52
+ exports.CredentialAccessDenied = CredentialAccessDenied;
53
+ class IntegrationAlreadyExistsError extends Error {
54
+ }
55
+ exports.IntegrationAlreadyExistsError = IntegrationAlreadyExistsError;
44
56
  class EntryDecryptionError extends Error {
45
57
  key;
46
58
  value;
@@ -68,45 +80,37 @@ function handleError(command, error) {
68
80
  if (core_1.ux.action.running) {
69
81
  core_1.ux.action.stop(chalk_1.default.redBright('failed'));
70
82
  }
71
- let handled = false;
83
+ let unhandled = false;
72
84
  if (error instanceof NoIntegrationFoundError) {
73
85
  command.logToStderr(chalk_1.default.redBright('Your directory does not seem to contain an integration :('));
74
86
  command.logToStderr(`Make sure you are in the right directory and that you have a ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} file.`);
75
- handled = true;
76
87
  }
77
88
  else if (error instanceof NoConfigurationFileError) {
78
89
  command.logToStderr(chalk_1.default.redBright('This command requires a configuration file for your integration :('));
79
90
  command.logToStderr(`This file should be located at ${chalk_1.default.yellowBright(path_1.default.relative(process.cwd(), (0, configuration_1.getConfigurationPath)()))}.`);
80
- handled = true;
81
91
  }
82
92
  else if (error instanceof ConfigurationMalformed) {
83
93
  command.logToStderr(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} was found but its not a valid JSON file!`));
84
- handled = true;
85
94
  }
86
95
  else if (error instanceof ConfigurationInvalid) {
87
96
  command.logToStderr(chalk_1.default.redBright(`Your ${chalk_1.default.yellowBright(configuration_1.DEFAULT_CONFIGURATION_NAME)} is invalid!`));
88
97
  command.logToStderr();
89
98
  command.logToStderr(error.prettyDetails);
90
- handled = true;
91
99
  }
92
100
  else if (error instanceof NoRefreshTokenError) {
93
101
  command.logToStderr(chalk_1.default.redBright('No refresh token found in your configuration file'));
94
- handled = true;
95
102
  }
96
103
  else if (error instanceof FailedToRetrieveAccessTokenError) {
97
104
  command.logToStderr(chalk_1.default.redBright('Failed to retrieve access token'));
98
105
  command.logToStderr();
99
106
  command.logToStderr(error.message);
100
- handled = true;
101
107
  }
102
108
  else if (error instanceof InvalidRequestContentTypeError) {
103
109
  command.logToStderr(chalk_1.default.redBright('Invalid request content type'));
104
- handled = true;
105
110
  command.logToStderr();
106
111
  command.logToStderr(error.message);
107
112
  }
108
113
  else if (error instanceof integrationsPlatform_1.HttpError) {
109
- handled = true;
110
114
  command.logToStderr();
111
115
  command.logToStderr((0, json_colorizer_1.default)(JSON.stringify(error.data, null, 2)));
112
116
  }
@@ -114,13 +118,11 @@ function handleError(command, error) {
114
118
  command.logToStderr();
115
119
  command.logToStderr(chalk_1.default.redBright('Your API key is not set!'));
116
120
  command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first.`);
117
- handled = true;
118
121
  }
119
122
  else if (error instanceof AuthenticationFailed) {
120
123
  command.logToStderr();
121
124
  command.logToStderr(chalk_1.default.redBright('This command requires that you are logged to Unito!'));
122
125
  command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first.`);
123
- handled = true;
124
126
  }
125
127
  else if (error instanceof DecryptionAuthenticationError) {
126
128
  command.logToStderr();
@@ -128,7 +130,6 @@ function handleError(command, error) {
128
130
  command.logToStderr('Your configuration contains secrets (i.e. in top-level secrets, in test accounts, etc.).');
129
131
  command.logToStderr('To decrypt those secrets locally, you must authenticate to Unito.');
130
132
  command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first.`);
131
- handled = true;
132
133
  }
133
134
  else if (error instanceof EntryDecryptionError) {
134
135
  command.logToStderr();
@@ -140,15 +141,31 @@ function handleError(command, error) {
140
141
  command.logToStderr(`1. The integration was deployed once with the ${chalk_1.default.yellowBright('publish')} command.`);
141
142
  command.logToStderr('2. You have access to the integration.');
142
143
  command.logToStderr(`3. The secret was encrypted for the ${chalk_1.default.yellowBright(error.environment)} environment.`);
143
- handled = true;
144
144
  }
145
145
  else if (error instanceof MissingAuth2AuthorizationError) {
146
146
  command.logToStderr();
147
147
  command.logToStderr(chalk_1.default.redBright(`No Oauth2 authorization found in your configuration file`));
148
- // TODO: Update link once the documentation is made available publicly
149
- command.logToStderr('See https://staging-dev.unito.io/docs/integrations/configuration/authorizations#oauth-2 for more information on how to configure Oauth2');
150
- handled = true;
148
+ command.logToStderr('See https://dev.unito.io/docs/connectors/configuration/authorizations#oauth-2 for more information on how to configure Oauth2');
149
+ }
150
+ else if (error instanceof CredentialAuthenticationError) {
151
+ command.logToStderr();
152
+ command.logToStderr(chalk_1.default.redBright('The credential cannot be obtained!'));
153
+ command.logToStderr('To obtain information on the credential, you must authenticate to Unito.');
154
+ command.logToStderr(`Make sure to run the ${chalk_1.default.yellowBright('login')} command first.`);
155
+ }
156
+ else if (error instanceof CredentialAccessDenied) {
157
+ command.logToStderr();
158
+ command.logToStderr(chalk_1.default.redBright('The credential cannot be obtained!'));
159
+ command.logToStderr("You don't have access to this credential or the credential doesn't exist.");
160
+ }
161
+ else if (error instanceof IntegrationAlreadyExistsError) {
162
+ command.logToStderr();
163
+ command.logToStderr(chalk_1.default.redBright(`The integration already exists in this folder.`));
164
+ command.logToStderr(`Make sure to provide a unique name for your integration.`);
165
+ }
166
+ else {
167
+ unhandled = true;
151
168
  }
152
- return handled;
169
+ return !unhandled;
153
170
  }
154
171
  exports.handleError = handleError;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.writeTestAccount = exports.writeConfiguration = exports.getConfiguration = exports.getConfigurationPath = exports.ENCRYPTION_PREFIX = exports.DEFAULT_CONFIGURATION_NAME = exports.CredentialScope = exports.CrawlMode = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const core_1 = require("@oclif/core");
6
5
  const fs = tslib_1.__importStar(require("fs"));
7
6
  const ajv_1 = tslib_1.__importDefault(require("ajv"));
8
7
  const ajv_formats_1 = tslib_1.__importDefault(require("ajv-formats"));
@@ -48,7 +47,6 @@ async function getConfiguration(environment, customConfigPath) {
48
47
  const configurationPath = customConfigPath
49
48
  ? `${process.cwd()}${customConfigPath.startsWith('/') ? customConfigPath : `/${customConfigPath}`}`
50
49
  : getConfigurationPath(environment);
51
- core_1.ux.log(`Loading ${configurationPath} configuration file`);
52
50
  try {
53
51
  fileContent = await fs.promises.readFile(configurationPath, 'utf-8');
54
52
  }
@@ -0,0 +1,3 @@
1
+ import * as GlobalConfiguration from './globalConfiguration';
2
+ import { Credential } from '../services/integrationsPlatform';
3
+ export declare function fetchCredential(environment: GlobalConfiguration.Environment, configDir: string, credentialId: number): Promise<Credential>;
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fetchCredential = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const errors_1 = require("../errors");
6
+ const GlobalConfiguration = tslib_1.__importStar(require("./globalConfiguration"));
7
+ const integrationsPlatform_1 = require("./integrationsPlatform");
8
+ const integrationsPlatform_2 = require("../services/integrationsPlatform");
9
+ async function fetchCredential(environment, configDir, credentialId) {
10
+ const globalConfiguration = await GlobalConfiguration.read(configDir);
11
+ try {
12
+ await (0, integrationsPlatform_1.validateAuthenticated)(globalConfiguration, environment);
13
+ }
14
+ catch {
15
+ throw new errors_1.CredentialAuthenticationError();
16
+ }
17
+ let credential;
18
+ try {
19
+ credential = await (0, integrationsPlatform_2.getCredential)(credentialId);
20
+ }
21
+ catch {
22
+ throw new errors_1.CredentialAccessDenied();
23
+ }
24
+ return credential;
25
+ }
26
+ exports.fetchCredential = fetchCredential;
@@ -1,2 +1,3 @@
1
1
  export declare function validateIsIntegrationDirectory(): void;
2
2
  export declare function isIntegrationDirectory(): boolean;
3
+ export declare function copyBoilerplate(integrationName: string, destinationPath: string): Promise<string>;
@@ -1,13 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isIntegrationDirectory = exports.validateIsIntegrationDirectory = void 0;
3
+ exports.copyBoilerplate = exports.isIntegrationDirectory = exports.validateIsIntegrationDirectory = void 0;
4
4
  const tslib_1 = require("tslib");
5
+ const path_1 = tslib_1.__importDefault(require("path"));
5
6
  const fs_1 = tslib_1.__importDefault(require("fs"));
6
7
  const errors_1 = require("../errors");
8
+ const errors_2 = require("../errors");
7
9
  const configuration_1 = require("./configuration");
8
10
  function validateIsIntegrationDirectory() {
9
11
  if (!isIntegrationDirectory()) {
10
- throw new errors_1.NoIntegrationFoundError();
12
+ throw new errors_2.NoIntegrationFoundError();
11
13
  }
12
14
  }
13
15
  exports.validateIsIntegrationDirectory = validateIsIntegrationDirectory;
@@ -15,3 +17,36 @@ function isIntegrationDirectory() {
15
17
  return fs_1.default.existsSync((0, configuration_1.getConfigurationPath)());
16
18
  }
17
19
  exports.isIntegrationDirectory = isIntegrationDirectory;
20
+ async function copyBoilerplate(integrationName, destinationPath) {
21
+ const sourcePath = path_1.default.join(__dirname, `../../boilerplate`);
22
+ const targetPath = `${destinationPath}/${integrationName.toLowerCase().replace(/ /g, '_')}`;
23
+ if (fs_1.default.existsSync(targetPath)) {
24
+ throw new errors_1.IntegrationAlreadyExistsError();
25
+ }
26
+ await fs_1.default.promises.mkdir(targetPath, { recursive: true });
27
+ await copyFilesAndFolders(sourcePath, targetPath, ['node_modules', 'dist']);
28
+ // The .npmrc file is created here because
29
+ // it will be excluded during the CLI package's publishing process by npm.
30
+ const npmrcContent = ['engine-strict=true', 'strict-ssl=true'].join('\n');
31
+ await fs_1.default.promises.writeFile(path_1.default.join(targetPath, '.npmrc'), npmrcContent);
32
+ return targetPath;
33
+ }
34
+ exports.copyBoilerplate = copyBoilerplate;
35
+ async function copyFilesAndFolders(source, destination, excludedFolders) {
36
+ const files = await fs_1.default.promises.readdir(source);
37
+ for (const file of files) {
38
+ if (excludedFolders.includes(file)) {
39
+ continue;
40
+ }
41
+ const sourcePath = path_1.default.join(source, file);
42
+ const targetPath = path_1.default.join(destination, file);
43
+ const stats = await fs_1.default.promises.stat(sourcePath);
44
+ if (stats.isFile()) {
45
+ await fs_1.default.promises.copyFile(sourcePath, targetPath);
46
+ }
47
+ else if (stats.isDirectory()) {
48
+ await fs_1.default.promises.mkdir(targetPath);
49
+ await copyFilesAndFolders(sourcePath, targetPath, excludedFolders);
50
+ }
51
+ }
52
+ }
@@ -0,0 +1,4 @@
1
+ import { Oauth2Response, Oauth2Payload } from '../services/oauth2Helper';
2
+ import { Environment } from './globalConfiguration';
3
+ export declare function performOAuth2Flow(applicationCredentials: Oauth2Payload, environment?: Environment): Promise<Oauth2Response>;
4
+ export declare function updateToken(applicationCredentials: Oauth2Payload, refreshToken: string): Promise<Oauth2Response>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateToken = exports.performOAuth2Flow = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const oauth2Helper_1 = tslib_1.__importDefault(require("../services/oauth2Helper"));
6
+ const errors_1 = require("../errors");
7
+ const globalConfiguration_1 = require("./globalConfiguration");
8
+ async function performOAuth2Flow(applicationCredentials, environment = globalConfiguration_1.Environment.Production) {
9
+ const oauthHelper = new oauth2Helper_1.default(applicationCredentials, environment);
10
+ const serverUrl = await oauthHelper.startServer();
11
+ const healthCheck = await fetch(`${serverUrl}/health`);
12
+ if (healthCheck.status !== 200) {
13
+ throw new Error('OAuthServer did not start');
14
+ }
15
+ await oauthHelper.authorize();
16
+ const oauth2Response = await oauthHelper.callbackIsDone();
17
+ await oauthHelper.stopServer();
18
+ if (!oauth2Response.accessToken) {
19
+ throw new errors_1.FailedToRetrieveAccessTokenError('Access token was not returned');
20
+ }
21
+ return oauth2Response;
22
+ }
23
+ exports.performOAuth2Flow = performOAuth2Flow;
24
+ /* istanbul ignore next */
25
+ // No point to test this function as it is just a wrapper around OAuth2Helper
26
+ async function updateToken(applicationCredentials, refreshToken) {
27
+ const oauthHelper = new oauth2Helper_1.default(applicationCredentials);
28
+ return oauthHelper.updateToken(refreshToken);
29
+ }
30
+ exports.updateToken = updateToken;
@@ -38,3 +38,4 @@ export declare function getIntegrationEvents(integrationId: number, options?: {
38
38
  limit?: number;
39
39
  }): Promise<IntegrationEvent[]>;
40
40
  export declare function updateIntegration(integrationId: number, configuration: Configuration): Promise<Integration>;
41
+ export declare function getCredential(credentialId: number): Promise<Credential>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateIntegration = exports.getIntegrationEvents = exports.inviteUserToIntegration = exports.createIntegration = exports.publishIntegration = exports.getIntegrations = exports.getIntegrationByName = exports.getIntegration = exports.reencryptData = exports.decryptData = exports.encryptData = exports.getProfile = exports.setApiKey = exports.getApiKey = exports.setEnvironment = exports.Servers = exports.HttpError = void 0;
3
+ exports.getCredential = exports.updateIntegration = exports.getIntegrationEvents = exports.inviteUserToIntegration = exports.createIntegration = exports.publishIntegration = exports.getIntegrations = exports.getIntegrationByName = exports.getIntegration = exports.reencryptData = exports.decryptData = exports.encryptData = exports.getProfile = exports.setApiKey = exports.getApiKey = exports.setEnvironment = exports.Servers = exports.HttpError = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const fs = tslib_1.__importStar(require("fs"));
6
6
  const integrations_platform_client_1 = tslib_1.__importDefault(require("@unito/integrations-platform-client"));
@@ -153,3 +153,7 @@ async function updateIntegration(integrationId, configuration) {
153
153
  });
154
154
  }
155
155
  exports.updateIntegration = updateIntegration;
156
+ async function getCredential(credentialId) {
157
+ return integrations_platform_client_1.default.getCredentialById(credentialId);
158
+ }
159
+ exports.getCredential = getCredential;