@unito/integration-cli 0.55.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 (150) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +32 -0
  3. package/bin/run +11 -0
  4. package/bin/run.cmd +3 -0
  5. package/dist/.eslintrc.d.ts +10 -0
  6. package/dist/.eslintrc.js +20 -0
  7. package/dist/integrationGenerator/errors.d.ts +2 -0
  8. package/dist/integrationGenerator/errors.js +6 -0
  9. package/dist/integrationGenerator/index.d.ts +2 -0
  10. package/dist/integrationGenerator/index.js +5 -0
  11. package/dist/integrationGenerator/integrationBoilerplate/.dockerignore +3 -0
  12. package/dist/integrationGenerator/integrationBoilerplate/.eslintrc.js +74 -0
  13. package/dist/integrationGenerator/integrationBoilerplate/.nvmrc +1 -0
  14. package/dist/integrationGenerator/integrationBoilerplate/.prettierignore +1 -0
  15. package/dist/integrationGenerator/integrationBoilerplate/.prettierrc +7 -0
  16. package/dist/integrationGenerator/integrationBoilerplate/.unito.json +1 -0
  17. package/dist/integrationGenerator/integrationBoilerplate/Dockerfile +38 -0
  18. package/dist/integrationGenerator/integrationBoilerplate/README.md +21 -0
  19. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.dockerignore +3 -0
  20. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.eslintrc.js +74 -0
  21. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.nvmrc +1 -0
  22. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.prettierignore +1 -0
  23. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.prettierrc +7 -0
  24. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/.unito.json +1 -0
  25. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/Dockerfile +38 -0
  26. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/README.md +21 -0
  27. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/package.json +43 -0
  28. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/index.ts +94 -0
  29. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/logger.ts +55 -0
  30. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/middlewares/additionalLoggingContext.ts +22 -0
  31. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/middlewares/correlationId.ts +13 -0
  32. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/middlewares/credentials.ts +38 -0
  33. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/request.ts +59 -0
  34. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/routes/index.ts +11 -0
  35. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/routes/me.ts +15 -0
  36. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/src/routes/root.ts +12 -0
  37. package/dist/integrationGenerator/integrationBoilerplate/integrationBoilerplate/tsconfig.json +37 -0
  38. package/dist/integrationGenerator/integrationBoilerplate/package.json +43 -0
  39. package/dist/integrationGenerator/integrationBoilerplate/src/index.ts +90 -0
  40. package/dist/integrationGenerator/integrationBoilerplate/src/logger.ts +37 -0
  41. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/correlationId.ts +18 -0
  42. package/dist/integrationGenerator/integrationBoilerplate/src/middlewares/credentials.ts +38 -0
  43. package/dist/integrationGenerator/integrationBoilerplate/src/request.ts +59 -0
  44. package/dist/integrationGenerator/integrationBoilerplate/src/routes/index.ts +11 -0
  45. package/dist/integrationGenerator/integrationBoilerplate/src/routes/me.ts +15 -0
  46. package/dist/integrationGenerator/integrationBoilerplate/src/routes/root.ts +12 -0
  47. package/dist/integrationGenerator/integrationBoilerplate/tsconfig.json +37 -0
  48. package/dist/integrationGenerator/src/index.d.ts +1 -0
  49. package/dist/integrationGenerator/src/index.js +5 -0
  50. package/dist/integrationGenerator/src/resources/index.d.ts +1 -0
  51. package/dist/integrationGenerator/src/resources/index.js +5 -0
  52. package/dist/integrationGenerator/src/resources/integration.d.ts +9 -0
  53. package/dist/integrationGenerator/src/resources/integration.js +60 -0
  54. package/dist/integrationGenerator/test/resources/integration.test.d.ts +1 -0
  55. package/dist/integrationGenerator/test/resources/integration.test.js +51 -0
  56. package/dist/schemas/authorization.json +204 -0
  57. package/dist/schemas/automation.json +81 -0
  58. package/dist/schemas/configuration.json +89 -0
  59. package/dist/scripts/generateTypes.d.ts +8 -0
  60. package/dist/scripts/generateTypes.js +44 -0
  61. package/dist/src/baseCommand.d.ts +14 -0
  62. package/dist/src/baseCommand.js +39 -0
  63. package/dist/src/commands/activity.d.ts +12 -0
  64. package/dist/src/commands/activity.js +75 -0
  65. package/dist/src/commands/dev.d.ts +15 -0
  66. package/dist/src/commands/dev.js +123 -0
  67. package/dist/src/commands/encrypt.d.ts +11 -0
  68. package/dist/src/commands/encrypt.js +50 -0
  69. package/dist/src/commands/init.d.ts +10 -0
  70. package/dist/src/commands/init.js +51 -0
  71. package/dist/src/commands/invite.d.ts +11 -0
  72. package/dist/src/commands/invite.js +71 -0
  73. package/dist/src/commands/login.d.ts +11 -0
  74. package/dist/src/commands/login.js +76 -0
  75. package/dist/src/commands/oauth2.d.ts +10 -0
  76. package/dist/src/commands/oauth2.js +99 -0
  77. package/dist/src/commands/publish.d.ts +28 -0
  78. package/dist/src/commands/publish.js +302 -0
  79. package/dist/src/commands/test.d.ts +9 -0
  80. package/dist/src/commands/test.js +165 -0
  81. package/dist/src/commands/upgrade.d.ts +7 -0
  82. package/dist/src/commands/upgrade.js +88 -0
  83. package/dist/src/configurationTypes.d.ts +209 -0
  84. package/dist/src/configurationTypes.js +49 -0
  85. package/dist/src/errors.d.ts +38 -0
  86. package/dist/src/errors.js +159 -0
  87. package/dist/src/hooks/init/displayLogo.d.ts +3 -0
  88. package/dist/src/hooks/init/displayLogo.js +37 -0
  89. package/dist/src/index.d.ts +1 -0
  90. package/dist/src/index.js +5 -0
  91. package/dist/src/oauth2Helper/oauth2Helper.d.ts +63 -0
  92. package/dist/src/oauth2Helper/oauth2Helper.js +235 -0
  93. package/dist/src/oauth2Helper/types.d.ts +22 -0
  94. package/dist/src/oauth2Helper/types.js +2 -0
  95. package/dist/src/resources/configuration.d.ts +30 -0
  96. package/dist/src/resources/configuration.js +191 -0
  97. package/dist/src/resources/decryption.d.ts +5 -0
  98. package/dist/src/resources/decryption.js +62 -0
  99. package/dist/src/resources/fileSystem.d.ts +2 -0
  100. package/dist/src/resources/fileSystem.js +22 -0
  101. package/dist/src/resources/globalConfiguration.d.ts +13 -0
  102. package/dist/src/resources/globalConfiguration.js +44 -0
  103. package/dist/src/resources/integrations.d.ts +2 -0
  104. package/dist/src/resources/integrations.js +17 -0
  105. package/dist/src/resources/integrationsPlatform.d.ts +2 -0
  106. package/dist/src/resources/integrationsPlatform.js +33 -0
  107. package/dist/src/services/integrationsPlatform.d.ts +36 -0
  108. package/dist/src/services/integrationsPlatform.js +162 -0
  109. package/dist/src/services/oauth2Helper.d.ts +3 -0
  110. package/dist/src/services/oauth2Helper.js +34 -0
  111. package/dist/test/commands/activity.test.d.ts +1 -0
  112. package/dist/test/commands/activity.test.js +62 -0
  113. package/dist/test/commands/dev.test.d.ts +1 -0
  114. package/dist/test/commands/dev.test.js +139 -0
  115. package/dist/test/commands/encrypt.test.d.ts +1 -0
  116. package/dist/test/commands/encrypt.test.js +73 -0
  117. package/dist/test/commands/init.test.d.ts +1 -0
  118. package/dist/test/commands/init.test.js +45 -0
  119. package/dist/test/commands/invite.test.d.ts +1 -0
  120. package/dist/test/commands/invite.test.js +56 -0
  121. package/dist/test/commands/login.test.d.ts +1 -0
  122. package/dist/test/commands/login.test.js +90 -0
  123. package/dist/test/commands/oauth2.test.d.ts +1 -0
  124. package/dist/test/commands/oauth2.test.js +104 -0
  125. package/dist/test/commands/publish.test.d.ts +1 -0
  126. package/dist/test/commands/publish.test.js +429 -0
  127. package/dist/test/commands/test.test.d.ts +1 -0
  128. package/dist/test/commands/test.test.js +171 -0
  129. package/dist/test/commands/upgrade.test.d.ts +1 -0
  130. package/dist/test/commands/upgrade.test.js +47 -0
  131. package/dist/test/errors.test.d.ts +1 -0
  132. package/dist/test/errors.test.js +96 -0
  133. package/dist/test/helpers/init.d.ts +1 -0
  134. package/dist/test/helpers/init.js +6 -0
  135. package/dist/test/mocha.hooks.d.ts +2 -0
  136. package/dist/test/mocha.hooks.js +37 -0
  137. package/dist/test/oauth2Helper/oauth2Helper.test.d.ts +1 -0
  138. package/dist/test/oauth2Helper/oauth2Helper.test.js +150 -0
  139. package/dist/test/resources/configuration.test.d.ts +1 -0
  140. package/dist/test/resources/configuration.test.js +586 -0
  141. package/dist/test/resources/decryption.test.d.ts +1 -0
  142. package/dist/test/resources/decryption.test.js +68 -0
  143. package/dist/test/resources/globalConfiguration.test.d.ts +1 -0
  144. package/dist/test/resources/globalConfiguration.test.js +32 -0
  145. package/dist/test/services/integrationsPlatform.test.d.ts +1 -0
  146. package/dist/test/services/integrationsPlatform.test.js +168 -0
  147. package/dist/test/services/oauth2Helper.test.d.ts +1 -0
  148. package/dist/test/services/oauth2Helper.test.js +85 -0
  149. package/oclif.manifest.json +423 -0
  150. package/package.json +98 -0
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.open = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const express_1 = tslib_1.__importDefault(require("express"));
6
+ const cors_1 = tslib_1.__importDefault(require("cors"));
7
+ const openUrl = tslib_1.__importStar(require("openurl"));
8
+ const configurationTypes_1 = require("../configurationTypes");
9
+ const errors_1 = require("../errors");
10
+ // It allows to stub openUrl library in the test
11
+ exports.open = openUrl;
12
+ class OAuth2Helper {
13
+ server = null;
14
+ clientId;
15
+ clientSecret;
16
+ providerAuthorizationUrl;
17
+ tokenUrl;
18
+ scopes;
19
+ grantType;
20
+ requestContentType;
21
+ responseContentType;
22
+ refreshToken;
23
+ code = '';
24
+ serverUrl = '';
25
+ tokenRequestParameters;
26
+ refreshRequestParameters;
27
+ /**
28
+ * Constructs an instance of OAuthHelper.
29
+ * @param clientId The client ID for your OAuth application.
30
+ * @param clientSecret The client secret for your OAuth application.
31
+ * @param authorizationUrl The URL for the authorization endpoint of the provider.
32
+ * @param scopes The scopes required for the OAuth authorization.
33
+ * @param providerTokenUrl The URL for the token endpoint of the provider.
34
+ */
35
+ constructor(authorizationInfo) {
36
+ const { clientId, clientSecret, authorizationUrl, scopes, tokenUrl, grantType, requestContentType, responseContentType, refreshToken, refreshRequestParameters, tokenRequestParameters, } = authorizationInfo;
37
+ this.startServer = this.startServer.bind(this);
38
+ this.stopServer = this.stopServer.bind(this);
39
+ this.handleAuthorize = this.handleAuthorize.bind(this);
40
+ this.handleCallback = this.handleCallback.bind(this);
41
+ this.handleToken = this.handleToken.bind(this);
42
+ this.clientId = clientId;
43
+ this.clientSecret = clientSecret;
44
+ this.providerAuthorizationUrl = authorizationUrl;
45
+ this.scopes = scopes.map(scope => scope.name);
46
+ this.tokenUrl = tokenUrl;
47
+ this.grantType = grantType ?? configurationTypes_1.GrantType.AUTHORIZATION_CODE;
48
+ this.requestContentType = requestContentType ?? configurationTypes_1.RequestContentType.URL_ENCODED;
49
+ this.responseContentType = responseContentType ?? configurationTypes_1.RequestContentType.JSON;
50
+ this.refreshToken = refreshToken;
51
+ this.tokenRequestParameters = tokenRequestParameters;
52
+ this.refreshRequestParameters = refreshRequestParameters;
53
+ }
54
+ /**
55
+ * Handles the authorization request and redirects the user to the provider's authorization page.
56
+ * @param req The express Request object.
57
+ * @param res The express Response object.
58
+ */
59
+ async handleAuthorize(_req, res) {
60
+ if (!this.providerAuthorizationUrl) {
61
+ res.status(422).send({ message: 'providerAuthorizationUrl must be defined in .unito.json' });
62
+ return;
63
+ }
64
+ const authUrl = new URL(this.providerAuthorizationUrl);
65
+ const params = new URLSearchParams(authUrl.search);
66
+ if (this.clientId) {
67
+ params.set('client_id', this.clientId);
68
+ }
69
+ params.set('redirect_uri', `${this.serverUrl}/credentials/new/oauth2/callback`);
70
+ if (this.scopes) {
71
+ params.set('scope', this.scopes.join(' '));
72
+ }
73
+ params.set('response_type', 'code');
74
+ authUrl.search = params.toString();
75
+ exports.open.open(authUrl.toString());
76
+ res.json();
77
+ }
78
+ /**
79
+ * Handles the callback request from the provider and stores the authorization code.
80
+ * @param req The express Request object.
81
+ * @param res The express Response object.
82
+ */
83
+ async handleCallback(req, res) {
84
+ const { code } = req.query;
85
+ this.code = code;
86
+ res.json();
87
+ }
88
+ encodeBody(bodyData, contentType) {
89
+ switch (contentType) {
90
+ case configurationTypes_1.RequestContentType.URL_ENCODED:
91
+ return new URLSearchParams(bodyData).toString();
92
+ case configurationTypes_1.RequestContentType.JSON:
93
+ return JSON.stringify(bodyData);
94
+ }
95
+ }
96
+ /**
97
+ * Handles the token request to exchange the authorization code for an access token.
98
+ * @param req The express Request object.
99
+ * @param res The express Response object.
100
+ */
101
+ async handleToken(_req, res) {
102
+ if (!Object.values(configurationTypes_1.RequestContentType).includes(this.requestContentType)) {
103
+ res.status(400).json({ error: `Request content type not supported: ${this.requestContentType}` });
104
+ }
105
+ const bodyData = {
106
+ code: this.code,
107
+ grant_type: this.grantType,
108
+ redirect_uri: `${this.serverUrl}/credentials/new/oauth2/callback`,
109
+ };
110
+ if (this.clientId) {
111
+ bodyData.client_id = this.clientId;
112
+ }
113
+ if (this.clientSecret) {
114
+ bodyData.client_secret = this.clientSecret;
115
+ }
116
+ const body = this.encodeBody(bodyData, this.requestContentType);
117
+ const fetchOptions = {
118
+ headers: {
119
+ 'Content-type': this.requestContentType,
120
+ ...(this.tokenRequestParameters?.header ?? {}),
121
+ },
122
+ body,
123
+ method: 'POST',
124
+ };
125
+ try {
126
+ const fetchResult = await fetch(this.tokenUrl, fetchOptions);
127
+ if (fetchResult.status !== 200) {
128
+ res.status(500).json({ error: `Error fetching token: ${await fetchResult.text()}` });
129
+ }
130
+ const response = await fetchResult.json();
131
+ const credentialsInfo = {
132
+ accessToken: response.access_token,
133
+ refreshToken: response.refresh_token,
134
+ };
135
+ res.json(credentialsInfo);
136
+ }
137
+ catch (error) {
138
+ res.status(500).json({ error: 'Failed to retrieve access token' });
139
+ }
140
+ }
141
+ async updateToken() {
142
+ if (!this.refreshToken) {
143
+ throw new errors_1.NoRefreshTokenError();
144
+ }
145
+ if (!Object.values(configurationTypes_1.RequestContentType).includes(this.requestContentType)) {
146
+ throw new errors_1.InvalidRequestContentTypeError(`Request content type not supported: ${this.requestContentType}`);
147
+ }
148
+ const bodyData = {
149
+ grant_type: 'refresh_token',
150
+ refresh_token: this.refreshToken,
151
+ };
152
+ if (this.clientId) {
153
+ bodyData.client_id = this.clientId;
154
+ }
155
+ if (this.clientSecret) {
156
+ bodyData.client_secret = this.clientSecret;
157
+ }
158
+ const fetchOptions = {
159
+ headers: {
160
+ 'Content-type': this.requestContentType,
161
+ ...(this.refreshRequestParameters?.header ?? {}),
162
+ },
163
+ body: this.encodeBody(bodyData, this.requestContentType),
164
+ method: 'POST',
165
+ };
166
+ try {
167
+ const fetchResult = await fetch(this.tokenUrl, fetchOptions);
168
+ if (fetchResult.status !== 200) {
169
+ throw new errors_1.FailedToRetrieveAccessTokenError(await fetchResult.text());
170
+ }
171
+ const response = await fetchResult.json();
172
+ const credentialsInfo = {
173
+ accessToken: response.access_token,
174
+ refreshToken: response.refresh_token,
175
+ };
176
+ return credentialsInfo;
177
+ }
178
+ catch (error) {
179
+ throw new errors_1.FailedToRetrieveAccessTokenError(JSON.stringify(error));
180
+ }
181
+ }
182
+ /**
183
+ * Starts the Express server for handling OAuth callbacks.
184
+ * @returns The URL of the server.
185
+ */
186
+ /* istanbul ignore next */
187
+ startServer() {
188
+ const app = (0, express_1.default)();
189
+ const PORT = process.env.OAUTH2_PORT ?? 9002;
190
+ app.use((0, cors_1.default)({ credentials: true, origin: true }));
191
+ app.get('/health', (req, res) => {
192
+ res.send('pong');
193
+ });
194
+ app.get('/credentials/new/oauth2/authorize', this.handleAuthorize);
195
+ app.get('/credentials/new/oauth2/callback', this.handleCallback);
196
+ app.get('/credentials/new/oauth2/token', this.handleToken);
197
+ this.server = app.listen(PORT, () => {
198
+ console.log(`Listening at port ${PORT}`);
199
+ });
200
+ this.serverUrl = `http://localhost:${PORT}`;
201
+ return this.serverUrl;
202
+ }
203
+ /**
204
+ * Stops the Express server.
205
+ */
206
+ /* istanbul ignore next */
207
+ stopServer() {
208
+ if (this.server) {
209
+ this.server.close(() => {
210
+ console.log('Server has stopped');
211
+ });
212
+ }
213
+ }
214
+ /**
215
+ * Waits for the authorization code to be set.
216
+ * @returns A promise that resolves when the code is set.
217
+ */
218
+ /* istanbul ignore next */
219
+ async callbackIsDone() {
220
+ if (this.code) {
221
+ return true;
222
+ }
223
+ else {
224
+ return new Promise(resolve => {
225
+ const interval = setInterval(() => {
226
+ if (this.code) {
227
+ clearInterval(interval);
228
+ resolve(true);
229
+ }
230
+ }, 100);
231
+ });
232
+ }
233
+ }
234
+ }
235
+ exports.default = OAuth2Helper;
@@ -0,0 +1,22 @@
1
+ import { Oauth2 } from '../configurationTypes';
2
+ export interface Oauth2Credentials {
3
+ clientId: string;
4
+ clientSecret: string;
5
+ }
6
+ export interface AuthorizePayload extends Oauth2Credentials {
7
+ providerAuthorizationUrl: string;
8
+ scopes?: string;
9
+ providerAccessTokenUrl: string;
10
+ }
11
+ export interface CallbackPayload {
12
+ code: string;
13
+ }
14
+ export interface Oauth2Response {
15
+ accessToken: string;
16
+ refreshToken?: string;
17
+ }
18
+ export interface TokenPayload extends Oauth2Credentials {
19
+ providerTokenUrl: string;
20
+ code: string;
21
+ }
22
+ export type Oauth2Payload = Oauth2 & Omit<Oauth2Response, 'accessToken'>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,30 @@
1
+ import { Configuration } from '../configurationTypes';
2
+ import { Environment } from './globalConfiguration';
3
+ export declare enum CrawlMode {
4
+ FULL = "full",
5
+ SAMPLE = "sample",
6
+ SINGLE = "single"
7
+ }
8
+ export declare enum CredentialScope {
9
+ DEVELOPMENT = "development",
10
+ COMPLIANCE = "compliance"
11
+ }
12
+ export declare const DEFAULT_CONFIGURATION_NAME: string;
13
+ export declare const ENCRYPTION_PREFIX = "unito-secret-v1://";
14
+ /**
15
+ * Check for environment specific configuration, otherwise uses the default one.
16
+ *
17
+ * Production environment always uses the default configuration.
18
+ * @param environment targeted environment
19
+ * @returns path to the environment configuration file
20
+ */
21
+ export declare function getConfigurationPath(environment?: Environment): string;
22
+ export declare function getConfiguration(environment: Environment, customConfigPath?: string): Promise<Configuration>;
23
+ /**
24
+ * Write the configuration to the default configuration file.
25
+ */
26
+ export declare function writeConfiguration(configuration: Configuration): Promise<void>;
27
+ export declare function writeTestAccount(configuration: Configuration, account: {
28
+ accessToken: string;
29
+ refreshToken?: string;
30
+ }, accountName: string): Promise<void>;
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeTestAccount = exports.writeConfiguration = exports.getConfiguration = exports.getConfigurationPath = exports.ENCRYPTION_PREFIX = exports.DEFAULT_CONFIGURATION_NAME = exports.CredentialScope = exports.CrawlMode = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const core_1 = require("@oclif/core");
6
+ const fs = tslib_1.__importStar(require("fs"));
7
+ const ajv_1 = tslib_1.__importDefault(require("ajv"));
8
+ const ajv_formats_1 = tslib_1.__importDefault(require("ajv-formats"));
9
+ const better_ajv_errors_1 = tslib_1.__importDefault(require("better-ajv-errors"));
10
+ const configurationTypes_1 = require("../configurationTypes");
11
+ const errors_1 = require("../errors");
12
+ const integrations_1 = require("./integrations");
13
+ const globalConfiguration_1 = require("./globalConfiguration");
14
+ var CrawlMode;
15
+ (function (CrawlMode) {
16
+ CrawlMode["FULL"] = "full";
17
+ CrawlMode["SAMPLE"] = "sample";
18
+ CrawlMode["SINGLE"] = "single";
19
+ })(CrawlMode || (exports.CrawlMode = CrawlMode = {}));
20
+ var CredentialScope;
21
+ (function (CredentialScope) {
22
+ CredentialScope["DEVELOPMENT"] = "development";
23
+ CredentialScope["COMPLIANCE"] = "compliance";
24
+ })(CredentialScope || (exports.CredentialScope = CredentialScope = {}));
25
+ exports.DEFAULT_CONFIGURATION_NAME = '.unito.json';
26
+ exports.ENCRYPTION_PREFIX = 'unito-secret-v1://';
27
+ /**
28
+ * Check for environment specific configuration, otherwise uses the default one.
29
+ *
30
+ * Production environment always uses the default configuration.
31
+ * @param environment targeted environment
32
+ * @returns path to the environment configuration file
33
+ */
34
+ function getConfigurationPath(environment = globalConfiguration_1.Environment.Production) {
35
+ const environmentBasedPath = `${process.cwd()}/.unito.${environment}.json`;
36
+ if (environment !== globalConfiguration_1.Environment.Production && fs.existsSync(environmentBasedPath)) {
37
+ return environmentBasedPath;
38
+ }
39
+ else {
40
+ return `${process.cwd()}/${exports.DEFAULT_CONFIGURATION_NAME}`;
41
+ }
42
+ }
43
+ exports.getConfigurationPath = getConfigurationPath;
44
+ async function getConfiguration(environment, customConfigPath) {
45
+ (0, integrations_1.validateIsIntegrationDirectory)();
46
+ let configuration;
47
+ let fileContent;
48
+ const configurationPath = customConfigPath
49
+ ? `${process.cwd()}${customConfigPath.startsWith('/') ? customConfigPath : `/${customConfigPath}`}`
50
+ : getConfigurationPath(environment);
51
+ core_1.ux.log(`Loading ${configurationPath} configuration file`);
52
+ try {
53
+ fileContent = await fs.promises.readFile(configurationPath, 'utf-8');
54
+ }
55
+ catch (error) {
56
+ throw new errors_1.NoConfigurationFileError();
57
+ }
58
+ try {
59
+ configuration = JSON.parse(fileContent);
60
+ }
61
+ catch (error) {
62
+ throw new errors_1.ConfigurationMalformed();
63
+ }
64
+ // Initialize the required structure in the configuration.
65
+ if (!configuration.testAccounts) {
66
+ configuration.testAccounts = { development: {} };
67
+ }
68
+ if (!configuration.testAccounts.development) {
69
+ configuration.testAccounts.development = {};
70
+ }
71
+ for (const authorization of configuration.authorizations ?? []) {
72
+ if (authorization.oauth2) {
73
+ if (!authorization.oauth2.grantType) {
74
+ authorization.oauth2.grantType = configurationTypes_1.GrantType.AUTHORIZATION_CODE;
75
+ }
76
+ if (!authorization.oauth2.requestContentType) {
77
+ authorization.oauth2.requestContentType = configurationTypes_1.RequestContentType.URL_ENCODED;
78
+ }
79
+ if (!authorization.oauth2.responseContentType) {
80
+ authorization.oauth2.responseContentType = configurationTypes_1.RequestContentType.JSON;
81
+ }
82
+ }
83
+ }
84
+ await validateConfiguration(configuration);
85
+ return configuration;
86
+ }
87
+ exports.getConfiguration = getConfiguration;
88
+ /**
89
+ * Write the configuration to the default configuration file.
90
+ */
91
+ async function writeConfiguration(configuration) {
92
+ (0, integrations_1.validateIsIntegrationDirectory)();
93
+ await validateConfiguration(configuration);
94
+ await fs.promises.writeFile(getConfigurationPath(globalConfiguration_1.Environment.Production), JSON.stringify(configuration, null, 2));
95
+ }
96
+ exports.writeConfiguration = writeConfiguration;
97
+ async function writeTestAccount(configuration, account, accountName) {
98
+ // istanbul ignore next
99
+ if (accountName !== 'development' && accountName !== 'compliance') {
100
+ throw new Error('Invalid account name');
101
+ }
102
+ configuration.testAccounts = configuration.testAccounts ?? {};
103
+ configuration.testAccounts[accountName] = account;
104
+ await writeConfiguration(configuration);
105
+ }
106
+ exports.writeTestAccount = writeTestAccount;
107
+ async function validateConfiguration(configuration) {
108
+ const directory = `${__dirname}/../../schemas`;
109
+ const files = await fs.promises.readdir(directory);
110
+ const jsonFiles = files.filter(filename => filename.endsWith('.json'));
111
+ const schemasContent = await Promise.all(jsonFiles.map(filename => fs.promises.readFile(`${directory}/${filename}`, 'utf8')));
112
+ const schemas = schemasContent.map(content => JSON.parse(content));
113
+ const spec = new ajv_1.default({ schemas, keywords: ['tsEnumNames'], allErrors: true });
114
+ (0, ajv_formats_1.default)(spec);
115
+ const schema = 'https://unito.io/integration_cli/configuration.schema.json';
116
+ const validate = spec.getSchema(schema);
117
+ if (!validate) {
118
+ throw new Error(`Schema ${schema} not found'`);
119
+ }
120
+ // ESLint seems confused about this AJV function and thinks it is async.
121
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
122
+ validate(configuration);
123
+ if (validate.errors) {
124
+ throw new errors_1.ConfigurationInvalid('Your configuration file is invalid!', validate.errors, (0, better_ajv_errors_1.default)(schema, configuration, validate.errors, { indent: 2 }));
125
+ }
126
+ // Validate test accounts.
127
+ if (configuration.testAccounts && configuration.authorizations?.length) {
128
+ for (const [name, account] of Object.entries(configuration.testAccounts)) {
129
+ if (Object.keys(account).length) {
130
+ validateTestAccount(name, account, configuration.authorizations, spec);
131
+ }
132
+ }
133
+ }
134
+ }
135
+ function validateTestAccount(credentialName, credential, authorizationDefinitions, spec) {
136
+ const authorizationSchemas = authorizationDefinitions.map(constructAuthorizationSchema);
137
+ const schema = { anyOf: authorizationSchemas };
138
+ const validate = spec.compile(schema);
139
+ validate(credential);
140
+ if (validate.errors) {
141
+ throw new errors_1.ConfigurationInvalid(`Your testAccount ${credentialName} is invalid!`, validate.errors, (0, better_ajv_errors_1.default)(schema, credential, validate.errors, { indent: 2 }));
142
+ }
143
+ }
144
+ function constructAuthorizationSchema(authorizationDefinition) {
145
+ const authorizationSchema = {
146
+ type: 'object',
147
+ additionalProperties: true,
148
+ };
149
+ if (authorizationDefinition.method === configurationTypes_1.Method.OAUTH2) {
150
+ authorizationSchema.properties = {
151
+ accessToken: {
152
+ type: 'string',
153
+ },
154
+ refreshToken: {
155
+ type: 'string',
156
+ },
157
+ expiresIn: {
158
+ type: 'number',
159
+ },
160
+ tokenType: {
161
+ type: 'string',
162
+ },
163
+ scope: {
164
+ type: 'string',
165
+ },
166
+ oauth2ExtraParameters: {
167
+ type: 'object',
168
+ additionalProperties: true,
169
+ },
170
+ };
171
+ authorizationSchema.required = ['accessToken'];
172
+ }
173
+ const authorizationVariables = Object.entries(authorizationDefinition.variables ?? {});
174
+ if (authorizationVariables.length) {
175
+ const variableProperties = Object.fromEntries(authorizationVariables.map(([name, definition]) => [
176
+ name,
177
+ {
178
+ // Sanitize Type to compile schema
179
+ type: ['boolean', 'number'].includes(definition.type) ? definition.type : 'string',
180
+ format: definition.format,
181
+ pattern: definition.pattern,
182
+ },
183
+ ]));
184
+ authorizationSchema.properties = { ...authorizationSchema.properties, ...variableProperties };
185
+ const required = Array.from(new Set(authorizationVariables.filter(([, definition]) => definition.required).map(([name]) => name)));
186
+ if (required.length) {
187
+ (authorizationSchema.required ??= []).push(...required);
188
+ }
189
+ }
190
+ return authorizationSchema;
191
+ }
@@ -0,0 +1,5 @@
1
+ import { Configuration } from '../configurationTypes';
2
+ import * as GlobalConfiguration from './globalConfiguration';
3
+ import { CredentialScope } from './configuration';
4
+ export declare function decryptTestAccountCredentials(configuration: Configuration, environment: GlobalConfiguration.Environment, testAccount: CredentialScope, configDir: string): Promise<Record<string, unknown>>;
5
+ export declare function decryptSecrets(configuration: Configuration, environment: GlobalConfiguration.Environment, configDir: string): Promise<Record<string, unknown>>;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decryptSecrets = exports.decryptTestAccountCredentials = 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 configuration_1 = require("./configuration");
9
+ const integrationsPlatform_2 = require("../services/integrationsPlatform");
10
+ async function decryptTestAccountCredentials(configuration, environment, testAccount, configDir) {
11
+ const credentials = configuration.testAccounts?.[testAccount];
12
+ if (!credentials) {
13
+ return {};
14
+ }
15
+ // Get encrypted credential entries
16
+ const encryptedEntries = Object.entries(credentials).filter((entry) => typeof entry[1] === 'string' && entry[1].startsWith(configuration_1.ENCRYPTION_PREFIX));
17
+ if (!encryptedEntries.length) {
18
+ return credentials;
19
+ }
20
+ // Copy credentials to avoid mutating the configuration.
21
+ const decryptedCredentials = structuredClone(credentials);
22
+ const globalConfiguration = await GlobalConfiguration.read(configDir);
23
+ try {
24
+ await (0, integrationsPlatform_1.validateAuthenticated)(globalConfiguration, environment);
25
+ }
26
+ catch (err) {
27
+ throw new errors_1.DecryptionAuthenticationError('credentials');
28
+ }
29
+ for (const [key, encryptedCredential] of encryptedEntries) {
30
+ try {
31
+ decryptedCredentials[key] = (await (0, integrationsPlatform_2.decryptData)(configuration.name, encryptedCredential)).decryptedData;
32
+ }
33
+ catch (err) {
34
+ throw new errors_1.EntryDecryptionError(key, encryptedCredential, environment);
35
+ }
36
+ }
37
+ return decryptedCredentials;
38
+ }
39
+ exports.decryptTestAccountCredentials = decryptTestAccountCredentials;
40
+ async function decryptSecrets(configuration, environment, configDir) {
41
+ if (!Object.entries(configuration.secrets ?? {}).length) {
42
+ return {};
43
+ }
44
+ const globalConfiguration = await GlobalConfiguration.read(configDir);
45
+ try {
46
+ await (0, integrationsPlatform_1.validateAuthenticated)(globalConfiguration, environment);
47
+ }
48
+ catch (err) {
49
+ throw new errors_1.DecryptionAuthenticationError('secrets');
50
+ }
51
+ const decryptedSecrets = {};
52
+ for (const [key, encryptedSecret] of Object.entries(configuration.secrets ?? {})) {
53
+ try {
54
+ decryptedSecrets[key] = (await (0, integrationsPlatform_2.decryptData)(configuration.name, encryptedSecret)).decryptedData;
55
+ }
56
+ catch (err) {
57
+ throw new errors_1.EntryDecryptionError(key, encryptedSecret, environment);
58
+ }
59
+ }
60
+ return decryptedSecrets;
61
+ }
62
+ exports.decryptSecrets = decryptSecrets;
@@ -0,0 +1,2 @@
1
+ /// <reference types="node" />
2
+ export declare function getFileBuffer(fileName: string, maxFileSize: number): Promise<Buffer | null>;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getFileBuffer = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const promises_1 = tslib_1.__importDefault(require("fs/promises"));
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ const errors_1 = require("../errors");
8
+ async function getFileBuffer(fileName, maxFileSize) {
9
+ const filePath = path_1.default.resolve(fileName);
10
+ try {
11
+ await promises_1.default.access(filePath);
12
+ }
13
+ catch (error) {
14
+ return null;
15
+ }
16
+ const fileStat = await promises_1.default.stat(filePath);
17
+ if (fileStat.size > maxFileSize) {
18
+ throw new errors_1.FileSizeExceeded(`File exceeds the size limit: ${maxFileSize}`);
19
+ }
20
+ return promises_1.default.readFile(filePath);
21
+ }
22
+ exports.getFileBuffer = getFileBuffer;
@@ -0,0 +1,13 @@
1
+ export interface Configuration {
2
+ apiKey: string | undefined;
3
+ apiKeyStaging: string | undefined;
4
+ apiKeyLocal: string | undefined;
5
+ }
6
+ export declare enum Environment {
7
+ Local = "local",
8
+ Staging = "staging",
9
+ Production = "production"
10
+ }
11
+ export declare function getDefault(): Configuration;
12
+ export declare function read(baseDir: string): Promise<Configuration>;
13
+ export declare function write(baseDir: string, configuration: Configuration): Promise<void>;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.write = exports.read = exports.getDefault = exports.Environment = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs_1 = tslib_1.__importDefault(require("fs"));
6
+ const path_1 = tslib_1.__importDefault(require("path"));
7
+ var Environment;
8
+ (function (Environment) {
9
+ Environment["Local"] = "local";
10
+ Environment["Staging"] = "staging";
11
+ Environment["Production"] = "production";
12
+ })(Environment || (exports.Environment = Environment = {}));
13
+ function getDefault() {
14
+ return {
15
+ apiKey: undefined,
16
+ apiKeyStaging: undefined,
17
+ apiKeyLocal: undefined,
18
+ };
19
+ }
20
+ exports.getDefault = getDefault;
21
+ async function read(baseDir) {
22
+ await fs_1.default.promises.mkdir(path_1.default.dirname(getConfigurationPath(baseDir)), { recursive: true });
23
+ let configuration;
24
+ try {
25
+ const file = await fs_1.default.promises.readFile(getConfigurationPath(baseDir), 'utf-8');
26
+ configuration = JSON.parse(file);
27
+ }
28
+ catch {
29
+ configuration = getDefault();
30
+ }
31
+ return { ...getDefault(), ...configuration };
32
+ }
33
+ exports.read = read;
34
+ async function write(baseDir, configuration) {
35
+ await fs_1.default.promises.mkdir(path_1.default.dirname(getConfigurationPath(baseDir)), { recursive: true });
36
+ await fs_1.default.promises.writeFile(getConfigurationPath(baseDir), JSON.stringify(configuration, null, 2), {
37
+ encoding: 'utf8',
38
+ flag: 'w',
39
+ });
40
+ }
41
+ exports.write = write;
42
+ function getConfigurationPath(baseDir) {
43
+ return `${baseDir}/configuration.json`;
44
+ }
@@ -0,0 +1,2 @@
1
+ export declare function validateIsIntegrationDirectory(): void;
2
+ export declare function isIntegrationDirectory(): boolean;
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isIntegrationDirectory = exports.validateIsIntegrationDirectory = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const fs_1 = tslib_1.__importDefault(require("fs"));
6
+ const errors_1 = require("../errors");
7
+ const configuration_1 = require("./configuration");
8
+ function validateIsIntegrationDirectory() {
9
+ if (!isIntegrationDirectory()) {
10
+ throw new errors_1.NoIntegrationFoundError();
11
+ }
12
+ }
13
+ exports.validateIsIntegrationDirectory = validateIsIntegrationDirectory;
14
+ function isIntegrationDirectory() {
15
+ return fs_1.default.existsSync((0, configuration_1.getConfigurationPath)());
16
+ }
17
+ exports.isIntegrationDirectory = isIntegrationDirectory;
@@ -0,0 +1,2 @@
1
+ import * as GlobalConfiguration from './globalConfiguration';
2
+ export declare function validateAuthenticated(globalConfiguration: GlobalConfiguration.Configuration, environment: GlobalConfiguration.Environment): Promise<void>;